diff --git a/README.md b/README.md index 8e4ae94..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,15 +0,0 @@ -# Jannex Admin Dashboard - -With this system you can easily run your Python scripts and visualize them in the user interface to manage them more easily. You can see who started the task and who worked on it later in the task view. When a group task is started, the backend server starts the Python script and sends the result to the web UI. The web UI can then be used to start the other tasks or to repeat or undo the current task. - -## Features - -- Dynamic Group Task System -- Equipment Documentation System -- Advanced log system with log viewer and log filter -- Robot control system -- Role System -- Scanner integration to use mobile or pc devices as qrcode scanners -- User login system -- User deactivation system -- User API key system diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index a23345c..ca88ee6 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -8,7 +8,12 @@ "confirm": "Bestätigen", "create": "Erstellen" }, - "contactAdmin": "Bitte kontaktieren Sie einen Administrator" + "action": "Aktion", + "contactAdmin": "Bitte kontaktieren Sie einen Administrator", + "username": "Anzeigename", + "accountName": "Benutzername", + "password": "Passwort", + "noDataFound": "Keine Daten gefunden" }, "pageNotFound": { "title": "Seite nicht gefunden", @@ -28,5 +33,12 @@ "calendar": "Kalender", "support": "Unterstützung", "feedback": "Feedback" + }, + "employees": { + "pageTitle": "Mitarbeiter", + "addEmployee": "Mitarbeiter anlegen", + "modalAddEmployee": { + "checkboxPasswordChange": "Mitarbeiter auffordern, das Passwort zu ändern (empfohlen)" + } } } diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 9c82a7f..6e35f47 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -8,7 +8,12 @@ "confirm": "Confirm", "create": "Create" }, - "contactAdmin": "Please contact an administrator" + "action": "Action", + "contactAdmin": "Please contact an administrator", + "username": "Username", + "accountName": "Account name", + "password": "Password", + "noDataFound": "No data found" }, "pageNotFound": { "title": "Page Not Found", @@ -28,5 +33,12 @@ "calendar": "Calendar", "support": "Support", "feedback": "Feedback" + }, + "employees": { + "pageTitle": "Employees", + "addEmployee": "Add employee", + "modalAddEmployee": { + "checkboxPasswordChange": "Require employee to change password (recommended)" + } } } diff --git a/src/Components/MyTable/index.js b/src/Components/MyTable/index.js new file mode 100644 index 0000000..1058b4d --- /dev/null +++ b/src/Components/MyTable/index.js @@ -0,0 +1,27 @@ +import { Table } from "antd"; +import { useTranslation } from "react-i18next"; + +export default function MyTable({ props }) { + const { t } = useTranslation(); + + return ( + + {t("common.noDataFound")} + + ), + }} + /> + ); +} diff --git a/src/Pages/Employees/index.js b/src/Pages/Employees/index.js index 8fe4044..7ab508b 100644 --- a/src/Pages/Employees/index.js +++ b/src/Pages/Employees/index.js @@ -1,67 +1,217 @@ -import { PlusOutlined } from "@ant-design/icons"; -import { Button, Table } from "antd"; +import { LockOutlined, PlusOutlined, UserOutlined } from "@ant-design/icons"; +import { Button, Checkbox, Col, Form, Grid, Input, Row, Table } from "antd"; +import MyModal, { + MyModalCloseCreateButtonFooter, +} from "../../Components/MyModal"; +import { useEffect, useState } from "react"; +import { Constants, myFetch, EncodeStringToBase64 } from "../../utils"; +import { useTranslation } from "react-i18next"; +import MyTable from "../../Components/MyTable"; + +const { useBreakpoint } = Grid; export default function Employees() { + const { t } = useTranslation(); + const screenBreakpoint = useBreakpoint(); + + const [employees, setEmployees] = useState([]); + const [isAddEmployeeModalOpen, setIsAddEmployeeModalOpen] = useState(false); + const [username, setUsername] = useState(""); + const [accountName, setAccountName] = useState(""); + const [password, setPassword] = useState(""); + const [isRequesting, setIsRequesting] = useState(false); + const getTableColumns = () => { return [ { - title: "Name", - dataIndex: "name", - key: "name", + title: t("common.accountName"), + dataIndex: "account_name", + key: "account_name", }, { - title: "Age", - dataIndex: "age", - key: "age", + title: t("common.username"), + dataIndex: "username", + key: "username", }, { - title: "Action", + title: t("common.action"), dataIndex: "action", key: "actions", - render: () => Delete, + render: () => {t("common.button.delete")}, }, ]; }; const getTableItems = () => { - return [ - { - key: "1", - name: "John Brown", - age: 32, - address: "New York No. 1 Lake Park", - }, - { - key: "2", - name: "Jim Green", - age: 42, - address: "London No. 1 Lake Park", - }, - { - key: "3", - name: "Joe Black", - age: 32, - address: "Sidney No. 1 Lake Park", - }, - ]; + return employees.map((employee) => { + return { + key: employee.account_name, + account_name: employee.account_name, + username: employee.username, + }; + }); }; + const handleAddEmployeeModalClose = () => { + setIsAddEmployeeModalOpen(false); + setUsername(""); + setAccountName(""); + setPassword(""); + }; + + const fetchEmployees = () => { + myFetch("/users", "GET") + .then((data) => { + setIsRequesting(false); + setEmployees(data.employees); + }) + .catch((errStatus) => { + console.log(errStatus); + }); + }; + + useEffect(() => { + setIsRequesting(true); + + fetchEmployees(); + }, []); + return ( <>
-

Employees

-
-
+ + + { + setIsRequesting(true); + + myFetch("/users", "POST", { + username: username, + accountName: accountName, + password: EncodeStringToBase64(password), + }) + .then(() => { + setIsRequesting(false); + handleAddEmployeeModalClose(); + + fetchEmployees(); + }) + .catch((errStatus) => { + console.log(errStatus); + + setIsRequesting(false); + }); + }} + /> + } + > +
+ + } + placeholder={t("common.username")} + value={username} + onChange={(e) => setUsername(e.target.value)} + minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH} + maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH} + /> + + + + } + placeholder={t("common.accountName")} + value={accountName} + onChange={(e) => setAccountName(e.target.value)} + minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH} + maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH} + /> + + + + } + placeholder={t("common.password")} + value={password} + onChange={(e) => setPassword(e.target.value)} + minLength={Constants.GLOBALS.MIN_PASSWORD_LENGTH} + maxLength={Constants.GLOBALS.MAX_PASSWORD_LENGTH} + /> + + + + + {t("employees.modalAddEmployee.checkboxPasswordChange")} + + + +
); } diff --git a/src/Pages/Login/index.js b/src/Pages/Login/index.js index 3f8f261..380fb09 100644 --- a/src/Pages/Login/index.js +++ b/src/Pages/Login/index.js @@ -11,6 +11,7 @@ import { useState } from "react"; export default function Login() { const [username, setUsername] = useState(""); + const [accountName, setAccountName] = useState(""); const [password, setPassword] = useState(""); const [api, contextHolder] = notification.useNotification(); @@ -27,14 +28,14 @@ export default function Login() { api["error"]({ message: "Login failed", - description: "Please check your username and password!", + description: "Please check your accountName and password!", }); }; const handleSubmit = () => { if ( - username.length > Constants.GLOBALS.MAX_USERNAME_LENGTH || - username.length < Constants.GLOBALS.MIN_USERNAME_LENGTH || + accountName.length > Constants.GLOBALS.MAX_ACCOUNT_NAME_LENGTH || + accountName.length < Constants.GLOBALS.MIN_ACCOUNT_NAME_LENGTH || password.length > Constants.GLOBALS.MAX_PASSWORD_LENGTH || password.length < Constants.GLOBALS.MIN_PASSWORD_LENGTH ) { @@ -42,13 +43,19 @@ export default function Login() { return; } + let body = { + accountName: accountName.toLocaleLowerCase(), + password: EncodeStringToBase64(password), + }; + + if (selectedMethod === "2") { + body.username = username; + } + myFetch( `/user/auth/${selectedMethod === "1" ? "login" : "signup"}`, "POST", - { - username: username, - password: EncodeStringToBase64(password), - }, + body, {}, myFetchContentType.JSON, "", @@ -102,25 +109,50 @@ export default function Login() { />
+ {selectedMethod === "2" && ( + + } + placeholder="Anzeigename" + onChange={(e) => setUsername(e.target.value)} + minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH} + maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH} + /> + + )} + } placeholder="Benutzername" - onChange={(e) => setUsername(e.target.value)} - minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH} - maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH} + onChange={(e) => setAccountName(e.target.value)} + minLength={Constants.GLOBALS.MIN_ACCOUNT_NAME_LENGTH} + maxLength={Constants.GLOBALS.MAX_ACCOUNT_NAME_LENGTH} /> +