Skip to content

Commit

Permalink
Fix generation of repeat internal IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
fongsean committed Sep 18, 2024
1 parent 2fc1fb9 commit d83100c
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import type {
} from '../../../interfaces/renderProps.interface';
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import useInitialiseRepeatGroups from '../../../hooks/useInitialiseRepeatGroups';
import { nanoid } from 'nanoid';
import cloneDeep from 'lodash.clonedeep';
import { useQuestionnaireStore } from '../../../stores';
import useRepeatGroups from '../../../hooks/useRepeatGroups';
import RepeatGroupView from './RepeatGroupView';
import { generateNewRepeatId } from '../../../utils/repeatId';

interface RepeatGroupProps
extends PropsWithQrRepeatGroupChangeHandler,
Expand Down Expand Up @@ -104,7 +104,7 @@ function RepeatGroup(props: RepeatGroupProps) {
setRepeatGroups([
...repeatGroups,
{
nanoId: nanoid(),
nanoId: generateNewRepeatId(qItem.linkId),
qrItem: null
}
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import type {
PropsWithShowMinimalViewAttribute
} from '../../../interfaces/renderProps.interface';
import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import { nanoid } from 'nanoid';
import { createEmptyQrItem } from '../../../utils/qrItem';
import { FullWidthFormComponentBox } from '../../Box.styles';
import AddItemButton from './AddItemButton';
Expand All @@ -33,6 +32,7 @@ import useInitialiseRepeatAnswers from '../../../hooks/useInitialiseRepeatAnswer
import ItemFieldGrid from '../ItemParts/ItemFieldGrid';
import useReadOnly from '../../../hooks/useReadOnly';
import { useQuestionnaireStore } from '../../../stores';
import { generateExistingRepeatId, generateNewRepeatId } from '../../../utils/repeatId';

interface RepeatItemProps
extends PropsWithQrItemChangeHandler,
Expand All @@ -56,7 +56,7 @@ function RepeatItem(props: RepeatItemProps) {

const readOnly = useReadOnly(qItem, parentIsReadOnly);

const repeatAnswers = useInitialiseRepeatAnswers(qrItem);
const repeatAnswers = useInitialiseRepeatAnswers(qItem.linkId, qrItem);

// Event Handlers
function handleAnswerChange(newQrItem: QuestionnaireResponseItem, index: number) {
Expand All @@ -81,7 +81,7 @@ function RepeatItem(props: RepeatItemProps) {
}

function handleAddItem() {
const updatedRepeatAnswers = [...repeatAnswers, { id: nanoid() }];
const updatedRepeatAnswers = [...repeatAnswers, { id: generateNewRepeatId(qItem.linkId) }];

onQrItemChange({
...createEmptyQrItem(qItem, undefined),
Expand All @@ -100,7 +100,7 @@ function RepeatItem(props: RepeatItemProps) {

return (
<RepeatField
key={answer?.id ?? nanoid()}
key={answer?.id ?? generateExistingRepeatId(qItem.linkId, index)}
qItem={qItem}
qrItem={repeatAnswerQrItem}
answer={answer}
Expand Down Expand Up @@ -131,7 +131,9 @@ function RepeatItem(props: RepeatItemProps) {
}

return (
<Collapse key={answer?.id ?? nanoid()} timeout={200}>
<Collapse
key={answer?.id ?? generateExistingRepeatId(qItem.linkId, index)}
timeout={200}>
<RepeatField
qItem={qItem}
qrItem={repeatAnswerQrItem}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import type {
PropsWithQrRepeatGroupChangeHandler,
PropsWithShowMinimalViewAttribute
} from '../../../interfaces/renderProps.interface';
import { nanoid } from 'nanoid';
import useReadOnly from '../../../hooks/useReadOnly';
import GroupTableView from './GroupTableView';
import type { GroupTableRowModel } from '../../../interfaces/groupTable.interface';
import { getGroupTableItemsToUpdate } from '../../../utils/groupTable';
import useGroupTableRows from '../../../hooks/useGroupTableRows';
import { flushSync } from 'react-dom';
import { generateNewRepeatId } from '../../../utils/repeatId';

interface GroupTableProps
extends PropsWithQrRepeatGroupChangeHandler,
Expand Down Expand Up @@ -62,7 +62,10 @@ function GroupTable(props: GroupTableProps) {

const readOnly = useReadOnly(qItem, parentIsReadOnly);

const { tableRows, selectedIds, setTableRows, setSelectedIds } = useGroupTableRows(qrItems);
const { tableRows, selectedIds, setTableRows, setSelectedIds } = useGroupTableRows(
qItem.linkId,
qrItems
);

// Generate item labels as table headers
const qItems = qItem.item;
Expand Down Expand Up @@ -114,7 +117,7 @@ function GroupTable(props: GroupTableProps) {
}

function handleAddRow() {
const newRowNanoId = nanoid();
const newRowNanoId = generateNewRepeatId(qItem.linkId);
setTableRows([
...tableRows,
{
Expand Down
4 changes: 2 additions & 2 deletions packages/smart-forms-renderer/src/hooks/useGroupTableRows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import { useState } from 'react';
import useInitialiseGroupTable from './useInitialiseGroupTable';
import type { QuestionnaireResponseItem } from 'fhir/r4';

function useGroupTableRows(qrItems: QuestionnaireResponseItem[]) {
const initialisedGroupTableRows = useInitialiseGroupTable(qrItems);
function useGroupTableRows(linkId: string, qrItems: QuestionnaireResponseItem[]) {
const initialisedGroupTableRows = useInitialiseGroupTable(linkId, qrItems);

const [tableRows, setTableRows] = useState(initialisedGroupTableRows);
const [selectedIds, setSelectedIds] = useState<string[]>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@
*/

import type { QuestionnaireResponseItem } from 'fhir/r4';
import { nanoid } from 'nanoid';
import type { GroupTableRowModel } from '../interfaces/groupTable.interface';
import { generateExistingRepeatId, generateNewRepeatId } from '../utils/repeatId';

function useInitialiseGroupTable(qrItems: QuestionnaireResponseItem[]): GroupTableRowModel[] {
function useInitialiseGroupTable(
linkId: string,
qrItems: QuestionnaireResponseItem[]
): GroupTableRowModel[] {
let initialGroupTableRows: GroupTableRowModel[] = [
{
nanoId: nanoid(),
nanoId: generateNewRepeatId(linkId),
qrItem: null
}
];

if (qrItems.length > 0) {
initialGroupTableRows = qrItems.map((qrItem) => {
initialGroupTableRows = qrItems.map((qrItem, index) => {
return {
nanoId: nanoid(),
nanoId: generateExistingRepeatId(linkId, index),
qrItem
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,23 @@
*/

import type { QuestionnaireResponseItem, QuestionnaireResponseItemAnswer } from 'fhir/r4';
import { nanoid } from 'nanoid';
import { useMemo } from 'react';
import { generateExistingRepeatId, generateNewRepeatId } from '../utils/repeatId';

function useInitialiseRepeatAnswers(
linkId: string,
qrItem: QuestionnaireResponseItem | null
): (QuestionnaireResponseItemAnswer | null)[] {
return useMemo(() => {
let initialRepeatAnswers: (QuestionnaireResponseItemAnswer | null)[] = [{ id: nanoid() }];

if (qrItem?.answer) {
initialRepeatAnswers = qrItem.answer.map((answer) => {
if (!answer.id) {
answer.id = nanoid();
}
return answer;
});
if (!qrItem?.answer) {
return [{ id: generateNewRepeatId(linkId) }];
}

return initialRepeatAnswers;
}, [qrItem]);
return qrItem.answer.map((answer, index) => ({
...answer,
id: answer.id ?? generateExistingRepeatId(linkId, index)
}));
}, [linkId, qrItem]);
}

export default useInitialiseRepeatAnswers;
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
*/

import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
import { nanoid } from 'nanoid';
import type { RepeatGroupSingle } from '../interfaces/repeatGroup.interface';
import { useMemo } from 'react';
import { generateExistingRepeatId, generateNewRepeatId } from '../utils/repeatId';

function useInitialiseRepeatGroups(
qItem: QuestionnaireItem,
Expand All @@ -28,15 +28,15 @@ function useInitialiseRepeatGroups(
() => {
let initialRepeatGroupAnswers: RepeatGroupSingle[] = [
{
nanoId: nanoid(),
nanoId: generateNewRepeatId(qItem.linkId),
qrItem: null
}
];

if (qrItems.length > 0) {
initialRepeatGroupAnswers = qrItems.map((qrItem) => {
initialRepeatGroupAnswers = qrItems.map((qrItem, index) => {
return {
nanoId: nanoid(),
nanoId: generateExistingRepeatId(qItem.linkId, index),
qrItem
};
});
Expand Down
3 changes: 2 additions & 1 deletion packages/smart-forms-renderer/src/utils/manageForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { initialiseQuestionnaireResponse } from './initialise';
import { removeEmptyAnswers } from './removeEmptyAnswers';
import { readEncounter, readPatient, readUser } from '../api/smartClient';
import type Client from 'fhirclient/lib/Client';
import cloneDeep from 'lodash.clonedeep';

/**
* Build the form with an initial Questionnaire and an optional filled QuestionnaireResponse.
Expand Down Expand Up @@ -95,7 +96,7 @@ export async function initialiseFhirClient(fhirClient: Client): Promise<void> {
* @author Sean Fong
*/
export function getResponse(): QuestionnaireResponse {
return questionnaireResponseStore.getState().updatableResponse;
return cloneDeep(questionnaireResponseStore.getState().updatableResponse);
}

/**
Expand Down
27 changes: 27 additions & 0 deletions packages/smart-forms-renderer/src/utils/repeatId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 Commonwealth Scientific and Industrial Research
* Organisation (CSIRO) ABN 41 687 119 230.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { nanoid } from 'nanoid';

export function generateNewRepeatId(linkId: string): string {
return `${linkId}-${nanoid()}`;
}

export function generateExistingRepeatId(linkId: string, index: number): string {
const paddedIndex = index.toString().padStart(6, '0');
return `${linkId}-${paddedIndex}`;
}

0 comments on commit d83100c

Please sign in to comment.