diff --git a/mapping_workbench/frontend/package.json b/mapping_workbench/frontend/package.json index ba57436ff..b086f666f 100644 --- a/mapping_workbench/frontend/package.json +++ b/mapping_workbench/frontend/package.json @@ -87,6 +87,7 @@ "react": "18.2.0", "react-apexcharts": "1.4.0", "react-beautiful-dnd": "13.1.1", + "react-codemirror-merge": "^4.23.7", "react-dom": "18.2.0", "react-draft-wysiwyg": "1.15.0", "react-dropzone": "14.2.3", diff --git a/mapping_workbench/frontend/src/api/file-collections/file-resources/index.js b/mapping_workbench/frontend/src/api/file-collections/file-resources/index.js index 967c38162..3c0d6542f 100644 --- a/mapping_workbench/frontend/src/api/file-collections/file-resources/index.js +++ b/mapping_workbench/frontend/src/api/file-collections/file-resources/index.js @@ -1,5 +1,6 @@ import {SectionApi} from "src/api/section"; import {appApi} from "src/api/app"; +import {sessionApi} from '../../session'; export class FileResourcesApi extends SectionApi { get FILE_RESOURCE_FORMATS() { @@ -33,8 +34,17 @@ export class FileResourcesApi extends SectionApi { } async getFileResource(id) { - let endpoint = this.paths['file_resource'].replace(':id', id); - let data = await appApi.get(endpoint); + const endpoint = this.paths['file_resource'].replace(':id', id); + const data = await appApi.get(endpoint); + return Promise.resolve(data); + } +// http://localhost:8000/api/v1/test_data_suites/file_resources/678f5c9d607a7f61f94c11c5/transform/history?project=678f5b8d6f271a8aa40e9633 + + async getFileHistory(id) { + const filters = {}; + filters['project'] = sessionApi.getSessionProject(); + const endpoint = this.paths['file_history'].replace(':id', id); + const data = await appApi.get(endpoint, filters); return Promise.resolve(data); } } diff --git a/mapping_workbench/frontend/src/components/app/form/codeMirrorDefault.js b/mapping_workbench/frontend/src/components/app/form/codeMirrorDefault.js index 4b1b725e6..ca2cc0221 100644 --- a/mapping_workbench/frontend/src/components/app/form/codeMirrorDefault.js +++ b/mapping_workbench/frontend/src/components/app/form/codeMirrorDefault.js @@ -1,4 +1,4 @@ -import CodeMirror from "@uiw/react-codemirror"; +import CodeMirror, {EditorState, EditorView} from "@uiw/react-codemirror"; import {githubDark, githubLight} from "@uiw/codemirror-themes-all"; import {yaml} from '@codemirror/lang-yaml' import {xml} from '@codemirror/lang-xml' @@ -8,10 +8,11 @@ import {turtle} from 'codemirror-lang-turtle'; import {sparql} from 'codemirror-lang-sparql'; +import {Box} from "@mui/system"; import {useTheme} from "@mui/material/styles"; import FormLabel from "@mui/material/FormLabel"; import FormControl from "@mui/material/FormControl"; -import {Box} from "@mui/system"; +import CodeMirrorMerge from 'react-codemirror-merge'; const languageSwitch = (lang) => { @@ -32,7 +33,39 @@ const languageSwitch = (lang) => { } } -const CodeMirrorDefault = ({value, onChange, lang, label, disabled, style}) => { +const Original = CodeMirrorMerge.Original; +const Modified = CodeMirrorMerge.Modified; + +export const CodeMirrorCompare = ({value, previousValue, lang, label, style, name}) => { + const theme = useTheme() + return ( + + + {label} + + + + + + + + + ) +} + +const CodeMirrorDefault = ({value, onChange, lang, label, disabled, style, name}) => { const theme = useTheme(); return ( diff --git a/mapping_workbench/frontend/src/pages/app/test-data-suites/[id]/resource-manager/[fid]/edit.js b/mapping_workbench/frontend/src/pages/app/test-data-suites/[id]/resource-manager/[fid]/edit.js index 269f8c385..4901b6f4d 100644 --- a/mapping_workbench/frontend/src/pages/app/test-data-suites/[id]/resource-manager/[fid]/edit.js +++ b/mapping_workbench/frontend/src/pages/app/test-data-suites/[id]/resource-manager/[fid]/edit.js @@ -1,5 +1,4 @@ import {useCallback, useEffect, useState} from "react"; -import {useFormik} from "formik"; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; @@ -7,9 +6,12 @@ import Chip from '@mui/material/Chip'; import Link from '@mui/material/Link'; import Stack from '@mui/material/Stack'; import Paper from "@mui/material/Paper"; -import SvgIcon from '@mui/material/SvgIcon'; +import Button from '@mui/material/Button'; import Divider from "@mui/material/Divider"; +import SvgIcon from '@mui/material/SvgIcon'; +import MenuItem from '@mui/material/MenuItem'; import Checkbox from "@mui/material/Checkbox"; +import TextField from '@mui/material/TextField'; import Grid from "@mui/material/Unstable_Grid2"; import Typography from '@mui/material/Typography'; import FormControlLabel from "@mui/material/FormControlLabel"; @@ -22,11 +24,13 @@ import {Layout as AppLayout} from 'src/layouts/app'; import {RouterLink} from 'src/components/router-link'; import {FormTextField} from "src/components/app/form/text-field"; import {ForItemEditForm} from "src/contexts/app/section/for-item-form"; -import CodeMirrorDefault from "src/components/app/form/codeMirrorDefault"; +import CodeMirrorDefault, {CodeMirrorCompare} from "src/components/app/form/codeMirrorDefault"; import {ForItemDataState} from "src/contexts/app/section/for-item-data-state"; import {FileResourceEditForm} from 'src/sections/app/file-manager/file-resource-edit-form'; import {testDataFileResourcesApi as sectionApi} from 'src/api/test-data-suites/file-resources'; import {MappingPackageFormSelect} from 'src/sections/app/mapping-package/components/mapping-package-form-select'; +import {useGlobalState} from '../../../../../../hooks/use-global-state'; +import timeTransformer from '../../../../../../utils/time-transformer'; const useItem = (sectionApi, id) => { @@ -51,13 +55,22 @@ const useItem = (sectionApi, id) => { const ExtraForm = (props) => { const { item, - formik + formik, + compare_items, } = props; + const {timeSetting} = useGlobalState() + + const [showCompare, setShowCompare] = useState(false) + + const handleCompareChange = e => { + formik.setFieldValue('compare_item', e.target.value) + } const handleTransformTestDataChange = useCallback((event) => { formik.setFieldValue('transform_test_data', event.target.checked); }, [formik]); + return ( { - formik.setValues('rdf_manifestation', value)} - lang={'TTL'} - /> + + {compare_items.length && } + + + {showCompare && + {compare_items.map((compare_item) => ( + + {timeTransformer(compare_item.created_at, timeSetting)} + + ))} + } + + + {showCompare ? + formik.setValues('rdf_manifestation', value)} + lang='TTL' + /> : + formik.setValues('rdf_manifestation', value)} + lang='TTL' + />} ) } +const useFileHistory = (sectionApi, id) => { + const [compareItems, setCompareItems] = useState([]) + + useEffect(() => { + id && handleItemHistoryGet(id) + }, [id]) + + const handleItemHistoryGet = () => { + sectionApi.getFileHistory(id) + .then(res => setCompareItems(res)) + .catch(err => console.error(err)) + } + + return compareItems +} + const Page = () => { const router = useRouter(); const {id, fid} = router.query; const formState = useItem(sectionApi, fid); + const compare_items = useFileHistory(sectionApi, fid) const item = formState.item; - const formik = useFormik({ - initialValues: {"rdf_manifestation": item && item.rdf_manifestation} - }); - usePageView(); if (!item) { @@ -133,7 +193,8 @@ const Page = () => { identifier: item.identifier || '', rdf_manifestation: item.rdf_manifestation || '', transform_test_data: false, - mapping_package_id: null + mapping_package_id: null, + compare_items: compare_items } return ( diff --git a/mapping_workbench/frontend/src/paths.js b/mapping_workbench/frontend/src/paths.js index 16aecb316..6293961dc 100644 --- a/mapping_workbench/frontend/src/paths.js +++ b/mapping_workbench/frontend/src/paths.js @@ -256,6 +256,7 @@ export const apiPaths = { item: '/test_data_suites/:id', file_resources: '/test_data_suites/:id/file_resources', file_resource: '/test_data_suites/file_resources/:id', + file_history: '/test_data_suites/file_resources/:id/transform/history', assign_mapping_packages: '/test_data_suites/assign_mapping_packages', tasks: { transform_test_data: '/test_data_suites/tasks/transform_test_data', diff --git a/mapping_workbench/frontend/src/sections/app/file-manager/file-resource-edit-form.js b/mapping_workbench/frontend/src/sections/app/file-manager/file-resource-edit-form.js index fa1745f93..1af09c76c 100644 --- a/mapping_workbench/frontend/src/sections/app/file-manager/file-resource-edit-form.js +++ b/mapping_workbench/frontend/src/sections/app/file-manager/file-resource-edit-form.js @@ -1,4 +1,5 @@ import PropTypes from 'prop-types'; +import {useState} from 'react'; import * as Yup from 'yup'; import {useFormik} from 'formik'; @@ -18,12 +19,14 @@ import {useRouter} from 'src/hooks/use-router'; import {RouterLink} from 'src/components/router-link'; import {FormTextArea} from "src/components/app/form/text-area"; import {FormTextField} from "src/components/app/form/text-field"; -import {FormCodeTextArea} from "src/components/app/form/code-text-area"; import {toastError, toastLoad, toastSuccess} from "src/components/app-toast"; -import CodeMirrorDefault from "../../../components/app/form/codeMirrorDefault"; +import CodeMirrorDefault, {CodeMirrorCompare} from "src/components/app/form/codeMirrorDefault"; +import {useGlobalState} from '../../../hooks/use-global-state'; +import timeTransformer from '../../../utils/time-transformer'; export const FileResourceEditForm = (props) => { const router = useRouter(); + const [showCompare, setShowCompare] = useState(false) const { itemctx, collection_id, @@ -46,8 +49,9 @@ export const FileResourceEditForm = (props) => { filename: data.filename || '', format: data.format || sectionApi.FILE_RESOURCE_DEFAULT_FORMAT || '', content: data.content || '', - file: null - }, extra_form_fields) + file: null, + compare_item: extra_form_fields.compare_items?.[0] + }, extra_form_fields,) } const initialValues = initFormValues(item); @@ -113,6 +117,12 @@ export const FileResourceEditForm = (props) => { formik.values.file = e.target.files[0]; } + const handleCompareChange = e => { + formik.setFieldValue('compare_item', e.target.value) + } + + const {timeSetting} = useGlobalState() + return (
{ - formik.setFieldValue('content', value)}/> + + {extra_form_fields?.compare_items.length && } + + {showCompare && + {extra_form_fields?.compare_items.map((compare_item) => ( + + {timeTransformer(compare_item.created_at,timeSetting)} + + ))} + } + + {showCompare ? + formik.setValues('rdf_manifestation', value)} + lang={formik.values.format} + /> : + formik.setFieldValue('content', value)}/>} @@ -222,13 +263,15 @@ export const FileResourceEditForm = (props) => { - {extra_form && ( - - - {extra_form({item: item, formik: formik})} - - - )} + { + extra_form && ( + + + {extra_form({item, formik, compare_items: extra_form_fields.compare_items})} + + + ) + } { - ); + ) + ; }; FileResourceEditForm.propTypes = { diff --git a/mapping_workbench/frontend/src/sections/app/mapping-package/components/mapping-package-form-select/mapping-package-form-select.js b/mapping_workbench/frontend/src/sections/app/mapping-package/components/mapping-package-form-select/mapping-package-form-select.js index ba50a819b..76890ed69 100644 --- a/mapping_workbench/frontend/src/sections/app/mapping-package/components/mapping-package-form-select/mapping-package-form-select.js +++ b/mapping_workbench/frontend/src/sections/app/mapping-package/components/mapping-package-form-select/mapping-package-form-select.js @@ -42,33 +42,31 @@ export const MappingPackageFormSelect = (props) => { }, [mappingPackagesStore.items]); return ( - <> - - -   + + +   + + {mappingPackagesStore.items.map((mapping_package) => ( + + {mapping_package.title} - {mappingPackagesStore.items.map((mapping_package) => ( - - {mapping_package.title} - - ))} - - + ))} + ); };