diff --git a/app/src/main/ui/src/components/users/UserForm.tsx b/app/src/main/ui/src/components/users/UserForm.tsx index 7e52bf3c..b855629b 100644 --- a/app/src/main/ui/src/components/users/UserForm.tsx +++ b/app/src/main/ui/src/components/users/UserForm.tsx @@ -1,18 +1,19 @@ import {deprecated_Form as Form, Details} from "@cloudogu/ces-theme-tailwind"; +import type {NotifyFunction, UseFormHandlerFunctions} from "@cloudogu/deprecated-ces-theme-tailwind"; import {Button, H2, ListWithSearchbar} from "@cloudogu/deprecated-ces-theme-tailwind"; import {TrashIcon} from "@heroicons/react/24/outline"; +import {ChangeEvent, useState} from "react"; import {twMerge} from "tailwind-merge"; import {t} from "../../helpers/i18nHelpers"; import {useConfirmation} from "../../hooks/useConfirmation"; import {Prompt} from "../../hooks/usePrompt"; import useUserFormHandler from "../../hooks/useUserFormHandler"; +import type {Group} from "../../services/Groups"; import {GroupsService} from "../../services/Groups"; import {ConfirmationDialog} from "../ConfirmationDialog"; import {useApplicationContext} from "../contexts/ApplicationContext"; import HelpLink from "../helpLink"; -import type {Group} from "../../services/Groups"; import type {User} from "../../services/Users"; -import type {NotifyFunction, UseFormHandlerFunctions} from "@cloudogu/deprecated-ces-theme-tailwind"; const MAX_SEARCH_RESULTS = 10; @@ -31,9 +32,17 @@ export interface UserFormProps { export default function UserForm(props: UserFormProps) { const {handler, notification, notify} = useUserFormHandler(props.initialUser, (values: T) => props.onSubmit(values, notify, handler)); const {open, setOpen: toggleModal, targetName: groupName, setTargetName: setGroupName} = useConfirmation(); + const [formDisabled, setFormDisabled] = useState(true); const {admin} = useApplicationContext().casUser; + const originalChangeFunction = handler.handleChange; + + handler.handleChange = (e:ChangeEvent) => { + originalChangeFunction(e); + hasEmptyRequiredFields(); + }; + const addGroup = (groupName: string): void => { if (handler.values.memberOf.indexOf(groupName) < 0) { const newGroups = [...handler.values.memberOf, groupName]; @@ -83,6 +92,24 @@ export default function UserForm(props: UserFormProps) { /> ); + const hasEmptyRequiredFields = (): void => { + const form = document.forms.item(0); + console.log("Check for null values"); + if (form) { + const inputs: NodeListOf = form.querySelectorAll("input:required"); + for (const input of inputs) { + if (!input.value) { + setFormDisabled(true); + return; + } + } + setFormDisabled(false); + return; + } + setFormDisabled(true); + return; + }; + return ( <> (props: UserFormProps) { {t("users.externalUserWarning")} )} - + {t("editUser.labels.username")} - + {t("editUser.labels.givenName")} - + {t("editUser.labels.surname")} - + {t("editUser.labels.displayName")} - + {t("editUser.labels.email")} {!props.initialUser.external && <> - + {t("editUser.labels.password")} - + {t("editUser.labels.confirmPassword")} @@ -156,7 +183,7 @@ export default function UserForm(props: UserFormProps) { )}
- {props.additionalButtons as JSX.Element} diff --git a/app/src/main/ui/src/i18n/de.json b/app/src/main/ui/src/i18n/de.json index 4133fd45..4e4af75f 100644 --- a/app/src/main/ui/src/i18n/de.json +++ b/app/src/main/ui/src/i18n/de.json @@ -21,15 +21,15 @@ "editUser.errors.username.maxlength": "Darf höchstens 128 zeichen enthalten", "editUser.errors.username.minlength": "Muss mindestens 2 Zeichen enthalten", "editUser.errors.username.required": "Nutzername muss ausgefüllt sein.", - "editUser.labels.confirmPassword": "Passwort bestätigen", - "editUser.labels.displayName": "Anzeigename", - "editUser.labels.email": "E-Mail", + "editUser.labels.confirmPassword": "Passwort bestätigen*", + "editUser.labels.displayName": "Anzeigename*", + "editUser.labels.email": "E-Mail*", "editUser.labels.external": "Externer Account", - "editUser.labels.givenName": "Vorname", + "editUser.labels.givenName": "Vorname*", "editUser.labels.mustChangePassword": "Nutzer muss sein Passwort beim nächsten Login ändern", - "editUser.labels.password": "Passwort", - "editUser.labels.surname": "Nachname", - "editUser.labels.username": "Nutzername", + "editUser.labels.password": "Passwort*", + "editUser.labels.surname": "Nachname*", + "editUser.labels.username": "Nutzername*", "editUser.notification.error": "Die Account Informationen konnten nicht gespeichert werden. Bitte versuchen Sie es später erneut.", "editUser.notification.success": "Die Account Informationen wurden erfolgreich gespeichert.", "general.applicationName": "User Management", diff --git a/app/src/main/ui/src/i18n/en.json b/app/src/main/ui/src/i18n/en.json index 2081704a..4feea53b 100644 --- a/app/src/main/ui/src/i18n/en.json +++ b/app/src/main/ui/src/i18n/en.json @@ -21,15 +21,15 @@ "editUser.errors.username.maxlength": "May contain a maximum of 128 characters", "editUser.errors.username.minlength": "Must contain at least 2 characters", "editUser.errors.username.required": "Username is required.", - "editUser.labels.confirmPassword": "Confirm Password", - "editUser.labels.displayName": "Display Name", - "editUser.labels.email": "E-Mail", + "editUser.labels.confirmPassword": "Confirm Password*", + "editUser.labels.displayName": "Display Name*", + "editUser.labels.email": "E-Mail*", "editUser.labels.external": "External account", - "editUser.labels.givenName": "Given Name", + "editUser.labels.givenName": "Given Name*", "editUser.labels.mustChangePassword": "The user must change the password at the next login", - "editUser.labels.password": "Password", - "editUser.labels.surname": "Surname", - "editUser.labels.username": "Username", + "editUser.labels.password": "Password*", + "editUser.labels.surname": "Surname*", + "editUser.labels.username": "Username*", "editUser.notification.error": "Account information could not be saved. Please try again later.", "editUser.notification.success": "Account information saved successfully.", "general.applicationName": "User Management", diff --git a/yarn.lock b/yarn.lock index b54b7b97..a192a973 100644 --- a/yarn.lock +++ b/yarn.lock @@ -107,7 +107,7 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" -assert-plus@^1.0.0, assert-plus@1.0.0: +assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== @@ -401,7 +401,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.6, "enquirer@>= 2.3.0 < 3": +enquirer@^2.3.6: version "2.4.1" resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz" integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== @@ -469,7 +469,7 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@^1.2.0, extsprintf@1.3.0: +extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== @@ -784,7 +784,7 @@ minimist@^1.2.8: resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -ms@^2.1.1, ms@2.1.2: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==