diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/__tests__/__snapshots__/utils.test.ts.snap b/specifyweb/frontend/js_src/lib/components/Attachments/__tests__/__snapshots__/utils.test.ts.snap index 206c6fdda2c..9e942dcbf2a 100644 --- a/specifyweb/frontend/js_src/lib/components/Attachments/__tests__/__snapshots__/utils.test.ts.snap +++ b/specifyweb/frontend/js_src/lib/components/Attachments/__tests__/__snapshots__/utils.test.ts.snap @@ -2,6 +2,7 @@ exports[`allTablesWithAttachments 1`] = ` [ + "[table AbsoluteAge]", "[table Accession]", "[table Agent]", "[table Borrow]", @@ -10,10 +11,10 @@ exports[`allTablesWithAttachments 1`] = ` "[table CollectionObject]", "[table ConservDescription]", "[table ConservEvent]", - "[table DNASequence]", - "[table DNASequencingRun]", "[table Deaccession]", "[table Disposal]", + "[table DNASequence]", + "[table DNASequencingRun]", "[table ExchangeIn]", "[table ExchangeOut]", "[table FieldNotebook]", @@ -25,18 +26,18 @@ exports[`allTablesWithAttachments 1`] = ` "[table Permit]", "[table Preparation]", "[table ReferenceWork]", + "[table RelativeAge]", "[table RepositoryAgreement]", + "[table Spdataset]", "[table Storage]", "[table Taxon]", "[table TreatmentEvent]", - "[table AbsoluteAge]", - "[table RelativeAge]", - "[table Spdataset]", ] `; exports[`attachmentRelatedTables 1`] = ` [ + "AbsoluteAgeAttachment", "AccessionAttachment", "AgentAttachment", "Attachment", @@ -46,10 +47,10 @@ exports[`attachmentRelatedTables 1`] = ` "CollectionObjectAttachment", "ConservDescriptionAttachment", "ConservEventAttachment", - "DNASequenceAttachment", - "DNASequencingRunAttachment", "DeaccessionAttachment", "DisposalAttachment", + "DNASequenceAttachment", + "DNASequencingRunAttachment", "ExchangeInAttachment", "ExchangeOutAttachment", "FieldNotebookAttachment", @@ -61,12 +62,11 @@ exports[`attachmentRelatedTables 1`] = ` "PermitAttachment", "PreparationAttachment", "ReferenceWorkAttachment", + "RelativeAgeAttachment", "RepositoryAgreementAttachment", + "SpDataSetAttachment", "StorageAttachment", "TaxonAttachment", "TreatmentEventAttachment", - "AbsoluteAgeAttachment", - "RelativeAgeAttachment", - "SpDataSetAttachment", ] `; diff --git a/specifyweb/frontend/js_src/lib/components/DataModel/tables.ts b/specifyweb/frontend/js_src/lib/components/DataModel/tables.ts index 30a40cbadc6..93c29044ac6 100644 --- a/specifyweb/frontend/js_src/lib/components/DataModel/tables.ts +++ b/specifyweb/frontend/js_src/lib/components/DataModel/tables.ts @@ -94,63 +94,74 @@ export const fetchContext = f }) .then(({ dataModel, localization }) => { schemaLocalization = localization; - dataModel + + const tablePairs = dataModel + .slice() .map((tableDefinition) => { const table = new SpecifyTable(tableDefinition); - overwriteReadOnly(genericTables, table.name, table); return [tableDefinition, table] as const; }) - .forEach(([tableDefinition, table]) => { - const [frontEndFields, callback] = ( - schemaExtras[table.name] as (typeof schemaExtras)['Agent'] | undefined - )?.(table as SpecifyTable) ?? [[]]; - const [literalFields, relationships] = split( - frontEndFields.map((field) => { - field.isReadOnly = true; - field.overrides.isReadOnly = true; - return field; - }), - (field) => field.isRelationship - ); - - overwriteReadOnly( - table, - 'literalFields', - processFields( - tableDefinition.fields.map( - (fieldDefinition) => new LiteralField(table, fieldDefinition) - ), - literalFields - ) - ); - overwriteReadOnly( - table, - 'relationships', - processFields( - tableDefinition.relationships.map( - (relationshipDefinition) => - new Relationship(table, relationshipDefinition) - ), - relationships - ) - ); - overwriteReadOnly(table, 'fields', [ - ...table.literalFields, - ...table.relationships, - ]); - overwriteReadOnly( - table, - 'field', - Object.fromEntries(table.fields.map((field) => [field.name, field])) - ); - - frontEndOnlyFields[table.name] = [ - ...literalFields, - ...relationships, - ].map(({ name }) => name); - - callback?.(); - }); + .sort(([, a], [, b]) => a.name.localeCompare(b.name)); + + // First, register all tables so lookups from Relationship constructors + // (which call `strictGetTable`) can find any related table. + tablePairs.forEach(([, table]) => { + overwriteReadOnly(genericTables, table.name, table); + }); + + // Then process fields and relationships for each table. + tablePairs.forEach(([tableDefinition, table]) => { + const [frontEndFields, callback] = + (schemaExtras[table.name] as (typeof schemaExtras)['Agent'] | undefined)?.( + table as SpecifyTable + ) ?? [[]]; + const [literalFields, relationships] = split( + frontEndFields.map((field) => { + field.isReadOnly = true; + field.overrides.isReadOnly = true; + return field; + }), + (field) => field.isRelationship + ); + + overwriteReadOnly( + table, + 'literalFields', + processFields( + tableDefinition.fields.map( + (fieldDefinition) => new LiteralField(table, fieldDefinition) + ), + literalFields + ) + ); + overwriteReadOnly( + table, + 'relationships', + processFields( + tableDefinition.relationships.map( + (relationshipDefinition) => + new Relationship(table, relationshipDefinition) + ), + relationships + ) + ); + overwriteReadOnly(table, 'fields', [ + ...table.literalFields, + ...table.relationships, + ]); + overwriteReadOnly( + table, + 'field', + Object.fromEntries(table.fields.map((field) => [field.name, field])) + ); + + frontEndOnlyFields[table.name] = [ + ...literalFields, + ...relationships, + ].map(({ name }) => name); + + callback?.(); + }); return tables; }); diff --git a/specifyweb/frontend/js_src/lib/components/FormEditor/__tests__/__snapshots__/createView.test.ts.snap b/specifyweb/frontend/js_src/lib/components/FormEditor/__tests__/__snapshots__/createView.test.ts.snap index d91863bbc5f..e09d65fa939 100644 --- a/specifyweb/frontend/js_src/lib/components/FormEditor/__tests__/__snapshots__/createView.test.ts.snap +++ b/specifyweb/frontend/js_src/lib/components/FormEditor/__tests__/__snapshots__/createView.test.ts.snap @@ -2,6 +2,9 @@ exports[`Tables with form tables computed correctly 1`] = ` [ + "[table AbsoluteAge]", + "[table AbsoluteAgeAttachment]", + "[table AbsoluteAgeCitation]", "[table Accession]", "[table AccessionAgent]", "[table AccessionAttachment]", @@ -36,9 +39,13 @@ exports[`Tables with form tables computed correctly 1`] = ` "[table CollectionObjectAttr]", "[table CollectionObjectAttribute]", "[table CollectionObjectCitation]", + "[table CollectionObjectGroup]", + "[table CollectionObjectGroupJoin]", + "[table CollectionObjectGroupType]", "[table CollectionObjectProperty]", - "[table CollectionRelType]", + "[table CollectionObjectType]", "[table CollectionRelationship]", + "[table CollectionRelType]", "[table Collector]", "[table CommonNameTx]", "[table CommonNameTxCitation]", @@ -48,12 +55,6 @@ exports[`Tables with form tables computed correctly 1`] = ` "[table ConservEvent]", "[table ConservEventAttachment]", "[table Container]", - "[table DNAPrimer]", - "[table DNASequence]", - "[table DNASequenceAttachment]", - "[table DNASequencingRun]", - "[table DNASequencingRunAttachment]", - "[table DNASequencingRunCitation]", "[table Deaccession]", "[table DeaccessionAgent]", "[table DeaccessionAttachment]", @@ -66,6 +67,12 @@ exports[`Tables with form tables computed correctly 1`] = ` "[table DisposalAttachment]", "[table DisposalPreparation]", "[table Division]", + "[table DNAPrimer]", + "[table DNASequence]", + "[table DNASequenceAttachment]", + "[table DNASequencingRun]", + "[table DNASequencingRunAttachment]", + "[table DNASequencingRunCitation]", "[table ExchangeIn]", "[table ExchangeInAttachment]", "[table ExchangeInPrep]", @@ -116,19 +123,23 @@ exports[`Tables with form tables computed correctly 1`] = ` "[table PcrPerson]", "[table Permit]", "[table PermitAttachment]", - "[table PrepType]", "[table Preparation]", "[table PreparationAttachment]", "[table PreparationAttr]", "[table PreparationAttribute]", "[table PreparationProperty]", + "[table PrepType]", "[table Project]", "[table ReferenceWork]", "[table ReferenceWorkAttachment]", + "[table RelativeAge]", + "[table RelativeAgeAttachment]", + "[table RelativeAgeCitation]", "[table RepositoryAgreement]", "[table RepositoryAgreementAttachment]", "[table Shipment]", "[table SpAuditLog]", + "[table SpDataSetAttachment]", "[table Storage]", "[table StorageAttachment]", "[table StorageTreeDef]", @@ -139,22 +150,11 @@ exports[`Tables with form tables computed correctly 1`] = ` "[table TaxonCitation]", "[table TaxonTreeDef]", "[table TaxonTreeDefItem]", + "[table TectonicUnit]", + "[table TectonicUnitTreeDef]", + "[table TectonicUnitTreeDefItem]", "[table TreatmentEvent]", "[table TreatmentEventAttachment]", "[table VoucherRelationship]", - "[table CollectionObjectType]", - "[table CollectionObjectGroup]", - "[table CollectionObjectGroupJoin]", - "[table CollectionObjectGroupType]", - "[table AbsoluteAge]", - "[table RelativeAge]", - "[table AbsoluteAgeAttachment]", - "[table RelativeAgeAttachment]", - "[table AbsoluteAgeCitation]", - "[table RelativeAgeCitation]", - "[table TectonicUnitTreeDef]", - "[table TectonicUnitTreeDefItem]", - "[table TectonicUnit]", - "[table SpDataSetAttachment]", ] `; diff --git a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/automapper.test.ts b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/automapper.test.ts index 801eca21018..90bfcaf93e5 100644 --- a/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/automapper.test.ts +++ b/specifyweb/frontend/js_src/lib/components/WbPlanView/__tests__/automapper.test.ts @@ -212,21 +212,21 @@ theories( test('circular tables are calculated correctly', () => expect(circularTables()).toMatchInlineSnapshot(` - [ - "[table Agent]", - "[table Container]", - "[table Geography]", - "[table GeographyTreeDefItem]", - "[table GeologicTimePeriod]", - "[table GeologicTimePeriodTreeDefItem]", - "[table LithoStrat]", - "[table LithoStratTreeDefItem]", - "[table ReferenceWork]", - "[table Storage]", - "[table StorageTreeDefItem]", - "[table Taxon]", - "[table TaxonTreeDefItem]", - "[table TectonicUnitTreeDefItem]", - "[table TectonicUnit]", - ] - `)); +[ + "[table Agent]", + "[table Container]", + "[table Geography]", + "[table GeographyTreeDefItem]", + "[table GeologicTimePeriod]", + "[table GeologicTimePeriodTreeDefItem]", + "[table LithoStrat]", + "[table LithoStratTreeDefItem]", + "[table ReferenceWork]", + "[table Storage]", + "[table StorageTreeDefItem]", + "[table Taxon]", + "[table TaxonTreeDefItem]", + "[table TectonicUnit]", + "[table TectonicUnitTreeDefItem]", +] +`));