From f7c30e1c54f85a5b83b514a8de55b297b71a1f5b Mon Sep 17 00:00:00 2001 From: Sharad S Date: Mon, 10 Feb 2025 13:42:18 -0500 Subject: [PATCH 1/8] Enable nested to-many in Workbench --- .../frontend/js_src/lib/components/WbPlanView/navigatorSpecs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigatorSpecs.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigatorSpecs.ts index 86c639f5167..96fdea7a477 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigatorSpecs.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigatorSpecs.ts @@ -56,7 +56,7 @@ const wbPlanView: NavigatorSpec = { * Hide nested -to-many relationships as they are not * supported by the WorkBench */ - allowNestedToMany: false, + allowNestedToMany: true, ensurePermission: () => userPreferences.get('workBench', 'wbPlanView', 'showNoAccessTables') ? 'create' From f6b6562e506795f9b9c19f3b07df76d055d21ae7 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Wed, 12 Feb 2025 15:41:38 -0500 Subject: [PATCH 2/8] Update test --- .../WbPlanView/__tests__/navigator.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts index f6487ecf342..dfa596f7b52 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts @@ -277,6 +277,15 @@ theories(getMappingLineData, [ customSelectSubtype: 'simple', selectLabel: localized('Determination'), fieldsData: { + collectionObject: { + isDefault: false, + isEnabled: true, + isHidden: false, + isRelationship: true, + isRequired: true, + optionLabel: 'Collection Object', + tableName: 'CollectionObject', + }, determinedDate: { optionLabel: 'Date', isEnabled: true, @@ -285,6 +294,15 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, + determiners: { + isDefault: false, + isEnabled: true, + isHidden: false, + isRelationship: true, + isRequired: false, + optionLabel: 'Determiners', + tableName: 'Determiner', + }, guid: { optionLabel: 'GUID', isEnabled: true, From 0fa6fc81b5d56e68cc93ff0d6333359fc7962354 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Fri, 14 Feb 2025 13:53:07 -0500 Subject: [PATCH 3/8] Add upload plan changes --- .../lib/components/WbPlanView/navigator.ts | 14 ++++---- .../WbPlanView/uploadPlanBuilder.ts | 13 +++---- .../components/WbPlanView/uploadPlanParser.ts | 36 +++++++++---------- .../js_src/lib/components/WorkBench/index.tsx | 20 ++++++++--- 4 files changed, 45 insertions(+), 38 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts index 1dd5a3291a1..e77ceb04ecb 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/navigator.ts @@ -588,15 +588,15 @@ export function getMappingLineData({ if (field.isRelationship) { isIncluded &&= - spec.allowNestedToMany || parentRelationship === undefined || (!isCircularRelationship(parentRelationship, field) && - !( - (relationshipIsToMany(field) || - relationshipIsRemoteToOne(field)) && - (relationshipIsToMany(parentRelationship) || - relationshipIsRemoteToOne(parentRelationship)) - )); + (spec.allowNestedToMany || + !( + (relationshipIsToMany(field) || + relationshipIsRemoteToOne(field)) && + (relationshipIsToMany(parentRelationship) || + relationshipIsRemoteToOne(parentRelationship)) + ))); isIncluded &&= !canDoAction || diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanBuilder.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanBuilder.ts index 72ca16707f4..dde8d53188d 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanBuilder.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanBuilder.ts @@ -1,5 +1,5 @@ import type { IR, RA, RR } from '../../utils/types'; -import { group, removeKey, split, toLowerCase } from '../../utils/utils'; +import { group, split, toLowerCase } from '../../utils/utils'; import type { SpecifyTable } from '../DataModel/specifyTable'; import { strictGetTable } from '../DataModel/tables'; import type { Tables } from '../DataModel/types'; @@ -139,13 +139,10 @@ function toUploadTable( [ fieldName.toLowerCase(), indexMappings(lines).map(([_index, lines]) => - removeKey( - toUploadTable( - table.strictGetRelationship(fieldName).relatedTable, - lines, - mustMatchPreferences - ), - 'toMany' + toUploadTable( + table.strictGetRelationship(fieldName).relatedTable, + lines, + mustMatchPreferences ) ), ] as const diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts index ebcbed09e33..8a3d8f80753 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts @@ -1,4 +1,4 @@ -import type { IR, RA, RR } from '../../utils/types'; +import type { IR, PartialBy, RA, RR } from '../../utils/types'; import type { SpecifyTable } from '../DataModel/specifyTable'; import { strictGetTable } from '../DataModel/tables'; import type { Tables } from '../DataModel/types'; @@ -23,7 +23,9 @@ export type ColumnDefinition = | string | (ColumnOptions & { readonly column: string }); -export type NestedUploadTable = Omit; +// NOTE: This comment was added after workbench supports nested-to-manys. +// Type is made Partial to not chock on legacy upload plans +export type NestedUploadTable = PartialBy; export type UploadTable = { readonly wbcols: IR; @@ -146,23 +148,21 @@ const parseUploadTable = ( [...mappingPath, table.strictGetRelationship(relationshipName).name] ) ), - ...('toMany' in uploadPlan - ? Object.entries(uploadPlan.toMany).flatMap( - ([relationshipName, mappings]) => - Object.values(mappings).flatMap((mapping, index) => - parseUploadTable( - table.strictGetRelationship(relationshipName).relatedTable, - mapping, - makeMustMatch, - [ - ...mappingPath, - table.strictGetRelationship(relationshipName).name, - formatToManyIndex(index + 1), - ] - ) - ) + ...Object.entries(uploadPlan.toMany ?? []).flatMap( + ([relationshipName, mappings]) => + Object.values(mappings).flatMap((mapping, index) => + parseUploadTable( + table.strictGetRelationship(relationshipName).relatedTable, + mapping, + makeMustMatch, + [ + ...mappingPath, + table.strictGetRelationship(relationshipName).name, + formatToManyIndex(index + 1), + ] + ) ) - : []), + ), ]; function parseUploadTableTypes( diff --git a/specifyweb/frontend/js_src/lib/components/WorkBench/index.tsx b/specifyweb/frontend/js_src/lib/components/WorkBench/index.tsx index 7246bbd6ce5..6db77592704 100644 --- a/specifyweb/frontend/js_src/lib/components/WorkBench/index.tsx +++ b/specifyweb/frontend/js_src/lib/components/WorkBench/index.tsx @@ -21,12 +21,20 @@ export function WorkBench(): JSX.Element { const datasetId = f.parseInt(id); const [dataset, setDataset] = useDataset(datasetId); - return datasetId === undefined ? - : - dataset === undefined ? : ; + return datasetId === undefined ? ( + + ) : dataset === undefined ? ( + + ) : ( + + ); } -export function WorkBenchSafe({getSetDataset}: {readonly getSetDataset: GetSet}): JSX.Element { +export function WorkBenchSafe({ + getSetDataset, +}: { + readonly getSetDataset: GetSet; +}): JSX.Element { const [dataset, setDataset] = getSetDataset; const [treeRanksLoaded = false] = useAsyncState(fetchTreeRanks, true); @@ -50,7 +58,9 @@ export function WorkBenchSafe({getSetDataset}: {readonly getSetDataset: GetSet - ) : ; + ) : ( + + ); } const fetchTreeRanks = async (): Promise => treeRanksPromise.then(f.true); From 82033cd99c8fd333c069657c462df7ac98fe9564 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Fri, 14 Feb 2025 13:53:30 -0500 Subject: [PATCH 4/8] Update tests --- .../WbPlanView/__tests__/navigator.test.ts | 644 ++++++++++-------- .../lib/tests/fixtures/uploadplan.1.json | 48 +- 2 files changed, 374 insertions(+), 318 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts index dfa596f7b52..543d7f8e795 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts @@ -20,8 +20,8 @@ theories(getMappingLineData, [ ], out: [ { - defaultValue: 'determinations', customSelectSubtype: 'simple', + defaultValue: 'determinations', selectLabel: localized('Collection Object'), fieldsData: { catalogNumber: { @@ -74,15 +74,6 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, - leftSideRels: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, - optionLabel: 'Left Side Rels', - tableName: 'CollectionRelationship', - }, altCatalogNumber: { optionLabel: 'Prev/Exch #', isEnabled: true, @@ -115,15 +106,6 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, - rightSideRels: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, - optionLabel: 'Right Side Rels', - tableName: 'CollectionRelationship', - }, fieldNumber: { optionLabel: 'Voucher', isEnabled: true, @@ -168,6 +150,24 @@ theories(getMappingLineData, [ isRelationship: true, tableName: 'CollectionObjectAttribute', }, + collection: { + optionLabel: 'Collection', + isEnabled: true, + isRequired: false, + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'Collection', + }, + collectionObjectAttachments: { + optionLabel: 'Collection Object Attachments', + isEnabled: true, + isRequired: false, + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'CollectionObjectAttachment', + }, collectionObjectCitations: { optionLabel: 'Collection Object Citations', isEnabled: true, @@ -213,23 +213,14 @@ theories(getMappingLineData, [ isRelationship: true, tableName: 'CollectingEvent', }, - collection: { - isDefault: false, + leftSideRels: { + optionLabel: 'Left Side Rels', isEnabled: true, - isHidden: false, - isRelationship: true, isRequired: false, - optionLabel: 'Collection', - tableName: 'Collection', - }, - collectionObjectAttachments: { - isDefault: false, - isEnabled: true, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Collection Object Attachments', - tableName: 'CollectionObjectAttachment', + tableName: 'CollectionRelationship', }, preparations: { optionLabel: 'Preparations', @@ -240,6 +231,15 @@ theories(getMappingLineData, [ isRelationship: true, tableName: 'Preparation', }, + rightSideRels: { + optionLabel: 'Right Side Rels', + isEnabled: true, + isRequired: false, + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'CollectionRelationship', + }, voucherRelationships: { optionLabel: 'Voucher Relationships', isEnabled: true, @@ -253,8 +253,8 @@ theories(getMappingLineData, [ tableName: 'CollectionObject', }, { - defaultValue: '#1', customSelectSubtype: 'toMany', + defaultValue: '#1', selectLabel: localized('Determination'), fieldsData: { '#1': { @@ -273,19 +273,10 @@ theories(getMappingLineData, [ tableName: 'Determination', }, { - defaultValue: 'taxon', customSelectSubtype: 'simple', + defaultValue: 'taxon', selectLabel: localized('Determination'), fieldsData: { - collectionObject: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: true, - optionLabel: 'Collection Object', - tableName: 'CollectionObject', - }, determinedDate: { optionLabel: 'Date', isEnabled: true, @@ -294,15 +285,6 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, - determiners: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, - optionLabel: 'Determiners', - tableName: 'Determiner', - }, guid: { optionLabel: 'GUID', isEnabled: true, @@ -328,6 +310,15 @@ theories(getMappingLineData, [ isRelationship: true, tableName: 'Agent', }, + determiners: { + optionLabel: 'Determiners', + isEnabled: true, + isRequired: false, + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'Determiner', + }, taxon: { optionLabel: 'Taxon', isEnabled: true, @@ -341,8 +332,8 @@ theories(getMappingLineData, [ tableName: 'Determination', }, { - defaultValue: '$Family', customSelectSubtype: 'tree', + defaultValue: '$Family', selectLabel: localized('Taxon'), fieldsData: { $Kingdom: { @@ -409,8 +400,8 @@ theories(getMappingLineData, [ tableName: 'Taxon', }, { - defaultValue: 'name', customSelectSubtype: 'simple', + defaultValue: 'name', selectLabel: localized('Taxon'), fieldsData: { author: { @@ -480,13 +471,14 @@ theories(getMappingLineData, [ { customSelectSubtype: 'simple', defaultValue: 'determinations', + selectLabel: localized('Collection Object'), fieldsData: { '-formatted': { - isDefault: false, - isEnabled: true, - isRelationship: false, optionLabel: '(formatted)', tableName: 'CollectionObject', + isRelationship: false, + isDefault: false, + isEnabled: true, }, absoluteAges: { isDefault: false, @@ -497,71 +489,142 @@ theories(getMappingLineData, [ optionLabel: 'Absolute Ages', tableName: 'AbsoluteAge', }, - accession: { - isDefault: false, + catalogNumber: { + optionLabel: 'Cat #', isEnabled: true, - isHidden: false, - isRelationship: true, isRequired: false, - optionLabel: 'Accession #', - tableName: 'Accession', - }, - altCatalogNumber: { + isHidden: false, isDefault: false, + isRelationship: false, + }, + 'catalogedDate-fullDate': { + optionLabel: 'Cat Date', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Prev/Exch #', }, - catalogNumber: { - isDefault: false, + 'catalogedDate-day': { + optionLabel: 'Cat Date (Day)', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Cat #', }, - 'catalogedDate-day': { + 'catalogedDate-month': { + optionLabel: 'Cat Date (Month)', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + 'catalogedDate-year': { + optionLabel: 'Cat Date (Year)', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + reservedText: { + optionLabel: 'CT Scan', + isEnabled: true, isRequired: false, - optionLabel: 'Cat Date (Day)', + isHidden: false, + isDefault: false, + isRelationship: false, }, - 'catalogedDate-fullDate': { + 'timestampModified-fullDate': { + optionLabel: 'Date Edited', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + 'timestampModified-day': { + optionLabel: 'Date Edited (Day)', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + 'timestampModified-month': { + optionLabel: 'Date Edited (Month)', + isEnabled: true, isRequired: false, - optionLabel: 'Cat Date', + isHidden: false, + isDefault: false, + isRelationship: false, }, - 'catalogedDate-month': { + 'timestampModified-year': { + optionLabel: 'Date Edited (Year)', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + guid: { + optionLabel: 'GUID', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + altCatalogNumber: { + optionLabel: 'Prev/Exch #', + isEnabled: true, isRequired: false, - optionLabel: 'Cat Date (Month)', + isHidden: false, + isDefault: false, + isRelationship: false, }, - 'catalogedDate-year': { + projectNumber: { + optionLabel: 'Project Number', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + remarks: { + optionLabel: 'Remarks', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + reservedText2: { + optionLabel: 'Reserved Text2', + isEnabled: true, isRequired: false, - optionLabel: 'Cat Date (Year)', + isHidden: false, + isDefault: false, + isRelationship: false, }, - cataloger: { + fieldNumber: { + optionLabel: 'Voucher', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + accession: { + optionLabel: 'Accession #', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Cataloger', - tableName: 'Agent', + tableName: 'Accession', }, cojo: { isDefault: false, @@ -572,49 +635,49 @@ theories(getMappingLineData, [ optionLabel: 'Cojo', tableName: 'CollectionObjectGroupJoin', }, - collectingEvent: { - isDefault: false, + cataloger: { + optionLabel: 'Cataloger', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, + tableName: 'Agent', + }, + collectionObjectAttribute: { + optionLabel: 'Col Obj Attribute', + isEnabled: true, isRequired: false, - optionLabel: 'Field No: Locality', - tableName: 'CollectingEvent', + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'CollectionObjectAttribute', }, collection: { - isDefault: false, + optionLabel: 'Collection', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Collection', tableName: 'Collection', }, collectionObjectAttachments: { - isDefault: false, + optionLabel: 'Collection Object Attachments', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Collection Object Attachments', tableName: 'CollectionObjectAttachment', }, - collectionObjectAttribute: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, - optionLabel: 'Col Obj Attribute', - tableName: 'CollectionObjectAttribute', - }, collectionObjectCitations: { - isDefault: false, + optionLabel: 'Collection Object Citations', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Collection Object Citations', tableName: 'CollectionObjectCitation', }, collectionObjectType: { @@ -627,73 +690,40 @@ theories(getMappingLineData, [ tableName: 'CollectionObjectType', }, determinations: { - isDefault: true, + optionLabel: 'Determinations', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: true, isRelationship: true, - isRequired: false, - optionLabel: 'Determinations', tableName: 'Determination', }, dnaSequences: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, optionLabel: 'DNA Sequences', - tableName: 'DNASequence', - }, - fieldNumber: { - isDefault: false, isEnabled: true, - isHidden: false, - isRelationship: false, isRequired: false, - optionLabel: 'Voucher', - }, - guid: { - isDefault: false, - isEnabled: true, isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'GUID', - }, - leftSideRels: { isDefault: false, - isEnabled: true, - isHidden: false, isRelationship: true, - isRequired: false, - optionLabel: 'Left Side Rels', - tableName: 'CollectionRelationship', + tableName: 'DNASequence', }, modifiedByAgent: { - isDefault: false, + optionLabel: 'Edited By', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Edited By', tableName: 'Agent', }, - preparations: { - isDefault: false, + collectingEvent: { + optionLabel: 'Field No: Locality', isEnabled: true, - isHidden: false, - isRelationship: true, isRequired: false, - optionLabel: 'Preparations', - tableName: 'Preparation', - }, - projectNumber: { - isDefault: false, - isEnabled: true, isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Project Number', + isDefault: false, + isRelationship: true, + tableName: 'CollectingEvent', }, relativeAges: { isDefault: false, @@ -704,297 +734,315 @@ theories(getMappingLineData, [ optionLabel: 'Relative Ages', tableName: 'RelativeAge', }, - remarks: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Remarks', - }, - reservedText: { - isDefault: false, + leftSideRels: { + optionLabel: 'Left Side Rels', isEnabled: true, - isHidden: false, - isRelationship: false, isRequired: false, - optionLabel: 'CT Scan', - }, - reservedText2: { - isDefault: false, - isEnabled: true, isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Reserved Text2', - }, - rightSideRels: { isDefault: false, - isEnabled: true, - isHidden: false, isRelationship: true, - isRequired: false, - optionLabel: 'Right Side Rels', tableName: 'CollectionRelationship', }, - 'timestampModified-day': { - isDefault: false, + preparations: { + optionLabel: 'Preparations', isEnabled: true, - isHidden: false, - isRelationship: false, isRequired: false, - optionLabel: 'Date Edited (Day)', - }, - 'timestampModified-fullDate': { - isDefault: false, - isEnabled: true, isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Date Edited', - }, - 'timestampModified-month': { isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Date Edited (Month)', + isRelationship: true, + tableName: 'Preparation', }, - 'timestampModified-year': { - isDefault: false, + rightSideRels: { + optionLabel: 'Right Side Rels', isEnabled: true, - isHidden: false, - isRelationship: false, isRequired: false, - optionLabel: 'Date Edited (Year)', + isHidden: false, + isDefault: false, + isRelationship: true, + tableName: 'CollectionRelationship', }, voucherRelationships: { - isDefault: false, + optionLabel: 'Voucher Relationships', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Voucher Relationships', tableName: 'VoucherRelationship', }, }, - selectLabel: localized('Collection Object'), tableName: 'CollectionObject', }, { customSelectSubtype: 'simple', defaultValue: 'taxon', + selectLabel: localized('Determination'), fieldsData: { '-formatted': { - isDefault: false, - isEnabled: true, - isRelationship: false, optionLabel: '(aggregated)', tableName: 'Determination', - }, - collectionObject: { + isRelationship: false, isDefault: false, isEnabled: true, - isHidden: false, - isRelationship: true, - isRequired: false, - optionLabel: 'Collection Object', - tableName: 'CollectionObject', }, - 'determinedDate-day': { - isDefault: false, + isCurrent: { + optionLabel: 'Current', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Date (Day)', }, 'determinedDate-fullDate': { - isDefault: false, + optionLabel: 'Date', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + 'determinedDate-day': { + optionLabel: 'Date (Day)', + isEnabled: true, isRequired: false, - optionLabel: 'Date', + isHidden: false, + isDefault: false, + isRelationship: false, }, 'determinedDate-month': { - isDefault: false, + optionLabel: 'Date (Month)', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Date (Month)', }, 'determinedDate-year': { + optionLabel: 'Date (Year)', + isEnabled: true, + isRequired: false, + isHidden: false, isDefault: false, + isRelationship: false, + }, + guid: { + optionLabel: 'GUID', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, + }, + typeStatusName: { + optionLabel: 'Type Status', + isEnabled: true, isRequired: false, - optionLabel: 'Date (Year)', + isHidden: false, + isDefault: false, + isRelationship: false, }, determiner: { - isDefault: false, + optionLabel: 'Determiner', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Determiner', tableName: 'Agent', }, determiners: { - isDefault: false, + optionLabel: 'Determiners', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: true, - isRequired: false, - optionLabel: 'Determiners', tableName: 'Determiner', }, - guid: { - isDefault: false, + preferredTaxon: { + optionLabel: 'Preferred Taxon', isEnabled: true, - isHidden: false, - isRelationship: false, isRequired: false, - optionLabel: 'GUID', - }, - isCurrent: { - isDefault: false, - isEnabled: true, isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Current', - }, - preferredTaxon: { isDefault: false, - isEnabled: true, - isHidden: false, isRelationship: true, - isRequired: false, - optionLabel: 'Preferred Taxon', tableName: 'Taxon', }, taxon: { - isDefault: true, + optionLabel: 'Taxon', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: true, isRelationship: true, - isRequired: false, - optionLabel: 'Taxon', tableName: 'Taxon', }, - typeStatusName: { - isDefault: false, - isEnabled: true, - isHidden: false, - isRelationship: false, - isRequired: false, - optionLabel: 'Type Status', - }, }, - selectLabel: localized('Determination'), tableName: 'Determination', }, { customSelectSubtype: 'tree', defaultValue: '$Family', + selectLabel: localized('Taxon'), fieldsData: { '$-any': { + optionLabel: '(any rank)', + isRelationship: true, isDefault: false, isEnabled: true, - isRelationship: true, - optionLabel: '(any rank)', tableName: 'Taxon', }, - $Class: { - isDefault: false, + $Kingdom: { + optionLabel: 'Kingdom', isRelationship: true, - optionLabel: 'Class', + isDefault: false, tableName: 'Taxon', }, - $Family: { - isDefault: true, + $Phylum: { + optionLabel: 'Phylum', isRelationship: true, - optionLabel: 'Family', - tableName: 'Taxon', - }, - $Genus: { isDefault: false, - isRelationship: true, - optionLabel: 'Genus', tableName: 'Taxon', }, - $Kingdom: { - isDefault: false, + $Class: { + optionLabel: 'Class', isRelationship: true, - optionLabel: 'Kingdom', + isDefault: false, tableName: 'Taxon', }, $Order: { - isDefault: false, - isRelationship: true, optionLabel: 'Order', - tableName: 'Taxon', - }, - $Phylum: { - isDefault: false, isRelationship: true, - optionLabel: 'Phylum', + isDefault: false, tableName: 'Taxon', }, - $Species: { - isDefault: false, + $Family: { + optionLabel: 'Family', isRelationship: true, - optionLabel: 'Species', + isDefault: true, tableName: 'Taxon', }, $Subfamily: { + optionLabel: 'Subfamily', + isRelationship: true, isDefault: false, + tableName: 'Taxon', + }, + $Genus: { + optionLabel: 'Genus', isRelationship: true, - optionLabel: 'Subfamily', + isDefault: false, tableName: 'Taxon', }, $Subgenus: { + optionLabel: 'Subgenus', + isRelationship: true, isDefault: false, + tableName: 'Taxon', + }, + $Species: { + optionLabel: 'Species', isRelationship: true, - optionLabel: 'Subgenus', + isDefault: false, tableName: 'Taxon', }, $Subspecies: { - isDefault: false, - isRelationship: true, optionLabel: 'Subspecies', + isRelationship: true, + isDefault: false, tableName: 'Taxon', }, }, - selectLabel: localized('Taxon'), tableName: 'Taxon', }, { customSelectSubtype: 'simple', defaultValue: 'name', + selectLabel: localized('Taxon'), fieldsData: { author: { - isDefault: false, + optionLabel: 'Author', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Author', }, + // TODO: Needed in #6196 and not in #6216 + // commonName: { + // optionLabel: 'Common Name', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, fullName: { - isDefault: false, + optionLabel: 'Full Name', isEnabled: true, + isRequired: false, isHidden: false, + isDefault: false, isRelationship: false, - isRequired: false, - optionLabel: 'Full Name', }, + // TODO: Needed in #6196 and not in #6216 + // guid: { + // optionLabel: 'GUID', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, + // isHybrid: { + // optionLabel: 'Is Hybrid', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, + // isAccepted: { + // optionLabel: 'Is Preferred', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, + // name: { + // optionLabel: 'Name', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: true, + // isRelationship: false, + // }, + // rankId: { + // optionLabel: 'Rank ID', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, + // remarks: { + // optionLabel: 'Remarks', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, + // source: { + // optionLabel: 'Source', + // isEnabled: true, + // isRequired: false, + // isHidden: false, + // isDefault: false, + // isRelationship: false, + // }, }, - selectLabel: localized('Taxon'), tableName: 'Taxon', }, ], diff --git a/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json b/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json index a639bc1327d..e5684fe5584 100644 --- a/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json +++ b/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json @@ -160,7 +160,8 @@ "toMany": {} } } - } + }, + "toMany": {} }, { "wbcols": {}, @@ -179,7 +180,8 @@ "toMany": {} } } - } + }, + "toMany": {} }, { "wbcols": {}, @@ -198,7 +200,8 @@ "toMany": {} } } - } + }, + "toMany": {} }, { "wbcols": {}, @@ -217,7 +220,8 @@ "toMany": {} } } - } + }, + "toMany": {} } ] } @@ -246,7 +250,8 @@ "toMany": {} } } - } + }, + "toMany": {} } ] } @@ -276,6 +281,7 @@ "mustMatchTreeRecord": { "ranks": { "Class": { + "treeId": 1, "treeNodeCols": { "name": { "matchBehavior": "ignoreAlways", @@ -283,40 +289,39 @@ "default": null, "column": "Class" } - }, - "treeId": 1 + } }, "Family": { + "treeId": 1, "treeNodeCols": { "name": "Family" - }, - "treeId": 1 + } }, "Genus": { + "treeId": 1, "treeNodeCols": { "name": "Genus" - }, - "treeId": 1 + } }, "Subgenus": { + "treeId": 1, "treeNodeCols": { "name": "Subgenus" - }, - "treeId": 1 + } }, "Species": { + "treeId": 1, "treeNodeCols": { "name": "Species", "author": "Species Author" - }, - "treeId": 1 + } }, "Subspecies": { + "treeId": 1, "treeNodeCols": { "name": "Subspecies", "author": "Subspecies Author" - }, - "treeId": 1 + } } } } @@ -334,7 +339,8 @@ "toMany": {} } } - } + }, + "toMany": {} }, { "wbcols": { @@ -352,7 +358,8 @@ "toMany": {} } } - } + }, + "toMany": {} } ], "preparations": [ @@ -370,7 +377,8 @@ "toMany": {} } } - } + }, + "toMany": {} } ] } From a56c65b9f380484466300b4d721935b10ed01e66 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Fri, 14 Feb 2025 18:57:22 +0000 Subject: [PATCH 5/8] Lint code with ESLint and Prettier Triggered by 82033cd99c8fd333c069657c462df7ac98fe9564 on branch refs/heads/issue-2331 --- .../WbPlanView/__tests__/navigator.test.ts | 136 +++++++++--------- .../components/WbPlanView/uploadPlanParser.ts | 6 +- 2 files changed, 74 insertions(+), 68 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts index 543d7f8e795..27c453c6d9f 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/navigator.test.ts @@ -968,15 +968,17 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, - // TODO: Needed in #6196 and not in #6216 - // commonName: { - // optionLabel: 'Common Name', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, + /* + * TODO: Needed in #6196 and not in #6216 + * commonName: { + * optionLabel: 'Common Name', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + */ fullName: { optionLabel: 'Full Name', isEnabled: true, @@ -985,63 +987,65 @@ theories(getMappingLineData, [ isDefault: false, isRelationship: false, }, - // TODO: Needed in #6196 and not in #6216 - // guid: { - // optionLabel: 'GUID', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, - // isHybrid: { - // optionLabel: 'Is Hybrid', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, - // isAccepted: { - // optionLabel: 'Is Preferred', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, - // name: { - // optionLabel: 'Name', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: true, - // isRelationship: false, - // }, - // rankId: { - // optionLabel: 'Rank ID', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, - // remarks: { - // optionLabel: 'Remarks', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, - // source: { - // optionLabel: 'Source', - // isEnabled: true, - // isRequired: false, - // isHidden: false, - // isDefault: false, - // isRelationship: false, - // }, + /* + * TODO: Needed in #6196 and not in #6216 + * guid: { + * optionLabel: 'GUID', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + * isHybrid: { + * optionLabel: 'Is Hybrid', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + * isAccepted: { + * optionLabel: 'Is Preferred', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + * name: { + * optionLabel: 'Name', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: true, + * isRelationship: false, + * }, + * rankId: { + * optionLabel: 'Rank ID', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + * remarks: { + * optionLabel: 'Remarks', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + * source: { + * optionLabel: 'Source', + * isEnabled: true, + * isRequired: false, + * isHidden: false, + * isDefault: false, + * isRelationship: false, + * }, + */ }, tableName: 'Taxon', }, diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts index 8a3d8f80753..bd9717f6824 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/uploadPlanParser.ts @@ -23,8 +23,10 @@ export type ColumnDefinition = | string | (ColumnOptions & { readonly column: string }); -// NOTE: This comment was added after workbench supports nested-to-manys. -// Type is made Partial to not chock on legacy upload plans +/* + * NOTE: This comment was added after workbench supports nested-to-manys. + * Type is made Partial to not chock on legacy upload plans + */ export type NestedUploadTable = PartialBy; export type UploadTable = { From f0822bf96521b36566cb048ad22e77827189bbd0 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Fri, 28 Mar 2025 16:12:20 -0400 Subject: [PATCH 6/8] Fix tests --- .../frontend/js_src/lib/tests/fixtures/uploadplan.1.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json b/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json index e5684fe5584..ea0336746b4 100644 --- a/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json +++ b/specifyweb/frontend/js_src/lib/tests/fixtures/uploadplan.1.json @@ -281,7 +281,6 @@ "mustMatchTreeRecord": { "ranks": { "Class": { - "treeId": 1, "treeNodeCols": { "name": { "matchBehavior": "ignoreAlways", @@ -292,32 +291,27 @@ } }, "Family": { - "treeId": 1, "treeNodeCols": { "name": "Family" } }, "Genus": { - "treeId": 1, "treeNodeCols": { "name": "Genus" } }, "Subgenus": { - "treeId": 1, "treeNodeCols": { "name": "Subgenus" } }, "Species": { - "treeId": 1, "treeNodeCols": { "name": "Species", "author": "Species Author" } }, "Subspecies": { - "treeId": 1, "treeNodeCols": { "name": "Subspecies", "author": "Subspecies Author" From 8f3891af0eeb1aa6a9b772790ddd714c798edae2 Mon Sep 17 00:00:00 2001 From: Sharad S Date: Fri, 28 Mar 2025 20:16:04 +0000 Subject: [PATCH 7/8] Lint code with ESLint and Prettier Triggered by f0822bf96521b36566cb048ad22e77827189bbd0 on branch refs/heads/issue-2331 --- .../lib/components/BatchEdit/MissingRanks.tsx | 2 +- .../lib/components/QueryBuilder/Formatter.tsx | 39 +++++++++++-------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/BatchEdit/MissingRanks.tsx b/specifyweb/frontend/js_src/lib/components/BatchEdit/MissingRanks.tsx index e73d0c2a7fc..2fbd1182e36 100644 --- a/specifyweb/frontend/js_src/lib/components/BatchEdit/MissingRanks.tsx +++ b/specifyweb/frontend/js_src/lib/components/BatchEdit/MissingRanks.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { batchEditText } from '../../localization/batchEdit'; import { commonText } from '../../localization/common'; import { interactionsText } from '../../localization/interactions'; -import type { RA,RR } from '../../utils/types'; +import type { RA, RR } from '../../utils/types'; import { H2, H3, Ul } from '../Atoms'; import { Button } from '../Atoms/Button'; import { Input, Label } from '../Atoms/Form'; diff --git a/specifyweb/frontend/js_src/lib/components/QueryBuilder/Formatter.tsx b/specifyweb/frontend/js_src/lib/components/QueryBuilder/Formatter.tsx index 1a0c237b7da..7925fc32b19 100644 --- a/specifyweb/frontend/js_src/lib/components/QueryBuilder/Formatter.tsx +++ b/specifyweb/frontend/js_src/lib/components/QueryBuilder/Formatter.tsx @@ -99,36 +99,41 @@ export function CatalogNumberFormatSelection({ ) .then((cots) => { const formattersMap = filterArray(cots).reduce((map, cot) => { - const format = cot.get('catalogNumberFormatName') ?? schema.catalogNumFormatName; + const format = + cot.get('catalogNumberFormatName') ?? + schema.catalogNumFormatName; const cotName = cot.get('name'); - + if (!map.has(format)) { map.set(format, { name: format, title: format, isDefault: format === schema.catalogNumFormatName, - cotNames: [] + cotNames: [], }); } - + const formatter = map.get(format)!; map.set(format, { ...formatter, - cotNames: [...formatter.cotNames, cotName] + cotNames: [...formatter.cotNames, cotName], }); return map; }, new Map()); - - return Array.from(formattersMap.values(), ({ name, isDefault, cotNames }) => { - const title = queryText.formatInputAs({ - commaSeparatedFormats: cotNames.join(', '), - }); - return { - name, - title, - isDefault - }; - }); + + return Array.from( + formattersMap.values(), + ({ name, isDefault, cotNames }) => { + const title = queryText.formatInputAs({ + commaSeparatedFormats: cotNames.join(', '), + }); + return { + name, + title, + isDefault, + }; + } + ); }), [] ), @@ -165,7 +170,7 @@ function FormatSelect({ readonly onChange: ((formatter: string | undefined) => void) | undefined; }): JSX.Element | null { const [formatterSelectIsOpen, setFormatterSelect] = React.useState(false); - + const id = useId('formatters-selection'); return availableFormatters === undefined ? ( From 072b0dc057809d9a10a0e1e30ff3a884c64332e7 Mon Sep 17 00:00:00 2001 From: Sharad S <16229739+sharadsw@users.noreply.github.com> Date: Tue, 15 Apr 2025 17:29:19 +0000 Subject: [PATCH 8/8] Lint code with ESLint and Prettier Triggered by f27581be3c61aa9de4e02cbbe8215c2fe2a664e4 on branch refs/heads/issue-2331 --- .../FormSliders/IntegratedRecordSelector.tsx | 482 +++++++++--------- .../components/Interactions/PrepDialog.tsx | 3 +- .../components/Interactions/PrepDialogRow.tsx | 6 +- .../js_src/lib/components/Reports/index.tsx | 6 +- .../lib/components/SearchDialog/index.tsx | 18 +- .../js_src/lib/localization/attachments.ts | 6 +- .../js_src/lib/localization/interactions.ts | 4 +- 7 files changed, 266 insertions(+), 259 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/FormSliders/IntegratedRecordSelector.tsx b/specifyweb/frontend/js_src/lib/components/FormSliders/IntegratedRecordSelector.tsx index 2970054414e..08a0e65e2f7 100644 --- a/specifyweb/frontend/js_src/lib/components/FormSliders/IntegratedRecordSelector.tsx +++ b/specifyweb/frontend/js_src/lib/components/FormSliders/IntegratedRecordSelector.tsx @@ -169,261 +169,263 @@ export function IntegratedRecordSelector({ isLoanPrep && (collection.related?.isNew() === true || collection.related?.needsSaved); - const [isWarningOpen, handleWarning,closeWarning] = useBooleanState() + const [isWarningOpen, handleWarning, closeWarning] = useBooleanState(); - return ( - - { - if (isInteraction) { - setInteractionResource(resources[0]); - handleOpenDialog(); - } - if (!isInteraction && formType !== 'formTable') - collection.add(resources); - handleAdding(resources); - }} - onDelete={(...args): void => { - if (isCollapsed) handleExpand(); - handleDelete?.(...args); - }} - onFetch={handleFetch} - onSlide={(index): void => { - handleExpand(); - if (typeof urlParameter === 'string') setIndex(index.toString()); - }} - {...rest} - > - {({ - dialogs, - slider, - resource, - onAdd: handleAdd, - onRemove: handleRemove, - showSearchDialog, - isLoading, - }): JSX.Element => ( - <> - {isInteraction && - typeof collection.related === 'object' && - isDialogOpen ? ( - - } - interactionResource={interactionResource} - itemCollection={ - collection as Collection - } - onClose={handleCloseDialog} - /> - ) : undefined} - {formType === 'form' ? ( - - ( - <> - + { + if (isInteraction) { + setInteractionResource(resources[0]); + handleOpenDialog(); + } + if (!isInteraction && formType !== 'formTable') + collection.add(resources); + handleAdding(resources); + }} + onDelete={(...args): void => { + if (isCollapsed) handleExpand(); + handleDelete?.(...args); + }} + onFetch={handleFetch} + onSlide={(index): void => { + handleExpand(); + if (typeof urlParameter === 'string') setIndex(index.toString()); + }} + {...rest} + > + {({ + dialogs, + slider, + resource, + onAdd: handleAdd, + onRemove: handleRemove, + showSearchDialog, + isLoading, + }): JSX.Element => ( + <> + {isInteraction && + typeof collection.related === 'object' && + isDialogOpen ? ( + + } + interactionResource={interactionResource} + itemCollection={ + collection as Collection + } + onClose={handleCloseDialog} + /> + ) : undefined} + {formType === 'form' ? ( + + ( + <> + + {!isDependent && + hasTablePermission( + relationship.relatedTable.name, + 'read' + ) && + typeof handleAdd === 'function' ? ( + 0) || + isTaxonTreeDefItemTable } + onClick={showSearchDialog} /> - {!isDependent && - hasTablePermission( - relationship.relatedTable.name, - 'read' - ) && - typeof handleAdd === 'function' ? ( - 0) || - isTaxonTreeDefItemTable + ) : undefined} + {hasTablePermission( + relationship.relatedTable.name, + 'create' + ) && typeof handleAdd === 'function' ? ( + isCOJO ? ( + } - onClick={showSearchDialog} /> - ) : undefined} - {hasTablePermission( - relationship.relatedTable.name, - 'create' - ) && typeof handleAdd === 'function' ? ( - isCOJO ? ( - - } - /> - ) : ( - 0) || - isTaxonTreeDefItemTable - } - onClick={(): void => { - const resource = - new collection.table.specifyTable.Resource(); - - if ( - isDependent || - viewName === relationship.relatedTable.view - ) { - focusFirstField(); - handleAdd([resource]); - return; - } - - if (state.type === 'AddResourceState') - setState({ type: 'MainState' }); - else - setState({ - type: 'AddResourceState', - resource, - handleAdd, - }); - }} - /> - ) - ) : undefined} - {hasTablePermission( - relationship.relatedTable.name, - isDependent ? 'delete' : 'read' - ) && typeof handleRemove === 'function' ? ( - 0) || + isTaxonTreeDefItemTable } onClick={(): void => { - if (isAttachmentTable) { - handleWarning() - } else { - handleRemove('minusButton'); + const resource = + new collection.table.specifyTable.Resource(); + + if ( + isDependent || + viewName === relationship.relatedTable.view + ) { + focusFirstField(); + handleAdd([resource]); + return; } + + if (state.type === 'AddResourceState') + setState({ type: 'MainState' }); + else + setState({ + type: 'AddResourceState', + resource, + handleAdd, + }); }} /> - ) : undefined} - { + if (isAttachmentTable) { + handleWarning(); + } else { + handleRemove('minusButton'); + } + }} /> - {isAttachmentTable && ( - - )} - {specifyNetworkBadge} - {!isToOne && slider} - - )} - isCollapsed={isCollapsed} - isDependent={isDependent} - isLoading={isLoading} - isSubForm={dialog === false} - key={resource?.cid} - preHeaderButtons={collapsibleButton} - resource={resource} - title={relationship.label} - onAdd={undefined} - onDeleted={ - collection.models.length <= 1 ? handleClose : undefined - } - onSaved={handleClose} - viewName={viewName} - /* - * Don't save the resource on save button click if it is a dependent - * resource - */ - onClose={handleClose} - /> - - ) : null} - {formType === 'formTable' ? ( - + {isAttachmentTable && ( + + )} + {specifyNetworkBadge} + {!isToOne && slider} + + )} isCollapsed={isCollapsed} + isDependent={isDependent} + isLoading={isLoading} + isSubForm={dialog === false} + key={resource?.cid} preHeaderButtons={collapsibleButton} - sortField={sortField} - viewName={viewName} - onAdd={ - isTaxonTreeDefItemTable - ? undefined - : (resources): void => { - if (!isInteraction) collection.add(resources); - handleAdd?.(resources); - } + resource={resource} + title={relationship.label} + onAdd={undefined} + onDeleted={ + collection.models.length <= 1 ? handleClose : undefined } + onSaved={handleClose} + viewName={viewName} + /* + * Don't save the resource on save button click if it is a dependent + * resource + */ onClose={handleClose} - onDelete={(resource, index): void => { - if (isAttachmentTable) { - handleWarning() - } else { - collection.remove(resource); - if (isCollapsed) handleExpand(); - handleDelete?.(index, 'minusButton'); - } - }} - onFetchMore={handleFetch} - /> - ) : null} - {dialogs} - {state.type === 'AddResourceState' && - typeof handleAdd === 'function' ? ( - setState({ type: 'MainState' })} - onDeleted={undefined} - onSaved={(): void => { - state.handleAdd([state.resource]); - setState({ type: 'MainState' }); - }} /> - ) : null} - {isWarningOpen && typeof handleRemove === 'function' && isAttachmentTable? - - : undefined - } - - )} - - - ); - } + + ) : null} + {formType === 'formTable' ? ( + { + if (!isInteraction) collection.add(resources); + handleAdd?.(resources); + } + } + onClose={handleClose} + onDelete={(resource, index): void => { + if (isAttachmentTable) { + handleWarning(); + } else { + collection.remove(resource); + if (isCollapsed) handleExpand(); + handleDelete?.(index, 'minusButton'); + } + }} + onFetchMore={handleFetch} + /> + ) : null} + {dialogs} + {state.type === 'AddResourceState' && + typeof handleAdd === 'function' ? ( + setState({ type: 'MainState' })} + onDeleted={undefined} + onSaved={(): void => { + state.handleAdd([state.resource]); + setState({ type: 'MainState' }); + }} + /> + ) : null} + {isWarningOpen && + typeof handleRemove === 'function' && + isAttachmentTable ? ( + + ) : undefined} + + )} + + + ); +} diff --git a/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialog.tsx b/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialog.tsx index e2428ab6ff5..54b60311193 100644 --- a/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialog.tsx +++ b/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialog.tsx @@ -176,7 +176,8 @@ export function PrepDialog({ const items = filterArray( preparations.map((preparation, index) => { - if (selected[index] === 0 || Number.isNaN(selected[index])) return undefined; + if (selected[index] === 0 || Number.isNaN(selected[index])) + return undefined; const result = new itemTable.Resource(); result.set( diff --git a/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialogRow.tsx b/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialogRow.tsx index d9cb47f06c8..32ea7169b79 100644 --- a/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialogRow.tsx +++ b/specifyweb/frontend/js_src/lib/components/Interactions/PrepDialogRow.tsx @@ -82,11 +82,13 @@ export function PrepDialogRow({ {preparation.taxon ? ( - + {localized(preparation.taxon)} ) : ( - {interactionsText.notAvailable()} + {interactionsText.notAvailable()} )} {preparation.prepType} diff --git a/specifyweb/frontend/js_src/lib/components/Reports/index.tsx b/specifyweb/frontend/js_src/lib/components/Reports/index.tsx index a2e6d3c879b..971a3557b20 100644 --- a/specifyweb/frontend/js_src/lib/components/Reports/index.tsx +++ b/specifyweb/frontend/js_src/lib/components/Reports/index.tsx @@ -248,9 +248,9 @@ function ReportRow({ - + diff --git a/specifyweb/frontend/js_src/lib/components/SearchDialog/index.tsx b/specifyweb/frontend/js_src/lib/components/SearchDialog/index.tsx index f0c77508b93..0b7ae8fb7f9 100644 --- a/specifyweb/frontend/js_src/lib/components/SearchDialog/index.tsx +++ b/specifyweb/frontend/js_src/lib/components/SearchDialog/index.tsx @@ -93,7 +93,7 @@ export function SearchDialog( }} /> ) : ( - + ); } @@ -186,7 +186,7 @@ function SearchForm({ onClose: handleClose, onUseQueryBuilder: handleUseQueryBuilder, onAdd: handleAdd, - multiple + multiple, }: { readonly forceCollection: number | undefined; readonly extraFilters: RA> | undefined; @@ -198,7 +198,7 @@ function SearchForm({ readonly onAdd?: | ((resources: RA>) => void) | undefined; - readonly multiple?: boolean + readonly multiple?: boolean; }): JSX.Element | null { const templateResource = React.useMemo( () => @@ -242,11 +242,13 @@ function SearchForm({ {queryText.queryBuilder()} - {multiple === true && } + {multiple === true && ( + + )} {commonText.search()} diff --git a/specifyweb/frontend/js_src/lib/localization/attachments.ts b/specifyweb/frontend/js_src/lib/localization/attachments.ts index ea0db3bde7b..d99287b0699 100644 --- a/specifyweb/frontend/js_src/lib/localization/attachments.ts +++ b/specifyweb/frontend/js_src/lib/localization/attachments.ts @@ -683,9 +683,9 @@ export const attachmentsText = createDictionary({ 'en-us': 'Download all found attachments', }, deleteAttachmentWarning: { - 'en-us': 'Are you sure you want to delete this attachment?' + 'en-us': 'Are you sure you want to delete this attachment?', }, attachmentDelition: { - 'en-us': 'Attachment deletion' - } + 'en-us': 'Attachment deletion', + }, } as const); diff --git a/specifyweb/frontend/js_src/lib/localization/interactions.ts b/specifyweb/frontend/js_src/lib/localization/interactions.ts index 34160d9b5c0..83d75f4c79e 100644 --- a/specifyweb/frontend/js_src/lib/localization/interactions.ts +++ b/specifyweb/frontend/js_src/lib/localization/interactions.ts @@ -388,6 +388,6 @@ export const interactionsText = createDictionary({ 'uk-ua': 'Продовжуйте без підготовки', }, notAvailable: { - 'en-us': 'Not available' - } + 'en-us': 'Not available', + }, } as const);