diff --git a/src/components/SingleTermView/OverView/Details.jsx b/src/components/SingleTermView/OverView/Details.jsx
index 8e61303f..5ea9fad9 100644
--- a/src/components/SingleTermView/OverView/Details.jsx
+++ b/src/components/SingleTermView/OverView/Details.jsx
@@ -7,11 +7,12 @@ import {
} from "@mui/material";
import PropTypes from "prop-types";
import OpenInNewOutlinedIcon from '@mui/icons-material/OpenInNewOutlined';
+import { formatTimestamp } from "../../../utils";
import { vars } from "../../../theme/variables";
const { gray800, gray500 } = vars;
-const Details = ({loading, data }) => {
+const Details = ({ loading, data, jsonData }) => {
const handleChipClick = (url) => {
window.open(url, '_blank');
};
@@ -34,6 +35,10 @@ const Details = ({loading, data }) => {
if (!data) {
return
No data available
;
}
+ const graphArray = jsonData["@graph"];
+ const lastGraphItem = graphArray[graphArray.length - 1]
+ const versionIRI = lastGraphItem?.["owl:versionIRI"]?.["@id"];
+ const versionInfo = formatTimestamp(lastGraphItem?.["owl:versionInfo"]);
return (
<>
@@ -75,7 +80,7 @@ const Details = ({loading, data }) => {
Existing IDs
- {data?.existingID && ( processExistingIds(data?.existingID).map((id) =>
+ {data?.existingID && (processExistingIds(data?.existingID).map((id) =>
} onClick={() => handleChipClick(id)} />
))}
@@ -111,7 +116,7 @@ const Details = ({loading, data }) => {
Version
- {data?.versionInfo}
+ {versionIRI.split('/version/')[1].split('/')[0]}
@@ -151,7 +156,7 @@ const Details = ({loading, data }) => {
Last modify timestamp
- {data?.lastModifyTimestamp}
+ {versionInfo}
@@ -162,7 +167,8 @@ const Details = ({loading, data }) => {
Details.propTypes = {
loading: PropTypes.bool.isRequired,
- data: PropTypes.object
+ data: PropTypes.object,
+ jsonData: PropTypes.object
};
export default Details;
diff --git a/src/components/SingleTermView/OverView/OverView.jsx b/src/components/SingleTermView/OverView/OverView.jsx
index 28c36d11..33441efd 100644
--- a/src/components/SingleTermView/OverView/OverView.jsx
+++ b/src/components/SingleTermView/OverView/OverView.jsx
@@ -9,18 +9,20 @@ import PropTypes from 'prop-types';
import Hierarchy from "./Hierarchy";
import Predicates from "./Predicates";
import RawDataViewer from "./RawDataViewer";
-import {useCallback, useEffect, useMemo, useState} from "react";
-import { getMatchTerms } from "../../../api/endpoints";
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { getMatchTerms, getRawData } from "../../../api/endpoints";
const OverView = ({ searchTerm, isCodeViewVisible, selectedDataFormat }) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
-
+ const [jsonData, setJsonData] = useState(null);
+
// eslint-disable-next-line react-hooks/exhaustive-deps
const fetchTerms = useCallback(
debounce((searchTerm) => {
if (searchTerm) {
getMatchTerms("base", searchTerm).then(data => {
+ console.log("data from api call: ", data)
setData(data?.results?.[0]);
setLoading(false);
});
@@ -28,24 +30,31 @@ const OverView = ({ searchTerm, isCodeViewVisible, selectedDataFormat }) => {
}, 300),
[]
);
-
+
+ const fetchJSONFile = useCallback(() => {
+ getRawData("base", searchTerm, 'jsonld').then(rawResponse => {
+ setJsonData(rawResponse);
+ })
+ }, [searchTerm]);
+
useEffect(() => {
setLoading(true);
fetchTerms(searchTerm);
+ fetchJSONFile();
return () => {
fetchTerms.cancel();
};
- }, [searchTerm, fetchTerms]);
+ }, [searchTerm, fetchTerms, fetchJSONFile]);
const memoData = useMemo(() => data, [data]);
-
+
return (
{isCodeViewVisible ? :
<>
-
+
diff --git a/src/components/SingleTermView/index.jsx b/src/components/SingleTermView/index.jsx
index ecb13764..51cc3423 100644
--- a/src/components/SingleTermView/index.jsx
+++ b/src/components/SingleTermView/index.jsx
@@ -16,7 +16,6 @@ import ToggleButton from '@mui/material/ToggleButton';
import CustomBreadcrumbs from "../common/CustomBreadcrumbs";
import ForkRightIcon from '@mui/icons-material/ForkRight';
import { vars } from "../../theme/variables";
-import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
import OntologySearch from "./OntologySearch";
import ModeEditOutlineOutlinedIcon from '@mui/icons-material/ModeEditOutlineOutlined';
import RateReviewOutlinedIcon from '@mui/icons-material/RateReviewOutlined';
@@ -45,10 +44,18 @@ import CreateForkDialog from "./CreateForkDialog";
import TermDialog from "../TermEditor/TermDialog";
import { getSelectedTermLabel } from "../../api/endpoints/apiService";
import { GlobalDataContext } from "../../contexts/DataContext";
+import { getRawData } from "../../api/endpoints";
-const { gray200, brand700, gray600 } = vars;
+const { gray200, gray600 } = vars;
-const dataFormats = ['JSON-LD', 'Turtle', 'N3', 'OWL', 'CSV']
+const dataFormats = ['JSON-LD', 'Turtle', 'N3', 'OWL', 'CSV'];
+const formatExtensions = {
+ 'JSON-LD': 'jsonld',
+ 'Turtle': 'ttl',
+ 'N3': 'n3',
+ 'OWL': 'owl',
+ 'CSV': 'csv'
+};
const SingleTermView = () => {
const [open, setOpen] = useState(false);
@@ -93,6 +100,8 @@ const SingleTermView = () => {
const handleDataFormatMenuItemClick = (value) => {
setSelectedDataFormat(value);
setDataFormatAnchorEl(null);
+
+ downloadFormattedData(value);
};
const handleOpenRequestMergeDialog = () => {
@@ -118,15 +127,30 @@ const SingleTermView = () => {
setTabValue(newValue);
};
+ const downloadFormattedData = (dataFormat) => {
+ getRawData("base", searchTerm, formatExtensions[dataFormat]).then(rawResponse => {
+ const formattedData = JSON.stringify(rawResponse, null, 2);
+ const blob = new Blob([formattedData], { type: 'application/json' });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `data.${formatExtensions[dataFormat]}`;
+ a.click();
+ URL.revokeObjectURL(url);
+ }).catch(error => {
+ console.error('Error downloading data:', error);
+ });
+ }
+
const CodeOrTreeIcon = () => {
return isCodeViewVisible ? :
}
const breadcrumbItems = [
{ label: '', href: '/', icon: HomeOutlinedIcon },
- { label: 'Term search', href: `/search?searchTerm=${searchTerm}` },
- { label: 'My organization 1', href: '#' },
- { label: 'ILX:0101901' },
+ { label: 'Term search', href: `/search?searchTerm=${storedSearchTerm}` },
+ { label: 'base', href: '#' },
+ { label: searchTerm.toUpperCase().replace("_", ":") },
];
useEffect(() => {
@@ -148,19 +172,7 @@ const SingleTermView = () => {
-
-
-
-
- fork1
-
- }
- label="Not merged"
- variant="outlined"
- className="rounded not-merged"
- />
-
+
Active Ontology:
diff --git a/src/utils.js b/src/utils.js
index f125688f..e30361fc 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -45,29 +45,29 @@ export const stableSort = (array, comparator) => {
export function compareArrays(originalArray, modifiedArray) {
if (!Array.isArray(originalArray) || !Array.isArray(modifiedArray)) {
- console.warn("compareArrays received invalid input", { originalArray, modifiedArray });
- return [];
+ console.warn("compareArrays received invalid input", { originalArray, modifiedArray });
+ return [];
}
-
+
return originalArray.filter(item => !modifiedArray.includes(item));
}
export function compareSentences(originalText, modifiedText) {
- // Split texts into sentences
- const originalSentences = originalText.match(/[^.!?]+[.!?]+/g) || [];
- const modifiedSentences = modifiedText.match(/[^.!?]+[.!?]+/g) || [];
-
- // Find sentences in original that are not in modified
- const uniqueSentences = originalSentences.filter(sentence =>
- !modifiedSentences.some(modSentence =>
- sentence.trim().toLowerCase() === modSentence.trim().toLowerCase()
- )
- );
- return uniqueSentences;
+ // Split texts into sentences
+ const originalSentences = originalText.match(/[^.!?]+[.!?]+/g) || [];
+ const modifiedSentences = modifiedText.match(/[^.!?]+[.!?]+/g) || [];
+
+ // Find sentences in original that are not in modified
+ const uniqueSentences = originalSentences.filter(sentence =>
+ !modifiedSentences.some(modSentence =>
+ sentence.trim().toLowerCase() === modSentence.trim().toLowerCase()
+ )
+ );
+ return uniqueSentences;
}
export function compareStrings(originalString, modifiedString) {
- return originalString !== modifiedString ? [originalString] : []
+ return originalString !== modifiedString ? [originalString] : []
}
export function compareObjects(originalObject, modifiedObject) {
@@ -75,11 +75,33 @@ export function compareObjects(originalObject, modifiedObject) {
}
export function getDataType(data) {
- if (Array.isArray(data)) return "array"
- if (typeof data === "string") return "string"
- if (typeof data === "number") return "number"
- if (typeof data === "boolean") return "boolean"
- if (data === null) return "null"
- if (typeof data === "object") return "object"
- return "unknown"
+ if (Array.isArray(data)) return "array"
+ if (typeof data === "string") return "string"
+ if (typeof data === "number") return "number"
+ if (typeof data === "boolean") return "boolean"
+ if (data === null) return "null"
+ if (typeof data === "object") return "object"
+ return "unknown"
+}
+
+export function formatTimestamp(rawDate) {
+ if (!rawDate || typeof rawDate !== 'string') return 'Invalid date';
+
+ try {
+ const cleanedDateStr = rawDate.replace(',', '.');
+ const date = new Date(cleanedDateStr);
+
+ if (isNaN(date)) return 'Invalid date';
+
+ const yyyy = date.getFullYear();
+ const mm = String(date.getMonth() + 1).padStart(2, '0');
+ const dd = String(date.getDate()).padStart(2, '0');
+ const hh = String(date.getHours()).padStart(2, '0');
+ const min = String(date.getMinutes()).padStart(2, '0');
+
+ return `${yyyy}-${mm}-${dd} ${hh}:${min}`;
+ } catch (e) {
+ return 'Invalid date';
+ }
}
+