diff --git a/taxonomy-editor-frontend/package-lock.json b/taxonomy-editor-frontend/package-lock.json
index b92d3921..54bab462 100644
--- a/taxonomy-editor-frontend/package-lock.json
+++ b/taxonomy-editor-frontend/package-lock.json
@@ -18,6 +18,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
+ "iso-639-1": "^2.1.15",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^11.18.3",
@@ -9971,6 +9972,14 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "node_modules/iso-639-1": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-2.1.15.tgz",
+ "integrity": "sha512-7c7mBznZu2ktfvyT582E2msM+Udc1EjOyhVRE/0ZsjD9LBtWSm23h3PtiRh2a35XoUsTQQjJXaJzuLjXsOdFDg==",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
"node_modules/istanbul-lib-coverage": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
@@ -24735,6 +24744,11 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "iso-639-1": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-2.1.15.tgz",
+ "integrity": "sha512-7c7mBznZu2ktfvyT582E2msM+Udc1EjOyhVRE/0ZsjD9LBtWSm23h3PtiRh2a35XoUsTQQjJXaJzuLjXsOdFDg=="
+ },
"istanbul-lib-coverage": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
diff --git a/taxonomy-editor-frontend/package.json b/taxonomy-editor-frontend/package.json
index cf25706a..ec268298 100644
--- a/taxonomy-editor-frontend/package.json
+++ b/taxonomy-editor-frontend/package.json
@@ -13,6 +13,7 @@
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
+ "iso-639-1": "^2.1.15",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^11.18.3",
diff --git a/taxonomy-editor-frontend/src/App.js b/taxonomy-editor-frontend/src/App.js
index 2eae8802..019411fe 100644
--- a/taxonomy-editor-frontend/src/App.js
+++ b/taxonomy-editor-frontend/src/App.js
@@ -2,6 +2,7 @@ import { createTheme, CssBaseline, ThemeProvider } from "@mui/material";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import ResponsiveAppBar from "./components/ResponsiveAppBar";
import Entry from "./pages/allentries";
+import EditEntry from "./pages/editentry";
import Home from './pages/home';
const theme = createTheme({
@@ -20,6 +21,7 @@ function App() {
} />
} />
+ } />
diff --git a/taxonomy-editor-frontend/src/components/useFetch.jsx b/taxonomy-editor-frontend/src/components/useFetch.jsx
index 299d20ad..55257d39 100644
--- a/taxonomy-editor-frontend/src/components/useFetch.jsx
+++ b/taxonomy-editor-frontend/src/components/useFetch.jsx
@@ -28,8 +28,7 @@ const reducer = (state, action) => {
}
const useFetch = (url) => {
- const [fetchInfo, dispatch] = useReducer(reducer, initialState)
-
+ const [fetchInfo, dispatch] = useReducer(reducer, initialState)
useEffect(() => {
const abortCont = new AbortController();
diff --git a/taxonomy-editor-frontend/src/pages/allentries/index.jsx b/taxonomy-editor-frontend/src/pages/allentries/index.jsx
index 56bbbbab..3db9463a 100644
--- a/taxonomy-editor-frontend/src/pages/allentries/index.jsx
+++ b/taxonomy-editor-frontend/src/pages/allentries/index.jsx
@@ -66,7 +66,7 @@ const Entry = () => {
-
diff --git a/taxonomy-editor-frontend/src/pages/editentry/AccumulateAllComponents.jsx b/taxonomy-editor-frontend/src/pages/editentry/AccumulateAllComponents.jsx
new file mode 100644
index 00000000..185b7bbd
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/AccumulateAllComponents.jsx
@@ -0,0 +1,53 @@
+import { Box } from "@mui/material";
+import { useEffect, useState } from "react";
+import useFetch from "../../components/useFetch";
+import { createURL } from "./createURL";
+import ListAllOtherProperties from "./ListAllOtherProperties";
+import ListAllProperties from "./ListAllProperties";
+import ListTranslations from "./ListTranslations";
+
+// Used for rendering node information
+// If node is an "entry": Relations, translations, comments and properties are rendered
+// If node is an "stopword/synonym": Stopwords/synonyms, language and comments are rendered
+// If node is "header/footer": Comments are rendered
+
+const AccumulateAllComponents = ({ id }) => {
+ const { url, isEntry } = createURL(id);
+ const [nodeObject, setNodeObject] = useState(null); // Storing node information
+ const { data: node, isPending, isError, isSuccess, errorMessage } = useFetch(url);
+
+ // Setting state of node after fetch
+ useEffect(() => {
+ setNodeObject(node?.[0]);
+ }, [node])
+
+ if (isError) {
+ return (
+
+ {isError && {errorMessage}
}
+
+ )
+ }
+ if (isPending) {
+ return (
+
+ {isPending && Loading...
}
+
+ )
+ }
+ return (
+
+ {/* Based on isEntry, respective components are rendered */}
+ { isEntry ?
+
+ { !!nodeObject &&
+ <>
+ > }
+ :
+ <> >
+ }
+
+ );
+}
+
+export default AccumulateAllComponents;
\ No newline at end of file
diff --git a/taxonomy-editor-frontend/src/pages/editentry/ListAllOtherProperties.jsx b/taxonomy-editor-frontend/src/pages/editentry/ListAllOtherProperties.jsx
new file mode 100644
index 00000000..07545ac5
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/ListAllOtherProperties.jsx
@@ -0,0 +1,24 @@
+import { Box, Typography } from "@mui/material";
+
+// Parent component used for rendering info
+// on a stopword, synonym, header or footer
+
+const ListAllOtherProperties = ({ nodeObject, id, setNodeObject }) => {
+
+ return (
+
+ Comments
+
+ {id.startsWith('stopword') ?
+
+ Stopwords
+ :
+
+ Synonyms
+ }
+
+
+ );
+}
+
+export default ListAllOtherProperties;
\ No newline at end of file
diff --git a/taxonomy-editor-frontend/src/pages/editentry/ListAllProperties.jsx b/taxonomy-editor-frontend/src/pages/editentry/ListAllProperties.jsx
new file mode 100644
index 00000000..52e58428
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/ListAllProperties.jsx
@@ -0,0 +1,14 @@
+import { Typography, Box } from "@mui/material";
+
+// Sub-component used for rendering comments and properties of an "entry"
+
+const ListAllProperties = ({ nodeObject, setNodeObject }) => {
+ return (
+
+ Comments
+ Properties
+
+ );
+}
+
+export default ListAllProperties;
\ No newline at end of file
diff --git a/taxonomy-editor-frontend/src/pages/editentry/ListTranslations.jsx b/taxonomy-editor-frontend/src/pages/editentry/ListTranslations.jsx
new file mode 100644
index 00000000..bcb7a430
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/ListTranslations.jsx
@@ -0,0 +1,95 @@
+import { Typography, Paper, TextField, Stack, Box } from "@mui/material";
+import ISO6391 from 'iso-639-1';
+
+// Sub-component for rendering translation of an "entry"
+
+const ListTranslations = ({ nodeObject, setNodeObject }) => {
+ let renderedTranslations = {}
+
+ Object.keys(nodeObject).forEach((key) => {
+
+ // Get all tags and its corresponding language code
+ // Tagids need to be recomputed, so shouldn't be rendered
+ // Main language isn't considered, since it's rendered separately
+
+ if (key.startsWith('tags') &&
+ !key.endsWith(nodeObject.main_language) &&
+ !key.includes('ids')) {
+
+ // Slice the language code
+ let languageCode = key.slice(-2);
+ renderedTranslations[languageCode] = nodeObject[key]
+ }
+ })
+
+ // Helper function used for changing state
+ function changeData(key, index, value) {
+ key = 'tags_' + key;
+ const duplicateData = {...nodeObject};
+ duplicateData[key][index] = value;
+ setNodeObject(duplicateData);
+ }
+
+ return (
+
+ {/* Title */}
+ Translations
+ {/* Main Language */}
+
+ { ISO6391.getName(nodeObject.main_language) }
+
+ {/* Render main language tags */}
+
+ {
+ nodeObject["tags_"+nodeObject['main_language']].map((tag, index) => {
+ return (
+ // TODO: Key to be replaced by a UUID
+
+ {
+ changeData(nodeObject['main_language'], index, event.target.value)
+ }}
+ value={tag}
+ variant="outlined" />
+
+ )
+ })
+ }
+
+
+ {/* All other languages */}
+ {
+ Object.entries(renderedTranslations).map( ([lang, value]) => {
+ return (
+
+
+ {ISO6391.getName(lang)}
+
+ {/* Render all related tags */}
+ {
+ value.map((tag, index) => {
+ return (
+
+ {
+ changeData(lang, index, event.target.value)
+ }}
+ value={tag}
+ variant="outlined" />
+
+ )
+ })
+ }
+
+ )
+ } )
+ }
+
+ );
+}
+
+export default ListTranslations;
\ No newline at end of file
diff --git a/taxonomy-editor-frontend/src/pages/editentry/createURL.jsx b/taxonomy-editor-frontend/src/pages/editentry/createURL.jsx
new file mode 100644
index 00000000..7f06a59a
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/createURL.jsx
@@ -0,0 +1,18 @@
+import { API_URL } from "../../constants.js"
+
+export function createURL(id) {
+
+ // Finding URL to send requests
+ let url = API_URL;
+ let isEntry = false;
+
+ // ID's can look like: __header__, __footer__, synomym:0, stopword:0
+ // For an entry, id looks like en:yogurts
+ if (id.startsWith('__header__')) { url += 'header/' }
+ else if (id.startsWith('__footer__')) { url += 'footer/' }
+ else if (id.startsWith('synonym')) { url += `synonym/${id}/` }
+ else if (id.startsWith('stopword')) { url += `stopword/${id}/` }
+ else { url += `entry/${id}/`; isEntry = true; }
+
+ return {url, isEntry}
+}
\ No newline at end of file
diff --git a/taxonomy-editor-frontend/src/pages/editentry/index.jsx b/taxonomy-editor-frontend/src/pages/editentry/index.jsx
new file mode 100644
index 00000000..3500a058
--- /dev/null
+++ b/taxonomy-editor-frontend/src/pages/editentry/index.jsx
@@ -0,0 +1,19 @@
+import { Typography } from "@mui/material";
+import { useParams } from "react-router-dom";
+import AccumulateAllComponents from "./AccumulateAllComponents";
+
+const EditEntry = () => {
+ const { id } = useParams();
+ return (
+
+
+
+ You are now editing "{id}"
+
+
+
+
+ );
+}
+
+export default EditEntry;
\ No newline at end of file