Skip to content

Commit 368eddf

Browse files
committed
Add a better way to get table scoping
Resolve even indirect scopes
1 parent ab3cdad commit 368eddf

File tree

9 files changed

+334
-22
lines changed

9 files changed

+334
-22
lines changed

specifyweb/frontend/js_src/lib/components/DataModel/__tests__/__snapshots__/specifyModel.test.ts.snap

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,3 +1025,193 @@ exports[`localization is loaded 1`] = `
10251025
"type": null,
10261026
}
10271027
`;
1028+
1029+
exports[`tableScoping 1`] = `
1030+
{
1031+
"Accession": "division",
1032+
"AccessionAgent": "accession > division",
1033+
"AccessionAttachment": "accession > division",
1034+
"AccessionAuthorization": "accession > division",
1035+
"AccessionCitation": "accession > division",
1036+
"Address": "agent > division",
1037+
"AddressOfRecord": undefined,
1038+
"Agent": "division",
1039+
"AgentAttachment": "agent > division",
1040+
"AgentGeography": "agent > division",
1041+
"AgentIdentifier": "agent > division",
1042+
"AgentSpecialty": "agent > division",
1043+
"AgentVariant": "agent > division",
1044+
"Appraisal": undefined,
1045+
"Attachment": undefined,
1046+
"AttachmentImageAttribute": undefined,
1047+
"AttachmentMetadata": undefined,
1048+
"AttachmentTag": undefined,
1049+
"AttributeDef": "discipline",
1050+
"Author": undefined,
1051+
"AutoNumberingScheme": undefined,
1052+
"Borrow": undefined,
1053+
"BorrowAgent": undefined,
1054+
"BorrowAttachment": undefined,
1055+
"BorrowMaterial": undefined,
1056+
"BorrowReturnMaterial": undefined,
1057+
"CollectingEvent": "discipline",
1058+
"CollectingEventAttachment": "collectingEvent > discipline",
1059+
"CollectingEventAttr": "collectingEvent > discipline",
1060+
"CollectingEventAttribute": "discipline",
1061+
"CollectingEventAuthorization": "collectingEvent > discipline",
1062+
"CollectingTrip": "discipline",
1063+
"CollectingTripAttachment": "collectingTrip > discipline",
1064+
"CollectingTripAttribute": "discipline",
1065+
"CollectingTripAuthorization": "collectingTrip > discipline",
1066+
"Collection": "discipline",
1067+
"CollectionObject": "collection",
1068+
"CollectionObjectAttachment": "collectionObject",
1069+
"CollectionObjectAttr": "collectionObject",
1070+
"CollectionObjectAttribute": undefined,
1071+
"CollectionObjectCitation": "collectionObject",
1072+
"CollectionObjectProperty": "collectionObject",
1073+
"CollectionRelType": undefined,
1074+
"CollectionRelationship": undefined,
1075+
"Collector": "division",
1076+
"CommonNameTx": "taxon > definition > discipline",
1077+
"CommonNameTxCitation": "commonNameTx > taxon > definition > discipline",
1078+
"ConservDescription": "collectionObject",
1079+
"ConservDescriptionAttachment": "conservDescription > collectionObject",
1080+
"ConservEvent": "conservDescription > collectionObject",
1081+
"ConservEventAttachment": "conservEvent > conservDescription > collectionObject",
1082+
"Container": undefined,
1083+
"DNAPrimer": undefined,
1084+
"DNASequence": "collectionObject",
1085+
"DNASequenceAttachment": "dnaSequence > collectionObject",
1086+
"DNASequencingRun": "dnaSequence > collectionObject",
1087+
"DNASequencingRunAttachment": "dnaSequencingRun > dnaSequence > collectionObject",
1088+
"DNASequencingRunCitation": "sequencingRun > dnaSequence > collectionObject",
1089+
"DataType": undefined,
1090+
"Deaccession": undefined,
1091+
"DeaccessionAgent": undefined,
1092+
"DeaccessionAttachment": undefined,
1093+
"Determination": "collectionObject",
1094+
"DeterminationCitation": "determination > collectionObject",
1095+
"Determiner": "determination > collectionObject",
1096+
"Discipline": "division",
1097+
"Disposal": undefined,
1098+
"DisposalAgent": undefined,
1099+
"DisposalAttachment": undefined,
1100+
"DisposalPreparation": undefined,
1101+
"Division": undefined,
1102+
"ExchangeIn": "division",
1103+
"ExchangeInAttachment": "exchangeIn > division",
1104+
"ExchangeInPrep": "discipline",
1105+
"ExchangeOut": "division",
1106+
"ExchangeOutAttachment": "exchangeOut > division",
1107+
"ExchangeOutPrep": "discipline",
1108+
"Exsiccata": undefined,
1109+
"ExsiccataItem": "collectionObject",
1110+
"Extractor": "dnaSequence > collectionObject",
1111+
"FieldNotebook": "collection",
1112+
"FieldNotebookAttachment": "fieldNotebook > collection",
1113+
"FieldNotebookPage": "discipline",
1114+
"FieldNotebookPageAttachment": "fieldNotebookPage > discipline",
1115+
"FieldNotebookPageSet": "discipline",
1116+
"FieldNotebookPageSetAttachment": "fieldNotebookPageSet > discipline",
1117+
"FundingAgent": "division",
1118+
"GeoCoordDetail": undefined,
1119+
"Geography": undefined,
1120+
"GeographyTreeDef": undefined,
1121+
"GeographyTreeDefItem": undefined,
1122+
"GeologicTimePeriod": undefined,
1123+
"GeologicTimePeriodTreeDef": undefined,
1124+
"GeologicTimePeriodTreeDefItem": undefined,
1125+
"Gift": "discipline",
1126+
"GiftAgent": "discipline",
1127+
"GiftAttachment": "gift > discipline",
1128+
"GiftPreparation": "discipline",
1129+
"GroupPerson": "division",
1130+
"InfoRequest": undefined,
1131+
"Institution": undefined,
1132+
"InstitutionNetwork": undefined,
1133+
"Journal": undefined,
1134+
"LatLonPolygon": "locality > discipline",
1135+
"LatLonPolygonPnt": "latLonPolygon > locality > discipline",
1136+
"LithoStrat": undefined,
1137+
"LithoStratTreeDef": undefined,
1138+
"LithoStratTreeDefItem": undefined,
1139+
"Loan": "discipline",
1140+
"LoanAgent": "discipline",
1141+
"LoanAttachment": "loan > discipline",
1142+
"LoanPreparation": "discipline",
1143+
"LoanReturnPreparation": "discipline",
1144+
"Locality": "discipline",
1145+
"LocalityAttachment": "locality > discipline",
1146+
"LocalityCitation": "discipline",
1147+
"LocalityDetail": "locality > discipline",
1148+
"LocalityNameAlias": "discipline",
1149+
"MaterialSample": "preparation > collectionObject",
1150+
"MorphBankView": undefined,
1151+
"OtherIdentifier": "collectionObject",
1152+
"PaleoContext": "discipline",
1153+
"PcrPerson": "dnaSequence > collectionObject",
1154+
"Permit": undefined,
1155+
"PermitAttachment": undefined,
1156+
"PickList": "collection",
1157+
"PickListItem": "pickList > collection",
1158+
"PrepType": "collection",
1159+
"Preparation": "collectionObject",
1160+
"PreparationAttachment": "preparation > collectionObject",
1161+
"PreparationAttr": "preparation > collectionObject",
1162+
"PreparationAttribute": undefined,
1163+
"PreparationProperty": "preparation > collectionObject",
1164+
"Project": undefined,
1165+
"RecordSet": undefined,
1166+
"RecordSetItem": undefined,
1167+
"ReferenceWork": undefined,
1168+
"ReferenceWorkAttachment": undefined,
1169+
"RepositoryAgreement": "division",
1170+
"RepositoryAgreementAttachment": "repositoryAgreement > division",
1171+
"Shipment": "discipline",
1172+
"SpAppResource": "spAppResourceDir > collection",
1173+
"SpAppResourceData": "spAppResource > spAppResourceDir > collection",
1174+
"SpAppResourceDir": "collection",
1175+
"SpAuditLog": undefined,
1176+
"SpAuditLogField": undefined,
1177+
"SpExportSchema": "discipline",
1178+
"SpExportSchemaItem": "spExportSchema > discipline",
1179+
"SpExportSchemaItemMapping": "exportSchemaItem > spExportSchema > discipline",
1180+
"SpExportSchemaMapping": undefined,
1181+
"SpFieldValueDefault": undefined,
1182+
"SpLocaleContainer": "discipline",
1183+
"SpLocaleContainerItem": "container > discipline",
1184+
"SpLocaleItemStr": undefined,
1185+
"SpPermission": undefined,
1186+
"SpPrincipal": undefined,
1187+
"SpQuery": undefined,
1188+
"SpQueryField": undefined,
1189+
"SpReport": "appResource > spAppResourceDir > collection",
1190+
"SpSymbiotaInstance": undefined,
1191+
"SpTaskSemaphore": "collection",
1192+
"SpVersion": undefined,
1193+
"SpViewSetObj": "spAppResourceDir > collection",
1194+
"SpVisualQuery": undefined,
1195+
"SpecifyUser": undefined,
1196+
"Storage": undefined,
1197+
"StorageAttachment": undefined,
1198+
"StorageTreeDef": undefined,
1199+
"StorageTreeDefItem": undefined,
1200+
"Taxon": "definition > discipline",
1201+
"TaxonAttachment": "taxon > definition > discipline",
1202+
"TaxonAttribute": undefined,
1203+
"TaxonCitation": "taxon > definition > discipline",
1204+
"TaxonTreeDef": "discipline",
1205+
"TaxonTreeDefItem": "treeDef > discipline",
1206+
"TreatmentEvent": "collectionObject",
1207+
"TreatmentEventAttachment": "treatmentEvent > collectionObject",
1208+
"VoucherRelationship": "collectionObject",
1209+
"Workbench": undefined,
1210+
"WorkbenchDataItem": undefined,
1211+
"WorkbenchRow": undefined,
1212+
"WorkbenchRowExportedRelationship": undefined,
1213+
"WorkbenchRowImage": undefined,
1214+
"WorkbenchTemplate": undefined,
1215+
"WorkbenchTemplateMappingItem": undefined,
1216+
}
1217+
`;

specifyweb/frontend/js_src/lib/components/DataModel/__tests__/specifyModel.test.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -593,27 +593,23 @@ describe('getAggregator', () => {
593593

594594
describe('getScopingRelationship', () => {
595595
test('can get scoping relationship when scoped to Collection Object', () =>
596-
expect(schema.models.Determination.getScopingRelationship()?.name).toBe(
596+
expect(schema.models.Determination.getDirectScope()?.name).toBe(
597597
'collectionObject'
598598
));
599599
test('can get scoping relationship when scoped to Collection', () =>
600-
expect(schema.models.CollectionObject.getScopingRelationship()?.name).toBe(
600+
expect(schema.models.CollectionObject.getDirectScope()?.name).toBe(
601601
'collection'
602602
));
603603
test('can get scoping relationship when scoped to Discipline', () =>
604-
expect(schema.models.CollectingEvent.getScopingRelationship()?.name).toBe(
604+
expect(schema.models.CollectingEvent.getDirectScope()?.name).toBe(
605605
'discipline'
606606
));
607607
test('can get scoping relationship when scoped to Division', () =>
608-
expect(schema.models.Discipline.getScopingRelationship()?.name).toBe(
609-
'division'
610-
));
608+
expect(schema.models.Discipline.getDirectScope()?.name).toBe('division'));
611609
test('can get scoping relationship when scoped to Institution', () =>
612-
expect(schema.models.Division.getScopingRelationship()?.name).toBe(
613-
'institution'
614-
));
610+
expect(schema.models.Division.getDirectScope()?.name).toBe('institution'));
615611
test('returns undefined if table is not scoped', () =>
616-
expect(schema.models.SpecifyUser.getScopingRelationship()).toBeUndefined());
612+
expect(schema.models.SpecifyUser.getDirectScope()).toBeUndefined());
617613
});
618614

619615
describe('getScopingPath', () => {
@@ -653,3 +649,16 @@ test('toJSON', () =>
653649
expect(schema.models.CollectionObject.toJSON()).toBe(
654650
'[table CollectionObject]'
655651
));
652+
653+
test('tableScoping', () =>
654+
expect(
655+
Object.fromEntries(
656+
Object.entries(schema.models).map(([name, table]) => [
657+
name,
658+
table
659+
.getScope()
660+
?.map(({ name }) => name)
661+
.join(' > '),
662+
])
663+
)
664+
).toMatchSnapshot());

specifyweb/frontend/js_src/lib/components/DataModel/domain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { fail } from '../Errors/Crash';
1818
* Some tasks to do after a new resource is created
1919
*/
2020
globalEvents.on('newResource', (resource) => {
21-
const domainField = resource.specifyModel.getScopingRelationship();
21+
const domainField = resource.specifyModel.getDirectScope();
2222
if (domainField === undefined) return;
2323

2424
const domainFieldName =
@@ -91,7 +91,7 @@ export function getCollectionForResource(
9191
const collectionUrl = resource.get('collectionMemberId') as number | null;
9292
if (typeof collectionUrl === 'number') return collectionUrl;
9393

94-
const domainField = resource.specifyModel.getScopingRelationship();
94+
const domainField = resource.specifyModel.getDirectScope();
9595
if (domainField === undefined) return undefined;
9696

9797
const domainResourceId = idFromUrl(resource.get(domainField.name) ?? '');
@@ -108,7 +108,7 @@ export function getCollectionForResource(
108108
export const fetchCollectionsForResource = async (
109109
resource: SpecifyResource<AnySchema>
110110
): Promise<RA<number> | undefined> =>
111-
f.maybe(resource.specifyModel.getScopingRelationship(), async (domainField) =>
111+
f.maybe(resource.specifyModel.getDirectScope(), async (domainField) =>
112112
(resource as SpecifyResource<CollectionObject>)
113113
?.rgetPromise(domainField.name as 'collection')
114114
.then(async (resource) => {

specifyweb/frontend/js_src/lib/components/DataModel/schemaBase.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515
import type { Tables } from './types';
1616
import { load } from '../InitialContext';
1717
import type { SpecifyModel } from './specifyModel';
18-
import type { RA, RR, Writable } from '../../utils/types';
18+
import type { RR, Writable } from '../../utils/types';
1919

2020
export type Schema = {
2121
readonly domainLevelIds: RR<typeof domainLevels[number], number>;
2222
readonly embeddedCollectingEvent: boolean;
2323
readonly embeddedPaleoContext: boolean;
2424
readonly paleoContextChildTable: string;
2525
readonly catalogNumFormatName: string;
26-
readonly orgHierarchy: RA<keyof Tables>;
26+
readonly orgHierarchy: readonly [
27+
'CollectionObject',
28+
'Collection',
29+
'Discipline',
30+
'Division',
31+
'Institution'
32+
];
2733
readonly models: {
2834
readonly [TABLE_NAME in keyof Tables]: SpecifyModel<Tables[TABLE_NAME]>;
2935
};

0 commit comments

Comments
 (0)