From 972075b06990758717faecdc63f720bceb192e8c Mon Sep 17 00:00:00 2001 From: TomDijkema Date: Wed, 20 Nov 2024 12:54:13 +0100 Subject: [PATCH 01/13] Refactor and update the Annotation Tour Refactor and update the Annotation Tour --- src/app/Store.ts | 6 +- .../digitalSpecimen/DigitalSpecimen.tsx | 18 +- .../tourSteps/AnnotateTourSteps.tsx | 255 ++++++++++++++++++ .../AnnotationSidePanel.tsx | 10 +- .../components/AnnotationsOverview.tsx | 17 +- .../components/SortingFilters.tsx | 2 +- .../annotationSidePanel/components/TopBar.tsx | 2 +- .../annotationWizard/AnnotationWizard.tsx | 28 +- .../steps/AnnotationFormStep.tsx | 27 +- .../steps/AnnotationSummaryStep.tsx | 128 +++++---- .../steps/AnnotationTargetStep.tsx | 2 +- .../annotationWizard/steps/NewInstance.tsx | 25 +- .../elements/topBarActions/TopBarActions.tsx | 2 +- src/redux-store/TourSlice.ts | 61 +++++ src/sources/tourText/digitalSpecimen.json | 38 +-- 15 files changed, 528 insertions(+), 93 deletions(-) create mode 100644 src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx create mode 100644 src/redux-store/TourSlice.ts diff --git a/src/app/Store.ts b/src/app/Store.ts index dc9f2eb4..838df07d 100644 --- a/src/app/Store.ts +++ b/src/app/Store.ts @@ -5,10 +5,11 @@ import type { PreloadedStateShapeFromReducersMapObject } from '@reduxjs/toolkit' /* Import Redux Slices */ import AnnotateReducer from 'redux-store/AnnotateSlice'; import BootReducder from 'redux-store/BootSlice'; -import GlobalReducer from 'redux-store/GlobalSlice'; -import SearchReducer from 'redux-store/SearchSlice'; import DigitalMediaReducer from 'redux-store/DigitalMediaSlice'; import DigitalSpecimenReducer from 'redux-store/DigitalSpecimenSlice'; +import GlobalReducer from 'redux-store/GlobalSlice'; +import SearchReducer from 'redux-store/SearchSlice'; +import TourReducer from 'redux-store/TourSlice'; const rootReducer = combineReducers({ @@ -18,6 +19,7 @@ const rootReducer = combineReducers({ digitalSpecimen: DigitalSpecimenReducer, global: GlobalReducer, search: SearchReducer, + tour: TourReducer }); export const setupStore = (preloadedState?: PreloadedStateShapeFromReducersMapObject) => { diff --git a/src/components/digitalSpecimen/DigitalSpecimen.tsx b/src/components/digitalSpecimen/DigitalSpecimen.tsx index 26afe70e..7972f1e9 100644 --- a/src/components/digitalSpecimen/DigitalSpecimen.tsx +++ b/src/components/digitalSpecimen/DigitalSpecimen.tsx @@ -28,6 +28,7 @@ import GetDigitalSpecimenMasJobRecords from 'api/digitalSpecimen/GetDigitalSpeci import ScheduleDigitalSpecimenMas from "api/digitalSpecimen/ScheduleDigitalSpecimenMas"; /* Import Components */ +import AnnotateTourSteps from './tourSteps/AnnotateTourSteps'; import DigitalSpecimenTourSteps from './tourSteps/DigitalSpecimenTourSteps'; import { ContentBlock, IdCard, TopBar } from './components/DigitalSpecimenComponents'; import { AnnotationSidePanel, BreadCrumbs, Header, Footer } from 'components/elements/Elements'; @@ -49,10 +50,16 @@ const DigitalSpecimen = () => { const [digitalSpecimenDigitalMedia, setDigitalSpecimenDigitalMedia] = useState(); const [annotationMode, setAnnotationMode] = useState(false); const [selectedTabIndex, setSelectedTabIndex] = useState(0); - const tourTopics: TourTopic[] = [{ - name: 'digitalSpecimen', - title: 'About this page' - }]; + const tourTopics: TourTopic[] = [ + { + name: 'digitalSpecimen', + title: 'About this page' + }, + { + name: 'annotate', + title: 'Using annotations' + } + ]; /* OnLoad, fetch digital specimen data */ fetch.FetchMultiple({ @@ -191,6 +198,9 @@ const DigitalSpecimen = () => { + ); }; diff --git a/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx b/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx new file mode 100644 index 00000000..487d8da9 --- /dev/null +++ b/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx @@ -0,0 +1,255 @@ +/* Import Dependencies */ +import { Steps } from 'intro.js-react'; +import KeycloakService from 'app/Keycloak'; +import { useRef, useState } from 'react'; + +/* Import Hooks */ +import { useTrigger } from 'app/Hooks'; + +/* Import Config */ +import StepsConfig from 'app/config/StepsConfig'; + +/* Import Hooks */ +import { useAppSelector, useAppDispatch } from 'app/Hooks'; + +/* Import Store */ +import { setAnnotationTarget } from 'redux-store/AnnotateSlice'; +import { + setAnnotationWizardDummyAnnotation, setAnnotationWizardSelectedIndex, + getAnnotationWizardToggle, setAnnotationWizardToggle, setAnnotationWizardFormValues +} from 'redux-store/TourSlice'; +import { getTourTopic, setTourTopic } from 'redux-store/GlobalSlice'; + +/* Import Sources */ +import DigitalSpecimenTourStepsText from 'sources/tourText/digitalSpecimen.json'; + + +/* Props Type */ +type Props = { + annotationMode: boolean, + SetAnnotationMode: Function +}; + + +/** + * Component that renders the tour steps for the digital specimen page + * @param annotationMode Boolean that indicates if the annotation mode is on or not + * @param SetAnnotationMode Function to set the annotation mode + * @returns JSX Component + */ +const AnnotateTourSteps = (props: Props) => { + const { annotationMode, SetAnnotationMode } = props; + + /* Hooks */ + const dispatch = useAppDispatch(); + const trigger = useTrigger(); + const stepsRef = useRef(null); + + /* Base variables */ + const tourTopic = useAppSelector(getTourTopic); + const annotationWizardToggle = useAppSelector(getAnnotationWizardToggle); + const digitalSpecimenSteps = DigitalSpecimenTourStepsText.annotate; + const { options } = StepsConfig(); + const [steps, setSteps] = useState<{ + intro: string, + element?: string + }[]>([]); + + /* Construct Intro.js steps for digital specimen page */ + trigger.SetTrigger(() => { + const steps: { + intro: string, + element?: string + }[] = []; + + digitalSpecimenSteps.forEach((step, index) => { + if ([0, 1, 2, 3, 4, 5].includes(index) || (KeycloakService.IsLoggedIn() && KeycloakService.GetParsedToken()?.orcid)) { + steps.push({ + intro: step, + element: `.tourAnnotate${index + 1}` + }); + } + }); + + setSteps(steps); + }, []); + + /** + * Function that checks what to do on a step change + * @param nextIndex The next (selected) index in the step chain + * @param resolve Function to resolve the step promise + */ + const OnStepChange = async (nextIndex: number, resolve: Function) => { + /* Handlers for step 1, 2 and 3 */ + if ([1, 2, 3].includes(nextIndex) && annotationMode) { + SetAnnotationMode(false); + } else if (![1, 2, 3].includes(nextIndex) && !annotationMode) { + SetAnnotationMode(true); + } + + /* Handlers for step 5 and 6 */ + if ([5, 6].includes(nextIndex) && annotationWizardToggle) { + dispatch(setAnnotationWizardToggle(false)); + } + + if ([7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18].includes(nextIndex)) { + dispatch(setAnnotationWizardToggle(true)); + } else { + dispatch(setAnnotationWizardToggle(false)); + } + + if (nextIndex > 9 && nextIndex < 19) { + dispatch(setAnnotationTarget({ + jsonPath: "$['ods:hasEntityRelationships']", + type: 'class' + })); + } else { + dispatch(setAnnotationTarget(undefined)); + } + + if (nextIndex === 9) { + dispatch(setAnnotationWizardFormValues({ + class: { + label: 'Entity Relationships', + value: "$['ods:hasEntityRelationships']" + }, + annotationValues: {}, + motivation: '', + jsonPath: '' + })); + } else if ([10, 11].includes(nextIndex)) { + dispatch(setAnnotationWizardFormValues({ + class: { + label: 'Entity Relationships', + value: "$['ods:hasEntityRelationships']" + }, + annotationValues: {}, + motivation: '', + jsonPath: '' + })); + } else if ([12, 13, 14].includes(nextIndex)) { + dispatch(setAnnotationWizardFormValues({ + class: { + label: 'Entity Relationships', + value: "$['ods:hasEntityRelationships']" + }, + annotationValues: {}, + motivation: 'ods:adding', + jsonPath: "$['ods:hasEntityRelationships'][999]" + })); + } else if ([15, 16, 17, 18].includes(nextIndex)) { + dispatch(setAnnotationWizardFormValues({ + class: { + label: 'Entity Relationships', + value: "$['ods:hasEntityRelationships']" + }, + annotationValues: { + "$'ods:hasEntityRelationships'_999": { + "dwc:relationshipOfResource": 'GeoCASe', + "ods:relatedResourceURI": 'https://geocase.eu/specimen/GIT338-118' + } + }, + motivation: 'ods:adding', + jsonPath: "$['ods:hasEntityRelationships'][999]" + })); + } else if (nextIndex === 19) { + dispatch(setAnnotationWizardDummyAnnotation({ + '@id': 'dummyAnnotation', + '@type': 'ods:Annotation', + "dcterms:identifier": 'dummyAnnotation', + 'ods:fdoType': 'https://doi.org/21.T11148/cf458ca9ee1d44a5608f', + 'ods:status': 'Active', + 'ods:version': 1, + 'oa:motivation': 'ods:adding', + 'oa:motivatedBy': '', + 'oa:hasTarget': { + '@id': 'dummyAnnotationTarget', + '@type': 'ods:DigitalSpecimen', + 'dcterms:identifier': 'dummyAnnotationTarget', + 'ods:fdoType': 'https://doi.org/21.T11148/894b1e6cad57e921764e', + 'oa:hasSelector': { + '@type': 'ods:ClassSelector', + 'ods:class': "$['ods:hasEntityRelationships']" + } + }, + 'oa:hasBody': { + '@type': 'oa:TextualBody', + 'oa:value': [ + '{"dwc:relationshipOfResource":"GeoCASe","ods:relatedResourceURI":"https://geocase.eu/specimen/GIT338-118"}' + ] + }, + 'dcterms:creator': { + '@id': 'dummyAnnotationCreator', + '@type': 'prov:SoftwareAgent', + 'schema:identifier': 'dummyAnnotationCreator', + 'schema:name': 'Tour Manager' + }, + 'dcterms:created': '2024-11-15T08:56:50.758Z', + 'dcterms:modified': '2024-11-15T08:56:50.758Z', + 'dcterms:issued': '2024-11-15T08:56:50.758Z', + 'as:generator': { + '@id': 'dummyAnnotationGenerator', + '@type': 'prov:SoftwareAgent', + 'schema:identifier': 'dummyAnnotationGenerator' + } + })); + } + + if (nextIndex < 9 && nextIndex > 18) { + dispatch(setAnnotationWizardFormValues({ + class: undefined, + annotationValues: {}, + motivation: '', + jsonPath: '' + })); + } + + if ([7, 8, 9].includes(nextIndex)) { + dispatch(setAnnotationWizardSelectedIndex(0)); + dispatch(setAnnotationTarget(undefined)); + } else if ([10, 11, 12].includes(nextIndex)) { + dispatch(setAnnotationWizardSelectedIndex(1)); + } else if ([13, 14, 15, 16].includes(nextIndex)) { + dispatch(setAnnotationWizardSelectedIndex(2)); + } else if ([17, 18].includes(nextIndex)) { + dispatch(setAnnotationWizardSelectedIndex(3)); + } + + if (nextIndex !== 19) { + dispatch(setAnnotationWizardDummyAnnotation(undefined)); + } + + setTimeout(() => { + stepsRef.current.updateStepElement(nextIndex - 1); + + resolve(true); + }, 500); + }; + + return ( + { + return new Promise((resolve) => { + OnStepChange(nextIndex + 1, resolve); + }); + }} + onStart={() => { + dispatch(setAnnotationWizardToggle(false)); + }} + onExit={() => { + dispatch(setTourTopic(undefined)); + dispatch(setAnnotationWizardFormValues(undefined)); + dispatch(setAnnotationWizardSelectedIndex(undefined)); + dispatch(setAnnotationTarget(undefined)); + dispatch(setAnnotationWizardToggle(false)); + dispatch(setAnnotationWizardDummyAnnotation(undefined)); + }} + options={options} + ref={stepsRef} + /> + ); +}; + +export default AnnotateTourSteps; \ No newline at end of file diff --git a/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx b/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx index 9852dd52..8b8bc67b 100644 --- a/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx +++ b/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx @@ -8,6 +8,7 @@ import { useAppDispatch, useAppSelector, useFetch } from 'app/Hooks'; /* Import Store */ import { getAnnotationTarget, setAnnotationTarget } from 'redux-store/AnnotateSlice'; +import { getAnnotationWizardToggle } from 'redux-store/TourSlice'; /* Import Types */ import { Annotation } from 'app/types/Annotation'; @@ -60,6 +61,7 @@ const AnnotationSidePanel = (props: Props) => { /* Base variables */ const annotationTarget = useAppSelector(getAnnotationTarget); + const tourAnnotationWizardToggle = useAppSelector(getAnnotationWizardToggle); const [annotations, setAnnotations] = useState([]); const [annotationWizardToggle, setAnnotationWizardToggle] = useState(false); const [masMenuToggle, setMasMenuToggle] = useState(false); @@ -81,7 +83,7 @@ const AnnotationSidePanel = (props: Props) => { triggers: [superClass, annotationWizardToggle], Method: GetAnnotations, Handler: (annotations: Annotation[]) => { - setAnnotations(annotations) + setAnnotations(annotations); } }); @@ -109,7 +111,9 @@ const AnnotationSidePanel = (props: Props) => { }); return ( -
+
{/* Top bar */} @@ -122,7 +126,7 @@ const AnnotationSidePanel = (props: Props) => { {/* Annotations overview or wizard depending on state */} - {(annotationWizardToggle && superClass) ? + {((annotationWizardToggle || tourAnnotationWizardToggle) && superClass) ? { /* Hooks */ const dispatch = useAppDispatch(); + /* Base variables */ + const tourAnnotationWizardDummyAnnotation = useAppSelector(getAnnotationWizardDummyAnnotation); + /** * Function to sort and filter annotations by the selected values * @param motivation The annotation motivation to filter by @@ -82,7 +86,10 @@ const AnnotationsOverview = (props: Props) => { }; /* Set overview annotations */ - const overviewAnnotations = SortAndFilerAnnotations(filterSortValues.motivation, filterSortValues.sortBy); + const overviewAnnotations = [ + ...(tourAnnotationWizardDummyAnnotation ? [tourAnnotationWizardDummyAnnotation] : []), + ...SortAndFilerAnnotations(filterSortValues.motivation, filterSortValues.sortBy) + ]; /** * Function to start editing an existing annotation @@ -148,9 +155,9 @@ const AnnotationsOverview = (props: Props) => { {/* Annotations */} - {overviewAnnotations.length ? overviewAnnotations.map(annotation => ( + {overviewAnnotations.length ? overviewAnnotations.map((annotation, index) => (
{ {/* Add annotation button */}
); }; diff --git a/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx b/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx index 487d8da9..7bf796e8 100644 --- a/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx +++ b/src/components/digitalSpecimen/tourSteps/AnnotateTourSteps.tsx @@ -32,7 +32,7 @@ type Props = { /** - * Component that renders the tour steps for the digital specimen page + * Component that renders the tour steps for the annotation tour on the digital specimen page * @param annotationMode Boolean that indicates if the annotation mode is on or not * @param SetAnnotationMode Function to set the annotation mode * @returns JSX Component @@ -48,22 +48,22 @@ const AnnotateTourSteps = (props: Props) => { /* Base variables */ const tourTopic = useAppSelector(getTourTopic); const annotationWizardToggle = useAppSelector(getAnnotationWizardToggle); - const digitalSpecimenSteps = DigitalSpecimenTourStepsText.annotate; + const annotateSteps = DigitalSpecimenTourStepsText.annotate; const { options } = StepsConfig(); const [steps, setSteps] = useState<{ intro: string, element?: string }[]>([]); - /* Construct Intro.js steps for digital specimen page */ + /* Construct Intro.js steps for annotation functionality on digital specimen page */ trigger.SetTrigger(() => { const steps: { intro: string, element?: string }[] = []; - digitalSpecimenSteps.forEach((step, index) => { - if ([0, 1, 2, 3, 4, 5].includes(index) || (KeycloakService.IsLoggedIn() && KeycloakService.GetParsedToken()?.orcid)) { + annotateSteps.forEach((step, index) => { + if ([0, 1, 2, 3, 4, 5, 20].includes(index) || (KeycloakService.IsLoggedIn() && KeycloakService.GetParsedToken()?.orcid)) { steps.push({ intro: step, element: `.tourAnnotate${index + 1}` diff --git a/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx b/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx new file mode 100644 index 00000000..602973ea --- /dev/null +++ b/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx @@ -0,0 +1,178 @@ +/* Import Dependencies */ +import { Steps } from 'intro.js-react'; +import KeycloakService from 'app/Keycloak'; +import { useRef, useState } from 'react'; + +/* Import Hooks */ +import { useTrigger } from 'app/Hooks'; + +/* Import Config */ +import StepsConfig from 'app/config/StepsConfig'; + +/* Import Hooks */ +import { useAppSelector, useAppDispatch } from 'app/Hooks'; + +/* Import Store */ +import { setAnnotationWizardToggle, setMasMenuToggle, setMasScheduleMenuToggle, setMasDummy, setMasMachineJobRecordDummy } from 'redux-store/TourSlice'; +import { getTourTopic, setTourTopic } from 'redux-store/GlobalSlice'; + +/* Import Sources */ +import DigitalSpecimenTourStepsText from 'sources/tourText/digitalSpecimen.json'; + + +/* Props Type */ +type Props = { + annotationMode: boolean, + SetAnnotationMode: Function +}; + + +/** + * Component that renders the tour steps for the machine annotation services on the digital specimen page + * @param annotationMode Boolean that indicates if the annotation mode is on or not + * @param SetAnnotationMode Function to set the annotation mode + * @returns JSX Component + */ +const MasTourSteps = (props: Props) => { + const { annotationMode, SetAnnotationMode } = props; + + /* Hooks */ + const dispatch = useAppDispatch(); + const trigger = useTrigger(); + const stepsRef = useRef(null); + + /* Base variables */ + const tourTopic = useAppSelector(getTourTopic); + const masSteps = DigitalSpecimenTourStepsText.mas; + const { options } = StepsConfig(); + const [steps, setSteps] = useState<{ + intro: string, + element?: string + }[]>([]); + + /* Construct Intro.js steps for MAS functionality on the digital specimen page */ + trigger.SetTrigger(() => { + const steps: { + intro: string, + element?: string + }[] = []; + + masSteps.forEach((step, index) => { + if ([0, 1, 2, 3, 4, 5, 6].includes(index) || (KeycloakService.IsLoggedIn() && KeycloakService.GetParsedToken()?.orcid)) { + steps.push({ + intro: step, + element: `.tourMas${index + 1}` + }); + } + }); + + setSteps(steps); + }, []); + + /** + * Function that checks what to do on a step change + * @param nextIndex The next (selected) index in the step chain + * @param resolve Function to resolve the step promise + */ + const OnStepChange = async (nextIndex: number, resolve: Function) => { + /* Handlers for step 1, 2 and 3 */ + if ([1, 2, 3].includes(nextIndex) && annotationMode) { + SetAnnotationMode(false); + } else if (![1, 2, 3].includes(nextIndex) && !annotationMode) { + SetAnnotationMode(true); + } + + if ([5, 6, 7, 8, 9, 10, 11, 12, 13].includes(nextIndex)) { + dispatch(setMasMenuToggle(true)); + } else { + dispatch(setMasMenuToggle(false)); + } + + if ([8, 9, 10].includes(nextIndex)) { + dispatch(setMasScheduleMenuToggle(true)); + } else { + dispatch(setMasScheduleMenuToggle(false)); + } + + if ([9, 10].includes(nextIndex)) { + dispatch(setMasDummy({ + '@id': 'MachineAnnotationServiceDummy', + '@type': 'ods:MachineAnnotationService', + 'schema:identifier': 'MachineAnnotationServiceDummy', + 'ods:fdoType': 'https://doi.org/10.15468/1a2b3c', + 'schema:name': 'Dummy Machine Annotation Service', + 'schema:description': 'A machine annotation service for showing off functionality', + 'schema:dateCreated': '2024-11-15T08:56:50.758Z', + 'schema:creator': { + '@id': 'MachineAnnotationServiceDummyAgent', + '@type': 'prov:SoftwareAgent' + }, + 'schema:dateModified': '2024-11-15T08:56:50.758Z', + 'ods:containerImage': 'dummyContainerImage', + 'ods:containerTag': 'dummyContainerTag', + 'ods:batchingPermitted': false, + 'ods:timeToLive': 1000 + })); + } else { + dispatch(setMasDummy(undefined)); + } + + if ([11, 12, 13].includes(nextIndex)) { + let state: 'SCHEDULED' | 'RUNNING' | 'FAILED' | 'COMPLETED' = 'SCHEDULED'; + + if (nextIndex === 12) { + state = 'COMPLETED'; + } else if (nextIndex === 13) { + state = 'FAILED'; + } + + dispatch(setMasMachineJobRecordDummy({ + annotations: [], + batchingRequested: false, + jobHandle: 'MachineJobRecordDummy', + masId: 'MachineAnnotationServiceDummy', + orcid: 'Tour Manager', + state, + targetId: 'DigitalSpecimenDummy', + targetType: 'ods:DigitalSpecimen', + timeCompleted: '2024-11-15T08:56:50.758Z', + timeStarted: '2024-11-15T08:56:50.758Z', + timeToLive: 1000 + })); + } else { + dispatch(setMasMachineJobRecordDummy(undefined)); + } + + setTimeout(() => { + stepsRef.current.updateStepElement(nextIndex - 1); + + resolve(true); + }, 500); + }; + + return ( + { + return new Promise((resolve) => { + OnStepChange(nextIndex + 1, resolve); + }); + }} + onStart={() => { + dispatch(setAnnotationWizardToggle(false)); + }} + onExit={() => { + dispatch(setTourTopic(undefined)); + dispatch(setMasDummy(undefined)); + dispatch(setMasMachineJobRecordDummy(undefined)); + dispatch(setMasMenuToggle(false)); + dispatch(setMasScheduleMenuToggle(false)); + }} + options={options} + ref={stepsRef} + /> + ); +}; + +export default MasTourSteps; \ No newline at end of file diff --git a/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx b/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx index 8b8bc67b..79656903 100644 --- a/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx +++ b/src/components/elements/annotationSidePanel/AnnotationSidePanel.tsx @@ -8,7 +8,7 @@ import { useAppDispatch, useAppSelector, useFetch } from 'app/Hooks'; /* Import Store */ import { getAnnotationTarget, setAnnotationTarget } from 'redux-store/AnnotateSlice'; -import { getAnnotationWizardToggle } from 'redux-store/TourSlice'; +import { getAnnotationWizardToggle, getMasMenuToggle } from 'redux-store/TourSlice'; /* Import Types */ import { Annotation } from 'app/types/Annotation'; @@ -62,6 +62,7 @@ const AnnotationSidePanel = (props: Props) => { /* Base variables */ const annotationTarget = useAppSelector(getAnnotationTarget); const tourAnnotationWizardToggle = useAppSelector(getAnnotationWizardToggle); + const tourMasMenuToggle = useAppSelector(getMasMenuToggle); const [annotations, setAnnotations] = useState([]); const [annotationWizardToggle, setAnnotationWizardToggle] = useState(false); const [masMenuToggle, setMasMenuToggle] = useState(false); @@ -111,7 +112,7 @@ const AnnotationSidePanel = (props: Props) => { }); return ( -
{/* Top bar */} @@ -142,7 +143,7 @@ const AnnotationSidePanel = (props: Props) => { SetFilterSortValues={setFilterSortValues} /> : <> - {(masMenuToggle && superClass) ? setMasMenuToggle(false)} SetLoading={setLoading} GetMas={GetMas} diff --git a/src/components/elements/annotationSidePanel/components/AnnotationsOverview.tsx b/src/components/elements/annotationSidePanel/components/AnnotationsOverview.tsx index 54ebaa79..1c112ec8 100644 --- a/src/components/elements/annotationSidePanel/components/AnnotationsOverview.tsx +++ b/src/components/elements/annotationSidePanel/components/AnnotationsOverview.tsx @@ -209,7 +209,9 @@ const AnnotationsOverview = (props: Props) => { {/* Machine annotation services button */} - + - + } - + { const [copyMessage, setCopyMessage] = useState('Copy'); const acceptedIdentification = digitalSpecimen['ods:hasIdentifications']?.find(identification => identification['ods:isVerifiedIdentification']); const collectors: string[] = []; - const collectionEvent: Event | undefined = digitalSpecimen['ods:hasEvents']?.find(event => event['dwc:eventType'] === 'Collection'); + const collectionEvent: Event | undefined = digitalSpecimen['ods:hasEvents']?.find(event => event['dwc:eventType'] === 'Collecting Event'); const topicDisciplinesWithIdentifications: string[] = [ 'Anthropology', 'Botany', @@ -48,11 +48,16 @@ const DigitalSpecimenOverview = (props: Props) => { ]; /* Construct collectors array */ - digitalSpecimen['ods:hasAgents']?.filter(agent => agent['ods:hasRoles']?.find(role => role['schema:roleName'] === 'collector')).forEach(agent => { - if (agent['schema:name']) { - collectors.push(agent['schema:name']); - } - }); + digitalSpecimen['ods:hasEvents']?.filter( + event => event['ods:hasAgents']?.filter( + agent => agent['ods:hasRoles']?.find( + role => role['schema:roleName'] === 'collector') + ).forEach(agent => { + if (agent['schema:name']) { + collectors.push(agent['schema:name']); + } + }) + ); /** * Function to craft a citation string for this digital specimen @@ -98,7 +103,7 @@ const DigitalSpecimenOverview = (props: Props) => {

- Collection date: + Collection date: {collectionEvent?.['dwc:eventDate']}

@@ -107,7 +112,7 @@ const DigitalSpecimenOverview = (props: Props) => {

- Country: + Country: {collectionEvent?.['ods:hasLocation']?.['dwc:country']}

@@ -116,7 +121,7 @@ const DigitalSpecimenOverview = (props: Props) => {

- Locality: + Locality: {collectionEvent?.['ods:hasLocation']?.['dwc:locality']}

diff --git a/src/components/elements/annotationSidePanel/components/masMenu/components/MasScheduleMenu.tsx b/src/components/elements/annotationSidePanel/components/masMenu/components/MasScheduleMenu.tsx index 28b13235..08d79aa6 100644 --- a/src/components/elements/annotationSidePanel/components/masMenu/components/MasScheduleMenu.tsx +++ b/src/components/elements/annotationSidePanel/components/masMenu/components/MasScheduleMenu.tsx @@ -144,23 +144,50 @@ const MASScheduleMenu = (props: Props) => { const mas = masOption.value === 'machineAnnotationServiceDummy' ? tourMasDummy : mass.find(mas => mas["schema:identifier"] === masOption.value); + let linkToOrchestration: string; + + if (window.location.hostname.includes('dev') || window.location.hostname.includes('localhost')) { + linkToOrchestration = `https://dev-orchestration.dissco.tech/MAS/${mas?.["@id"]?.replace(import.meta.env.VITE_HANDLE_URL, '')}`; + } else { + linkToOrchestration = `https://orchestration.dissco.tech/MAS/${mas?.["@id"]?.replace(import.meta.env.VITE_HANDLE_URL, '')}`; + } + if (mas) { return ( - = 1 ? 'mt-2' : ''} > - {/* MAS title */} -

- {mas?.["schema:name"]} -

+ {/* MAS title and link */} + + +

+ {mas?.['schema:name']} +

+ + + + +

+ View details of MAS +

+
+ +
{/* MAS description */} -

- {mas?.["schema:description"]} -

+ + +

+ {mas?.['schema:description']} +

+ +
); }; diff --git a/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx b/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx index a8c29104..d677b2ed 100644 --- a/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx +++ b/src/components/digitalSpecimen/tourSteps/masTourSteps.tsx @@ -23,19 +23,17 @@ import DigitalSpecimenTourStepsText from 'sources/tourText/digitalSpecimen.json' /* Props Type */ type Props = { - annotationMode: boolean, SetAnnotationMode: Function }; /** * Component that renders the tour steps for the machine annotation services on the digital specimen page - * @param annotationMode Boolean that indicates if the annotation mode is on or not * @param SetAnnotationMode Function to set the annotation mode * @returns JSX Component */ const MasTourSteps = (props: Props) => { - const { annotationMode, SetAnnotationMode } = props; + const { SetAnnotationMode } = props; /* Hooks */ const dispatch = useAppDispatch(); From 11fe49c27b455e128abdc66f1ead5bc2a1192d9e Mon Sep 17 00:00:00 2001 From: TomDijkema Date: Tue, 26 Nov 2024 15:29:42 +0100 Subject: [PATCH 12/13] Update types --- src/app/types/Annotation.d.ts | 2 +- src/app/types/ChronometricAge.d.ts | 174 +++++++++++++++ src/app/types/DigitalSpecimen.d.ts | 204 +++++++++++++++++- src/app/types/Identification.d.ts | 4 + src/app/types/SpecimenPart.d.ts | 106 +++++++++ src/app/types/TaxonIdentification.d.ts | 4 + src/sources/dataModel/annotation.json | 2 +- src/sources/dataModel/chronometricAge.json | 2 +- src/sources/dataModel/digitalSpecimen.json | 2 +- .../dataModel/taxonIdentification.json | 2 +- 10 files changed, 491 insertions(+), 11 deletions(-) diff --git a/src/app/types/Annotation.d.ts b/src/app/types/Annotation.d.ts index 33bf556f..146b54bb 100644 --- a/src/app/types/Annotation.d.ts +++ b/src/app/types/Annotation.d.ts @@ -20,7 +20,7 @@ export interface Annotation { /** * The handle of the annotation. It is a unique identifier for the annotation. It is composed of the handle of the document followed by a slash and a unique identifier for the annotation. */ - "dcterms:identifier"?: string; + "dcterms:identifier": string; /** * The DOI to the FDO type of the object */ diff --git a/src/app/types/ChronometricAge.d.ts b/src/app/types/ChronometricAge.d.ts index 9bd6c4bb..d47afe1c 100644 --- a/src/app/types/ChronometricAge.d.ts +++ b/src/app/types/ChronometricAge.d.ts @@ -46,6 +46,10 @@ export interface ChronometricAge { * The reference system associated with the latestChronometricAge */ "chrono:latestChronometricAgeReferenceSystem"?: string; + /** + * A description of or reference to the methods used to determine the chronometric age. + */ + "chrono:chronometricAgeProtocol"?: string; /** * The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years */ @@ -78,4 +82,174 @@ export interface ChronometricAge { * Notes or comments about the ChronometricAge */ "chrono:chronometricAgeRemarks"?: string; + /** + * The agent(s) involved in the determination of the chronometric age, uses `ods:Agent` + */ + "ods:hasAgents"?: Agent[]; +} +export interface Agent { + /** + * The identifier for the Agent object + */ + "@id"?: string; + /** + * The type of the agent, the prov ontology is only used in the prov-o ods:CreateUpdateTombstoneEvent + */ + "@type": + | "schema:Person" + | "schema:Organization" + | "schema:SoftwareApplication" + | "prov:Person" + | "prov:SoftwareAgent"; + /** + * The primary unique identifier of the Agent object. All identifiers will also be added to the ods:hasIdentifiers array + */ + "schema:identifier"?: string; + /** + * Full name of the agent + */ + "schema:name"?: string; + /** + * Contains all roles associated with the agent in the context of the Digital Object. Should always contain at least one role + * + * @minItems 1 + */ + "ods:hasRoles"?: [ + { + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }, + ...{ + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }[] + ]; + /** + * Email of the agent + */ + "schema:email"?: string; + /** + * URL to a website of the agent + */ + "schema:url"?: string; + /** + * Contains all identifiers associated with the agent + */ + "ods:hasIdentifiers"?: Identifier[]; +} +/** + * Object used to describe identifiers of a Digital Object, based on https://rs.gbif.org/extension/gbif/1.0/identifier.xml but includes ods specific terms + */ +export interface Identifier { + /** + * The identifier for the Identifier object. + */ + "@id"?: string; + /** + * The type of the digital object, in this case a ods:Identifier + */ + "@type": "ods:Identifier"; + /** + * A name for the identifier + */ + "dcterms:title": string; + /** + * The type of the value in the `dcterms:identifier` field + */ + "dcterms:type"?: + | "ARK" + | "arXiv" + | "bibcode" + | "DOI" + | "EAN13" + | "EISSN" + | "Handle" + | "IGSN" + | "ISBN" + | "ISSN" + | "ISTC" + | "LISSN" + | "LSID" + | "PMID" + | "PURL" + | "UPC" + | "URL" + | "URN" + | "w3id" + | "UUID" + | "Other" + | "Locally unique identifier"; + /** + * The value for the identifier + */ + "dcterms:identifier": string; + /** + * All possible mime types of content that can be returned by identifier in case the identifier is resolvable. Plain UUIDs for example do not have a dc:format return type, as they are not resolvable on their own. For a list of MIME types see the list maintained by IANA: http://www.iana.org/assignments/media-types/index.html, in particular the text http://www.iana.org/assignments/media-types/text/ and application http://www.iana.org/assignments/media-types/application/ types. Frequently used values are text/html, text/xml, application/rdf+xml, application/json + */ + "dcterms:format"?: string[]; + /** + * Additional keywords that the publisher may prefer to be attached to the identifier + */ + "dcterms:subject"?: string[]; + /** + * Indicates whether the identifier is part of the physical label + */ + "ods:isPartOfLabel"?: boolean; + /** + * Indicates whether the identifier is a persistent identifier + */ + "ods:gupriLevel"?: + | "LocallyUniqueStable" + | "GloballyUniqueStable" + | "GloballyUniqueStableResolvable" + | "GloballyUniqueStablePersistentResolvable" + | "GloballyUniqueStablePersistentResolvableFDOCompliant"; + /** + * Indicates the status of the identifier + */ + "ods:identifierStatus"?: "Preferred" | "Alternative" | "Superseded"; } diff --git a/src/app/types/DigitalSpecimen.d.ts b/src/app/types/DigitalSpecimen.d.ts index a7e8a1ba..0cfe277d 100644 --- a/src/app/types/DigitalSpecimen.d.ts +++ b/src/app/types/DigitalSpecimen.d.ts @@ -241,11 +241,15 @@ export interface DigitalSpecimen { /** * Contains all agents that are connected to the specimen. Agents that are part of a specific part of the specimen should be added there. For example a Collector is connected to the CollectingEvent so is add in the event */ - "ods:hasAgents"?: Agent7[]; + "ods:hasAgents"?: Agent8[]; /** * Contains information about any events that occurred specifically on the specimen part, for example a sampling event */ "ods:hasEvents"?: Event1[]; + /** + * Contains information about the chronometric age of the specimen part + */ + "ods:hasChronometricAges"?: ChronometricAge1[]; "ods:hasTombstoneMetadata"?: TombstoneMetadata; } export interface SpecimenPart { @@ -748,6 +752,10 @@ export interface TaxonIdentification { * A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name. */ "ods:scientificNameHTMLLabel"?: string; + /** + * A Hyper Text Markup Language (HTML) representation of the genus name. Includes correct formatting of the name. + */ + "ods:genusHTMLLabel"?: string; /** * The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode */ @@ -1958,6 +1966,10 @@ export interface ChronometricAge { * The reference system associated with the latestChronometricAge */ "chrono:latestChronometricAgeReferenceSystem"?: string; + /** + * A description of or reference to the methods used to determine the chronometric age. + */ + "chrono:chronometricAgeProtocol"?: string; /** * The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years */ @@ -1990,6 +2002,104 @@ export interface ChronometricAge { * Notes or comments about the ChronometricAge */ "chrono:chronometricAgeRemarks"?: string; + /** + * The agent(s) involved in the determination of the chronometric age, uses `ods:Agent` + */ + "ods:hasAgents"?: Agent6[]; +} +export interface Agent6 { + /** + * The identifier for the Agent object + */ + "@id"?: string; + /** + * The type of the agent, the prov ontology is only used in the prov-o ods:CreateUpdateTombstoneEvent + */ + "@type": + | "schema:Person" + | "schema:Organization" + | "schema:SoftwareApplication" + | "prov:Person" + | "prov:SoftwareAgent"; + /** + * The primary unique identifier of the Agent object. All identifiers will also be added to the ods:hasIdentifiers array + */ + "schema:identifier"?: string; + /** + * Full name of the agent + */ + "schema:name"?: string; + /** + * Contains all roles associated with the agent in the context of the Digital Object. Should always contain at least one role + * + * @minItems 1 + */ + "ods:hasRoles"?: [ + { + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }, + ...{ + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }[] + ]; + /** + * Email of the agent + */ + "schema:email"?: string; + /** + * URL to a website of the agent + */ + "schema:url"?: string; + /** + * Contains all identifiers associated with the agent + */ + "ods:hasIdentifiers"?: Identifier[]; } export interface Assertion2 { /** @@ -2100,9 +2210,9 @@ export interface EntityRelationship { /** * The agent(s) who created the entityRelationship, contains an ods:Agent object */ - "ods:hasAgents"?: Agent6[]; + "ods:hasAgents"?: Agent7[]; } -export interface Agent6 { +export interface Agent7 { /** * The identifier for the Agent object */ @@ -2371,7 +2481,7 @@ export interface Citation2 { */ "ods:hasAgents"?: Agent1[]; } -export interface Agent7 { +export interface Agent8 { /** * The identifier for the Agent object */ @@ -2599,6 +2709,88 @@ export interface Event1 { "ods:hasAgents"?: Agent3[]; "ods:hasLocation"?: Location; } +export interface ChronometricAge1 { + /** + * The identifier for the Chronometric Age object. + */ + "@id"?: string; + /** + * The type of the digital object, in this case ods:ChronometricAge + */ + "@type": "ods:ChronometricAge"; + /** + * An identifier for the set of information associated with a ChronometricAge + */ + "chrono:chronometricAgeID"?: string; + /** + * The verbatim age for a specimen, whether reported by a dating assay, associated references, or legacy information + */ + "chrono:verbatimChronometricAge"?: string; + /** + * The output of a dating assay before it is calibrated into an age using a specific conversion protocol. + */ + "chrono:uncalibratedChronometricAge"?: string; + /** + * The method used for converting the uncalibratedChronometricAge into a chronometric age in years, as captured in the earliestChronometricAge, earliestChronometricAgeReferenceSystem, latestChronometricAge, and latestChronometricAgeReferenceSystem fields. + */ + "chrono:chronometricAgeConversionProtocol"?: string; + /** + * The maximum/earliest/oldest possible age of a specimen as determined by a dating method + */ + "chrono:earliestChronometricAge"?: number; + /** + * The reference system associated with the earliestChronometricAge + */ + "chrono:earliestChronometricAgeReferenceSystem"?: string; + /** + * The minimum/latest/youngest possible age of a specimen as determined by a dating method + */ + "chrono:latestChronometricAge"?: number; + /** + * The reference system associated with the latestChronometricAge + */ + "chrono:latestChronometricAgeReferenceSystem"?: string; + /** + * A description of or reference to the methods used to determine the chronometric age. + */ + "chrono:chronometricAgeProtocol"?: string; + /** + * The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years + */ + "chrono:chronometricAgeUncertaintyInYears"?: number; + /** + * The method used to generate the value of chronometricAgeUncertaintyInYears + */ + "chrono:chronometricAgeUncertaintyMethod"?: string; + /** + * A description of the material on which the chronometricAgeProtocol was actually performed, if known. + */ + "chrono:materialDated"?: string; + /** + * An identifier for the MaterialSample on which the chronometricAgeProtocol was performed, if applicable + */ + "chrono:materialDatedID"?: string; + /** + * The relationship of the materialDated to the subject of the ChronometricAge record, from which the ChronometricAge of the subject is inferred + */ + "chrono:materialDatedRelationship"?: string; + /** + * The date on which the ChronometricAge was determined + */ + "chrono:chronometricAgeDeterminedDate"?: string; + /** + * A list (concatenated and separated) of identifiers (publication, bibliographic reference, global unique identifier, URI) of literature associated with the ChronometricAge. + */ + "chrono:chronometricAgeReferences"?: string; + /** + * Notes or comments about the ChronometricAge + */ + "chrono:chronometricAgeRemarks"?: string; + /** + * The agent(s) involved in the determination of the chronometric age, uses `ods:Agent` + */ + "ods:hasAgents"?: Agent6[]; +} /** * Object containing the tombstone metadata of the object. Only present when ods:status is ods:Tombstone */ @@ -2620,7 +2812,7 @@ export interface TombstoneMetadata { * * @minItems 1 */ - "ods:hasAgents": [Agent8, ...Agent8[]]; + "ods:hasAgents": [Agent9, ...Agent9[]]; /** * The PIDs of the object the tombstoned object is related to */ @@ -2643,7 +2835,7 @@ export interface TombstoneMetadata { "ods:relationshipType": string; }[]; } -export interface Agent8 { +export interface Agent9 { /** * The identifier for the Agent object */ diff --git a/src/app/types/Identification.d.ts b/src/app/types/Identification.d.ts index c197f761..f87b037b 100644 --- a/src/app/types/Identification.d.ts +++ b/src/app/types/Identification.d.ts @@ -393,6 +393,10 @@ export interface TaxonIdentification { * A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name. */ "ods:scientificNameHTMLLabel"?: string; + /** + * A Hyper Text Markup Language (HTML) representation of the genus name. Includes correct formatting of the name. + */ + "ods:genusHTMLLabel"?: string; /** * The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode */ diff --git a/src/app/types/SpecimenPart.d.ts b/src/app/types/SpecimenPart.d.ts index 4fd467ab..1c3e7bb1 100644 --- a/src/app/types/SpecimenPart.d.ts +++ b/src/app/types/SpecimenPart.d.ts @@ -505,6 +505,10 @@ export interface TaxonIdentification { * A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name. */ "ods:scientificNameHTMLLabel"?: string; + /** + * A Hyper Text Markup Language (HTML) representation of the genus name. Includes correct formatting of the name. + */ + "ods:genusHTMLLabel"?: string; /** * The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode */ @@ -1715,6 +1719,10 @@ export interface ChronometricAge { * The reference system associated with the latestChronometricAge */ "chrono:latestChronometricAgeReferenceSystem"?: string; + /** + * A description of or reference to the methods used to determine the chronometric age. + */ + "chrono:chronometricAgeProtocol"?: string; /** * The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years */ @@ -1747,4 +1755,102 @@ export interface ChronometricAge { * Notes or comments about the ChronometricAge */ "chrono:chronometricAgeRemarks"?: string; + /** + * The agent(s) involved in the determination of the chronometric age, uses `ods:Agent` + */ + "ods:hasAgents"?: Agent6[]; +} +export interface Agent6 { + /** + * The identifier for the Agent object + */ + "@id"?: string; + /** + * The type of the agent, the prov ontology is only used in the prov-o ods:CreateUpdateTombstoneEvent + */ + "@type": + | "schema:Person" + | "schema:Organization" + | "schema:SoftwareApplication" + | "prov:Person" + | "prov:SoftwareAgent"; + /** + * The primary unique identifier of the Agent object. All identifiers will also be added to the ods:hasIdentifiers array + */ + "schema:identifier"?: string; + /** + * Full name of the agent + */ + "schema:name"?: string; + /** + * Contains all roles associated with the agent in the context of the Digital Object. Should always contain at least one role + * + * @minItems 1 + */ + "ods:hasRoles"?: [ + { + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }, + ...{ + /** + * The identifier for the agent role, preferably a URL to a controlled vocabulary + */ + "@id"?: string; + /** + * The type of the object, in this case schema:Role + */ + "@type": "schema:Role"; + /** + * The category that best matches the nature of a role of an Agent + */ + "schema:roleName": string; + /** + * Date the agent began the role + */ + "schema:startDate"?: string; + /** + * Date the agent ended the role + */ + "schema:endDate"?: string; + /** + * Can be used to indicate the order of importance when there are multiple agents with the same role. Lower order means higher importance. + */ + "schema:position"?: number; + }[] + ]; + /** + * Email of the agent + */ + "schema:email"?: string; + /** + * URL to a website of the agent + */ + "schema:url"?: string; + /** + * Contains all identifiers associated with the agent + */ + "ods:hasIdentifiers"?: Identifier[]; } diff --git a/src/app/types/TaxonIdentification.d.ts b/src/app/types/TaxonIdentification.d.ts index 49f9f298..7c89fff9 100644 --- a/src/app/types/TaxonIdentification.d.ts +++ b/src/app/types/TaxonIdentification.d.ts @@ -30,6 +30,10 @@ export interface TaxonIdentification { * A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name. */ "ods:scientificNameHTMLLabel"?: string; + /** + * A Hyper Text Markup Language (HTML) representation of the genus name. Includes correct formatting of the name. + */ + "ods:genusHTMLLabel"?: string; /** * The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode */ diff --git a/src/sources/dataModel/annotation.json b/src/sources/dataModel/annotation.json index cab79808..15cf4534 100644 --- a/src/sources/dataModel/annotation.json +++ b/src/sources/dataModel/annotation.json @@ -1 +1 @@ -{"$id":"https://schemas.dissco.tech/schemas/fdo-type/annotation/0.4.0/annotation.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Annotation Version 0.4.0","title":"Annotation","description":"Information about the Annotation data model. This model has been based on the W3C Web Annotation model","type":"object","properties":{"@id":{"type":"string","description":"The unique identifier (handle) of the Annotation object","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"@type":{"type":"string","description":"The type of the object, in this case ods:Annotation","const":"ods:Annotation"},"dcterms:identifier":{"type":"string","description":"The handle of the annotation. It is a unique identifier for the annotation. It is composed of the handle of the document followed by a slash and a unique identifier for the annotation.","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"ods:fdoType":{"type":"string","description":"The DOI to the FDO type of the object","pattern":"^https://doi\\.org/[\\w\\.]+/[\\w\\.]+","examples":["https://doi.org/21.T11148/bbad8c4e101e8af01115","https://doi.org/21.T11148/894b1e6cad57e921764e"]},"ods:status":{"enum":["Draft","Active","Tombstone"],"description":"The status of the Digital Object. A digital object can be in Draft, when it is not published yet. Active when it is published and the object is active and Tombstone which means the object has been archived."},"ods:jobID":{"type":"string","description":"Handle of the job record, if the annotation was produced by a Machine Annotation Service, only filled when annotation was created by a MAS","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"ods:version":{"type":"integer","description":"The version of the object, each change generates a new version. The version starts at 1 and each change will increment the version number with 1","minimum":1,"examples":[1,3,5]},"oa:motivation":{"description":"The motivation for why an annotation was proposed. Based on a selection of https://www.w3.org/TR/annotation-model/#motivation-and-purpose. The motivation ods:adding and ods:deleting are added for DiSSCo's purposes.","enum":["ods:adding","ods:deleting","oa:assessing","oa:editing","oa:commenting"]},"oa:motivatedBy":{"type":"string","description":"Describes the reason for the annotation","examples":["The country is incorrect","Identified a new link to a record in ENA"]},"oa:hasTarget":{"type":"object","description":"Indicates the particular object and part of the object on which the annotation has been made","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/annotationTarget.json"},"oa:hasBody":{"type":"object","description":"The body of the annotation contains the specific value of the annotation","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/annotationBody.json"},"dcterms:creator":{"type":"object","description":"Contains information about the creator of the annotation","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"dcterms:created":{"type":"string","format":"date-time","description":"The date and time when the annotation was created, following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-09-02T12:31:34.806Z"]},"dcterms:modified":{"type":"string","format":"date-time","description":"The date and time when the annotation was last modified, generating a new version. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-10-02T12:31:34.806Z"]},"dcterms:issued":{"type":"string","format":"date-time","description":"The date and time when the annotation was generated. Generated is here seen as when the object was stored/indexed. In most case this will be the annotation-processing-service. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-09-02T13:31:34.806Z"]},"as:generator":{"type":"object","description":"Object containing information on who generated the object. Generated is here seen as who stored/indexed the object. In most case this will be the annotation-processing-service. Contains an ods:Agent object.","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"ods:hasAggregateRating":{"type":"object","description":"The average rating based on multiple ratings or reviews","properties":{"@type":{"type":"string","const":"schema:AggregateRating","description":"Indicates which type of aggregateRating we are using."},"schema:ratingCount":{"type":"integer","description":"The count of total number of ratings","minimum":0,"examples":[3]},"schema:ratingValue":{"type":"number","description":"The rating for the content","examples":[4.5]}},"required":["@type","schema:ratingCount","schema:ratingValue"],"additionalProperties":false},"ods:batchID":{"type":"string","format":"uuid","description":"Internally generated PID to identify the batch the annotation was generated by","examples":["123e4567-e89b-12d3-a456-426614174000"]},"ods:placeInBatch":{"type":"integer","description":"For batching only. Links annotation to batchMetadata provided in a batch event. If present, must correspond to an ods:placeInBatch in the batch metadata","examples":[1,5]},"ods:mergingDecisionStatus":{"type":"string","enum":["Pending","Rejected","Approved"],"description":"The merging status of the annotation. Only present when motivation is ods:adding or oa:editing"},"ods:mergingStateChangeDate":{"type":"string","format":"date-time","description":"The date and time when the annotation was merging state was changed. Only present when motivation is ods:adding or oa:editing. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX"},"ods:hasMergingStateChangedBy":{"type":"object","description":"Object containing information on who changed the merging state of the annotation. Only present when motivation is ods:adding or oa:editing. Contains an ods:Agent object.","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"ods:hasTombstoneMetadata":{"type":"object","description":"Object containing the tombstone metadata of the object. Only present when ods:status is ods:Tombstone","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/tombstoneMetadata.json"}},"required":["@id","@type","ods:ID","rdf:type","ods:version","oa:motivation","oa:hasTarget","oa:hasBody","dcterms:creator","dcterms:created","dcterms:modified","as:generator","dcterms:issued"],"additionalProperties":false} \ No newline at end of file +{"$id":"https://schemas.dissco.tech/schemas/fdo-type/annotation/0.4.0/annotation.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Annotation Version 0.4.0","title":"Annotation","description":"Information about the Annotation data model. This model has been based on the W3C Web Annotation model","type":"object","properties":{"@id":{"type":"string","description":"The unique identifier (handle) of the Annotation object","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"@type":{"type":"string","description":"The type of the object, in this case ods:Annotation","const":"ods:Annotation"},"dcterms:identifier":{"type":"string","description":"The handle of the annotation. It is a unique identifier for the annotation. It is composed of the handle of the document followed by a slash and a unique identifier for the annotation.","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"ods:fdoType":{"type":"string","description":"The DOI to the FDO type of the object","pattern":"^https://doi\\.org/[\\w\\.]+/[\\w\\.]+","examples":["https://doi.org/21.T11148/bbad8c4e101e8af01115","https://doi.org/21.T11148/894b1e6cad57e921764e"]},"ods:status":{"enum":["Draft","Active","Tombstone"],"description":"The status of the Digital Object. A digital object can be in Draft, when it is not published yet. Active when it is published and the object is active and Tombstone which means the object has been archived."},"ods:jobID":{"type":"string","description":"Handle of the job record, if the annotation was produced by a Machine Annotation Service, only filled when annotation was created by a MAS","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/XXX-XXX-XXX"]},"ods:version":{"type":"integer","description":"The version of the object, each change generates a new version. The version starts at 1 and each change will increment the version number with 1","minimum":1,"examples":[1,3,5]},"oa:motivation":{"description":"The motivation for why an annotation was proposed. Based on a selection of https://www.w3.org/TR/annotation-model/#motivation-and-purpose. The motivation ods:adding and ods:deleting are added for DiSSCo's purposes.","enum":["ods:adding","ods:deleting","oa:assessing","oa:editing","oa:commenting"]},"oa:motivatedBy":{"type":"string","description":"Describes the reason for the annotation","examples":["The country is incorrect","Identified a new link to a record in ENA"]},"oa:hasTarget":{"type":"object","description":"Indicates the particular object and part of the object on which the annotation has been made","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/annotationTarget.json"},"oa:hasBody":{"type":"object","description":"The body of the annotation contains the specific value of the annotation","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/annotationBody.json"},"dcterms:creator":{"type":"object","description":"Contains information about the creator of the annotation","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"dcterms:created":{"type":"string","format":"date-time","description":"The date and time when the annotation was created, following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-09-02T12:31:34.806Z"]},"dcterms:modified":{"type":"string","format":"date-time","description":"The date and time when the annotation was last modified, generating a new version. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-10-02T12:31:34.806Z"]},"dcterms:issued":{"type":"string","format":"date-time","description":"The date and time when the annotation was generated. Generated is here seen as when the object was stored/indexed. In most case this will be the annotation-processing-service. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-09-02T13:31:34.806Z"]},"as:generator":{"type":"object","description":"Object containing information on who generated the object. Generated is here seen as who stored/indexed the object. In most case this will be the annotation-processing-service. Contains an ods:Agent object.","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"ods:hasAggregateRating":{"type":"object","description":"The average rating based on multiple ratings or reviews","properties":{"@type":{"type":"string","const":"schema:AggregateRating","description":"Indicates which type of aggregateRating we are using."},"schema:ratingCount":{"type":"integer","description":"The count of total number of ratings","minimum":0,"examples":[3]},"schema:ratingValue":{"type":"number","description":"The rating for the content","examples":[4.5]}},"required":["@type","schema:ratingCount","schema:ratingValue"],"additionalProperties":false},"ods:batchID":{"type":"string","format":"uuid","description":"Internally generated PID to identify the batch the annotation was generated by","examples":["123e4567-e89b-12d3-a456-426614174000"]},"ods:placeInBatch":{"type":"integer","description":"For batching only. Links annotation to batchMetadata provided in a batch event. If present, must correspond to an ods:placeInBatch in the batch metadata","examples":[1,5]},"ods:mergingDecisionStatus":{"type":"string","enum":["Pending","Rejected","Approved"],"description":"The merging status of the annotation. Only present when motivation is ods:adding or oa:editing"},"ods:mergingStateChangeDate":{"type":"string","format":"date-time","description":"The date and time when the annotation was merging state was changed. Only present when motivation is ods:adding or oa:editing. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX"},"ods:hasMergingStateChangedBy":{"type":"object","description":"Object containing information on who changed the merging state of the annotation. Only present when motivation is ods:adding or oa:editing. Contains an ods:Agent object.","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"},"ods:hasTombstoneMetadata":{"type":"object","description":"Object containing the tombstone metadata of the object. Only present when ods:status is ods:Tombstone","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/tombstoneMetadata.json"}},"required":["@id","@type","dcterms:identifier","rdf:type","ods:version","oa:motivation","oa:hasTarget","oa:hasBody","dcterms:creator","dcterms:created","dcterms:modified","as:generator","dcterms:issued"],"additionalProperties":false} \ No newline at end of file diff --git a/src/sources/dataModel/chronometricAge.json b/src/sources/dataModel/chronometricAge.json index f737bcde..89d09739 100644 --- a/src/sources/dataModel/chronometricAge.json +++ b/src/sources/dataModel/chronometricAge.json @@ -1 +1 @@ -{"$id":"https://schemas.dissco.tech/schemas/fdo-type/digital-specimen/0.4.0/chronometric-age.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Chronometric Age Version 0.4.0","title":"ChronometricAge","type":"object","properties":{"@id":{"type":"string","description":"The identifier for the Chronometric Age object."},"@type":{"type":"string","const":"ods:ChronometricAge","description":"The type of the digital object, in this case ods:ChronometricAge"},"chrono:chronometricAgeID":{"type":"string","description":"An identifier for the set of information associated with a ChronometricAge","examples":["https://www.canadianarchaeology.ca/samples/70673"]},"chrono:verbatimChronometricAge":{"type":"string","description":"The verbatim age for a specimen, whether reported by a dating assay, associated references, or legacy information","examples":["27 BC to 14 AD","250 AD"]},"chrono:uncalibratedChronometricAge":{"type":"string","description":"The output of a dating assay before it is calibrated into an age using a specific conversion protocol.","examples":["1510 +/- 25 14C yr BP","16.26 Ma +/- 0.016"]},"chrono:chronometricAgeConversionProtocol":{"type":"string","description":"The method used for converting the uncalibratedChronometricAge into a chronometric age in years, as captured in the earliestChronometricAge, earliestChronometricAgeReferenceSystem, latestChronometricAge, and latestChronometricAgeReferenceSystem fields.","examples":["INTCAL13","sequential 6 phase Bayesian model and IntCal13 calibration"]},"chrono:earliestChronometricAge":{"type":"integer","description":"The maximum/earliest/oldest possible age of a specimen as determined by a dating method","examples":[100,1200]},"chrono:earliestChronometricAgeReferenceSystem":{"type":"string","description":"The reference system associated with the earliestChronometricAge","examples":["BP","AD"]},"chrono:latestChronometricAge":{"type":"integer","description":"The minimum/latest/youngest possible age of a specimen as determined by a dating method","examples":[12,540]},"chrono:latestChronometricAgeReferenceSystem":{"type":"string","description":"The reference system associated with the latestChronometricAge","examples":["BCE","BP"]},"chrono:chronometricAgeUncertaintyInYears":{"type":"integer","description":"The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years","examples":[100,1200]},"chrono:chronometricAgeUncertaintyMethod":{"type":"string","description":"The method used to generate the value of chronometricAgeUncertaintyInYears","examples":["2-sigma calibrated range","Half of 95% confidence interval"]},"chrono:materialDated":{"type":"string","description":"A description of the material on which the chronometricAgeProtocol was actually performed, if known.","examples":["Charred wood","Tooth"]},"chrono:materialDatedID":{"type":"string","description":"An identifier for the MaterialSample on which the chronometricAgeProtocol was performed, if applicable","examples":["https://doi.org/10.22/XXX-XXX-XXX","https://www.ebi.ac.uk/metagenomics/samples/SRS1930158"]},"chrono:materialDatedRelationship":{"type":"string","description":"The relationship of the materialDated to the subject of the ChronometricAge record, from which the ChronometricAge of the subject is inferred","examples":["sameAs","inContextWith"]},"chrono:chronometricAgeDeterminedDate":{"type":"string","description":"The date on which the ChronometricAge was determined","examples":["2018-11-13T20:20:39+00:00","1906-06"]},"chrono:chronometricAgeReferences":{"type":"string","description":"A list (concatenated and separated) of identifiers (publication, bibliographic reference, global unique identifier, URI) of literature associated with the ChronometricAge.","examples":["https://doi.org/10.1007/s10814-019-09140-x"]},"chrono:chronometricAgeRemarks":{"type":"string","description":"Notes or comments about the ChronometricAge","examples":["Beta Analytic number: 323913"]}},"ods:hasAgents":{"type":"array","description":"The agent(s) involved in the determination of the chronometric age, uses `ods:Agent`","items":{"type":"object","$ref":"https://schemas.dissco.tech/schemas/fdo-type/shared-model/0.4.0/agent.json"}},"required":["@type"],"additionalProperties":false} \ No newline at end of file +{"$id":"https://schemas.dissco.tech/schemas/fdo-type/digital-specimen/0.4.0/chronometric-age.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Chronometric Age Version 0.4.0","title":"ChronometricAge","type":"object","properties":{"@id":{"type":"string","description":"The identifier for the Chronometric Age object."},"@type":{"type":"string","const":"ods:ChronometricAge","description":"The type of the digital object, in this case ods:ChronometricAge"},"chrono:chronometricAgeID":{"type":"string","description":"An identifier for the set of information associated with a ChronometricAge","examples":["https://www.canadianarchaeology.ca/samples/70673"]},"chrono:verbatimChronometricAge":{"type":"string","description":"The verbatim age for a specimen, whether reported by a dating assay, associated references, or legacy information","examples":["27 BC to 14 AD","250 AD"]},"chrono:uncalibratedChronometricAge":{"type":"string","description":"The output of a dating assay before it is calibrated into an age using a specific conversion protocol.","examples":["1510 +/- 25 14C yr BP","16.26 Ma +/- 0.016"]},"chrono:chronometricAgeConversionProtocol":{"type":"string","description":"The method used for converting the uncalibratedChronometricAge into a chronometric age in years, as captured in the earliestChronometricAge, earliestChronometricAgeReferenceSystem, latestChronometricAge, and latestChronometricAgeReferenceSystem fields.","examples":["INTCAL13","sequential 6 phase Bayesian model and IntCal13 calibration"]},"chrono:earliestChronometricAge":{"type":"integer","description":"The maximum/earliest/oldest possible age of a specimen as determined by a dating method","examples":[100,1200]},"chrono:earliestChronometricAgeReferenceSystem":{"type":"string","description":"The reference system associated with the earliestChronometricAge","examples":["BP","AD"]},"chrono:latestChronometricAge":{"type":"integer","description":"The minimum/latest/youngest possible age of a specimen as determined by a dating method","examples":[12,540]},"chrono:latestChronometricAgeReferenceSystem":{"type":"string","description":"The reference system associated with the latestChronometricAge","examples":["BCE","BP"]},"chrono:chronometricAgeProtocol":{"type":"string","description":"A description of or reference to the methods used to determine the chronometric age.","examples":["Radiocarbon dating","Uranium-series dating"]},"chrono:chronometricAgeUncertaintyInYears":{"type":"integer","description":"The temporal uncertainty of the earliestChronometricAge and latestChronometicAge in years","examples":[100,1200]},"chrono:chronometricAgeUncertaintyMethod":{"type":"string","description":"The method used to generate the value of chronometricAgeUncertaintyInYears","examples":["2-sigma calibrated range","Half of 95% confidence interval"]},"chrono:materialDated":{"type":"string","description":"A description of the material on which the chronometricAgeProtocol was actually performed, if known.","examples":["Charred wood","Tooth"]},"chrono:materialDatedID":{"type":"string","description":"An identifier for the MaterialSample on which the chronometricAgeProtocol was performed, if applicable","examples":["https://doi.org/10.22/XXX-XXX-XXX","https://www.ebi.ac.uk/metagenomics/samples/SRS1930158"]},"chrono:materialDatedRelationship":{"type":"string","description":"The relationship of the materialDated to the subject of the ChronometricAge record, from which the ChronometricAge of the subject is inferred","examples":["sameAs","inContextWith"]},"chrono:chronometricAgeDeterminedDate":{"type":"string","description":"The date on which the ChronometricAge was determined","examples":["2018-11-13T20:20:39+00:00","1906-06"]},"chrono:chronometricAgeReferences":{"type":"string","description":"A list (concatenated and separated) of identifiers (publication, bibliographic reference, global unique identifier, URI) of literature associated with the ChronometricAge.","examples":["https://doi.org/10.1007/s10814-019-09140-x"]},"chrono:chronometricAgeRemarks":{"type":"string","description":"Notes or comments about the ChronometricAge","examples":["Beta Analytic number: 323913"]},"ods:hasAgents":{"type":"array","description":"The agent(s) involved in the determination of the chronometric age, uses `ods:Agent`","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"}}},"required":["@type"],"additionalProperties":false} \ No newline at end of file diff --git a/src/sources/dataModel/digitalSpecimen.json b/src/sources/dataModel/digitalSpecimen.json index cfcb46b0..b82403df 100644 --- a/src/sources/dataModel/digitalSpecimen.json +++ b/src/sources/dataModel/digitalSpecimen.json @@ -1 +1 @@ -{"$id":"https://schemas.dissco.tech/schemas/digitalobjects/digital-specimen/0.4.0/digital-specimen.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Digital Specimen Version 0.4.0","title":"DigitalSpecimen","type":"object","properties":{"@id":{"type":"string","description":"The unique identifier of the Digital Specimen object, follows the Digital Object Identifier (DOI) standard","pattern":"^https://doi\\.org/[\\w\\.]+/(\\w){3}-(\\w){3}-(\\w){3}","examples":["https://doi.org/10.22/XXX-XXX-XXX"]},"@type":{"description":"The type of the object, in this case ods:DigitalSpecimen","const":"ods:DigitalSpecimen"},"dcterms:identifier":{"type":"string","description":"The unique identifier of the Digital Specimen object, follows the Digital Object Identifier (DOI) standard.","pattern":"^https://doi\\.org/[\\w\\.]+/(\\w){3}-(\\w){3}-(\\w){3}","examples":["https://doi.org/10.3535/XXX-XXX-XXX"]},"ods:version":{"type":"integer","description":"The version of the object, each change generates a new version. The version starts at 1 and each change will increment the version number with 1","minimum":1,"examples":[1]},"ods:status":{"type":"string","enum":["Draft","Active","Tombstone"],"description":"The status of the Digital Object. A digital object can be in Draft, when it is not published yet. Active when it is published and the object is active and Tombstone which means the object has been archived."},"dcterms:modified":{"type":"string","description":"The timestamp that the object was last changed, which resulted in a new version of the object. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-10-02T12:31:34.806Z"]},"dcterms:created":{"type":"string","description":"The timestamp that the object was created in DiSSCo. following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX\"","format":"date-time","examples":["2023-10-02T12:31:34.806Z"]},"ods:fdoType":{"type":"string","description":"The DOI to the FDO type of the object","pattern":"^https://doi\\.org/[\\w\\.]+/[\\w\\.]+","examples":["https://doi.org/21.T11148/bbad8c4e101e8af01115","https://doi.org/21.T11148/894b1e6cad57e921764e"]},"ods:midsLevel":{"type":"integer","description":"The level of the Minimum Information about a Digital Specimen of the object, for the full specification see https://www.tdwg.org/community/cd/mids/","minimum":0,"maximum":3},"ods:normalisedPhysicalSpecimenID":{"type":"string","description":"The physical specimen identifier of the object. When locally unique this is a combination between source-system-id and the local identifier. This identifier is used to check if an object exists in the DiSSCo infrastructure when the DOI is not available.","examples":["NHMD193630:040ck2b86","https://data.biodiversitydata.nl/naturalis/specimen/RGM.234626"]},"ods:physicalSpecimenID":{"type":"string","description":"The physical specimen identifier of the object. The main identifier of the object is used (which can be indicated by the user through the DataMapping). If the ods:physicalSpecimenIDType is Resolvable or Global, this identifier is the same as the `ods:normalisedPhysicalSpecimenID`","examples":["https://hdl.handle.net/20.500.12000/1","NHMD193630","https://data.biodiversitydata.nl/naturalis/specimen/RGM.234626"]},"ods:physicalSpecimenIDType":{"type":"string","description":"To indicate if type of the physical identifier, Resolvable means a resolvable identifier over the internet such as a PURL, Global means a globally unique identifier such as a UUID, Local means a locally identifier unique only within the dataset.","enum":["Resolvable","Global","Local"]},"ods:isKnownToContainMedia":{"type":"boolean","description":"Indicates if there are any media objects attached to this specimen","examples":[true]},"ods:sourceSystemID":{"type":"string","description":"The handle to the source system object which retrieved the data from the CMS","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/0Z6-P2P-VR5","https://hdl.handle.net/20.5000.1025/24P-6R9-JQ5"]},"ods:sourceSystemName":{"type":"string","description":"The name of the source system as provided to DiSSCo","examples":["Naturalis Biodiversity Center (NL) - Vermes","Chelicerata collection (TSZCh) The Arctic University Museum of Norway"]},"ods:livingOrPreserved":{"description":"Whether the specimen is living or preserved","enum":["Living","Preserved"]},"ods:metadataLanguages":{"type":"array","description":"The language of the Digital Specimen metadata. Only indicate, not enforced. Recommended to use three letter code from ISO 639-2 codes found on https://id.loc.gov/vocabulary/iso639-2.html","items":{"type":"string"},"examples":[["eng","fra","deu"],["dut"]]},"dcterms:license":{"type":"string","description":"A legal document giving official permission to do something with the resource.","examples":["https://creativecommons.org/licenses/by/4.0/","https://creativecommons.org/licenses/by-nc-sa/4.0/"]},"dwc:basisOfRecord":{"type":"string","description":"The specific nature of the data record","examples":["PreservedSpecimen","FossilSpecimen"]},"ods:organisationCode":{"type":"string","description":"The name (or acronym) in use by the institution having custody of the object(s) or information referred to in the record.","examples":["MNF","MNHN"]},"ods:organisationID":{"type":"string","description":"ROR or Wikidata identifier of the organisation","pattern":"^(https?://ror\\.org/0\\w{6}[0-9]{2})|^(https?://www\\.wikidata\\.org/wiki/Q\\w+)","examples":["https://ror.org/015hz7p22","https://www.wikidata.org/wiki/Q641676","https://ror.org/03wkt5x30"]},"ods:organisationName":{"type":"string","description":"Primary organisation name according to ROR or Wikidata","examples":["National Museum of Natural History","Tallinn University of Technology","Muséum national d'Histoire naturelle"]},"dwc:collectionCode":{"type":"string","description":"The name, acronym, coden, or initialism identifying the collection or data set from which the record was derived","examples":["Mammals","EBIRD"]},"dwc:collectionID":{"type":"string","description":"An identifier for the collection or dataset from which the record was derived","examples":["https://www.gbif.org/grscicoll/collection/fbd3ed74-5a21-4e01-b86a-33d36f032d9c"]},"ods:topicOrigin":{"type":"string","description":"Highest-level terms identifying the fundamentals of the activities, in which context the objects in the collection were collected","enum":["Natural","Human-made","Mixed origin","Unclassified"],"examples":["Natural"]},"ods:topicDomain":{"type":"string","description":"High-level terms providing general domain information with which the objects are associated","enum":["Life","Environment","Earth System","Extraterrestrial","Cultural Artefacts","Archive Material","Unclassified"],"examples":["Life"]},"ods:topicDiscipline":{"type":"string","description":"Overarching classification of the scientific discipline to which the objects within the collection belong or are related","enum":["Anthropology","Botany","Astrogeology","Geology","Microbiology","Palaeontology","Zoology","Ecology","Other Biodiversity","Other Geodiversity","Unclassified"],"examples":["Botany"]},"ods:topicCategory":{"type":"string","description":"Countable things (objects) served as a more detailed classification of each of the disciplines","examples":["Protozoa","Bryophytes","Water-ice sample"]},"ods:specimenName":{"type":"string","description":"The accepted specimen name of the digital specimen","examples":["Roptrocerus typographi (Györfi, 1952)"]},"dwc:informationWithheld":{"type":"string","description":"Additional information that exists, but that has not been shared in the given record","examples":["location information not given for endangered species"]},"dwc:preparations":{"type":"string","description":"A list (concatenated and separated) of preparations and preservation methods for a ods:SpecimenPart","examples":["fossil","herbrarium sheet"]},"dwc:disposition":{"type":"string","description":"The current state of a specimen with respect to a collection","examples":["in collection","destroyed"]},"ods:isMarkedAsType":{"type":"boolean","description":"The material entity is marked as a type specimen"},"dwc:dataGeneralizations":{"type":"string","description":"Actions taken to make the shared data less specific or complete than in its original form. Suggests that alternative data of higher quality may be available on request","examples":["Coordinates generalized from original GPS coordinates to the nearest half degree grid cell."]},"ods:ownerOrganisationCode":{"type":"string","description":"The name (or acronym) in use by the institution having ownership of the object(s) or information referred to in the record","examples":["APN","InBio"]},"dwc:datasetName":{"type":"string","description":"The name identifying the data set from which the record was derived","examples":["Hummingbirds","Naturalis Biodiversity Center (NL) - Paleontology"]},"dwc:datasetID":{"type":"string","description":"An identifier for the set of data. May be a global unique identifier or an identifier specific to a collection or institution","examples":["b15d4952-7d20-46f1-8a3e-556a512b04c5"]},"dcterms:accessRights":{"type":"string","description":"Information about who access the resource or an indication of its security status. Access Rights may include information regarding access or restrictions based on privacy, security, or other policies","examples":["not-for-profit use only"]},"dcterms:rightsHolder":{"type":"string","description":"A person or organization owning or managing rights over the resource","examples":["Museu de História Natural e da Ciência da Universidade do Porto"]},"dwc:organismID":{"type":"string","description":"An identifier for the organism instance. May be a globally unique identifier or an identifier specific to the data set","examples":["http://arctos.database.museum/guid/WNMU:Mamm:1249"]},"dwc:organismName":{"type":"string","description":"A textual name or label assigned to an organism instance","examples":["Boab Prison Tree","J pod"]},"dwc:organismScope":{"type":"string","description":"A description of the kind of organism instance. Can be used to indicate whether the organism instance represents a discrete organism or if it represents a particular type of aggregation","examples":["colony","pack"]},"dwc:organismRemarks":{"type":"string","description":"Comments or notes about the organism","examples":["One of a litter of six","Organism has been split up into multiple specimen, some of which are in different institutions"]},"dwc:organismQuantity":{"type":"string","description":"A number or enumeration value for the quantity of organisms","examples":["27","12.5"]},"dwc:organismQuantityType":{"type":"string","description":"A dwc:organismQuantityType must have a corresponding dwc:organismQuantity","examples":["individuals","% biomass"]},"dwc:verbatimLabel":{"type":"string","description":"The content of this term should include no embellishments, prefixes, headers or other additions made to the text. Abbreviations must not be expanded and supposed misspellings must not be corrected. Lines or breakpoints between blocks of text that could be verified by seeing the original labels or images of them may be used. Examples of material entities include preserved specimens, fossil specimens, and material samples. Best practice is to use UTF-8 for all characters","examples":["ILL: Union Co. Wolf Lake by Powder Plant Bridge. 1 March 1975 Coll. S. Ketzler, S. Herbert\n\nMonotoma longicollis 4 ♂ Det TC McElrath 2018\n\nINHS Insect Collection 456782"]},"dwc:dynamicProperties":{"type":"string","description":"A list of additional measurements, facts, characteristics, or assertions about the record. Meant to provide a mechanism for structured content","examples":["{\"relativeHumidity\": 28,\"airTemperatureInCelsius\": 22}"]},"ods:hasSpecimenParts":{"type":"array","description":"Contains all specimen parts that are part of this Digital Specimen based on for example a shared registration number","minItems":0,"items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/specimenPart.json"}},"ods:hasAssertions":{"type":"array","description":"Contains any assertions that can be made about the specimen, such as measurements","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/assertion.json"}},"ods:hasEntityRelationships":{"type":"array","description":"Contains relationships to external resources that provide further information about the specimen, for example about the taxonomy or the organisation","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/entityRelationship.json"}},"ods:hasIdentifications":{"type":"array","description":"Contains all identification that have been made on the specimen","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/identification.json"}},"ods:hasIdentifiers":{"type":"array","description":"Contains all identifiers that are connected to the specimen, either about the physical or digital specimen","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/identifier.json"}},"ods:hasCitations":{"type":"array","description":"Contains information about any publication in which this specimen is mentioned","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/citation.json"}},"ods:hasAgents":{"type":"array","description":"Contains all agents that are connected to the specimen. Agents that are part of a specific part of the specimen should be added there. For example a Collector is connected to the CollectingEvent so is add in the event","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"}},"ods:hasEvents":{"type":"array","description":"Contains information about any events that occurred specifically on the specimen part, for example a sampling event","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/event.json"}},"ods:hasTombstoneMetadata":{"type":"object","description":"Object containing the tombstone metadata of the object. Only present when ods:status is ods:Tombstone","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/tombstoneMetadata.json"}},"required":["@id","@type","dcterms:identifier","ods:version","ods:fdoType","dcterms:created","dcterms:modified","ods:midsLevel","ods:normalisedPhysicalSpecimenID","ods:physicalSpecimenID","ods:physicalSpecimenIDType","ods:sourceSystemID","ods:organisationID"],"additionalProperties":false} \ No newline at end of file +{"$id":"https://schemas.dissco.tech/schemas/digitalobjects/digital-specimen/0.4.0/digital-specimen.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Digital Specimen Version 0.4.0","title":"DigitalSpecimen","type":"object","properties":{"@id":{"type":"string","description":"The unique identifier of the Digital Specimen object, follows the Digital Object Identifier (DOI) standard","pattern":"^https://doi\\.org/[\\w\\.]+/(\\w){3}-(\\w){3}-(\\w){3}","examples":["https://doi.org/10.22/XXX-XXX-XXX"]},"@type":{"description":"The type of the object, in this case ods:DigitalSpecimen","const":"ods:DigitalSpecimen"},"dcterms:identifier":{"type":"string","description":"The unique identifier of the Digital Specimen object, follows the Digital Object Identifier (DOI) standard.","pattern":"^https://doi\\.org/[\\w\\.]+/(\\w){3}-(\\w){3}-(\\w){3}","examples":["https://doi.org/10.3535/XXX-XXX-XXX"]},"ods:version":{"type":"integer","description":"The version of the object, each change generates a new version. The version starts at 1 and each change will increment the version number with 1","minimum":1,"examples":[1]},"ods:status":{"type":"string","enum":["Draft","Active","Tombstone"],"description":"The status of the Digital Object. A digital object can be in Draft, when it is not published yet. Active when it is published and the object is active and Tombstone which means the object has been archived."},"dcterms:modified":{"type":"string","description":"The timestamp that the object was last changed, which resulted in a new version of the object. Following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX","examples":["2023-10-02T12:31:34.806Z"]},"dcterms:created":{"type":"string","description":"The timestamp that the object was created in DiSSCo. following the ISO Date Time Format yyyy-MM-dd'T'HH:mm:ss.SSSXXX\"","format":"date-time","examples":["2023-10-02T12:31:34.806Z"]},"ods:fdoType":{"type":"string","description":"The DOI to the FDO type of the object","pattern":"^https://doi\\.org/[\\w\\.]+/[\\w\\.]+","examples":["https://doi.org/21.T11148/bbad8c4e101e8af01115","https://doi.org/21.T11148/894b1e6cad57e921764e"]},"ods:midsLevel":{"type":"integer","description":"The level of the Minimum Information about a Digital Specimen of the object, for the full specification see https://www.tdwg.org/community/cd/mids/","minimum":0,"maximum":3},"ods:normalisedPhysicalSpecimenID":{"type":"string","description":"The physical specimen identifier of the object. When locally unique this is a combination between source-system-id and the local identifier. This identifier is used to check if an object exists in the DiSSCo infrastructure when the DOI is not available.","examples":["NHMD193630:040ck2b86","https://data.biodiversitydata.nl/naturalis/specimen/RGM.234626"]},"ods:physicalSpecimenID":{"type":"string","description":"The physical specimen identifier of the object. The main identifier of the object is used (which can be indicated by the user through the DataMapping). If the ods:physicalSpecimenIDType is Resolvable or Global, this identifier is the same as the `ods:normalisedPhysicalSpecimenID`","examples":["https://hdl.handle.net/20.500.12000/1","NHMD193630","https://data.biodiversitydata.nl/naturalis/specimen/RGM.234626"]},"ods:physicalSpecimenIDType":{"type":"string","description":"To indicate if type of the physical identifier, Resolvable means a resolvable identifier over the internet such as a PURL, Global means a globally unique identifier such as a UUID, Local means a locally identifier unique only within the dataset.","enum":["Resolvable","Global","Local"]},"ods:isKnownToContainMedia":{"type":"boolean","description":"Indicates if there are any media objects attached to this specimen","examples":[true]},"ods:sourceSystemID":{"type":"string","description":"The handle to the source system object which retrieved the data from the CMS","pattern":"^https://hdl\\.handle\\.net/[\\w.]+/(.){3}-(.){3}-(.){3}","examples":["https://hdl.handle.net/20.5000.1025/0Z6-P2P-VR5","https://hdl.handle.net/20.5000.1025/24P-6R9-JQ5"]},"ods:sourceSystemName":{"type":"string","description":"The name of the source system as provided to DiSSCo","examples":["Naturalis Biodiversity Center (NL) - Vermes","Chelicerata collection (TSZCh) The Arctic University Museum of Norway"]},"ods:livingOrPreserved":{"description":"Whether the specimen is living or preserved","enum":["Living","Preserved"]},"ods:metadataLanguages":{"type":"array","description":"The language of the Digital Specimen metadata. Only indicate, not enforced. Recommended to use three letter code from ISO 639-2 codes found on https://id.loc.gov/vocabulary/iso639-2.html","items":{"type":"string"},"examples":[["eng","fra","deu"],["dut"]]},"dcterms:license":{"type":"string","description":"A legal document giving official permission to do something with the resource.","examples":["https://creativecommons.org/licenses/by/4.0/","https://creativecommons.org/licenses/by-nc-sa/4.0/"]},"dwc:basisOfRecord":{"type":"string","description":"The specific nature of the data record","examples":["PreservedSpecimen","FossilSpecimen"]},"ods:organisationCode":{"type":"string","description":"The name (or acronym) in use by the institution having custody of the object(s) or information referred to in the record.","examples":["MNF","MNHN"]},"ods:organisationID":{"type":"string","description":"ROR or Wikidata identifier of the organisation","pattern":"^(https?://ror\\.org/0\\w{6}[0-9]{2})|^(https?://www\\.wikidata\\.org/wiki/Q\\w+)","examples":["https://ror.org/015hz7p22","https://www.wikidata.org/wiki/Q641676","https://ror.org/03wkt5x30"]},"ods:organisationName":{"type":"string","description":"Primary organisation name according to ROR or Wikidata","examples":["National Museum of Natural History","Tallinn University of Technology","Muséum national d'Histoire naturelle"]},"dwc:collectionCode":{"type":"string","description":"The name, acronym, coden, or initialism identifying the collection or data set from which the record was derived","examples":["Mammals","EBIRD"]},"dwc:collectionID":{"type":"string","description":"An identifier for the collection or dataset from which the record was derived","examples":["https://www.gbif.org/grscicoll/collection/fbd3ed74-5a21-4e01-b86a-33d36f032d9c"]},"ods:topicOrigin":{"type":"string","description":"Highest-level terms identifying the fundamentals of the activities, in which context the objects in the collection were collected","enum":["Natural","Human-made","Mixed origin","Unclassified"],"examples":["Natural"]},"ods:topicDomain":{"type":"string","description":"High-level terms providing general domain information with which the objects are associated","enum":["Life","Environment","Earth System","Extraterrestrial","Cultural Artefacts","Archive Material","Unclassified"],"examples":["Life"]},"ods:topicDiscipline":{"type":"string","description":"Overarching classification of the scientific discipline to which the objects within the collection belong or are related","enum":["Anthropology","Botany","Astrogeology","Geology","Microbiology","Palaeontology","Zoology","Ecology","Other Biodiversity","Other Geodiversity","Unclassified"],"examples":["Botany"]},"ods:topicCategory":{"type":"string","description":"Countable things (objects) served as a more detailed classification of each of the disciplines","examples":["Protozoa","Bryophytes","Water-ice sample"]},"ods:specimenName":{"type":"string","description":"The accepted specimen name of the digital specimen","examples":["Roptrocerus typographi (Györfi, 1952)"]},"dwc:informationWithheld":{"type":"string","description":"Additional information that exists, but that has not been shared in the given record","examples":["location information not given for endangered species"]},"dwc:preparations":{"type":"string","description":"A list (concatenated and separated) of preparations and preservation methods for a ods:SpecimenPart","examples":["fossil","herbrarium sheet"]},"dwc:disposition":{"type":"string","description":"The current state of a specimen with respect to a collection","examples":["in collection","destroyed"]},"ods:isMarkedAsType":{"type":"boolean","description":"The material entity is marked as a type specimen"},"dwc:dataGeneralizations":{"type":"string","description":"Actions taken to make the shared data less specific or complete than in its original form. Suggests that alternative data of higher quality may be available on request","examples":["Coordinates generalized from original GPS coordinates to the nearest half degree grid cell."]},"ods:ownerOrganisationCode":{"type":"string","description":"The name (or acronym) in use by the institution having ownership of the object(s) or information referred to in the record","examples":["APN","InBio"]},"dwc:datasetName":{"type":"string","description":"The name identifying the data set from which the record was derived","examples":["Hummingbirds","Naturalis Biodiversity Center (NL) - Paleontology"]},"dwc:datasetID":{"type":"string","description":"An identifier for the set of data. May be a global unique identifier or an identifier specific to a collection or institution","examples":["b15d4952-7d20-46f1-8a3e-556a512b04c5"]},"dcterms:accessRights":{"type":"string","description":"Information about who access the resource or an indication of its security status. Access Rights may include information regarding access or restrictions based on privacy, security, or other policies","examples":["not-for-profit use only"]},"dcterms:rightsHolder":{"type":"string","description":"A person or organization owning or managing rights over the resource","examples":["Museu de História Natural e da Ciência da Universidade do Porto"]},"dwc:organismID":{"type":"string","description":"An identifier for the organism instance. May be a globally unique identifier or an identifier specific to the data set","examples":["http://arctos.database.museum/guid/WNMU:Mamm:1249"]},"dwc:organismName":{"type":"string","description":"A textual name or label assigned to an organism instance","examples":["Boab Prison Tree","J pod"]},"dwc:organismScope":{"type":"string","description":"A description of the kind of organism instance. Can be used to indicate whether the organism instance represents a discrete organism or if it represents a particular type of aggregation","examples":["colony","pack"]},"dwc:organismRemarks":{"type":"string","description":"Comments or notes about the organism","examples":["One of a litter of six","Organism has been split up into multiple specimen, some of which are in different institutions"]},"dwc:organismQuantity":{"type":"string","description":"A number or enumeration value for the quantity of organisms","examples":["27","12.5"]},"dwc:organismQuantityType":{"type":"string","description":"A dwc:organismQuantityType must have a corresponding dwc:organismQuantity","examples":["individuals","% biomass"]},"dwc:verbatimLabel":{"type":"string","description":"The content of this term should include no embellishments, prefixes, headers or other additions made to the text. Abbreviations must not be expanded and supposed misspellings must not be corrected. Lines or breakpoints between blocks of text that could be verified by seeing the original labels or images of them may be used. Examples of material entities include preserved specimens, fossil specimens, and material samples. Best practice is to use UTF-8 for all characters","examples":["ILL: Union Co. Wolf Lake by Powder Plant Bridge. 1 March 1975 Coll. S. Ketzler, S. Herbert\n\nMonotoma longicollis 4 ♂ Det TC McElrath 2018\n\nINHS Insect Collection 456782"]},"dwc:dynamicProperties":{"type":"string","description":"A list of additional measurements, facts, characteristics, or assertions about the record. Meant to provide a mechanism for structured content","examples":["{\"relativeHumidity\": 28,\"airTemperatureInCelsius\": 22}"]},"ods:hasSpecimenParts":{"type":"array","description":"Contains all specimen parts that are part of this Digital Specimen based on for example a shared registration number","minItems":0,"items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/specimenPart.json"}},"ods:hasAssertions":{"type":"array","description":"Contains any assertions that can be made about the specimen, such as measurements","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/assertion.json"}},"ods:hasEntityRelationships":{"type":"array","description":"Contains relationships to external resources that provide further information about the specimen, for example about the taxonomy or the organisation","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/entityRelationship.json"}},"ods:hasIdentifications":{"type":"array","description":"Contains all identification that have been made on the specimen","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/identification.json"}},"ods:hasIdentifiers":{"type":"array","description":"Contains all identifiers that are connected to the specimen, either about the physical or digital specimen","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/identifier.json"}},"ods:hasCitations":{"type":"array","description":"Contains information about any publication in which this specimen is mentioned","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/citation.json"}},"ods:hasAgents":{"type":"array","description":"Contains all agents that are connected to the specimen. Agents that are part of a specific part of the specimen should be added there. For example a Collector is connected to the CollectingEvent so is add in the event","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/agent.json"}},"ods:hasEvents":{"type":"array","description":"Contains information about any events that occurred specifically on the specimen part, for example a sampling event","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/event.json"}},"ods:hasChronometricAges":{"type":"array","description":"Contains information about the chronometric age of the specimen part","items":{"type":"object","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/chronometricAge.json"}},"ods:hasTombstoneMetadata":{"type":"object","description":"Object containing the tombstone metadata of the object. Only present when ods:status is ods:Tombstone","$ref":"/home/tom/Documents/GitHub/disscover/src/sources/dataModel/tombstoneMetadata.json"}},"required":["@id","@type","dcterms:identifier","ods:version","ods:fdoType","dcterms:created","dcterms:modified","ods:midsLevel","ods:normalisedPhysicalSpecimenID","ods:physicalSpecimenID","ods:physicalSpecimenIDType","ods:sourceSystemID","ods:organisationID"],"additionalProperties":false} \ No newline at end of file diff --git a/src/sources/dataModel/taxonIdentification.json b/src/sources/dataModel/taxonIdentification.json index 519caf21..24503b50 100644 --- a/src/sources/dataModel/taxonIdentification.json +++ b/src/sources/dataModel/taxonIdentification.json @@ -1 +1 @@ -{"$id":"https://schemas.dissco.tech/schemas/fdo-type/digital-specimen/0.4.0/taxon-identification.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Taxon Identification object Version 0.4.0","title":"TaxonIdentification","type":"object","properties":{"@id":{"type":"string","description":"The identifier for the Taxon Identification object."},"@type":{"type":"string","const":"ods:TaxonIdentification","description":"The type of the digital object, in this case a ods:TaxonIdentification"},"dwc:taxonID":{"type":"string","description":"An identifier for the set of dwc:Taxon information. May be a global unique identifier or an identifier specific to the data set","examples":["https://www.catalogueoflife.org/data/taxon/5TXLM","https://www.catalogueoflife.org/data/taxon/6J6FX"]},"dwc:scientificName":{"type":"string","description":"The full scientific name, with authorship and date information if known. This should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the dwc:identificationQualifier term","examples":["Roptrocerus typographi (Györfi, 1952)","Alyssum strigosum Banks & Sol."]},"dwc:scientificNameID":{"type":"string","description":"An identifier for the nomenclatural (not taxonomic) details of a scientific name","examples":["urn:lsid:ipni.org:names:37829-1:1.3"]},"ods:scientificNameHTMLLabel":{"type":"string","description":"A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name.","examples":["Absidia ginsan Komin. et al., 1952","Alyssum strigosum Banks & Sol."]},"dwc:scientificNameAuthorship":{"type":"string","description":"The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode","examples":["(Torr.) J.T. Howell"]},"dwc:namePublishedInYear":{"type":"string","description":"The four-digit year in which the dwc:scientificName was published","examples":["1992","2022"]},"dwc:taxonRank":{"type":"string","description":"The taxonomic rank of the most specific name in the dwc:scientificName","examples":["species","genus"]},"dwc:verbatimTaxonRank":{"type":"string","description":"The taxonomic rank of the most specific name in the dwc:scientificName as it appears in the original record","examples":["Agamospecies","apomict"]},"dwc:taxonRemarks":{"type":"string","description":"Comments or notes about the taxon or name","examples":["This name is a misspelling in common use"]},"dwc:kingdom":{"type":"string","description":"The full scientific name of the kingdom in which the ods:TaxonIdentification is classified","examples":["animalia"]},"dwc:phylum":{"type":"string","description":"The full scientific name of the phylum or division in which the ods:TaxonIdentification is classified","examples":["Chordata"]},"dwc:class":{"type":"string","description":"The full scientific name of the class in which the ods:TaxonIdentification is classified","examples":["Hepaticopsida"]},"dwc:order":{"type":"string","description":"The full scientific name of the order in which the ods:TaxonIdentification is classified","examples":["Carnivora"]},"dwc:family":{"type":"string","description":"The full scientific name of the family in which the ods:TaxonIdentification is classified","examples":["Felidae"]},"dwc:subfamily":{"type":"string","description":"The full scientific name of the subfamily in which the ods:TaxonIdentification is classified","examples":["Orchidoideae"]},"dwc:genus":{"type":"string","description":"The full scientific name of the genus in which the ods:TaxonIdentification is classified","examples":["Puma"]},"dwc:specificEpithet":{"type":"string","description":"The name of the first or species epithet of the dwc:scientificName","examples":["concolor"]},"dwc:taxonomicStatus":{"type":"string","description":"The status of the use of the dwc:scientificName as a label for a taxon. Requires taxonomic opinion to define the scope of a ods:TaxonIdentification. Rules of priority then are used to define the taxonomic status of the nomenclature contained in that scope, combined with the experts opinion. It must be linked to a specific taxonomic reference that defines the concept","examples":["accepted"]},"dwc:nomenclaturalCode":{"type":"string","description":"The nomenclatural code (or codes in the case of an ambiregnal name) under which the dwc:scientificName is constructed","examples":["ICBN","BC"]},"dwc:vernacularName":{"type":"string","description":"A common or vernacular name","examples":["Meerval | Wels | Catfish | Silure glane | Wels | Waller | Siluro | Malle","American Eagle"]},"dwc:subgenus":{"type":"string","description":"The full scientific name of the subgenus in which the ods:TaxonIdentification is classified. Values should include the genus to avoid homonym confusion","examples":["Strobus","Pilosella"]},"dwc:acceptedNameUsage":{"type":"string","description":"The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) ods:TaxonIdentification","examples":["Flaccisagitta hexaptera (d'Orbigny, 1836)","Lysimachia arvensis subsp. arvensis","https://www.catalogueoflife.org/data/taxon/BPC8M"]},"dwc:acceptedNameUsageID":{"type":"string","description":"An identifier for the name usage (documented meaning of the name according to a source) of the currently valid (zoological) or accepted (botanical) taxon","examples":["https://www.catalogueoflife.org/data/taxon/6J6FX","https://www.catalogueoflife.org/data/taxon/BPC8M"]},"dwc:cultivarEpithet":{"type":"string","description":"Part of the name of a cultivar, cultivar group or grex that follows the dwc:scientificName","examples":["King Edward"]},"dwc:genericName":{"type":"string","description":"The genus part of the dwc:scientificName without authorship","examples":["Felis"]},"dwc:infragenericEpithet":{"type":"string","description":"The infrageneric part of a binomial name at ranks above species but below genus","examples":["Abacetillus"]},"dwc:infraspecificEpithet":{"type":"string","description":"The name of the lowest or terminal infraspecific epithet of the dwc:scientificName, excluding any rank designation","examples":["oxyadenia"]},"dwc:nomenclaturalStatus":{"type":"string","description":"The status related to the original publication of the name and its conformance to the relevant rules of nomenclature. It is based essentially on an algorithm according to the business rules of the code. It requires no taxonomic opinion","examples":["nom. illeg."]},"dwc:originalNameUsage":{"type":"string","description":"The taxon name, with authorship and date information if known, as it originally appeared when first established under the rules of the associated dwc:nomenclaturalCode. The basionym (botany) or basonym (bacteriology) of the dwc:scientificName or the senior/earlier homonym for replaced names","examples":["Pinus abies"]},"dwc:subtribe":{"type":"string","description":"The full scientific name of the subtribe in which the ods:TaxonIdentification is classified","examples":["Plotinini"]},"dwc:superfamily":{"type":"string","description":"The full scientific name of the superfamily in which the ods:TaxonIdentification is classified","examples":["Cerithioidea"]},"dwc:tribe":{"type":"string","description":"The full scientific name of the tribe in which the ods:TaxonIdentification is classified","examples":["Arethuseae"]}},"required":["@type","dwc:scientificName"],"additionalProperties":false} \ No newline at end of file +{"$id":"https://schemas.dissco.tech/schemas/fdo-type/digital-specimen/0.4.0/taxon-identification.json","$schema":"https://json-schema.org/draft/2020-12/schema","$comment":"Taxon Identification object Version 0.4.0","title":"TaxonIdentification","type":"object","properties":{"@id":{"type":"string","description":"The identifier for the Taxon Identification object."},"@type":{"type":"string","const":"ods:TaxonIdentification","description":"The type of the digital object, in this case a ods:TaxonIdentification"},"dwc:taxonID":{"type":"string","description":"An identifier for the set of dwc:Taxon information. May be a global unique identifier or an identifier specific to the data set","examples":["https://www.catalogueoflife.org/data/taxon/5TXLM","https://www.catalogueoflife.org/data/taxon/6J6FX"]},"dwc:scientificName":{"type":"string","description":"The full scientific name, with authorship and date information if known. This should be the name in lowest level taxonomic rank that can be determined. This term should not contain identification qualifications, which should instead be supplied in the dwc:identificationQualifier term","examples":["Roptrocerus typographi (Györfi, 1952)","Alyssum strigosum Banks & Sol."]},"dwc:scientificNameID":{"type":"string","description":"An identifier for the nomenclatural (not taxonomic) details of a scientific name","examples":["urn:lsid:ipni.org:names:37829-1:1.3"]},"ods:scientificNameHTMLLabel":{"type":"string","description":"A Hyper Text Markup Language (HTML) representation of the scientific name. Includes correct formatting of the name.","examples":["Absidia ginsan Komin. et al., 1952","Alyssum strigosum Banks & Sol."]},"ods:genusHTMLLabel":{"type":"string","description":"A Hyper Text Markup Language (HTML) representation of the genus name. Includes correct formatting of the name.","examples":["Absidia ginsan Komin. et al., 1952","Alyssum strigosum Banks & Sol."]},"dwc:scientificNameAuthorship":{"type":"string","description":"The authorship information for the dwc:scientificName formatted according to the conventions of the applicable dwc:nomenclaturalCode","examples":["(Torr.) J.T. Howell"]},"dwc:namePublishedInYear":{"type":"string","description":"The four-digit year in which the dwc:scientificName was published","examples":["1992","2022"]},"dwc:taxonRank":{"type":"string","description":"The taxonomic rank of the most specific name in the dwc:scientificName","examples":["species","genus"]},"dwc:verbatimTaxonRank":{"type":"string","description":"The taxonomic rank of the most specific name in the dwc:scientificName as it appears in the original record","examples":["Agamospecies","apomict"]},"dwc:taxonRemarks":{"type":"string","description":"Comments or notes about the taxon or name","examples":["This name is a misspelling in common use"]},"dwc:kingdom":{"type":"string","description":"The full scientific name of the kingdom in which the ods:TaxonIdentification is classified","examples":["animalia"]},"dwc:phylum":{"type":"string","description":"The full scientific name of the phylum or division in which the ods:TaxonIdentification is classified","examples":["Chordata"]},"dwc:class":{"type":"string","description":"The full scientific name of the class in which the ods:TaxonIdentification is classified","examples":["Hepaticopsida"]},"dwc:order":{"type":"string","description":"The full scientific name of the order in which the ods:TaxonIdentification is classified","examples":["Carnivora"]},"dwc:family":{"type":"string","description":"The full scientific name of the family in which the ods:TaxonIdentification is classified","examples":["Felidae"]},"dwc:subfamily":{"type":"string","description":"The full scientific name of the subfamily in which the ods:TaxonIdentification is classified","examples":["Orchidoideae"]},"dwc:genus":{"type":"string","description":"The full scientific name of the genus in which the ods:TaxonIdentification is classified","examples":["Puma"]},"dwc:specificEpithet":{"type":"string","description":"The name of the first or species epithet of the dwc:scientificName","examples":["concolor"]},"dwc:taxonomicStatus":{"type":"string","description":"The status of the use of the dwc:scientificName as a label for a taxon. Requires taxonomic opinion to define the scope of a ods:TaxonIdentification. Rules of priority then are used to define the taxonomic status of the nomenclature contained in that scope, combined with the experts opinion. It must be linked to a specific taxonomic reference that defines the concept","examples":["accepted"]},"dwc:nomenclaturalCode":{"type":"string","description":"The nomenclatural code (or codes in the case of an ambiregnal name) under which the dwc:scientificName is constructed","examples":["ICBN","BC"]},"dwc:vernacularName":{"type":"string","description":"A common or vernacular name","examples":["Meerval | Wels | Catfish | Silure glane | Wels | Waller | Siluro | Malle","American Eagle"]},"dwc:subgenus":{"type":"string","description":"The full scientific name of the subgenus in which the ods:TaxonIdentification is classified. Values should include the genus to avoid homonym confusion","examples":["Strobus","Pilosella"]},"dwc:acceptedNameUsage":{"type":"string","description":"The full name, with authorship and date information if known, of the currently valid (zoological) or accepted (botanical) ods:TaxonIdentification","examples":["Flaccisagitta hexaptera (d'Orbigny, 1836)","Lysimachia arvensis subsp. arvensis","https://www.catalogueoflife.org/data/taxon/BPC8M"]},"dwc:acceptedNameUsageID":{"type":"string","description":"An identifier for the name usage (documented meaning of the name according to a source) of the currently valid (zoological) or accepted (botanical) taxon","examples":["https://www.catalogueoflife.org/data/taxon/6J6FX","https://www.catalogueoflife.org/data/taxon/BPC8M"]},"dwc:cultivarEpithet":{"type":"string","description":"Part of the name of a cultivar, cultivar group or grex that follows the dwc:scientificName","examples":["King Edward"]},"dwc:genericName":{"type":"string","description":"The genus part of the dwc:scientificName without authorship","examples":["Felis"]},"dwc:infragenericEpithet":{"type":"string","description":"The infrageneric part of a binomial name at ranks above species but below genus","examples":["Abacetillus"]},"dwc:infraspecificEpithet":{"type":"string","description":"The name of the lowest or terminal infraspecific epithet of the dwc:scientificName, excluding any rank designation","examples":["oxyadenia"]},"dwc:nomenclaturalStatus":{"type":"string","description":"The status related to the original publication of the name and its conformance to the relevant rules of nomenclature. It is based essentially on an algorithm according to the business rules of the code. It requires no taxonomic opinion","examples":["nom. illeg."]},"dwc:originalNameUsage":{"type":"string","description":"The taxon name, with authorship and date information if known, as it originally appeared when first established under the rules of the associated dwc:nomenclaturalCode. The basionym (botany) or basonym (bacteriology) of the dwc:scientificName or the senior/earlier homonym for replaced names","examples":["Pinus abies"]},"dwc:subtribe":{"type":"string","description":"The full scientific name of the subtribe in which the ods:TaxonIdentification is classified","examples":["Plotinini"]},"dwc:superfamily":{"type":"string","description":"The full scientific name of the superfamily in which the ods:TaxonIdentification is classified","examples":["Cerithioidea"]},"dwc:tribe":{"type":"string","description":"The full scientific name of the tribe in which the ods:TaxonIdentification is classified","examples":["Arethuseae"]}},"required":["@type","dwc:scientificName"],"additionalProperties":false} \ No newline at end of file From ada9cf12c5fa9e51e72611bb33964c2c38e0319f Mon Sep 17 00:00:00 2001 From: TomDijkema Date: Tue, 26 Nov 2024 15:45:25 +0100 Subject: [PATCH 13/13] Build fix 3 --- package-lock.json | 20 +++++++++++++++++--- package.json | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b31d3012..85da8d43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", + "@types/css-font-loading-module": "^0.0.14", "@types/cytoscape": "^3.21.5", "@types/jsonpath": "^0.2.4", "@types/leaflet": "^1.9.12", @@ -1920,6 +1921,12 @@ "@pixi/core": "7.4.2" } }, + "node_modules/@pixi/assets/node_modules/@types/css-font-loading-module": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.12.tgz", + "integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==", + "license": "MIT" + }, "node_modules/@pixi/color": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@pixi/color/-/color-7.4.2.tgz", @@ -2166,6 +2173,12 @@ "ismobilejs": "^1.1.0" } }, + "node_modules/@pixi/settings/node_modules/@types/css-font-loading-module": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.12.tgz", + "integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==", + "license": "MIT" + }, "node_modules/@pixi/sprite": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-7.4.2.tgz", @@ -2871,9 +2884,10 @@ "license": "MIT" }, "node_modules/@types/css-font-loading-module": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.12.tgz", - "integrity": "sha512-x2tZZYkSxXqWvTDgveSynfjq/T2HyiZHXb00j/+gy19yp70PHCizM48XFdjBCWH7eHBD0R5i/pw9yMBP/BH5uA==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.14.tgz", + "integrity": "sha512-+EwJ/RW2vPqbYn0JXRHy593huPCtgmLF/kg57iLK9KUn6neTqGGOTZ0CbssP8Uou/gqT/5XmWKQ8A7ve7xNV6A==", + "dev": true, "license": "MIT" }, "node_modules/@types/cytoscape": { diff --git a/package.json b/package.json index 1853f67a..cdcd0eed 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", + "@types/css-font-loading-module": "^0.0.14", "@types/cytoscape": "^3.21.5", "@types/jsonpath": "^0.2.4", "@types/leaflet": "^1.9.12",