Skip to content

Commit

Permalink
Merge pull request #634 from sanger/blogRegistration
Browse files Browse the repository at this point in the history
Blog registration
  • Loading branch information
khelwood authored Apr 18, 2024
2 parents a32d43a + 81dc549 commit 37a1811
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 20 deletions.
14 changes: 10 additions & 4 deletions src/components/upload/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ const FileUploader = <T extends object>({

/**Callback function to perform upload**/
const uploadFiles = React.useCallback(
(existingExternalNames?: string[]) => {
(existingExternalNames?: string[], ignoreExternalNames?: boolean) => {
if (files.length === 0) return;
setUploadInProgress(undefined);
setConfirmUploadOutcome(undefined);
files.forEach((file) => {
requestUpload(file, setUploadInProgress, existingExternalNames);
requestUpload(file, setUploadInProgress, existingExternalNames, ignoreExternalNames);
});
},
[setUploadInProgress, setConfirmUploadOutcome, files, requestUpload]
Expand Down Expand Up @@ -218,8 +218,14 @@ const FileUploader = <T extends object>({
<ClashModal
registrationResult={clashes}
onConfirm={() => {
const existingExternalNames: string[] = clashes.clashes.map((clash) => clash.tissue.externalName!);
uploadFiles(existingExternalNames);
uploadFiles(clashes.clashes.map((clash) => clash.tissue.externalName!));
setClashes(undefined);
}}
onConfirmAndUnrelease={() => {
uploadFiles(
clashes.clashes.map((clash) => clash.tissue.externalName!),
true
);
setClashes(undefined);
}}
onCancel={() => {
Expand Down
8 changes: 6 additions & 2 deletions src/components/upload/useUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,18 @@ export function useUpload<T>(url: string, errorField?: string) {
(
file: File,
notifyUploadProgress?: (uploadProgress: UploadProgress | undefined) => void,
existingExternalNames?: string[]
existingExternalNames?: string[],
ignoreExternalNames: boolean = false
) => {
const retUploadResult: UploadResult<T> = { file, success: false, error: undefined, response: undefined };
async function postUpload(url: string, file: File) {
const formData = new FormData();
formData.append('file', file);
if (existingExternalNames) {
formData.append('existingExternalNames', existingExternalNames.join(','));
formData.append(
ignoreExternalNames ? 'ignoreExternalNames' : 'existingExternalNames',
existingExternalNames.join(',')
);
}
return await fetch(url, {
method: 'POST',
Expand Down
23 changes: 18 additions & 5 deletions src/lib/machines/registration/registrationMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { ClientError } from 'graphql-request';

export interface RegistrationContext<F, M> {
registrationFormInput: Maybe<F>;
buildRegistrationInput: (formInput: F, existingTissues?: Array<string>) => Promise<M>;
buildRegistrationInput: (
formInput: F,
existingTissues?: Array<string>,
ignoreExistingTissues?: boolean
) => Promise<M>;
registrationService: (mutationInput: M) => Promise<RegisterResultFieldsFragment>;
registrationResult: Maybe<RegisterResultFieldsFragment>;
registrationErrors: Maybe<ServerErrors>;
Expand All @@ -15,6 +19,7 @@ export interface RegistrationContext<F, M> {
type SubmitFormEvent<F> = {
type: 'SUBMIT_FORM';
values: F;
ignoreExistingTissues?: boolean;
};

type EditSubmissionEvent = {
Expand All @@ -41,7 +46,11 @@ export type RegistrationEvent<F> =
* XState state machine for Registration
*/
export function createRegistrationMachine<F, M>(
buildRegistrationInput: (formInput: F, existingTissues?: Array<string>) => Promise<M>,
buildRegistrationInput: (
formInput: F,
existingTissues?: Array<string>,
ignoreExistingTissues?: boolean
) => Promise<M>,
registrationService: (mutationInput: M) => Promise<RegisterResultFieldsFragment>
) {
return createMachine(
Expand Down Expand Up @@ -71,12 +80,15 @@ export function createRegistrationMachine<F, M>(
invoke: {
id: 'submitting',
src: fromPromise(({ input }) => {
return buildRegistrationInput(input.values, input.confirmedTissues).then(input.registrationService);
return buildRegistrationInput(input.values, input.confirmedTissues, input.ignoreExistingTissues).then(
input.registrationService
);
}),
input: ({ context, event }) => ({
values: (event as SubmitFormEvent<F>).values,
registrationService: context.registrationService,
confirmedTissues: context.confirmedTissues
confirmedTissues: context.confirmedTissues,
ignoreExistingTissues: (event as SubmitFormEvent<F>).ignoreExistingTissues
}),

onDone: {
Expand Down Expand Up @@ -138,7 +150,8 @@ export function createRegistrationMachine<F, M>(
if (event.type !== 'xstate.error.actor.submitting') {
return context;
}
context.registrationErrors = extractServerErrors(event.error);
context.registrationErrors =
event.error instanceof ClientError ? extractServerErrors(event.error) : event.error;
return context;
})
},
Expand Down
17 changes: 12 additions & 5 deletions src/pages/BlockRegistration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ function buildRegistrationSchema(registrationInfo: GetRegistrationInfoQuery) {
*/
export function buildRegisterTissuesMutationVariables(
formValues: RegistrationFormValues,
existingTissues: Array<string> = []
existingTissues: Array<string> = [],
ignoreExistingTissues: boolean = false
): Promise<RegisterTissuesMutationVariables> {
return new Promise((resolve) => {
const blocks = formValues.tissues.reduce<BlockRegisterRequest[]>((memo, tissue) => {
return new Promise((resolve, reject) => {
let blocks = formValues.tissues.reduce<BlockRegisterRequest[]>((memo, tissue) => {
return [
...memo,
...tissue.blocks.map<BlockRegisterRequest>((block) => {
Expand All @@ -138,7 +139,7 @@ export function buildRegisterTissuesMutationVariables(
highestSection: block.lastKnownSectionNumber,
hmdmc: tissue.hmdmc.trim(),
labwareType: block.labwareType.trim(),
lifeStage: tissue.lifeStage in LifeStage ? tissue.lifeStage : undefined,
lifeStage: Object.values(LifeStage).includes(tissue.lifeStage) ? tissue.lifeStage : undefined,
tissueType: tissue.tissueType.trim(),
spatialLocation: block.spatialLocation,
replicateNumber: block.replicateNumber,
Expand All @@ -151,7 +152,7 @@ export function buildRegisterTissuesMutationVariables(
: undefined
};

if (existingTissues.includes(blockRegisterRequest.externalIdentifier)) {
if (!ignoreExistingTissues && existingTissues.includes(blockRegisterRequest.externalIdentifier)) {
blockRegisterRequest.existingTissue = true;
}

Expand All @@ -160,6 +161,12 @@ export function buildRegisterTissuesMutationVariables(
];
}, []);

if (ignoreExistingTissues) {
blocks = blocks.filter((block) => !existingTissues.includes(block.externalIdentifier));
}
if (blocks.length === 0) {
reject({ problems: ['No blocks to register after filtering the ones with existing tissues'] });
}
resolve({ request: { blocks, workNumbers: formValues.workNumbers } });
});
}
Expand Down
18 changes: 15 additions & 3 deletions src/pages/registration/ClashModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ type ClashModalProps = {
registrationResult: RegisterResultFieldsFragment;
onConfirm: () => void;
onCancel: () => void;
onConfirmAndUnrelease: () => void;
};

export default function ClashModal({ registrationResult, onConfirm, onCancel }: ClashModalProps) {
export default function ClashModal({
registrationResult,
onConfirm,
onCancel,
onConfirmAndUnrelease
}: ClashModalProps) {
const linkToUnrelease: string = registrationResult.clashes
.map((clash) => {
return clash.labware.map((lw) => `barcode=${lw.barcode}`).join('&');
Expand Down Expand Up @@ -65,8 +71,14 @@ export default function ClashModal({ registrationResult, onConfirm, onCancel }:
<BlueButton onClick={onConfirm} className="w-full text-base sm:ml-3 sm:w-auto sm:text-sm">
Confirm
</BlueButton>
<Link to={`/admin/unrelease?${linkToUnrelease}`} className="mt-3 w-full sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
<BlueButton action="tertiary">Unrelease</BlueButton>
<Link
to={`/admin/unrelease?${linkToUnrelease}`}
target="_blank"
className="mt-3 w-full sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
>
<BlueButton action="tertiary" onClick={onConfirmAndUnrelease}>
Confirm and Unrelease
</BlueButton>
</Link>
<BlueButton action="secondary" onClick={onCancel} className="mt-3 w-full sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
Cancel
Expand Down
1 change: 1 addition & 0 deletions src/pages/registration/Registration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function Registration<M, T extends TissueValues<B>, B, R extends Required<Labwar
<ClashModal
registrationResult={registrationResult}
onConfirm={() => send({ type: 'SUBMIT_FORM', values })}
onConfirmAndUnrelease={() => send({ type: 'SUBMIT_FORM', values, ignoreExistingTissues: true })}
onCancel={() => send({ type: 'EDIT_SUBMISSION' })}
/>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/registration/RegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const RegistrationForm = <T extends TissueValues<B>, B>({
// Available spatial locations are determined by the current tissue type
const availableSpatialLocations: GetRegistrationInfoQuery['tissueTypes'][number]['spatialLocations'] = useMemo(() => {
return (
registrationInfo.tissueTypes.find((tt) => tt.name === values.tissues[currentIndex].tissueType)
registrationInfo.tissueTypes.find((tt) => tt.name === values.tissues[currentIndex]?.tissueType)
?.spatialLocations ?? []
);
}, [registrationInfo.tissueTypes, values.tissues, currentIndex]);
Expand Down

0 comments on commit 37a1811

Please sign in to comment.