diff --git a/.gitignore b/.gitignore index 5687c5ff..126723cd 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,4 @@ spieldata teams-api-calls.md .run/ client/locale_parser.js - +PlayGroundTest.java diff --git a/client/src/locale/en.js b/client/src/locale/en.js index e3d285e3..388b380c 100644 --- a/client/src/locale/en.js +++ b/client/src/locale/en.js @@ -266,8 +266,13 @@ const en = { expiryDate: "Valid till", acceptedAt: "Date accepted", roleExpiryDate: "Role expiry date", - roleExpiryDateQuestion: "Set a custom role expiration period", + roleExpiryDateQuestion: "Set a custom role expiration", roleExpiryDateInfo: "This role will be removed from the user {{expiry}}", + roleExpiryDateInfoDefault: "By default this role will be removed from a user after {{days}} days", + removeRole: "Remove role", + after: "After", + on: "On", + days: "Days", customInviterDisplayNameQuestion: "Set a custom inviter name", inviterDisplayName: "Custom inviter display name for invitations", inviterDisplayNamePlaceholder: "e.g. working@home.university.nl", @@ -316,6 +321,7 @@ const en = { no: "No", ok: "OK", or: "or ", + fixed: "or set a fixed date", edit: "Edit", reset: "Reset", cancel: "Cancel", diff --git a/client/src/locale/nl.js b/client/src/locale/nl.js index 502eee04..3385e8e5 100644 --- a/client/src/locale/nl.js +++ b/client/src/locale/nl.js @@ -268,6 +268,11 @@ const nl = { roleExpiryDate: "Verloopdatum rol", roleExpiryDateQuestion: "Zet een specifieke verloopdatum voor de rol", roleExpiryDateInfo: "Deze rol wordt verwijderd van de gebruiker {{expiry}}", + roleExpiryDateInfoDefault: "Default wordt deze rol verwijderd van de gebruiker na 365 dagen", + removeRole: "Verwijder rol", + after: "Na", + on: "Op", + days: "dagen", customInviterDisplayNameQuestion: "Zet een specifieke naam voor de uitnodiger", inviterDisplayName: "Specifieke naam uitnodiger voor in de uitnodiging", inviterDisplayNamePlaceholder: "Bijv. werken@thuis.universiteit.nl", diff --git a/client/src/pages/RoleForm.jsx b/client/src/pages/RoleForm.jsx index bab2405c..fac6917e 100644 --- a/client/src/pages/RoleForm.jsx +++ b/client/src/pages/RoleForm.jsx @@ -3,6 +3,7 @@ import {useLocation, useNavigate, useParams} from "react-router-dom"; import {useAppStore} from "../stores/AppStore"; import I18n from "../locale/I18n"; import {AUTHORITIES, isUserAllowed, urnFromRole} from "../utils/UserRole"; +import Select from "react-select"; import { allProviders, consequencesRoleDeletion, @@ -30,10 +31,13 @@ import SwitchField from "../components/SwitchField"; import {dateFromEpoch, displayExpiryDate, futureDate} from "../utils/Date"; import DOMPurify from "dompurify"; import WarningIndicator from "../components/WarningIndicator"; +import {DateField} from "../components/DateField"; const DEFAULT_EXPIRY_DAYS = 365; const CUT_OFF_DELETED_USER = 5; +const removeByOptions = ["after", "on"].map(val => ({value: val, label: I18n.t(`invitations.${val}`)})) + export const RoleForm = () => { const location = useLocation(); const navigate = useNavigate(); @@ -62,6 +66,7 @@ export const RoleForm = () => { const [applications, setApplications] = useState([]); const [provisionings, setProvisionings] = useState({}); const [deletedUserRoles, setDeletedUserRoles] = useState(null); + const [removeRoleBy, setRemoveRoleBy] = useState(removeByOptions[0]); const allowedToEditApplication = useState(isUserAllowed(AUTHORITIES.INSTITUTION_ADMIN, user)); @@ -81,6 +86,10 @@ export const RoleForm = () => { } Promise.all(promises).then(res => { if (!newRole) { + if (res[0].defaultExpiryDate !== 0) { + res[0].defaultExpiryDate = new Date(res[0].defaultExpiryDate * 1000); + setRemoveRoleBy(removeByOptions[1]); + } setRole(res[0]); setCustomRoleExpiryDate(res[0].defaultExpiryDays !== DEFAULT_EXPIRY_DAYS) setCustomInviterDisplayName(!isEmpty(res[0].inviterDisplayName)) @@ -178,6 +187,15 @@ export const RoleForm = () => { }) } + const toggleRemoveBy = option => { + setRemoveRoleBy(option); + if (option.value === "after") { + setRole({...role, defaultExpiryDays: DEFAULT_EXPIRY_DAYS, defaultExpiryDate: null}); + } else { + setRole({...role, defaultExpiryDays: 0, defaultExpiryDate: futureDate(365, new Date())}); + } + } + const updateUserIfNecessary = (path, flashMessage) => { if (user.userRoles.some(userRole => userRole.role.id === role.id)) { //We need to refresh the roles of the User to ensure 100% consistency @@ -243,7 +261,7 @@ export const RoleForm = () => { && validOrganizationGUID && !isEmpty(applications[0]) && applications.every(app => !app || (!app.invalid && !isEmpty(app.landingPage))) - && role.defaultExpiryDays > 0 + && (role.defaultExpiryDays > 0 || role.defaultExpiryDate !== null) && (!isEmpty(role.inviterDisplayName) || !customInviterDisplayName); } @@ -277,6 +295,12 @@ export const RoleForm = () => { setApplications([...applications]); } + const deriveExpiryDate = () => { + console.log(`defaultExpityDate ${role.defaultExpiryDate}, defaultExpiryDays: ${role.defaultExpiryDays}`) + const expiryDate = isEmpty(role.defaultExpiryDate) ? futureDate(role.defaultExpiryDays, new Date()) : role.defaultExpiryDate; + return displayExpiryDate(expiryDate); + + }; const renderForm = () => { const valid = isValid(); const disabledSubmit = (!valid && !initial) || !validOrganizationGUID; @@ -439,27 +463,63 @@ export const RoleForm = () => { setCustomRoleExpiryDate(!customRoleExpiryDate)} - label={I18n.t("invitations.roleExpiryDateQuestion")} - info={I18n.t("invitations.roleExpiryDateInfo", { - expiry: displayExpiryDate(futureDate(role.defaultExpiryDays, new Date())) + onChange={() => { + if (customRoleExpiryDate) { + setRole({ + ...role, + defaultExpiryDays: DEFAULT_EXPIRY_DAYS, + defaultExpiryDate: null + }); + setRemoveRoleBy(removeByOptions[0]); + } + setCustomRoleExpiryDate(!customRoleExpiryDate); + }} + label={I18n.t(`invitations.roleExpiryDateQuestion`)} + info={I18n.t(`invitations.roleExpiryDateInfo${role.defaultExpiryDays === DEFAULT_EXPIRY_DAYS ? "Default" : ""}`, { + expiry: deriveExpiryDate(), + days: DEFAULT_EXPIRY_DAYS })} last={customRoleExpiryDate} /> - {customRoleExpiryDate && { - const val = parseInt(e.target.value); - const defaultExpiryDays = Number.isInteger(val) && val > 0 ? val : 0; - setRole( - {...role, defaultExpiryDays: defaultExpiryDays}) - }} - toolTip={I18n.t("tooltips.defaultExpiryDays")} - customClassName="inner-switch" - />} + {customRoleExpiryDate && +
+

{I18n.t("invitations.removeRole")}

+
+