From c125751f17a73cec7ce529efde924c492740cd99 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 26 Aug 2023 15:36:27 +0200 Subject: [PATCH] equipment documentation --- public/locales/de/translation.json | 62 ++++++- public/locales/en/translation.json | 62 ++++++- src/App.js | 2 +- src/Components/AppRoutes/index.js | 80 ++++++++- src/Components/MyModal/index.js | 2 + src/Components/MyTypography/index.js | 38 ++++ .../CreateEquipmentDocumentationModal.js | 162 +---------------- .../ViewEquipmentDocumentation.js | 86 +++++---- src/Pages/EquipmentDocumentation/index.js | 168 ++++++++++++------ src/utils.js | 2 + 10 files changed, 403 insertions(+), 261 deletions(-) create mode 100644 src/Components/MyTypography/index.js diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index e11748d..b8c6055 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -14,7 +14,15 @@ "confirm": "Bestätigen", "create": "Erstellen" }, - "contactAdmin": "Bitte kontaktieren Sie einen Administrator" + "contactAdmin": "Bitte kontaktieren Sie einen Administrator", + "text": { + "id": "ID:", + "createdAt": "Erstellt am:", + "updatedAt": "Aktualisiert am:", + "createdBy": "Erstellt von:", + "endedAt": "Beendet am:", + "type": "Typ:" + } }, "sideMenu": { "dashboard": "Dashboard", @@ -335,8 +343,54 @@ }, "header": { "scanners": "Scanner" } }, - "equipmentDocumentation": {}, - "equipmentViewModal": { - "equipmentDocumentationNotFound": "Gerätedokumentation nicht gefunden" + "equipmentDocumentationOverview": { + "messageErrorInvalidStockItem": "Ungültiges Stock Item", + "buttonCloseCamera": "Kamera schließen", + "scanEquipment": { + "title": "Ausrüstung scannen", + "inputPlaceholder": "Ausrüstungs ID", + "buttonSearch": "Suchen" + }, + "noEquipmentScannedResult": { + "title": "Keine Ausrüstung gescannt", + "description": "Bitte scannen Sie eine Ausrüstung" + } + }, + "equipmentDocumentationViewEditComponent": { + "selectDocumentationTypeOptions": [ + { "value": 1, "label": "Reparaturprotokoll" }, + { "value": 2, "label": "Dokumentation" } + ], + "titleNewDocumentation": "Neue Dokumentation", + "textDocumentationType": "Dokumentationstyp", + "buttonAddNote": "Notiz hinzufügen", + "buttonTakePicture": "Foto aufnehmen", + "buttonMoveUp": "Nach oben verschieben", + "buttonMoveDown": "Nach unten verschieben", + "buttonDelete": "Löschen", + "textImageNoImage": "Kein Bild", + "textImageNoImageSelected": "Kein Bild ausgewählt", + "textareaPlaceholder": "Notiz", + "modalImageFullscreenTitle": "Vorschau" + }, + "viewEquipmentDocumentations": { + "detailsPopover": { + "title": "Details" + }, + "result403": { + "title": "Keine Berechtigung", + "description": "Der Backend-Server ist nicht berechtigt, auf Invex zuzugreifen. Bitte kontaktieren Sie einen Administrator." + }, + "result500": { + "title": "Keine Ausrüstung gefunden", + "description": "Die gescannte Ausrüstung existiert nicht in Invex." + }, + "result404": { + "title": "Keine Dokumentation gefunden", + "description": "Für die gescannte Ausrüstung existiert keine Dokumentation." + } + }, + "createEquipmentDocumentationModal": { + "buttonCreateDocumentation": "Dokumentation erstellen" } } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 305803a..d27fe74 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -14,7 +14,15 @@ "confirm": "Confirm", "create": "Create" }, - "contactAdmin": "Please contact an administrator" + "contactAdmin": "Please contact an administrator", + "text": { + "id": "ID:", + "createdAt": "Created at:", + "updatedAt": "Updated at:", + "createdBy": "Created by:", + "endedAt": "Ended at:", + "type": "Type:" + } }, "sideMenu": { "dashboard": "Dashboard", @@ -334,8 +342,54 @@ }, "header": { "scanners": "Scanners" } }, - "equipmentDocumentation": {}, - "equipmentViewModal": { - "equipmentDocumentationNotFound": "Equipment documentation not found" + "equipmentDocumentationOverview": { + "messageErrorInvalidStockItem": "Invalid Stock Item", + "buttonCloseCamera": "Close Camera", + "scanEquipment": { + "title": "Scan Equipment", + "inputPlaceholder": "Equipment ID", + "buttonSearch": "Search" + }, + "noEquipmentScannedResult": { + "title": "No Equipment Scanned", + "description": "Please scan an equipment" + } + }, + "equipmentDocumentationViewEditComponent": { + "selectDocumentationTypeOptions": [ + { "value": 1, "label": "Repair protocol" }, + { "value": 2, "label": "Documentation" } + ], + "titleNewDocumentation": "New Documentation", + "textDocumentationType": "Documentation Type", + "buttonAddNote": "Add Note", + "buttonTakePicture": "Take Photo", + "buttonMoveUp": "Move Up", + "buttonMoveDown": "Move Down", + "buttonDelete": "Delete", + "textImageNoImage": "No Image", + "textImageNoImageSelected": "No Image Selected", + "textareaPlaceholder": "Note", + "modalImageFullscreenTitle": "Preview" + }, + "viewEquipmentDocumentations": { + "detailsPopover": { + "title": "Details" + }, + "result403": { + "title": "Unauthorized Access", + "description": "The backend server is not authorized to access Invex. Please contact an administrator." + }, + "result500": { + "title": "Equipment Not Found", + "description": "The scanned equipment does not exist in Invex." + }, + "result404": { + "title": "Documentation Not Found", + "description": "No documentation found for the scanned equipment." + } + }, + "createEquipmentDocumentationModal": { + "buttonCreateDocumentation": "Create Documentation" } } diff --git a/src/App.js b/src/App.js index e975b66..89cf7e2 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,7 @@ import { useState } from "react"; import "antd/dist/reset.css"; import "./App.css"; import Login from "./Pages/Login"; -import { Layout, notification } from "antd"; +import { Layout, message, notification } from "antd"; import { UseUserSession, WebSocketProvider } from "./utils"; import DashboardLayout from "./Components/DashboardLayout"; diff --git a/src/Components/AppRoutes/index.js b/src/Components/AppRoutes/index.js index c6259f6..04b051e 100644 --- a/src/Components/AppRoutes/index.js +++ b/src/Components/AppRoutes/index.js @@ -16,8 +16,83 @@ import GroupTasks from "../../Pages/GroupTasks/Overview"; import GroupTasksHistory from "../../Pages/GroupTasks/History"; import PageNotFound from "../../Pages/PageNotFound"; import EquipmentDocumentationOverview from "../../Pages/EquipmentDocumentation"; -import ViewEquipmentDocumentations from "../../Pages/EquipmentDocumentation/ViewEquipmentDocumentation"; +export default function AppRoutes() { + // const webSocketContext = useContext(WebSocketContext); + + console.log("appRoutes"); + + /* + TODO: move down +{hasPermission( + webSocketContext.User.Permissions, + Constants.PERMISSIONS.EQUIPMENT_DOCUMENTATION.VIEW + ) && ( + } + /> + )} + + + } + /> + + + + } + /> + */ + + return ( + + } /> + + } + /> + + } + /> + + } + /> + + } + /> + + } /> + + } /> + + } /> + + } /> + + } /> + + } /> + + ); +} /* + +/* export default function AppRoutes() { const webSocketContext = useContext(WebSocketContext); @@ -50,7 +125,7 @@ export default function AppRoutes() { } element={} /> - */ + */ /* return ( @@ -107,3 +182,4 @@ export default function AppRoutes() { ); } +*/ diff --git a/src/Components/MyModal/index.js b/src/Components/MyModal/index.js index d96427b..4440c13 100644 --- a/src/Components/MyModal/index.js +++ b/src/Components/MyModal/index.js @@ -10,6 +10,7 @@ export default function MyModal({ isOpen, onCancel, footer = , + title, }) { const screenBreakpoint = useBreakpoint(); @@ -21,6 +22,7 @@ export default function MyModal({ onCancel={onCancel} footer={footer} centered={screenBreakpoint.xs} + title={title} > {children} diff --git a/src/Components/MyTypography/index.js b/src/Components/MyTypography/index.js new file mode 100644 index 0000000..462a47b --- /dev/null +++ b/src/Components/MyTypography/index.js @@ -0,0 +1,38 @@ +import { EditOutlined } from "@ant-design/icons"; +import { Input, Typography } from "antd"; +import { useState } from "react"; +import { Constants } from "../../utils"; + +export default function MyTypography({ value, setValue, maxLength }) { + const [editing, setEditing] = useState(false); + + return ( +
+ {editing ? ( + setValue(e.target.value)} + maxLength={maxLength} + showCount + /> + ) : ( + + {value} + + )} + + setEditing(!editing)} + /> +
+ ); +} diff --git a/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js b/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js index 195db7b..ba8daf7 100644 --- a/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js +++ b/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js @@ -2,12 +2,14 @@ import { Button } from "antd"; import { useState } from "react"; import { PlusOutlined } from "@ant-design/icons"; import { EquipmentDocumentationViewEditComponent } from "."; +import { useTranslation } from "react-i18next"; export default function CreateEquipmentDocumentationModal({ stockItemId, fetchDocumentation, buttonBlock, }) { + const { t } = useTranslation(); const [isOpen, setIsOpen] = useState(false); return ( @@ -18,7 +20,7 @@ export default function CreateEquipmentDocumentationModal({ icon={} onClick={() => setIsOpen(true)} > - Create documentation + {t("createEquipmentDocumentationModal.buttonCreateDocumentation")} ); } - -/* -export default function CreateEquipmentDocumentationModal({ - scannerResult, - fetchDocumentation, - buttonBlock, -}) { - const [isOpen, setIsOpen] = useState(false); - const [title, setTitle] = useState("New documentation"); - const [selectedDocumentationType, setSelectedDocumentationType] = useState( - selectDocumentationTypeOptions[0].value - ); - const [notes, setNotes] = useState([emptyNote]); - const [isDocumentationUploading, setIsDocumentationUploading] = - useState(false); - - const handleCancel = () => setIsOpen(false); - - const handleCreate = () => { - setIsDocumentationUploading(true); - - const updatedNotes = [...notes]; - - updatedNotes.forEach((note, index) => { - if (note.image === null && note.description === "") { - updatedNotes.splice(index, 1); - } - }); - - let body = { - stockItemId: scannerResult, - type: selectedDocumentationType, - title: title, - notes: updatedNotes, - }; - - console.log("body", body); - - myFetch(`/equipment/documentation/create`, "POST", body, {}).then( - (data) => { - console.log("data", data); - - setIsDocumentationUploading(false); - fetchDocumentation(); - handleCancel(); - } - ); - }; - - const handleDescriptionChange = (index) => (e) => { - const updatedNotes = [...notes]; - - updatedNotes[index] = { - ...updatedNotes[index], - description: e.target.value, - }; - - setNotes(updatedNotes); - }; - - const handleImageChange = (index) => (newImage) => { - const updatedNotes = [...notes]; - - updatedNotes[index] = { - ...updatedNotes[index], - image: newImage, - }; - - setNotes(updatedNotes); - }; - - const handleAddNote = () => setNotes([...notes, emptyNote]); - - const isAddNoteButtonDisabled = () => { - const lastNote = notes[notes.length - 1]; - - return lastNote.image === null && lastNote.description === ""; - }; - - const isCreateButtonDisabled = () => { - if (notes.length === 0) return true; - - if (notes.length === 1) { - return notes[0].image === null && notes[0].description === ""; - } - - return false; - }; - - return ( - <> - - - - } - > - - {title} - - -
- Documentation type -
- - setInputValue(e.target.value)} /> @@ -128,14 +138,20 @@ export default function EquipmentDocumentationOverview() { icon={} onClick={() => { if (!isScannedQrCodeValid(inputValue)) { - message.error("Invalid stock item code"); + messageApi.error( + t( + "equipmentDocumentationOverview.messageErrorInvalidStockItem" + ) + ); return; } setScannerResult(inputValue); }} > - Search + {t( + "equipmentDocumentationOverview.scanEquipment.buttonSearch" + )} @@ -147,8 +163,12 @@ export default function EquipmentDocumentationOverview() { {scannerResult === "" ? ( ) : ( @@ -159,11 +179,6 @@ export default function EquipmentDocumentationOverview() { export const EmptyNote = { Image: null, Description: "" }; -const selectDocumentationTypeOptions = [ - { value: 1, label: "Repair protocol" }, - { value: 2, label: "Documentation" }, -]; - export function EquipmentDocumentationViewEditComponent({ createMode, isOpen, @@ -172,9 +187,17 @@ export function EquipmentDocumentationViewEditComponent({ stockItemId, documentationId, }) { - const [title, setTitle] = useState(createMode ? "New documentation" : ""); + const { t } = useTranslation(); + const [title, setTitle] = useState( + createMode + ? t("equipmentDocumentationViewEditComponent.titleNewDocumentation") + : "" + ); const [selectedDocumentationType, setSelectedDocumentationType] = useState( - selectDocumentationTypeOptions[0].value + t( + "equipmentDocumentationViewEditComponent.selectDocumentationTypeOptions", + { returnObjects: true } + )[0].value ); const [notes, setNotes] = useState([EmptyNote]); const [isDocumentationUploading, setIsDocumentationUploading] = @@ -199,12 +222,8 @@ export function EquipmentDocumentationViewEditComponent({ notes: updatedNotes, }; - console.log("body", body); - myFetch(`/equipment/documentation/create`, "POST", body, {}).then( (data) => { - console.log("data", data); - setIsDocumentationUploading(false); fetchDocumentation(); onCancel(); @@ -217,8 +236,6 @@ export function EquipmentDocumentationViewEditComponent({ const updatedNotes = [...notes]; - console.log("documentationResponse.current", documentationResponse.current); - updatedNotes.forEach((note, index) => { if (note.Image?.startsWith("http")) { updatedNotes[index].Image = JSON.parse( @@ -234,11 +251,7 @@ export function EquipmentDocumentationViewEditComponent({ notes: updatedNotes, }; - console.log("body", body); - myFetch(`/equipment/documentation/edit`, "POST", body, {}).then((data) => { - console.log("data", data); - setIsDocumentationUploading(false); fetchDocumentation(); onCancel(); @@ -279,7 +292,9 @@ export function EquipmentDocumentationViewEditComponent({ if (notes.length === 0) return true; if (notes.length === 1) { - return notes[0].Image === null && notes[0].Description === ""; + return ( + (notes[0].Image === null && notes[0].Description === "") || title === "" + ); } return false; @@ -294,8 +309,6 @@ export function EquipmentDocumentationViewEditComponent({ `/equipment/documentation/${stockItemId}/${documentationId}`, "GET" ).then((data) => { - console.log("data", data); - documentationResponse.current = data; setTitle(data.Title); @@ -320,6 +333,13 @@ export function EquipmentDocumentationViewEditComponent({ + } footer={ createMode ? ( - - {title} - -
- Documentation type + + {t("equipmentDocumentationViewEditComponent.textDocumentationType")} +