From 98f596bba81fb5ea43e07824e6750388a6e6cbfc Mon Sep 17 00:00:00 2001 From: Arnei Date: Thu, 10 Oct 2024 10:26:36 +0200 Subject: [PATCH 1/6] Display LifeCyclePolicies in UI (read-only) Adds a new tab to recordings called "LifeCycle Policies". Much like other tabs this tab displays information on its subject in a table format. Unlike i.e. the events tab, the LifeCycle Policies cannot be changed in any way, just be viewed. Editing is supposed to be added at a later date. Depends on PR https://github.com/opencast/opencast/pull/6139 being merged to make any sense. Similarly, if you would like to test this, your admin interface should point to an Opencast with the PR installed. --- src/App.tsx | 3 + src/components/events/Events.tsx | 19 +++ src/components/events/LifeCyclePolicies.tsx | 151 ++++++++++++++++++ src/components/events/Series.tsx | 21 ++- .../partials/LifeCyclePolicyActionCell.tsx | 62 +++++++ .../partials/LifeCyclePolicyIsActiveCell.tsx | 22 +++ .../LifeCyclePolicyAccessTab.tsx | 50 ++++++ .../LifeCyclePolicyGeneralTab.tsx | 120 ++++++++++++++ .../modals/LifeCyclePolicyDetails.tsx | 54 +++++++ src/components/shared/MainNav.tsx | 25 ++- src/components/shared/modals/DetailsModal.tsx | 48 ++++++ .../lifeCyclePoliciesTableConfig.ts | 30 ++++ .../tableConfigs/lifeCyclePoliciesTableMap.ts | 11 ++ .../adminui/languages/lang-en_US.json | 42 +++++ src/selectors/lifeCycleDetailsSelectors.ts | 7 + src/selectors/lifeCycleSelectors.ts | 7 + src/slices/lifeCycleDetailsSlice.ts | 136 ++++++++++++++++ src/slices/lifeCycleSlice.ts | 112 +++++++++++++ src/slices/tableSlice.ts | 3 +- src/store.ts | 5 + src/thunks/tableThunks.ts | 51 ++++++ 21 files changed, 975 insertions(+), 4 deletions(-) create mode 100644 src/components/events/LifeCyclePolicies.tsx create mode 100644 src/components/events/partials/LifeCyclePolicyActionCell.tsx create mode 100644 src/components/events/partials/LifeCyclePolicyIsActiveCell.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx create mode 100644 src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx create mode 100644 src/components/events/partials/modals/LifeCyclePolicyDetails.tsx create mode 100644 src/components/shared/modals/DetailsModal.tsx create mode 100644 src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts create mode 100644 src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts create mode 100644 src/selectors/lifeCycleDetailsSelectors.ts create mode 100644 src/selectors/lifeCycleSelectors.ts create mode 100644 src/slices/lifeCycleDetailsSlice.ts create mode 100644 src/slices/lifeCycleSlice.ts diff --git a/src/App.tsx b/src/App.tsx index 26742260bf..bf012cc542 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,7 @@ import Acls from "./components/users/Acls"; import About from "./components/About"; import { useAppDispatch } from "./store"; import { fetchOcVersion, fetchUserInfo } from "./slices/userInfoSlice"; +import LifeCyclePolicies from "./components/events/LifeCyclePolicies"; function App() { const dispatch = useAppDispatch(); @@ -41,6 +42,8 @@ function App() { } /> + } /> + } /> } /> diff --git a/src/components/events/Events.tsx b/src/components/events/Events.tsx index 0e1337a4f6..f3e6c73fc8 100644 --- a/src/components/events/Events.tsx +++ b/src/components/events/Events.tsx @@ -15,6 +15,7 @@ import EditMetadataEventsModal from "./partials/modals/EditMetadataEventsModal"; import { eventsTemplateMap } from "../../configs/tableConfigs/eventsTableMap"; import { loadEventsIntoTable, + loadLifeCyclePoliciesIntoTable, loadSeriesIntoTable, } from "../../thunks/tableThunks"; import { fetchFilters, fetchStats, editTextFilter } from "../../slices/tableFilterSlice"; @@ -43,6 +44,7 @@ import { import { fetchSeries } from "../../slices/seriesSlice"; import EventDetailsModal from "./partials/modals/EventDetailsModal"; import { showModal } from "../../selectors/eventDetailsSelectors"; +import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice"; // References for detecting a click outside of the container of the dropdown menu const containerAction = React.createRef(); @@ -99,6 +101,14 @@ const Events = () => { dispatch(loadSeriesIntoTable()); }; + const loadLifeCyclePolicies = async () => { + // Fetching policies from server + await dispatch(fetchLifeCyclePolicies()); + + // Load policies into table + dispatch(loadLifeCyclePoliciesIntoTable()); + }; + useEffect(() => { if ("events" !== currentFilterType) { dispatch(fetchFilters("events")) @@ -230,6 +240,15 @@ const Events = () => { {t("EVENTS.EVENTS.NAVIGATION.SERIES")} )} + {hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && ( + loadLifeCyclePolicies()} + > + {t("LIFECYCLE.NAVIGATION.POLICIES")} + + )} {/* Include status bar component*/} diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx new file mode 100644 index 0000000000..19f5c46755 --- /dev/null +++ b/src/components/events/LifeCyclePolicies.tsx @@ -0,0 +1,151 @@ +import React, { useEffect, useState } from "react"; +import MainNav from "../shared/MainNav"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; +import cn from "classnames"; +import TableFilters from "../shared/TableFilters"; +import Table from "../shared/Table"; +import Notifications from "../shared/Notifications"; +import { loadEventsIntoTable, loadLifeCyclePoliciesIntoTable, loadSeriesIntoTable } from "../../thunks/tableThunks"; +import { fetchFilters, editTextFilter, fetchStats } from "../../slices/tableFilterSlice"; +import Header from "../Header"; +import NavBar from "../NavBar"; +import MainView from "../MainView"; +import Footer from "../Footer"; +import { getUserInformation } from "../../selectors/userInfoSelectors"; +import { hasAccess } from "../../utils/utils"; +import { getCurrentFilterResource } from "../../selectors/tableFilterSelectors"; +import { useAppDispatch, useAppSelector } from "../../store"; +import { AsyncThunk } from "@reduxjs/toolkit"; +import { AsyncThunkConfig } from "@reduxjs/toolkit/dist/createAsyncThunk"; +import { getTotalLifeCyclePolicies } from "../../selectors/lifeCycleSelectors"; +import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice"; +import { lifeCyclePoliciesTemplateMap } from "../../configs/tableConfigs/lifeCyclePoliciesTableMap"; +import { fetchEvents } from "../../slices/eventSlice"; +import { setOffset } from "../../slices/tableSlice"; +import { fetchSeries } from "../../slices/seriesSlice"; + +/** + * This component renders the table view of policies + */ +const LifeCyclePolicies = () => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const [displayNavigation, setNavigation] = useState(false); + + const user = useAppSelector(state => getUserInformation(state)); + const policiesTotal = useAppSelector(state => getTotalLifeCyclePolicies(state)); + const currentFilterType = useAppSelector(state => getCurrentFilterResource(state)); + + const loadEvents = async () => { + // Fetching stats from server + dispatch(fetchStats()); + + // Fetching events from server + await dispatch(fetchEvents()); + + // Load events into table + dispatch(loadEventsIntoTable()); + }; + + const loadSeries = () => { + // Reset the current page to first page + dispatch(setOffset(0)); + + //fetching series from server + dispatch(fetchSeries()); + + //load series into table + dispatch(loadSeriesIntoTable()); + }; + + const loadLifeCyclePolicies = async () => { + // Fetching policies from server + await dispatch(fetchLifeCyclePolicies()); + + // Load policies into table + dispatch(loadLifeCyclePoliciesIntoTable()); + }; + + useEffect(() => { + if ("lifeCyclePolicies" !== currentFilterType) { + dispatch(fetchFilters("lifeCyclePolicies")); + } + + // Reset text filter + dispatch(editTextFilter("")); + + // Load policies on mount + loadLifeCyclePolicies().then((r) => console.info(r)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const toggleNavigation = () => { + setNavigation(!displayNavigation); + }; + + return ( + <> +
+ + {/* Include Burger-button menu*/} + + + + + + + {/* Include notifications component */} + + +
+ {/* Include filters component */} + {/* LifeCycle policies are not indexed, can't search or filter them */} + {/* But if we don't include this component, the policies won't load on page load, because the first + fetch request we send to the backend contains invalid params >.> */} + } + loadResourceIntoTable={loadLifeCyclePoliciesIntoTable} + resource={"lifeCyclePolicies"} + /> + +

{t("LIFECYCLE.POLICIES.TABLE.CAPTION")}

+

{t("TABLE_SUMMARY", { numberOfRows: policiesTotal })}

+
+ {/* Include table component */} + + +
+ + ); +}; + +export default LifeCyclePolicies; diff --git a/src/components/events/Series.tsx b/src/components/events/Series.tsx index 4dcce7f070..537ba99094 100644 --- a/src/components/events/Series.tsx +++ b/src/components/events/Series.tsx @@ -11,6 +11,7 @@ import DeleteSeriesModal from "./partials/modals/DeleteSeriesModal"; import { seriesTemplateMap } from "../../configs/tableConfigs/seriesTableMap"; import { loadEventsIntoTable, + loadLifeCyclePoliciesIntoTable, loadSeriesIntoTable, } from "../../thunks/tableThunks"; import { fetchFilters, fetchStats, editTextFilter } from "../../slices/tableFilterSlice"; @@ -34,6 +35,7 @@ import { showActionsSeries, } from "../../slices/seriesSlice"; import { fetchSeriesDetailsTobiraNew } from "../../slices/seriesSlice"; +import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice"; // References for detecting a click outside of the container of the dropdown menu const containerAction = React.createRef(); @@ -79,6 +81,14 @@ const Series = () => { dispatch(loadSeriesIntoTable()); }; + const loadLifeCyclePolicies = async () => { + // Fetching policies from server + await dispatch(fetchLifeCyclePolicies()); + + // Load policies into table + dispatch(loadLifeCyclePoliciesIntoTable()); + }; + useEffect(() => { if ("series" !== currentFilterType) { dispatch(fetchFilters("series")) @@ -186,8 +196,17 @@ const Series = () => { {t("EVENTS.EVENTS.NAVIGATION.SERIES")} )} + {hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && ( + loadLifeCyclePolicies()} + > + {t("LIFECYCLE.NAVIGATION.POLICIES")} + + )} - +
{hasAccess("ROLE_UI_SERIES_CREATE", user) && (
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TITLE")}{policy.title}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}{ + + }
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISCREATEDFROMCONFIG")}{ + + }
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETTYPE")}{t(policy.targetType)}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS")} + + + {Object.entries(policy.targetFilters).map(([key, value], index) => { + return( + + + + + ) + })} + +
{key}{value.value + ", " + value.type + ", " + value.must}
+
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TIMING")}{t(policy.timing)}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")}{t("dateFormats.dateTime.full", { dateTime: renderValidDate(policy.actionDate) })}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")}{policy.cronTrigger}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTION")}{t(policy.action)}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS")} + + + {Object.entries(policy.actionParameters).map(([key, value], index) => { + return( + + + + + ) + })} + +
{key}{value}
+
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ID")}{policy.id}
+ + + + + + ); +}; + +export default LifeCyclePolicyGeneralTab; diff --git a/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx new file mode 100644 index 0000000000..e818dd57c2 --- /dev/null +++ b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx @@ -0,0 +1,54 @@ +import React, { useState } from "react"; +import ModalNavigation from "../../../shared/modals/ModalNavigation"; +import { getLifeCyclePolicyDetails } from "../../../../selectors/lifeCycleDetailsSelectors"; +import LifeCyclePolicyGeneralTab from "../ModalTabsAndPages/LifeCyclePolicyGeneralTab"; +import LifeCyclePolicyDetailsAccessTab from "../ModalTabsAndPages/LifeCyclePolicyAccessTab"; +import { useAppSelector } from "../../../../store"; + +/** + * This component manages the tabs of the series details modal + */ +const LifeCyclePolicyDetails = () => { + const [page, setPage] = useState(0); + + const policy = useAppSelector(state => getLifeCyclePolicyDetails(state)); + + // information about tabs + const tabs = [ + { + tabTranslation: "LIFECYCLE.POLICIES.DETAILS.TAB.GENERAL", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_DETAILS_GENERAL_VIEW", + name: "general", + }, + { + tabTranslation: "LIFECYCLE.POLICIES.DETAILS.TAB.ACCESSPOLICIES", + accessRole: "ROLE_UI_LIFECYCLEPOLICIES_DETAILS_ACCESSPOLICIES_VIEW", + name: "WARNING: None of the changes you make here can be saved!", + }, + ]; + + const openTab = (tabNr: number) => { + setPage(tabNr); + }; + + return ( + <> + {/* Navigation */} + + +
+ {page === 0 && } + {page === 1 && + false} + /> + } +
+ + ); +}; + +export default LifeCyclePolicyDetails; diff --git a/src/components/shared/MainNav.tsx b/src/components/shared/MainNav.tsx index e0d40ab02a..5def5026a3 100644 --- a/src/components/shared/MainNav.tsx +++ b/src/components/shared/MainNav.tsx @@ -6,6 +6,7 @@ import { loadEventsIntoTable, loadGroupsIntoTable, loadJobsIntoTable, + loadLifeCyclePoliciesIntoTable, loadRecordingsIntoTable, loadSeriesIntoTable, loadServersIntoTable, @@ -34,6 +35,7 @@ import { fetchSeries } from "../../slices/seriesSlice"; import { fetchJobs } from "../../slices/jobSlice"; import { fetchEvents } from "../../slices/eventSlice"; import { Tooltip } from "./Tooltip"; +import { fetchLifeCyclePolicies } from "../../slices/lifeCycleSlice"; /** * This component renders the main navigation that opens when the burger button is clicked @@ -84,6 +86,19 @@ const MainNav = ({ dispatch(loadSeriesIntoTable()); }; + const loadLifeCyclePolicies = () => { + dispatch(fetchFilters("lifeCylePolicies")); + + // Reset the current page to first page + dispatch(setOffset(0)); + + // Fetching lifeCycle policies from server + dispatch(fetchLifeCyclePolicies()); + + // Load lifeCycle policies into table + dispatch(loadLifeCyclePoliciesIntoTable()); + }; + const loadRecordings = () => { dispatch(fetchFilters("recordings")); @@ -228,13 +243,19 @@ const MainNav = ({ - ) : ( - hasAccess("ROLE_UI_SERIES_VIEW", user) && ( + ) : hasAccess("ROLE_UI_SERIES_VIEW", user) ? ( loadSeries()}> + ) : ( + hasAccess("ROLE_UI_LIFECYCLEPOLICIES_VIEW", user) && ( + loadLifeCyclePolicies()}> + + + + ) ))} {hasAccess("ROLE_UI_NAV_CAPTURE_VIEW", user) && diff --git a/src/components/shared/modals/DetailsModal.tsx b/src/components/shared/modals/DetailsModal.tsx new file mode 100644 index 0000000000..5ebd58ec5a --- /dev/null +++ b/src/components/shared/modals/DetailsModal.tsx @@ -0,0 +1,48 @@ +import React, { PropsWithChildren } from "react"; +import { useTranslation } from "react-i18next"; +import { useHotkeys } from "react-hotkeys-hook"; +import { availableHotkeys } from "../../../configs/hotkeysConfig"; + +/** + * This component renders the modal for displaying series details + */ +const DetailsModal = ({ + handleClose, + prefix, + title, + children +}: PropsWithChildren<{ + handleClose: () => void + prefix: string + title: string +}>) => { + const { t } = useTranslation(); + + const close = () => { + handleClose(); + }; + + useHotkeys( + availableHotkeys.general.CLOSE_MODAL.sequence, + () => close(), + { description: t(availableHotkeys.general.CLOSE_MODAL.description) ?? undefined }, + [close], + ); + + return ( + <> +
+
+
+
+ {children} +
+ + ); +}; + +export default DetailsModal; diff --git a/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts b/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts new file mode 100644 index 0000000000..71a47c8a8e --- /dev/null +++ b/src/configs/tableConfigs/lifeCyclePoliciesTableConfig.ts @@ -0,0 +1,30 @@ +import { TableConfig } from "./aclsTableConfig"; + +export const lifeCyclePolicyTableConfig: TableConfig = { + columns: [ + { + name: "title", + label: "LIFECYCLE.POLICIES.TABLE.TITLE", + sortable: true, + }, + { + template: "LifeCyclePolicyIsActiveCell", + name: "isActive", + label: "LIFECYCLE.POLICIES.TABLE.ISACTIVE", + }, + { + name: "timing", + label: "LIFECYCLE.POLICIES.TABLE.TIMING", + sortable: true, + }, + { + template: "LifeCyclePolicyActionCell", + name: "actions", + label: "LIFECYCLE.POLICIES.TABLE.ACTION", + }, + ], + caption: "TABLE.CAPTION", + resource: "lifeCyclePolicies", + category: "events", + multiSelect: false, +}; diff --git a/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts b/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts new file mode 100644 index 0000000000..7a460a6363 --- /dev/null +++ b/src/configs/tableConfigs/lifeCyclePoliciesTableMap.ts @@ -0,0 +1,11 @@ +import LifeCyclePolicyActionCell from "../../components/events/partials/LifeCyclePolicyActionCell"; +import LifeCyclePolicyIsActiveCell from "../../components/events/partials/LifeCyclePolicyIsActiveCell"; + +/** + * This map contains the mapping between the template strings above and the corresponding react component. + * This helps to render different templates of cells more dynamically + */ +export const lifeCyclePoliciesTemplateMap = { + LifeCyclePolicyIsActiveCell: LifeCyclePolicyIsActiveCell, + LifeCyclePolicyActionCell: LifeCyclePolicyActionCell, +}; diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index 9ca41a06e7..cd16368d29 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -1249,6 +1249,48 @@ } } }, + "LIFECYCLE": { + "NAVIGATION": { + "POLICIES": "LifeCycle Policies" + }, + "POLICIES": { + "TABLE": { + "ACTION": "Actions", + "CAPTION": "LifeCycle Policies", + "ISACTIVE": "Active", + "TIMING": "Timing", + "TITLE": "Title", + "TOOLTIP": { + "DETAILS": "LifeCycle Policy Details" + } + }, + "DETAILS": { + "HEADER": "LifeCycle Policy Details", + "GENERAL": { + "ACTION": "Action", + "ACTIONDATE": "Action Date", + "ACTIONPARAMETERS": "Action Parameters", + "CAPTION": "LifeCycle Policy Details", + "CRONTRIGGER": "Cron Trigger", + "ID": "Identifier", + "ISACTIVE": "Active", + "ISCREATEDFROMCONFIG": "Created from Config", + "TARGETTYPE": "Target Type", + "TARGETFILTERS": "Target Filters", + "TIMING": "Timing", + "TITLE": "Title" + }, + "ACCESS": { + "LABEL": "Select a template", + "DESCRIPTION": "At least one role with Read and Write permissions is required." + }, + "TAB": { + "GENERAL": "General", + "ACCESSPOLICIES": "Access Policies" + } + } + } + }, "RECORDINGS": { "NAVIGATION": { "LOCATIONS": "Locations" diff --git a/src/selectors/lifeCycleDetailsSelectors.ts b/src/selectors/lifeCycleDetailsSelectors.ts new file mode 100644 index 0000000000..364368819a --- /dev/null +++ b/src/selectors/lifeCycleDetailsSelectors.ts @@ -0,0 +1,7 @@ +import { RootState } from "../store"; + +/** + * This file contains selectors regarding details of a certain lifeCyclePolicy/capture agent + */ +export const getLifeCyclePolicyDetails = (state: RootState) => state.lifeCyclePolicyDetails; +export const getLifeCyclePolicyDetailsAcl = (state: RootState) => state.lifeCyclePolicyDetails.accessControlEntries; diff --git a/src/selectors/lifeCycleSelectors.ts b/src/selectors/lifeCycleSelectors.ts new file mode 100644 index 0000000000..fadb641e3d --- /dev/null +++ b/src/selectors/lifeCycleSelectors.ts @@ -0,0 +1,7 @@ +import { RootState } from "../store"; + +/** + * This file contains selectors regarding acls + */ +export const getLifeCyclePolicies = (state: RootState) => state.lifeCycle.results; +export const getTotalLifeCyclePolicies = (state: RootState) => state.lifeCycle.total; diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts new file mode 100644 index 0000000000..2bba3cda56 --- /dev/null +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -0,0 +1,136 @@ +import { PayloadAction, SerializedError, createSlice } from '@reduxjs/toolkit' +import axios from 'axios'; +import { createAppAsyncThunk } from '../createAsyncThunkWithTypes'; +import { LifeCyclePolicy } from './lifeCycleSlice'; +import { TransformedAcl } from './aclDetailsSlice'; +import { createPolicy } from '../utils/resourceUtils'; +import { Ace } from './aclSlice'; + +/** + * This file contains redux reducer for actions affecting the state of a lifeCyclePolicy/capture agent + */ +interface LifeCyclePolicyDetailsState extends LifeCyclePolicy { + statusLifeCyclePolicyDetails: 'uninitialized' | 'loading' | 'succeeded' | 'failed', + errorLifeCyclePolicyDetails: SerializedError | null, +} + +// Initial state of lifeCyclePolicy details in redux store +const initialState: LifeCyclePolicyDetailsState = { + statusLifeCyclePolicyDetails: 'uninitialized', + errorLifeCyclePolicyDetails: null, + actionParameters: {}, + timing: "SPECIFIC_DATE", + action: "START_WORKFLOW", + targetType: "EVENT", + id: "", + title: "", + isActive: false, + isCreatedFromConfig: false, + actionDate: "", + cronTrigger: "", + targetFilters: {}, + accessControlEntries: [] +}; + +// fetch details of certain lifeCyclePolicy from server +export const fetchLifeCyclePolicyDetails = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyDetails', async (id: string) => { + const res = await axios.get(`/api/lifecyclemanagement/policies/${id}`); + const data = res.data; + + data.actionParameters = JSON.parse(data.actionParameters) + data.targetFilters = JSON.parse(data.targetFilters) + + let accessPolicies : { + id: number, + allow: boolean, + role: string, + action: string, + }[] = data.accessControlEntries; + let acls: TransformedAcl[] = []; + + const json = accessPolicies; + let newPolicies: { [key: string]: TransformedAcl } = {}; + let policyRoles: string[] = []; + for (let i = 0; i < json.length; i++) { + const policy: Ace = json[i]; + if (!newPolicies[policy.role]) { + newPolicies[policy.role] = createPolicy(policy.role); + policyRoles.push(policy.role); + } + if (policy.action === "read" || policy.action === "write") { + newPolicies[policy.role][policy.action] = policy.allow; + } else if (policy.allow === true) { //|| policy.allow === "true") { + newPolicies[policy.role].actions.push(policy.action); + } + } + acls = policyRoles.map((role) => newPolicies[role]); + + data.accessControlEntries = acls; + + return data; +}); + +// Dummy function for compatability +export const fetchLifeCyclePolicyDetailsAcls = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyDetailsAcls', async (id: string, {getState}) => { + const state = getState(); + return state.lifeCyclePolicyDetails.accessControlEntries; +}); + +// Dummy function for compatability +export const updateLifeCyclePolicyAccess = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyDetailsAcls', async (params: { + id: string, + policies: { acl: { ace: Ace[] } } +}, {dispatch}) => { + return false; +}); + +const lifeCyclePolicyDetailsSlice = createSlice({ + name: 'lifeCyclePolicyDetails', + initialState, + reducers: {}, + // These are used for thunks + extraReducers: builder => { + builder + .addCase(fetchLifeCyclePolicyDetails.pending, (state) => { + state.statusLifeCyclePolicyDetails = 'loading'; + }) + .addCase(fetchLifeCyclePolicyDetails.fulfilled, (state, action: PayloadAction<{ + actionParameters: LifeCyclePolicyDetailsState["actionParameters"], + timing: LifeCyclePolicyDetailsState["timing"], + action: LifeCyclePolicyDetailsState["action"], + targetType: LifeCyclePolicyDetailsState["targetType"], + id: LifeCyclePolicyDetailsState["id"], + title: LifeCyclePolicyDetailsState["title"], + isActive: LifeCyclePolicyDetailsState["isActive"], + isCreatedFromConfig: LifeCyclePolicyDetailsState["isCreatedFromConfig"], + actionDate: LifeCyclePolicyDetailsState["actionDate"], + cronTrigger: LifeCyclePolicyDetailsState["cronTrigger"], + targetFilters: LifeCyclePolicyDetailsState["targetFilters"], + accessControlEntries: LifeCyclePolicyDetailsState["accessControlEntries"], + }>) => { + state.statusLifeCyclePolicyDetails = 'succeeded'; + const lifeCyclePolicyDetails = action.payload; + state.actionParameters = lifeCyclePolicyDetails.actionParameters; + state.timing = lifeCyclePolicyDetails.timing; + state.action = lifeCyclePolicyDetails.action; + state.targetType = lifeCyclePolicyDetails.targetType; + state.id = lifeCyclePolicyDetails.id; + state.title = lifeCyclePolicyDetails.title; + state.isActive = lifeCyclePolicyDetails.isActive; + state.isCreatedFromConfig = lifeCyclePolicyDetails.isCreatedFromConfig; + state.actionDate = lifeCyclePolicyDetails.actionDate; + state.cronTrigger = lifeCyclePolicyDetails.cronTrigger; + state.targetFilters = lifeCyclePolicyDetails.targetFilters; + state.accessControlEntries = lifeCyclePolicyDetails.accessControlEntries; + }) + .addCase(fetchLifeCyclePolicyDetails.rejected, (state, action) => { + state.statusLifeCyclePolicyDetails = 'failed'; + state.errorLifeCyclePolicyDetails = action.error; + }); + } +}); + +// export const {} = lifeCyclePolicyDetailsSlice.actions; + +// Export the slice reducer as the default export +export default lifeCyclePolicyDetailsSlice.reducer; diff --git a/src/slices/lifeCycleSlice.ts b/src/slices/lifeCycleSlice.ts new file mode 100644 index 0000000000..cfa4e78192 --- /dev/null +++ b/src/slices/lifeCycleSlice.ts @@ -0,0 +1,112 @@ +import { PayloadAction, SerializedError, createSlice } from '@reduxjs/toolkit' +import { TableConfig } from "../configs/tableConfigs/aclsTableConfig"; +import { lifeCyclePolicyTableConfig } from "../configs/tableConfigs/lifeCyclePoliciesTableConfig"; +import axios from 'axios'; +import { getURLParams } from '../utils/resourceUtils'; +import { createAppAsyncThunk } from '../createAsyncThunkWithTypes'; +import { TransformedAcl } from './aclDetailsSlice'; + +type LifeCyclePolicyTiming = "SPECIFIC_DATE" | "REPEATING" | "ALWAYS"; +type LifeCyclePolicyAction = "START_WORKFLOW" +type LifeCyclePolicyTargetType = "EVENT" + +export type LifeCyclePolicy = { + actionParameters: { [key: string]: unknown }, // JSON. Variable, depends on action + timing: LifeCyclePolicyTiming, + action: LifeCyclePolicyAction, + targetType: LifeCyclePolicyTargetType, + id: string, + title: string, + isActive: boolean, + isCreatedFromConfig: boolean, + actionDate: string, // Date + cronTrigger: string, + targetFilters: { [key: string]: { + value: string, + type: "SEARCH" | "WILDCARD" | "GREATER_THAN" | "LESS_THAN", + must: boolean + }}, + accessControlEntries: TransformedAcl[] +} + +type LifeCycleState = { + status: 'uninitialized' | 'loading' | 'succeeded' | 'failed', + error: SerializedError | null, + results: LifeCyclePolicy[], + columns: TableConfig["columns"], + total: number, + count: number, + offset: number, + limit: number, +}; + +// Fill columns initially with columns defined in aclsTableConfig +const initialColumns = lifeCyclePolicyTableConfig.columns.map((column) => ({ + ...column, + deactivated: false, +})); + +// Initial state of acls in redux store +const initialState: LifeCycleState = { + status: 'uninitialized', + error: null, + results: [], + columns: initialColumns, + total: 0, + count: 0, + offset: 0, + limit: 0, +}; + +export const fetchLifeCyclePolicies = createAppAsyncThunk('lifeCycle/fetchLifeCyclePolicies', async (_, { getState }) => { + const state = getState(); + let params = getURLParams(state); + const res = await axios.get("/api/lifecyclemanagement/policies", { params: params }); + return res.data; +}); + +const lifeCycleSlice = createSlice({ + name: 'lifeCycle', + initialState, + reducers: { + setLifeCycleColumns(state, action: PayloadAction< + LifeCycleState["columns"] + >) { + state.columns = action.payload; + }, + }, + // These are used for thunks + extraReducers: builder => { + builder + .addCase(fetchLifeCyclePolicies.pending, (state) => { + state.status = 'loading'; + }) + // Pass the generated action creators to `.addCase()` + .addCase(fetchLifeCyclePolicies.fulfilled, (state, action: PayloadAction<{ + total: LifeCycleState["total"], + count: LifeCycleState["count"], + limit: LifeCycleState["limit"], + offset: LifeCycleState["offset"], + results: LifeCycleState["results"], + }>) => { + // Same "mutating" update syntax thanks to Immer + state.status = 'succeeded'; + const policies = action.payload; + state.total = policies.total; + state.count = policies.count; + state.limit = policies.limit; + state.offset = policies.offset; + state.results = policies.results; + }) + .addCase(fetchLifeCyclePolicies.rejected, (state, action) => { + state.status = 'failed'; + state.results = []; + state.error = action.error; + }); + } +}); + +export const { setLifeCycleColumns } = lifeCycleSlice.actions; + +// Export the slice reducer as the default export +export default lifeCycleSlice.reducer; diff --git a/src/slices/tableSlice.ts b/src/slices/tableSlice.ts index ae6455574e..001f95062d 100644 --- a/src/slices/tableSlice.ts +++ b/src/slices/tableSlice.ts @@ -10,6 +10,7 @@ import { AclResult } from './aclSlice'; import { ThemeDetailsType } from './themeSlice'; import { Series } from './seriesSlice'; import { Event } from './eventSlice'; +import { LifeCyclePolicy } from './lifeCycleSlice'; /* Overview of the structure of the data in arrays in state @@ -68,7 +69,7 @@ export function isSeries(row: Row | Event | Series | Recording | Server | Job | } // TODO: Improve row typing. While this somewhat correctly reflects the current state of our code, it is rather annoying to work with. -export type Row = { selected: boolean } & ( Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType ) +export type Row = { selected: boolean } & ( Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType | LifeCyclePolicy) type TableState = { status: 'uninitialized' | 'loading' | 'succeeded' | 'failed', diff --git a/src/store.ts b/src/store.ts index d6973a7233..1a6175c879 100644 --- a/src/store.ts +++ b/src/store.ts @@ -6,6 +6,7 @@ import tableFilterProfiles from "./slices/tableFilterProfilesSlice"; import events from "./slices/eventSlice"; import table from "./slices/tableSlice"; import series from "./slices/seriesSlice"; +import lifeCycle from "./slices/lifeCycleSlice"; import recordings from "./slices/recordingSlice"; import jobs from "./slices/jobSlice"; import servers from "./slices/serverSlice"; @@ -19,6 +20,7 @@ import notifications from "./slices/notificationSlice"; import workflows from "./slices/workflowSlice"; import eventDetails from "./slices/eventDetailsSlice"; import seriesDetails from "./slices/seriesDetailsSlice"; +import lifeCyclePolicyDetails from "./slices/lifeCycleDetailsSlice"; import userDetails from "./slices/userDetailsSlice"; import recordingDetails from "./slices/recordingDetailsSlice"; import groupDetails from "./slices/groupDetailsSlice"; @@ -38,6 +40,7 @@ import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2"; const tableFilterProfilesPersistConfig = { key: "tableFilterProfiles", storage, whitelist: ["profiles"] } const eventsPersistConfig = { key: "events", storage, whitelist: ["columns"] } const seriesPersistConfig = { key: "series", storage, whitelist: ["columns"] } +const lifeCyclePersistConfig = { key: "lifeCycle", storage, whitelist: ["columns"] } const tablePersistConfig = { key: "table", storage, whitelist: ["pagination"] } const recordingsPersistConfig = { key: "recordings", storage, whitelist: ["columns"] } const jobsPersistConfig = { key: "jobs", storage, whitelist: ["columns"] } @@ -54,6 +57,7 @@ const reducers = combineReducers({ tableFilterProfiles: persistReducer(tableFilterProfilesPersistConfig, tableFilterProfiles), events: persistReducer(eventsPersistConfig, events), series: persistReducer(seriesPersistConfig, series), + lifeCycle: persistReducer(lifeCyclePersistConfig, lifeCycle), table: persistReducer(tablePersistConfig, table), recordings: persistReducer(recordingsPersistConfig, recordings), jobs: persistReducer(jobsPersistConfig, jobs), @@ -69,6 +73,7 @@ const reducers = combineReducers({ eventDetails, themeDetails, seriesDetails, + lifeCyclePolicyDetails, recordingDetails, userDetails, groupDetails, diff --git a/src/thunks/tableThunks.ts b/src/thunks/tableThunks.ts index 45b92c27b0..95b7b13417 100644 --- a/src/thunks/tableThunks.ts +++ b/src/thunks/tableThunks.ts @@ -44,6 +44,8 @@ import { fetchRecordings, setRecordingsColumns } from "../slices/recordingSlice" import { setGroupColumns } from "../slices/groupSlice"; import { fetchAcls, setAclColumns } from "../slices/aclSlice"; import { AppDispatch, AppThunk, RootState } from "../store"; +import { lifeCyclePolicyTableConfig } from "../configs/tableConfigs/lifeCyclePoliciesTableConfig"; +import { fetchLifeCyclePolicies, setLifeCycleColumns } from "../slices/lifeCycleSlice"; /** * This file contains methods/thunks used to manage the table in the main view and its state changes @@ -147,6 +149,40 @@ export const loadSeriesIntoTable = (): AppThunk => (dispatch, getState) => { dispatch(loadResourceIntoTable(tableData)); }; +export const loadLifeCyclePoliciesIntoTable = (): AppThunk => (dispatch, getState) => { + const { lifeCycle, table } = getState() as RootState; + const pagination = table.pagination; + const resource = lifeCycle.results; + const total = lifeCycle.total; + + const pages = calculatePages(total / pagination.limit, pagination.offset); + + let tableData = { + resource: "lifeCyclePolicies", + rows: resource.map((obj) => { + return { ...obj, selected: false } + }), + columns: lifeCycle.columns, + multiSelect: table.multiSelect, + pages: pages, + sortBy: table.sortBy, + reverse: table.reverse, + totalItems: total, + }; + + if (table.resource !== "lifeCyclePolicies") { + const multiSelect = lifeCyclePolicyTableConfig.multiSelect; + + tableData = { + ...tableData, + sortBy: "title", + reverse: "ASC", + multiSelect: multiSelect, + }; + } + dispatch(loadResourceIntoTable(tableData)); +} + export const loadRecordingsIntoTable = (): AppThunk => (dispatch, getState) => { const { recordings, table } = getState() as RootState; const pagination = table.pagination; @@ -444,6 +480,11 @@ export const goToPage = (pageNumber: number) => async (dispatch: AppDispatch, ge dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + await dispatch(fetchLifeCyclePolicies()); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { await dispatch(fetchRecordings()); dispatch(loadRecordingsIntoTable()); @@ -513,6 +554,11 @@ export const updatePages = () => async (dispatch: AppDispatch, getState: () => R dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + await dispatch(fetchLifeCyclePolicies()); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { await dispatch(fetchRecordings()); dispatch(loadRecordingsIntoTable()); @@ -625,6 +671,11 @@ export const changeColumnSelection = (updatedColumns: TableConfig["columns"]) => dispatch(loadSeriesIntoTable()); break; } + case "lifeCyclePolicies": { + await dispatch(setLifeCycleColumns(updatedColumns)); + dispatch(loadLifeCyclePoliciesIntoTable()); + break; + } case "recordings": { await dispatch(setRecordingsColumns(updatedColumns)); dispatch(loadRecordingsIntoTable()); From 5e5a850e06a021781b2e2c50931cd9d424aae148 Mon Sep 17 00:00:00 2001 From: Arnei Date: Mon, 14 Oct 2024 09:37:07 +0200 Subject: [PATCH 2/6] Fix typescript complaint Type LifeCyclePolicy was missing on a union type. --- src/slices/tableSlice.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slices/tableSlice.ts b/src/slices/tableSlice.ts index 001f95062d..4efd01de3e 100644 --- a/src/slices/tableSlice.ts +++ b/src/slices/tableSlice.ts @@ -60,11 +60,11 @@ export function isRowSelectable(row: Row) { return false; } -export function isEvent(row: Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType): row is Event { +export function isEvent(row: Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType | LifeCyclePolicy): row is Event { return (row as Event).event_status !== undefined; } -export function isSeries(row: Row | Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType): row is Series { +export function isSeries(row: Row | Event | Series | Recording | Server | Job | Service | UserResult | Group | AclResult | ThemeDetailsType | LifeCyclePolicy): row is Series { return (row as Series).organizers !== undefined; } From c2d1c40f1d9006cadbdc4db448645626acb56f31 Mon Sep 17 00:00:00 2001 From: Arnei Date: Mon, 4 Nov 2024 11:40:05 +0100 Subject: [PATCH 3/6] Add Create, Edit, Delete for LifeCycle Policies Instead of only being able to view lifecycle policies, this commit lets you edit them, create new ones and even delete them. Depends on changes to the backend. --- package-lock.json | 2448 ++++++++++++----- package.json | 1 + src/components/events/LifeCyclePolicies.tsx | 39 + .../partials/LifeCyclePolicyActionCell.tsx | 37 +- .../LifeCyclePolicyAccessTab.tsx | 2 + .../LifeCyclePolicyGeneralTab.tsx | 265 +- .../NewLifeCyclePolicyGeneralPage.tsx | 40 + .../modals/LifeCyclePolicyDetails.tsx | 24 +- .../wizards/LifeCyclePolicyGeneralFields.tsx | 475 ++++ .../wizards/NewLifeCyclePolicySummary.tsx | 114 + .../wizards/NewLifeCyclePolicyWizard.tsx | 177 ++ .../partials/wizards/RenderWorkflowConfig.tsx | 24 +- src/components/shared/ConfirmModal.tsx | 2 +- src/components/shared/DropDown.tsx | 2 +- src/components/shared/NewResourceModal.tsx | 10 +- src/components/shared/wizard/RenderField.tsx | 68 +- .../shared/wizard/RenderMultiField.tsx | 2 +- src/configs/modalConfig.ts | 31 + .../adminui/languages/lang-en_US.json | 38 +- src/selectors/lifeCycleDetailsSelectors.ts | 3 + src/slices/lifeCycleDetailsSlice.ts | 96 +- src/slices/lifeCycleSlice.ts | 95 +- src/slices/workflowSlice.ts | 2 +- src/styles/main.scss | 5 + src/utils/componentStyles.ts | 2 + src/utils/dropDownUtils.ts | 13 +- src/utils/lifeCycleUtils.ts | 16 + src/utils/utils.ts | 10 + src/utils/validate.ts | 27 + 29 files changed, 3240 insertions(+), 828 deletions(-) create mode 100644 src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx create mode 100644 src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx create mode 100644 src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx create mode 100644 src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx create mode 100644 src/utils/lifeCycleUtils.ts diff --git a/package-lock.json b/package-lock.json index be31794a2a..e1ac46744a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "react-hotkeys-hook": "^4.5.1", "react-i18next": "^15.1.0", "react-icons": "^5.3.0", + "react-js-cron": "^5.0.1", "react-redux": "^9.1.2", "react-router-dom": "^6.27.0", "react-select": "^5.8.0", @@ -83,6 +84,115 @@ "node": ">=6.0.0" } }, + "node_modules/@ant-design/colors": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.1.0.tgz", + "integrity": "sha512-MMoDGWn1y9LdQJQSHiCC20x3uZ3CwQnv9QMz6pCmJOrqdgM9YxsoVVY0wtrdXbmfSgnV0KNk6zi09NAhMR2jvg==", + "peer": true, + "dependencies": { + "@ctrl/tinycolor": "^3.6.1" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.22.0.tgz", + "integrity": "sha512-W9XSFeRPR0mAN3OuxfuS/xhENCYKf+8s+QyNNER0FSWoK9OpISTag6CCweg6lq0hASQ/2Vcza0Z8/kGivCP0Ng==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.1.tgz", + "integrity": "sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ==", + "peer": true, + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/cssinjs/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "peer": true + }, + "node_modules/@ant-design/cssinjs/node_modules/stylis": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz", + "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", + "peer": true + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.5.1.tgz", + "integrity": "sha512-0UrM02MA2iDIgvLatWrj6YTCYe0F/cwXvVE0E2SqGrL7PZireQwgEKTKBisWpZyal5eXZLvuM98kju6YtYne8w==", + "peer": true, + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "peer": true + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -2252,6 +2362,15 @@ "node": ">=6.9.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -2270,6 +2389,11 @@ "stylis": "4.2.0" } }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2290,13 +2414,13 @@ } }, "node_modules/@emotion/cache": { - "version": "11.13.1", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", - "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.5.tgz", + "integrity": "sha512-Z3xbtJ+UcK76eWkagZ1onvn/wAVb1GOMuR15s30Fm2wrMgC7jzpnO2JZXr4eujTTqoQFUrZIw/rT0c6Zzjca1g==", "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.0", + "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } @@ -2312,9 +2436,10 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "peer": true }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.2", @@ -2353,17 +2478,22 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz", - "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.1", + "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, + "node_modules/@emotion/serialize/node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", @@ -2417,9 +2547,9 @@ } }, "node_modules/@emotion/utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz", - "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==" }, "node_modules/@emotion/weak-memoize": { "version": "0.3.1", @@ -2545,9 +2675,9 @@ } }, "node_modules/@floating-ui/react": { - "version": "0.26.27", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.27.tgz", - "integrity": "sha512-jLP72x0Kr2CgY6eTYi/ra3VA9LOkTo4C+DUTrbFgFOExKy3omYVmwMjNKqxAHdsnyLS96BIDLcO2SlnsNf8KUQ==", + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", @@ -2693,24 +2823,24 @@ "peer": true }, "node_modules/@mui/core-downloads-tracker": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.6.tgz", - "integrity": "sha512-nz1SlR9TdBYYPz4qKoNasMPRiGb4PaIHFkzLzhju0YVYS5QSuFF2+n7CsiHMIDcHv3piPu/xDWI53ruhOqvZwQ==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.10.tgz", + "integrity": "sha512-LY5wdiLCBDY7u+Od8UmFINZFGN/5ZU90fhAslf/ZtfP+5RhuY45f679pqYIxe0y54l6Gkv9PFOc8Cs10LDTBYg==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/material": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.6.tgz", - "integrity": "sha512-1yvejiQ/601l5AK3uIdUlAVElyCxoqKnl7QA+2oFB/2qYPWfRwDgavW/MoywS5Y2gZEslcJKhe0s2F3IthgFgw==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.10.tgz", + "integrity": "sha512-txnwYObY4N9ugv5T2n5h1KcbISegZ6l65w1/7tpSU5OB6MQCU94YkP8n/3slDw2KcEfRk4+4D8EUGfhSPMODEQ==", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/core-downloads-tracker": "^6.1.6", - "@mui/system": "^6.1.6", + "@mui/core-downloads-tracker": "^6.1.10", + "@mui/system": "^6.1.10", "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.6", + "@mui/utils": "^6.1.10", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.11", "clsx": "^2.1.1", @@ -2729,7 +2859,7 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^6.1.6", + "@mui/material-pigment-css": "^6.1.10", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -2749,42 +2879,13 @@ } } }, - "node_modules/@mui/material/node_modules/@mui/utils": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.6.tgz", - "integrity": "sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ==", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.19", - "@types/prop-types": "^15.7.13", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^18.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@mui/private-theming": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.6.tgz", - "integrity": "sha512-ioAiFckaD/fJSnTrUMWgjl9HYBWt7ixCh7zZw7gDZ+Tae7NuprNV6QJK95EidDT7K0GetR2rU3kAeIR61Myttw==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.10.tgz", + "integrity": "sha512-DqgsH0XFEweeG3rQfVkqTkeXcj/E76PGYWag8flbPdV8IYdMo+DfVdFlZK8JEjsaIVD2Eu1kJg972XnH5pfnBQ==", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/utils": "^6.1.6", + "@mui/utils": "^6.1.10", "prop-types": "^15.8.1" }, "engines": { @@ -2804,43 +2905,14 @@ } } }, - "node_modules/@mui/private-theming/node_modules/@mui/utils": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.6.tgz", - "integrity": "sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ==", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.19", - "@types/prop-types": "^15.7.13", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^18.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@mui/styled-engine": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.6.tgz", - "integrity": "sha512-I+yS1cSuSvHnZDBO7e7VHxTWpj+R7XlSZvTC4lS/OIbUNJOMMSd3UDP6V2sfwzAdmdDNBi7NGCRv2SZ6O9hGDA==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.10.tgz", + "integrity": "sha512-+NV9adKZYhslJ270iPjf2yzdVJwav7CIaXcMlPSi1Xy1S/zRe5xFgZ6BEoMdmGRpr34lIahE8H1acXP2myrvRw==", "dependencies": { "@babel/runtime": "^7.26.0", - "@emotion/cache": "^11.13.1", - "@emotion/serialize": "^1.3.2", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -2867,15 +2939,15 @@ } }, "node_modules/@mui/system": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.6.tgz", - "integrity": "sha512-qOf1VUE9wK8syiB0BBCp82oNBAVPYdj4Trh+G1s+L+ImYiKlubWhhqlnvWt3xqMevR+D2h1CXzA1vhX2FvA+VQ==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.10.tgz", + "integrity": "sha512-5YNIqxETR23SIkyP7MY2fFnXmplX/M4wNi2R+10AVRd3Ub+NLctWY/Vs5vq1oAMF0eSDLhRTGUjaUe+IGSfWqg==", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/private-theming": "^6.1.6", - "@mui/styled-engine": "^6.1.6", + "@mui/private-theming": "^6.1.10", + "@mui/styled-engine": "^6.1.10", "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.6", + "@mui/utils": "^6.1.10", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -2905,35 +2977,6 @@ } } }, - "node_modules/@mui/system/node_modules/@mui/utils": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.6.tgz", - "integrity": "sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ==", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.19", - "@types/prop-types": "^15.7.13", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^18.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@mui/types": { "version": "7.2.19", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz", @@ -2948,27 +2991,27 @@ } }, "node_modules/@mui/utils": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", - "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.10.tgz", + "integrity": "sha512-1ETuwswGjUiAf2dP9TkBy8p49qrw2wXa+RuAjNTRE5+91vtXJ1HKrs7H9s8CZd1zDlQVzUcUAPm9lpQwF5ogTw==", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/types": "^7.2.15", - "@types/prop-types": "^15.7.12", + "@babel/runtime": "^7.26.0", + "@mui/types": "^7.2.19", + "@types/prop-types": "^15.7.13", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^18.3.1" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -2977,13 +3020,13 @@ } }, "node_modules/@mui/x-date-pickers": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.18.0.tgz", - "integrity": "sha512-12tXIoMj9vpS8fS/bS3kWPCoVrH38vNGCxgplI0vOnUrN9rJuYJz3agLPJe1S0xciTw+9W8ZSe3soaW+owoz1Q==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.23.0.tgz", + "integrity": "sha512-Db9ElibVYHluXLVsRLfFwlYkL6/3NNE5AosSZiTx+Gw7uix/Z3pdjyHeA3ab65fU1tCk08XHY0PU6LQFifYB2g==", "dependencies": { - "@babel/runtime": "^7.25.6", - "@mui/utils": "^5.16.6", - "@mui/x-internals": "7.18.0", + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0", + "@mui/x-internals": "7.23.0", "@types/react-transition-group": "^4.4.11", "clsx": "^2.1.1", "prop-types": "^15.8.1", @@ -3006,10 +3049,10 @@ "dayjs": "^1.10.7", "luxon": "^3.0.2", "moment": "^2.29.4", - "moment-hijri": "^2.1.2", + "moment-hijri": "^2.1.2 || ^3.0.0", "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3042,12 +3085,12 @@ } }, "node_modules/@mui/x-internals": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.18.0.tgz", - "integrity": "sha512-lzCHOWIR0cAIY1bGrWSprYerahbnH5C31ql/2OWCEjcngL2NAV1M6oKI2Vp4HheqzJ822c60UyWyapvyjSzY/A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-7.23.0.tgz", + "integrity": "sha512-bPclKpqUiJYIHqmTxSzMVZi6MH51cQsn5U+8jskaTlo3J4QiMeCYJn/gn7YbeR9GOZFp8hetyHjoQoVHKRXCig==", "dependencies": { - "@babel/runtime": "^7.25.6", - "@mui/utils": "^5.16.6" + "@babel/runtime": "^7.25.7", + "@mui/utils": "^5.16.6 || ^6.0.0" }, "engines": { "node": ">=14.0.0" @@ -3057,7 +3100,7 @@ "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "react": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { @@ -3132,143 +3175,126 @@ "node": ">= 8" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@redux-devtools/extension": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", - "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.23.2", - "immutable": "^4.3.4" - }, - "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/@reduxjs/toolkit": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", - "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", - "dependencies": { - "immer": "^10.0.3", - "redux": "^5.0.1", - "redux-thunk": "^3.1.0", - "reselect": "^5.1.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } - } - }, - "node_modules/@remix-run/router": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz", - "integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", - "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "node_modules/@parcel/watcher": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", + "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", "dev": true, + "hasInstallScript": true, + "optional": true, "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.0", + "@parcel/watcher-darwin-arm64": "2.5.0", + "@parcel/watcher-darwin-x64": "2.5.0", + "@parcel/watcher-freebsd-x64": "2.5.0", + "@parcel/watcher-linux-arm-glibc": "2.5.0", + "@parcel/watcher-linux-arm-musl": "2.5.0", + "@parcel/watcher-linux-arm64-glibc": "2.5.0", + "@parcel/watcher-linux-arm64-musl": "2.5.0", + "@parcel/watcher-linux-x64-glibc": "2.5.0", + "@parcel/watcher-linux-x64-musl": "2.5.0", + "@parcel/watcher-win32-arm64": "2.5.0", + "@parcel/watcher-win32-ia32": "2.5.0", + "@parcel/watcher-win32-x64": "2.5.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", + "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", "cpu": [ - "arm" + "arm64" ], "dev": true, "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "android" - ] + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", + "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", + "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "darwin" - ] + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", + "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", "cpu": [ "arm" ], @@ -3276,12 +3302,19 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", + "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", "cpu": [ "arm" ], @@ -3289,12 +3322,19 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", + "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", "cpu": [ "arm64" ], @@ -3302,12 +3342,19 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", "cpu": [ "arm64" ], @@ -3315,51 +3362,39 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", - "cpu": [ - "ppc64" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", + "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", "cpu": [ - "riscv64" + "x64" ], "dev": true, "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", - "cpu": [ - "s390x" ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", "cpu": [ "x64" ], @@ -3367,58 +3402,316 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", + "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "linux" - ] + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", + "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", "cpu": [ - "arm64" + "ia32" ], "dev": true, "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", + "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", "cpu": [ - "ia32" + "x64" ], "dev": true, "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "peer": true, + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.0.tgz", + "integrity": "sha512-L+rZ4HXP2sJ1gHMGHjsg9jlYBX/SLN2D6OxP9Zn3qgtpMWtO2vUfxVFwiogHpAIqs54FnALxraUy/BCO1yRIgg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.5.tgz", + "integrity": "sha512-F1EJ4KjFpGAHAjuKvOyZB/6IZDkVx0bHl0M4fQM5wXcmm7lgTgVSSnR3bXwdmS6jOJGHOqfDxIJW3WUvwMIXhQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@redux-devtools/extension": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", + "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "immutable": "^4.3.4" + }, + "peerDependencies": { + "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", + "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "dependencies": { + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "win32" + "linux" ] }, "node_modules/@rushstack/eslint-patch": { @@ -3668,14 +3961,14 @@ } }, "node_modules/@swc/core": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.42.tgz", - "integrity": "sha512-iQrRk3SKndQZ4ptJv1rzeQSiCYQIhMjiO97QXOlCcCoaazOLKPnLnXzU4Kv0FuBFyYfG2FE94BoR0XI2BN02qw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.10.0.tgz", + "integrity": "sha512-+CuuTCmQFfzaNGg1JmcZvdUVITQXJk9sMnl1C2TiDLzOSVOJRwVD4dNo5dljX/qxpMAN+2BIYlwjlSkoGi6grg==", "dev": true, "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.13" + "@swc/types": "^0.1.17" }, "engines": { "node": ">=10" @@ -3685,16 +3978,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.42", - "@swc/core-darwin-x64": "1.7.42", - "@swc/core-linux-arm-gnueabihf": "1.7.42", - "@swc/core-linux-arm64-gnu": "1.7.42", - "@swc/core-linux-arm64-musl": "1.7.42", - "@swc/core-linux-x64-gnu": "1.7.42", - "@swc/core-linux-x64-musl": "1.7.42", - "@swc/core-win32-arm64-msvc": "1.7.42", - "@swc/core-win32-ia32-msvc": "1.7.42", - "@swc/core-win32-x64-msvc": "1.7.42" + "@swc/core-darwin-arm64": "1.10.0", + "@swc/core-darwin-x64": "1.10.0", + "@swc/core-linux-arm-gnueabihf": "1.10.0", + "@swc/core-linux-arm64-gnu": "1.10.0", + "@swc/core-linux-arm64-musl": "1.10.0", + "@swc/core-linux-x64-gnu": "1.10.0", + "@swc/core-linux-x64-musl": "1.10.0", + "@swc/core-win32-arm64-msvc": "1.10.0", + "@swc/core-win32-ia32-msvc": "1.10.0", + "@swc/core-win32-x64-msvc": "1.10.0" }, "peerDependencies": { "@swc/helpers": "*" @@ -3706,9 +3999,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.42.tgz", - "integrity": "sha512-fWhaCs2+8GDRIcjExVDEIfbptVrxDqG8oHkESnXgymmvqTWzWei5SOnPNMS8Q+MYsn/b++Y2bDxkcwmq35Bvxg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.10.0.tgz", + "integrity": "sha512-wCeUpanqZyzvgqWRtXIyhcFK3CqukAlYyP+fJpY2gWc/+ekdrenNIfZMwY7tyTFDkXDYEKzvn3BN/zDYNJFowQ==", "cpu": [ "arm64" ], @@ -3722,9 +4015,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.42.tgz", - "integrity": "sha512-ZaVHD2bijrlkCyD7NDzLmSK849Jgcx+6DdL4x1dScoz1slJ8GTvLtEu0JOUaaScQwA+cVlhmrmlmi9ssjbRLGQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.10.0.tgz", + "integrity": "sha512-0CZPzqTynUBO+SHEl/qKsFSahp2Jv/P2ZRjFG0gwZY5qIcr1+B/v+o74/GyNMBGz9rft+F2WpU31gz2sJwyF4A==", "cpu": [ "x64" ], @@ -3738,9 +4031,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.42.tgz", - "integrity": "sha512-iF0BJj7hVTbY/vmbvyzVTh/0W80+Q4fbOYschdUM3Bsud39TA+lSaPOefOHywkNH58EQ1z3EAxYcJOWNES7GFQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.10.0.tgz", + "integrity": "sha512-oq+DdMu5uJOFPtRkeiITc4kxmd+QSmK+v+OBzlhdGkSgoH3yRWZP+H2ao0cBXo93ZgCr2LfjiER0CqSKhjGuNA==", "cpu": [ "arm" ], @@ -3754,9 +4047,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.42.tgz", - "integrity": "sha512-xGu8j+DOLYTLkVmsfZPJbNPW1EkiWgSucT0nOlz77bLxImukt/0+HVm2hOwHSKuArQ8C3cjahAMY3b/s4VH2ww==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.10.0.tgz", + "integrity": "sha512-Y6+PC8knchEViRxiCUj3j8wsGXaIhuvU+WqrFqV834eiItEMEI9+Vh3FovqJMBE3L7d4E4ZQtgImHCXjrHfxbw==", "cpu": [ "arm64" ], @@ -3770,9 +4063,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.42.tgz", - "integrity": "sha512-qtW3JNO7i1yHEko59xxz+jY38+tYmB96JGzj6XzygMbYJYZDYbrOpXQvKbMGNG3YeTDan7Fp2jD0dlKf7NgDPA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.10.0.tgz", + "integrity": "sha512-EbrX9A5U4cECCQQfky7945AW9GYnTXtCUXElWTkTYmmyQK87yCyFfY8hmZ9qMFIwxPOH6I3I2JwMhzdi8Qoz7g==", "cpu": [ "arm64" ], @@ -3786,9 +4079,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.42.tgz", - "integrity": "sha512-F9WY1TN+hhhtiEzZjRQziNLt36M5YprMeOBHjsLVNqwgflzleSI7ulgnlQECS8c8zESaXj3ksGduAoJYtPC1cA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.10.0.tgz", + "integrity": "sha512-TaxpO6snTjjfLXFYh5EjZ78se69j2gDcqEM8yB9gguPYwkCHi2Ylfmh7iVaNADnDJFtjoAQp0L41bTV/Pfq9Cg==", "cpu": [ "x64" ], @@ -3802,9 +4095,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.42.tgz", - "integrity": "sha512-7YMdOaYKLMQ8JGfnmRDwidpLFs/6ka+80zekeM0iCVO48yLrJR36G0QGXzMjKsXI0BPhq+mboZRRENK4JfQnEA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.10.0.tgz", + "integrity": "sha512-IEGvDd6aEEKEyZFZ8oCKuik05G5BS7qwG5hO5PEMzdGeh8JyFZXxsfFXbfeAqjue4UaUUrhnoX+Ze3M2jBVMHw==", "cpu": [ "x64" ], @@ -3818,9 +4111,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.42.tgz", - "integrity": "sha512-C5CYWaIZEyqPl5W/EwcJ/mLBJFHVoUEa/IwWi0b4q2fCXcSCktQGwKXOQ+d67GneiZoiq0HasgcdMmMpGS9YRQ==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.10.0.tgz", + "integrity": "sha512-UkQ952GSpY+Z6XONj9GSW8xGSkF53jrCsuLj0nrcuw7Dvr1a816U/9WYZmmcYS8tnG2vHylhpm6csQkyS8lpCw==", "cpu": [ "arm64" ], @@ -3834,9 +4127,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.42.tgz", - "integrity": "sha512-3j47seZ5pO62mbrqvPe1iwhe2BXnM5q7iB+n2xgA38PCGYt0mnaJafqmpCXm/uYZOCMqSNynaoOWCMMZm4sqtA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.10.0.tgz", + "integrity": "sha512-a2QpIZmTiT885u/mUInpeN2W9ClCnqrV2LnMqJR1/Fgx1Afw/hAtiDZPtQ0SqS8yDJ2VR5gfNZo3gpxWMrqdVA==", "cpu": [ "ia32" ], @@ -3850,9 +4143,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.42", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.42.tgz", - "integrity": "sha512-FXl9MdeUogZLGDcLr6QIRdDVkpG0dkN4MLM4dwQ5kcAk+XfKPrQibX6M2kcfhsCx+jtBqtK7hRFReRXPWJZGbA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.10.0.tgz", + "integrity": "sha512-tZcCmMwf483nwsEBfUk5w9e046kMa1iSik4bP9Kwi2FGtOfHuDfIcwW4jek3hdcgF5SaBW1ktnK/lgQLDi5AtA==", "cpu": [ "x64" ], @@ -3872,9 +4165,9 @@ "dev": true }, "node_modules/@swc/types": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.13.tgz", - "integrity": "sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==", + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", + "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", "dev": true, "dependencies": { "@swc/counter": "^0.1.3" @@ -3955,9 +4248,9 @@ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/react": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", - "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -4012,9 +4305,9 @@ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" }, "node_modules/@types/trusted-types": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", - "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", @@ -4749,25 +5042,25 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.1.tgz", - "integrity": "sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.7.2.tgz", + "integrity": "sha512-y0byko2b2tSVVf5Gpng1eEhX1OvPC7x8yns1Fx8jDzlJp4LS6CMkCPfLw47cjyoMrshQDoQw4qcgjsU9VvlCew==", "dev": true, "dependencies": { "@swc/core": "^1.7.26" }, "peerDependencies": { - "vite": "^4 || ^5" + "vite": "^4 || ^5 || ^6" } }, "node_modules/@vitest/expect": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.4.tgz", - "integrity": "sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz", + "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.4", - "@vitest/utils": "2.1.4", + "@vitest/spy": "2.1.8", + "@vitest/utils": "2.1.8", "chai": "^5.1.2", "tinyrainbow": "^1.2.0" }, @@ -4776,12 +5069,12 @@ } }, "node_modules/@vitest/mocker": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.4.tgz", - "integrity": "sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz", + "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.4", + "@vitest/spy": "2.1.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.12" }, @@ -4802,9 +5095,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.4.tgz", - "integrity": "sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", + "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", "dev": true, "dependencies": { "tinyrainbow": "^1.2.0" @@ -4814,12 +5107,12 @@ } }, "node_modules/@vitest/runner": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.4.tgz", - "integrity": "sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz", + "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==", "dev": true, "dependencies": { - "@vitest/utils": "2.1.4", + "@vitest/utils": "2.1.8", "pathe": "^1.1.2" }, "funding": { @@ -4827,12 +5120,12 @@ } }, "node_modules/@vitest/snapshot": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.4.tgz", - "integrity": "sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz", + "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.4", + "@vitest/pretty-format": "2.1.8", "magic-string": "^0.30.12", "pathe": "^1.1.2" }, @@ -4841,9 +5134,9 @@ } }, "node_modules/@vitest/spy": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.4.tgz", - "integrity": "sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz", + "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==", "dev": true, "dependencies": { "tinyspy": "^3.0.2" @@ -4853,12 +5146,12 @@ } }, "node_modules/@vitest/utils": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz", - "integrity": "sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", + "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.4", + "@vitest/pretty-format": "2.1.8", "loupe": "^3.1.2", "tinyrainbow": "^1.2.0" }, @@ -4928,6 +5221,71 @@ "node": ">=4" } }, + "node_modules/antd": { + "version": "5.22.2", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.22.2.tgz", + "integrity": "sha512-vihhiJbm9VG3d6boUeD1q2MXMax+qBrXhgqCEC+45v8iGUF6m4Ct+lFiCW4oWaN3EABOsbVA6Svy3Rj/QkQFKw==", + "peer": true, + "dependencies": { + "@ant-design/colors": "^7.1.0", + "@ant-design/cssinjs": "^1.21.1", + "@ant-design/cssinjs-utils": "^1.1.1", + "@ant-design/icons": "^5.5.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.25.7", + "@ctrl/tinycolor": "^3.6.1", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.0", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.2.5", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.30.0", + "rc-checkbox": "~3.3.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.2.0", + "rc-dropdown": "~4.2.0", + "rc-field-form": "~2.5.1", + "rc-image": "~7.11.0", + "rc-input": "~1.6.3", + "rc-input-number": "~9.3.0", + "rc-mentions": "~2.17.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.9.3", + "rc-notification": "~5.6.2", + "rc-pagination": "~4.3.0", + "rc-picker": "~4.8.1", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.0", + "rc-resize-observer": "^1.4.0", + "rc-segmented": "~2.5.0", + "rc-select": "~14.16.3", + "rc-slider": "~11.1.7", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.48.1", + "rc-tabs": "~15.4.0", + "rc-textarea": "~1.8.2", + "rc-tooltip": "~6.2.1", + "rc-tree": "~5.10.1", + "rc-tree-select": "~5.24.4", + "rc-upload": "~4.8.1", + "rc-util": "^5.43.0", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -5550,6 +5908,12 @@ "node": ">= 0.8" } }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", + "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==", + "peer": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5569,6 +5933,15 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "peer": true, + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", @@ -5608,9 +5981,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -5722,6 +6095,12 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "peer": true + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -5816,6 +6195,19 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -5852,9 +6244,12 @@ } }, "node_modules/dompurify": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", - "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.2.tgz", + "integrity": "sha512-YMM+erhdZ2nkZ4fTNRTSI94mb7VG7uVF5vj5Zde7tImgnhZE3R6YW/IACGIHb2ux+QkEXMhe591N+5jWOmL4Zw==", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } }, "node_modules/dot-case": { "version": "3.0.4", @@ -6010,6 +6405,12 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -7381,20 +7782,6 @@ "dev": true, "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -7722,9 +8109,9 @@ } }, "node_modules/i18next": { - "version": "23.16.4", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.4.tgz", - "integrity": "sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg==", + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", "funding": [ { "type": "individual", @@ -8310,6 +8697,15 @@ "dev": true, "license": "MIT" }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "peer": true, + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8463,9 +8859,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" @@ -8605,6 +9001,13 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "optional": true + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -8828,215 +9231,820 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dependencies": { - "callsites": "^3.0.0" + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, + "node_modules/rc-cascader": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.30.0.tgz", + "integrity": "sha512-rrzSbk1Bdqbu+pDwiLCLHu72+lwX9BZ28+JKzoi0DWZ4N29QYFeip8Gctl33QVd2Xg3Rf14D3yAOG76ElJw16w==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.10.1", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz", + "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", + "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz", + "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.5.1.tgz", + "integrity": "sha512-33hunXwynQJyeae7LS3hMGTXNeRBjiPyPYgB0824EbmLHiXC1EBGyUwRh6xjLRy9c+en5WARYN0gJz5+JAqwig==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.0.tgz", + "integrity": "sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.6.3.tgz", + "integrity": "sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.3.0.tgz", + "integrity": "sha512-JQ363ywqRyxwgVxpg2z2kja3CehTpYdqR7emJ/6yJjRdbvo+RvfE83fcpBCIJRq3zLp8SakmEXq60qzWyZ7Usw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.6.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.17.0.tgz", + "integrity": "sha512-sfHy+qLvc+p8jx8GUsujZWXDOIlIimp6YQz7N5ONQ6bHsa2kyG+BLa5k2wuxgebBbH97is33wxiyq5UkiXRpHA==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.6.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.8.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.0.tgz", + "integrity": "sha512-vAL0yqPkmXWk3+YKRkmIR8TYj3RVdEt3ptG2jCJXWNAvQbT0VJJdRyHZ7kG/l1JsZlB+VJq/VcYOo69VR4oD+w==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.3.tgz", + "integrity": "sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.2.tgz", + "integrity": "sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz", + "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.3.0.tgz", + "integrity": "sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.8.2.tgz", + "integrity": "sha512-I6Nn4ngkRskSD//rsXDvjlEQ8CzX9kPQrUIb7+qTY49erJaa3/oKJWmi6JIxo/A7gy59phNmPTdhKosAa/NrQQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz", + "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", + "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.38.0", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.5.0.tgz", + "integrity": "sha512-B28Fe3J9iUFOhFJET3RoXAPFJ2u47QvLSYcZWC4tFYNGPEjug5LAxEasZlA/PpAxhdOPqGWsGbSj7ftneukJnw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.3", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.3.tgz", + "integrity": "sha512-51+j6s3fJJJXB7E+B6W1hM4Tjzv1B/Decooz9ilgegDBt3ZAth1b/xMwYCTrT5BbG2e53XACQsyDib2+3Ro1fg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" }, "engines": { - "node": ">=6" + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/rc-slider": { + "version": "11.1.7", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.7.tgz", + "integrity": "sha512-ytYbZei81TX7otdC0QvoYD72XSlxvTihNth5OeZ6PMXyEDq/vHdWFulQmfDGyXK1NwKwSlKgpvINOa88uT5g2A==", + "peer": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" }, "engines": { - "node": ">=8" + "node": ">=8.x" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, "engines": { - "node": ">=8" + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, + "node_modules/rc-table": { + "version": "7.48.1", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.48.1.tgz", + "integrity": "sha512-Z4mDKjWg+xz/Ezdw6ivWcbqRpaJ0QfCORRoRrlrw65KSGZLK8OcTdacH22/fyGb8L4It/0/9qcMm8VrVAk/WBw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.41.0", + "rc-virtual-list": "^3.14.2" + }, "engines": { - "node": ">=8" + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/rc-tabs": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.4.0.tgz", + "integrity": "sha512-llKuyiAVqmXm2z7OrmhX5cNb2ueZaL8ZyA2P4R+6/72NYYcbEgOXibwHiQCFY2RiN3swXl53SIABi2CumUS02g==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, "engines": { - "node": ">=8" + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "engines": { - "node": ">= 14.16" + "node_modules/rc-textarea": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.8.2.tgz", + "integrity": "sha512-UFAezAqltyR00a8Lf0IPAyTd29Jj9ee8wt8DqXyDMal7r/Cg/nDt3e1OOv3Th4W6mKaZijjgwuPXhAfVNTN8sw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.6.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" + "node_modules/rc-tooltip": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.1.tgz", + "integrity": "sha512-rws0duD/3sHHsD905Nex7FvoUGy2UBQRhTkKxeEvr2FB+r21HsOxcDJI0TzyO8NHhnAA8ILr8pfbSBg5Jj5KBg==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "license": "MIT", + "node_modules/rc-tree": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.10.1.tgz", + "integrity": "sha512-FPXb3tT/u39mgjr6JNlHaUTYfHkVGW56XaGDahDpEFLGsnPxGcVLNTjcqoQb/GNbSCycl7tD7EvIymwOTP0+Yw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, "engines": { - "node": ">= 0.4" + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/rc-tree-select": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.24.5.tgz", + "integrity": "sha512-PnyR8LZJWaiEFw0SHRqo4MNQWyyZsyMs8eNmo68uXZWjxc7QqeWcjPPoONN0rc90c3HZqGF9z+Roz+GLzY5GXA==", + "peer": true, "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.2.0" + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.10.1", + "rc-util": "^5.43.0" }, - "engines": { - "node": "^10 || ^12 || >=14" + "peerDependencies": { + "react": "*", + "react-dom": "*" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" + "node_modules/rc-upload": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.8.1.tgz", + "integrity": "sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/rc-util": { + "version": "5.43.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz", + "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==", + "peer": true, "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/property-expr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", - "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", + "node_modules/rc-virtual-list": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.15.0.tgz", + "integrity": "sha512-dF2YQztqrU3ijAeWOqscTshCEr7vpimzSqAVjO1AyAmaqcHulaXpnGR0ptK5PXfxTUy48VkJOiglMIxlkYGs0w==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, "engines": { - "node": ">=6" + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/raf-schd": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" - }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -9090,18 +10098,18 @@ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" }, "node_modules/react-hotkeys-hook": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.5.1.tgz", - "integrity": "sha512-scAEJOh3Irm0g95NIn6+tQVf/OICCjsQsC9NBHfQws/Vxw4sfq1tDQut5fhTEvPraXhu/sHxRd9lOtxzyYuNAg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.6.1.tgz", + "integrity": "sha512-XlZpbKUj9tkfgPgT9gA+1p7Ey6vFIZHttUjPqpTdyT5nqQ8mHL7elxvSbaC+dpSiHUSmr21Ya1mDxBZG3aje4Q==", "peerDependencies": { "react": ">=16.8.1", "react-dom": ">=16.8.1" } }, "node_modules/react-i18next": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.1.0.tgz", - "integrity": "sha512-zj3nJynMnZsy2gPZiOTC7XctCY5eQGqT3tcKMmfJWC9FMvgd+960w/adq61j8iPzpwmsXejqID9qC3Mqu1Xu2Q==", + "version": "15.1.3", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.1.3.tgz", + "integrity": "sha512-J11oA30FbM3NZegUZjn8ySK903z6PLBz/ZuBYyT1JMR0QPrW6PFXvl1WoUhortdGi9dM0m48/zJQlPskVZXgVw==", "dependencies": { "@babel/runtime": "^7.25.0", "html-parse-stringify": "^3.0.1" @@ -9120,9 +10128,9 @@ } }, "node_modules/react-icons": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", - "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", "peerDependencies": { "react": "*" } @@ -9132,6 +10140,16 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, + "node_modules/react-js-cron": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-js-cron/-/react-js-cron-5.0.1.tgz", + "integrity": "sha512-qHUb/qWeMvXklGW6/hLtH9CjboRU7pu2hHxGGErUDTjHDOLn/b6CZHvVsx/e3ak+UObwf4Y0BHSQJzpn1JpvvA==", + "peerDependencies": { + "antd": ">=5.8.0", + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, "node_modules/react-redux": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", @@ -9155,11 +10173,11 @@ } }, "node_modules/react-router": { - "version": "6.27.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz", - "integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", "dependencies": { - "@remix-run/router": "1.20.0" + "@remix-run/router": "1.21.0" }, "engines": { "node": ">=14.0.0" @@ -9169,12 +10187,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.27.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz", - "integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", + "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", "dependencies": { - "@remix-run/router": "1.20.0", - "react-router": "6.27.0" + "@remix-run/router": "1.21.0", + "react-router": "6.28.0" }, "engines": { "node": ">=14.0.0" @@ -9220,9 +10238,9 @@ } }, "node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "engines": { "node": ">= 14.16.0" @@ -9374,6 +10392,12 @@ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "peer": true + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -9420,9 +10444,9 @@ } }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", "dev": true, "dependencies": { "@types/estree": "1.0.6" @@ -9435,22 +10459,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", "fsevents": "~2.3.2" } }, @@ -9529,13 +10555,13 @@ } }, "node_modules/sass": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz", - "integrity": "sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==", + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz", + "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==", "dev": true, "dependencies": { "chokidar": "^4.0.0", - "immutable": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -9543,8 +10569,17 @@ }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, + "node_modules/sass/node_modules/immutable": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", + "dev": true + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -9553,6 +10588,15 @@ "loose-envify": "^1.1.0" } }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "peer": true, + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -9705,11 +10749,17 @@ "dev": true }, "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", "dev": true }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "peer": true + }, "node_modules/string-natural-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", @@ -9938,6 +10988,15 @@ "dev": true, "license": "MIT" }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "peer": true, + "engines": { + "node": ">=12.22" + } + }, "node_modules/tiny-case": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", @@ -9966,9 +11025,9 @@ "dev": true }, "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, "engines": { "node": "^18.0.0 || >=20.0.0" @@ -10012,6 +11071,12 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "peer": true + }, "node_modules/toposort": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", @@ -10194,9 +11259,9 @@ } }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -10342,9 +11407,9 @@ } }, "node_modules/uuid": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.2.tgz", - "integrity": "sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -10355,9 +11420,9 @@ } }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "dependencies": { "esbuild": "^0.21.3", @@ -10414,13 +11479,14 @@ } }, "node_modules/vite-node": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.4.tgz", - "integrity": "sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz", + "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", "pathe": "^1.1.2", "vite": "^5.0.0" }, @@ -10488,9 +11554,9 @@ } }, "node_modules/vite/node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -10508,7 +11574,7 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -10516,30 +11582,30 @@ } }, "node_modules/vitest": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.4.tgz", - "integrity": "sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==", - "dev": true, - "dependencies": { - "@vitest/expect": "2.1.4", - "@vitest/mocker": "2.1.4", - "@vitest/pretty-format": "^2.1.4", - "@vitest/runner": "2.1.4", - "@vitest/snapshot": "2.1.4", - "@vitest/spy": "2.1.4", - "@vitest/utils": "2.1.4", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz", + "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==", + "dev": true, + "dependencies": { + "@vitest/expect": "2.1.8", + "@vitest/mocker": "2.1.8", + "@vitest/pretty-format": "^2.1.8", + "@vitest/runner": "2.1.8", + "@vitest/snapshot": "2.1.8", + "@vitest/spy": "2.1.8", + "@vitest/utils": "2.1.8", "chai": "^5.1.2", "debug": "^4.3.7", "expect-type": "^1.1.0", "magic-string": "^0.30.12", "pathe": "^1.1.2", - "std-env": "^3.7.0", + "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.1", "tinypool": "^1.0.1", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.4", + "vite-node": "2.1.8", "why-is-node-running": "^2.3.0" }, "bin": { @@ -10554,8 +11620,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.4", - "@vitest/ui": "2.1.4", + "@vitest/browser": "2.1.8", + "@vitest/ui": "2.1.8", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index 6208ec3049..19d6ffcd83 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "react-hotkeys-hook": "^4.5.1", "react-i18next": "^15.1.0", "react-icons": "^5.3.0", + "react-js-cron": "^5.0.1", "react-redux": "^9.1.2", "react-router-dom": "^6.27.0", "react-select": "^5.8.0", diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx index 19f5c46755..157afeb9ca 100644 --- a/src/components/events/LifeCyclePolicies.tsx +++ b/src/components/events/LifeCyclePolicies.tsx @@ -24,6 +24,8 @@ import { lifeCyclePoliciesTemplateMap } from "../../configs/tableConfigs/lifeCyc import { fetchEvents } from "../../slices/eventSlice"; import { setOffset } from "../../slices/tableSlice"; import { fetchSeries } from "../../slices/seriesSlice"; +import NewResourceModal from "../shared/NewResourceModal"; +import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../slices/lifeCycleDetailsSlice"; /** * This component renders the table view of policies @@ -32,6 +34,7 @@ const LifeCyclePolicies = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [displayNavigation, setNavigation] = useState(false); + const [displayNewPolicyModal, setNewPolicyModal] = useState(false); const user = useAppSelector(state => getUserInformation(state)); const policiesTotal = useAppSelector(state => getTotalLifeCyclePolicies(state)); @@ -77,6 +80,11 @@ const LifeCyclePolicies = () => { // Load policies on mount loadLifeCyclePolicies().then((r) => console.info(r)); + + // Fetch policies repeatedly + let fetchInterval = setInterval(loadLifeCyclePolicies, 5000); + + return () => clearInterval(fetchInterval); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -84,10 +92,32 @@ const LifeCyclePolicies = () => { setNavigation(!displayNavigation); }; + const showNewPolicyModal = async () => { + await dispatch(fetchLifeCyclePolicyActions()); + await dispatch(fetchLifeCyclePolicyTargetTypes()); + await dispatch(fetchLifeCyclePolicyTimings()); + + setNewPolicyModal(true); + }; + + const hideNewPolicyModal = () => { + setNewPolicyModal(false); + }; + return ( <>
+ { + /* Display modal for new event if add event button is clicked */ + displayNewPolicyModal && ( + + ) + } + {/* Include Burger-button menu*/} @@ -120,6 +150,15 @@ const LifeCyclePolicies = () => { )} + +
+ {hasAccess("ROLE_UI_EVENTS_CREATE", user) && ( + + )} +
diff --git a/src/components/events/partials/LifeCyclePolicyActionCell.tsx b/src/components/events/partials/LifeCyclePolicyActionCell.tsx index ce5df1e317..78de162c74 100644 --- a/src/components/events/partials/LifeCyclePolicyActionCell.tsx +++ b/src/components/events/partials/LifeCyclePolicyActionCell.tsx @@ -2,12 +2,13 @@ import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { useAppDispatch, useAppSelector } from "../../../store"; import { Tooltip } from "../../shared/Tooltip"; -import { LifeCyclePolicy } from "../../../slices/lifeCycleSlice"; +import { deleteLifeCyclePolicy, LifeCyclePolicy } from "../../../slices/lifeCycleSlice"; import DetailsModal from "../../shared/modals/DetailsModal"; import LifeCyclePolicyDetails from "./modals/LifeCyclePolicyDetails"; import { hasAccess } from "../../../utils/utils"; import { getUserInformation } from "../../../selectors/userInfoSelectors"; import { fetchLifeCyclePolicyDetails } from "../../../slices/lifeCycleDetailsSlice"; +import ConfirmModal from "../../shared/ConfirmModal"; /** * This component renders the title cells of series in the table view @@ -21,6 +22,7 @@ const LifeCyclePolicyActionCell = ({ const dispatch = useAppDispatch(); const [displayLifeCyclePolicyDetails, setLifeCyclePolicyDetails] = useState(false); + const [displayDeleteConfirmation, setDeleteConfirmation] = useState(false); const user = useAppSelector(state => getUserInformation(state)); @@ -34,6 +36,18 @@ const LifeCyclePolicyActionCell = ({ setLifeCyclePolicyDetails(false); }; + const hideDeleteConfirmation = () => { + setDeleteConfirmation(false); + }; + + const showDeleteConfirmation = async () => { + setDeleteConfirmation(true); + }; + + const deletingPolicy = (id: string) => { + dispatch(deleteLifeCyclePolicy(id)); + }; + return ( <> {/* view details location/recording */} @@ -55,6 +69,27 @@ const LifeCyclePolicyActionCell = ({ )} + + {/* delete policy */} + {hasAccess("ROLE_UI_LIFECYCLEPOLICY_DELETE", user) && ( + + + + + +
+ + )} + {/*
*/} +
- - - + + )} + ); }; diff --git a/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx b/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx new file mode 100644 index 0000000000..532abdf59b --- /dev/null +++ b/src/components/events/partials/ModalTabsAndPages/NewLifeCyclePolicyGeneralPage.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import { FormikProps } from "formik"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; +import LifeCyclePolicyGeneralFields from "../wizards/LifeCyclePolicyGeneralFields"; +import { LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice"; + +/** + * This component renders the metadata page for new events and series in the wizards. + */ +const NewLifeCyclePolicyGeneralPage = ({ + formik, + nextPage, + header +}: { + formik: FormikProps, + nextPage: (values: T) => void, + header: string +}) => { + + return ( + <> +
+
+
+ {/* Table view containing input fields for metadata */} + +
+
+
+ + {/* Button for navigation to next page */} + + + ); +}; + +export default NewLifeCyclePolicyGeneralPage; diff --git a/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx index e818dd57c2..4cffc334ff 100644 --- a/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx +++ b/src/components/events/partials/modals/LifeCyclePolicyDetails.tsx @@ -1,18 +1,32 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import ModalNavigation from "../../../shared/modals/ModalNavigation"; import { getLifeCyclePolicyDetails } from "../../../../selectors/lifeCycleDetailsSelectors"; import LifeCyclePolicyGeneralTab from "../ModalTabsAndPages/LifeCyclePolicyGeneralTab"; import LifeCyclePolicyDetailsAccessTab from "../ModalTabsAndPages/LifeCyclePolicyAccessTab"; -import { useAppSelector } from "../../../../store"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { removeNotificationWizardForm } from "../../../../slices/notificationSlice"; +import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../../../slices/lifeCycleDetailsSlice"; /** * This component manages the tabs of the series details modal */ const LifeCyclePolicyDetails = () => { const [page, setPage] = useState(0); + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(removeNotificationWizardForm()); + dispatch(fetchLifeCyclePolicyActions()); + dispatch(fetchLifeCyclePolicyTargetTypes()); + dispatch(fetchLifeCyclePolicyTimings()); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const policy = useAppSelector(state => getLifeCyclePolicyDetails(state)); + // tracks, whether the policies are different to the initial value + const [policyChanged, setPolicyChanged] = useState(false); + // information about tabs const tabs = [ { @@ -23,7 +37,7 @@ const LifeCyclePolicyDetails = () => { { tabTranslation: "LIFECYCLE.POLICIES.DETAILS.TAB.ACCESSPOLICIES", accessRole: "ROLE_UI_LIFECYCLEPOLICIES_DETAILS_ACCESSPOLICIES_VIEW", - name: "WARNING: None of the changes you make here can be saved!", + name: "Access Policies" }, ]; @@ -42,8 +56,8 @@ const LifeCyclePolicyDetails = () => { false} + policyChanged={policyChanged} + setPolicyChanged={setPolicyChanged} /> } diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx new file mode 100644 index 0000000000..042f2046f0 --- /dev/null +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -0,0 +1,475 @@ +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { FieldArray, FieldProps, FormikProps } from "formik"; +import { Field } from "../../../shared/Field"; +import RenderField from "../../../shared/wizard/RenderField"; +import { ALL_TARGET_FILTER_TYPES, LifeCyclePolicy, TargetFilter } from "../../../../slices/lifeCycleSlice"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getLifeCyclePolicyActions, getLifeCyclePolicyTargetTypes, getLifeCyclePolicyTimings } from "../../../../selectors/lifeCycleDetailsSelectors"; +import DropDown from "../../../shared/DropDown"; +import { getEventMetadata } from "../../../../selectors/eventSelectors"; +import { fetchEventMetadata } from "../../../../slices/eventSlice"; + +/** + * This component renders the metadata page for new events and series in the wizards. + */ +// interface RequiredFormProps { +// sourceMode: string, +// processingWorkflow: string, +// } + +const LifeCyclePolicyGeneralFields = ({ + formik, + isNew, +}: { + formik: FormikProps, + isNew: boolean +}) => { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + + const actions = useAppSelector(state => getLifeCyclePolicyActions(state)); + const targetTypes = useAppSelector(state => getLifeCyclePolicyTargetTypes(state)); + const timings = useAppSelector(state => getLifeCyclePolicyTimings(state)); + const metadataFields = useAppSelector(state => getEventMetadata(state)); + + useEffect(() => { + dispatch(fetchEventMetadata()) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const ADDITIONAL_TARGET_FILTER_KEYS_EVENTS = [ + { + id: 'series_name', + type: 'text', + collection: undefined + }, + { + id: 'presenter', + type: 'text', + collection: undefined + }, + { + id: 'start_date', + type: 'date', + collection: undefined + }, + { + id: 'end_date', + type: 'date', + collection: undefined + }, + { + id: 'created', + type: 'date', + collection: undefined + }, + { + id: 'source', + type: 'text', + collection: undefined + }, + { + id: 'rights', + type: 'text', + collection: undefined + }, + { + id: 'location', + type: 'text', + collection: undefined + }, + ] + + const eventFilterOptions: { id: string, type: string, collection?: unknown }[] = [] + for (const field of metadataFields.fields) { + eventFilterOptions.push(field) + } + for (const field of ADDITIONAL_TARGET_FILTER_KEYS_EVENTS) { + eventFilterOptions.push(field) + } + + const createTargetFilter = (): TargetFilter => { + return { + value: "", + type: "SEARCH", + must: true + } + } + + const filterOptions = (targetType: string) => { + switch (targetType) { + case "EVENT": + return eventFilterOptions + default: + return [] + } + } + + return ( + <> +
+
{t("LIFECYCLE.POLICIES.NEW.GENERAL.CAPTION")}
+ + + + + + + + + + + + {!isNew && + + + + + } + + + + + + + + + + + + + + + + + + + + + {!isNew && + + + + + } + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TITLE")}* + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}* + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISCREATEDFROMCONFIG")} + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETTYPE")}* + ({ value: element, name: element }) ), + id: "language", + }} + component={RenderField} + /> +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TIMING")}* + ({ value: element, name: element }) ), + id: "language", + }} + component={RenderField} + /> +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTION")}* + ({ value: element, name: element }) ), + id: "language" + }} + component={RenderField} + /> +
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")} + {formik.values.timing === "SPECIFIC_DATE" && *} + + +
+ {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")} + {formik.values.timing === "REPEATING" && *} + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ID")} + {formik.values.id} +
+
+ +
+ + + {/* Target Filters like the ACLs + Can we make "key" a dropdown? + Type of "Value" should depend on key, e.g. for key "start_date" show a date picker + */} +
+
+ { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.CAPTION") } +
+ + + {/* column headers */} + + + + + + + + + + + + + {({ replace, remove, push }) => ( + <> + {Object.entries(formik.values.targetFiltersArray).map(([key, filter], index) => { + return( + + + + + + + + ) + })} + + + + + )} + + +
+ { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.FILTER") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.VALUE") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.TYPE") } + + { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.MUST") } + + { t("EVENTS.EVENTS.DETAILS.ACCESS.ACCESS_POLICY.ACTION") } +
+ e.id)} + creatable={true} + clearFieldName={`targetFiltersArray.${key}.value`} + component={DropdownField} + /> + + + + + + + +
+ +
+
+ + {formik.values.action === "START_WORKFLOW" && +
+
+ { t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS.CAPTION") } +
+ + + + + + + + + + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS.WORKFLOW_ID")}* + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS.WORKFLOW_PARAMETERS")} + + {/* Using our "WorkflowConfig" component would be nice, but it does not allow us to add or remove config options */} + {/* */} +
+
+ } + + ); +}; + + +export default LifeCyclePolicyGeneralFields; + +const DropdownField = ({ + field, + form: { setFieldValue }, + value, + values, + clearFieldName, + creatable = false +}: { + field: FieldProps["field"] + form: FieldProps["form"] + value: string, + values: string[] + clearFieldName: string + creatable: boolean +}) => { + const { t } = useTranslation(); + + return ( + { + setFieldValue(clearFieldName, undefined) + element && setFieldValue(field.name, element.value) + }} + placeholder={`-- ${t("SELECT_NO_OPTION_SELECTED")} --`} + creatable={creatable} + /> + ) +}; + +const getTargetFilterRenderType = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[] ) => { + const option = targetFilterOptions.find(e => e.id === filterName); + if (option === undefined) { + return "text"; + } + // Simplify types like "long_text" or "mixed_text" + if (option.type.includes("text")) { + return "text"; + } + return option.type; +} + +const getTargetFilterRenderCollection = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[] ) => { + const option = targetFilterOptions.find(e => e.id === filterName); + return option !== undefined ? option.collection : undefined +} diff --git a/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx b/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx new file mode 100644 index 0000000000..ddf79b8a47 --- /dev/null +++ b/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx @@ -0,0 +1,114 @@ +import React from "react"; +import { useTranslation } from "react-i18next"; +import AccessSummaryTable from "./summaryTables/AccessSummaryTable"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; +import { FormikProps } from "formik"; +import { renderValidDate } from "../../../../utils/dateUtils"; +import { initialFormValuesNewLifeCyclePolicy } from "../../../../configs/modalConfig"; + +/** + * This component renders the summary page for new series in the new series wizard. + */ +// interface RequiredFormProps { + +// } + +const NewLifeCyclePolicySummary = ({ + formik, + previousPage, +}: { + formik: FormikProps, + previousPage: (values: T, twoPagesBack?: boolean) => void, +}) => { + const { t } = useTranslation(); + + return ( + <> +
+
+
+ +
+
{t("LIFECYCLE.POLICIES.NEW.CAPTION")}
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + + + + {/* @ts-ignore */} + + {/* @ts-ignore */} + + + } + + + +
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TITLE")}{formik.values.title}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ISACTIVE")}{formik.values.isActive}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETTYPE")}{formik.values.targetType}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TIMING")}{formik.values.timing}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTION")}{formik.values.action}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")}{t("dateFormats.dateTime.medium", { dateTime: renderValidDate(formik.values.actionDate) } )}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")}{formik.values.cronTrigger}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.CAPTION")} + {formik.values.targetFiltersArray.map((filter) => ( +
{filter.filter}{filter.value}{filter.type}{filter.must.toString()}
{t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONPARAMETERS.CAPTION")} + {formik.values.action === "START_WORKFLOW" && +
{formik.values.actionParameters.workflowId}{formik.values.actionParameters.workflowParameters}
+
+
+ {/*Summary access configuration*/} + + +
+
+
+ + {/* Button for navigation to next page and previous page */} + + + ); +}; + +export default NewLifeCyclePolicySummary; diff --git a/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx b/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx new file mode 100644 index 0000000000..73b59719bf --- /dev/null +++ b/src/components/events/partials/wizards/NewLifeCyclePolicyWizard.tsx @@ -0,0 +1,177 @@ +import React, { useEffect, useState } from "react"; +import { Formik } from "formik"; +import NewAccessPage from "../ModalTabsAndPages/NewAccessPage"; +import WizardStepperEvent from "../../../shared/wizard/WizardStepperEvent"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { getUserInformation } from "../../../../selectors/userInfoSelectors"; +import { UserInfoState } from "../../../../slices/userInfoSlice"; +import { postNewLifeCyclePolicy } from "../../../../slices/lifeCycleSlice"; +import NewLifeCyclePolicyGeneralPage from "../ModalTabsAndPages/NewLifeCyclePolicyGeneralPage"; +import NewLifeCyclePolicySummary from "./NewLifeCyclePolicySummary"; +import { LifeCyclePolicySchema } from "../../../../utils/validate"; +import { initialFormValuesNewLifeCyclePolicy } from "../../../../configs/modalConfig"; +import { parseTargetFiltersForSubmit } from "../../../../utils/lifeCycleUtils"; + +/** + * This component manages the pages of the new event wizard and the submission of values + */ +const NewLifeCyclePolicyWizard = ({ + close, +}: { + close: () => void +}) => { + const dispatch = useAppDispatch(); + + const user = useAppSelector(state => getUserInformation(state)); + + const initialValues = getInitialValues(user); + + const [page, setPage] = useState(0); + const [snapshot, setSnapshot] = useState(initialValues); + const [pageCompleted, setPageCompleted] = useState<{ [key: number]: boolean }>({}); + + // Caption of steps used by Stepper + const steps = [ + { + translation: "LIFECYCLE.POLICIES.NEW.GENERAL.CAPTION", + name: "general", + hidden: false, + }, + { + translation: "EVENTS.EVENTS.NEW.ACCESS.CAPTION", + name: "access", + hidden: false, + }, + { + translation: "EVENTS.EVENTS.NEW.SUMMARY.CAPTION", + name: "summary", + hidden: false, + }, + ]; + + const nextPage = (values: typeof initialValues) => { + setSnapshot(values); + + // set page as completely filled out + let updatedPageCompleted = pageCompleted; + updatedPageCompleted[page] = true; + setPageCompleted(updatedPageCompleted); + + let newPage = page; + do { + newPage = newPage + 1; + } while(steps[newPage] && steps[newPage].hidden); + if (steps[newPage]) { + setPage(newPage) + } + }; + + const previousPage = (values: typeof initialValues) => { + setSnapshot(values); + + let newPage = page; + do { + newPage = newPage - 1; + } while(steps[newPage] && steps[newPage].hidden); + if (steps[newPage]) { + setPage(newPage) + } + }; + + const handleSubmit = (values: typeof initialValues) => { + const fixedValues = { + ...values, + targetFilters: parseTargetFiltersForSubmit(values.targetFiltersArray), + accessControlEntries: values.acls + } + if (fixedValues.action === "START_WORKFLOW") { + fixedValues.actionParameters["workflowParameters"] = JSON.parse(values.actionParameters["workflowParameters"] as string) + } + // values["accessControlEntries"] = values.acls; + const response = dispatch(postNewLifeCyclePolicy(fixedValues)); + console.info(response); + close(); + }; + + return ( + <> + handleSubmit(values)} + > + {/* Render wizard pages depending on current value of page variable */} + {(formik) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useEffect(() => { + formik.validateForm(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [page]); + + return ( + <> + {/* Stepper that shows each step of wizard as header */} + +
+ {page === 0 && ( + + )} + {page === 1 && ( + + )} + {page === 2 && ( + + )} +
+ + ); + }} +
+ + ); +} + +// Transform all initial values needed from information provided by backend +const getInitialValues = ( + user: UserInfoState +) => { + let initialValues = initialFormValuesNewLifeCyclePolicy; + + initialValues["acls"] = [ + { + role: user.userRole, + read: true, + write: true, + actions: [], + }, + ]; + + return initialValues; +}; + +export default NewLifeCyclePolicyWizard; diff --git a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx index 6a9c067fa7..c564699deb 100644 --- a/src/components/events/partials/wizards/RenderWorkflowConfig.tsx +++ b/src/components/events/partials/wizards/RenderWorkflowConfig.tsx @@ -6,7 +6,7 @@ import { getWorkflowDefById, } from "../../../../selectors/workflowSelectors"; import { useAppSelector } from "../../../../store"; -import { FieldSetField } from "../../../../slices/workflowSlice"; +import { ConfigurationPanelField, FieldSetField } from "../../../../slices/workflowSlice"; /** * This component renders the configuration panel for the selected workflow in the processing step of the new event @@ -32,10 +32,28 @@ const RenderWorkflowConfig = ({ const configPanel = !!workflowDef && workflowDef.configuration_panel_json ? workflowDef.configuration_panel_json : []; - const description = !!workflowDef && workflowDef.description + const description = !!workflowDef && workflowDef.description && !displayDescription ? workflowDef.description : ""; + return ( + + ); +}; + +export const WorkflowConfig = ({ + formik, + configPanel, + description +}: { + formik: FormikProps + configPanel: string | ConfigurationPanelField[] + description: string +}) => { const descriptionBoxStyle = { margin: "15px 0 0 0", position: "relative" as const, @@ -55,7 +73,7 @@ const RenderWorkflowConfig = ({ return ( <> - {displayDescription && description.length > 0 && ( + {description.length > 0 && (
{description.trim()}
diff --git a/src/components/shared/ConfirmModal.tsx b/src/components/shared/ConfirmModal.tsx index 91395fab88..4a4262dc23 100644 --- a/src/components/shared/ConfirmModal.tsx +++ b/src/components/shared/ConfirmModal.tsx @@ -15,7 +15,7 @@ const ConfirmModal = ({ deleteWithCautionMessage = "", }: { close: () => void, - resourceType: "EVENT" | "SERIES" | "LOCATION" | "USER" | "GROUP" | "ACL" | "THEME", + resourceType: "EVENT" | "SERIES" | "LOCATION" | "USER" | "GROUP" | "ACL" | "THEME" | "LIFECYCLE_POLICY", resourceName: string, resourceId: T, deleteMethod: (id: T) => void, diff --git a/src/components/shared/DropDown.tsx b/src/components/shared/DropDown.tsx index 2c746a6307..dfa3d0c922 100644 --- a/src/components/shared/DropDown.tsx +++ b/src/components/shared/DropDown.tsx @@ -18,7 +18,7 @@ import CreatableSelect from "react-select/creatable"; * - Creating typescript types for each "type" is moot atm, as a lot of them (i.e. capture agents) are not properly typed yet * I would suggest waiting with typing options until all of its inputs are properly typed */ -export type DropDownType = "language" | "isPartOf" | "license" | "captureAgent" | "aclRole" | "workflow" | "aclTemplate" | "newTheme" | "comment" | "theme" | "time" | "filter"; +export type DropDownType = "language" | "isPartOf" | "license" | "captureAgent" | "aclRole" | "workflow" | "aclTemplate" | "newTheme" | "comment" | "theme" | "time" | "filter" | "policyAction"; /** * This component provides a bar chart for visualising (statistics) data diff --git a/src/components/shared/NewResourceModal.tsx b/src/components/shared/NewResourceModal.tsx index 848e48df43..d47f022c7c 100644 --- a/src/components/shared/NewResourceModal.tsx +++ b/src/components/shared/NewResourceModal.tsx @@ -8,6 +8,7 @@ import NewGroupWizard from "../users/partials/wizard/NewGroupWizard"; import NewUserWizard from "../users/partials/wizard/NewUserWizard"; import { useHotkeys } from "react-hotkeys-hook"; import { availableHotkeys } from "../../configs/hotkeysConfig"; +import NewLifeCyclePolicyWizard from "../events/partials/wizards/NewLifeCyclePolicyWizard"; /** * This component renders the modal for adding new resources @@ -17,7 +18,7 @@ const NewResourceModal = ({ resource }: { handleClose: () => void, - resource: "events" | "series" | "user" | "group" | "acl" | "themes" + resource: "events" | "series" | "user" | "group" | "acl" | "themes" | "lifecyclepolicy" }) => { const { t } = useTranslation(); @@ -56,6 +57,9 @@ const NewResourceModal = ({ {resource === "user" && (

{t("USERS.USERS.DETAILS.NEWCAPTION")}

)} + {resource === "lifecyclepolicy" && ( +

{t("LIFECYCLE.POLICIES.NEW.CAPTION")}

+ )}
{resource === "events" && ( //New Event Wizard @@ -81,6 +85,10 @@ const NewResourceModal = ({ // New User Wizard )} + {resource === "lifecyclepolicy" && ( + // New LifeCyclePolicy Wizard + + )} ); diff --git a/src/components/shared/wizard/RenderField.tsx b/src/components/shared/wizard/RenderField.tsx index 1a72718c97..6e8a979847 100644 --- a/src/components/shared/wizard/RenderField.tsx +++ b/src/components/shared/wizard/RenderField.tsx @@ -10,6 +10,8 @@ import { parseISO } from "date-fns"; import { FieldProps } from "formik"; import { MetadataField } from "../../../slices/eventSlice"; import { renderValidDate } from "../../../utils/dateUtils"; +import Cron from "react-js-cron"; +import 'react-js-cron/dist/styles.css' const childRef = React.createRef(); /** @@ -23,7 +25,7 @@ const RenderField = ({ isFirstField = false, }: { field: FieldProps["field"] - metadataField: MetadataField + metadataField: { type: string, collection: { [key: string]: unknown }[], required: boolean, id: string }, //MetadataField form: FieldProps["form"] showCheck?: boolean, isFirstField?: boolean, @@ -129,6 +131,17 @@ const RenderField = ({ handleKeyDown={handleKeyDown} /> )} + {metadataField.type === "cron" && ( + + )} ); }; @@ -229,7 +242,7 @@ const EditableSingleSelect = ({ showCheck, }: { field: FieldProps["field"] - metadataField: MetadataField + metadataField: { type: string, collection: { [key: string]: unknown }[], required: boolean, id: string }, //MetadataField text: string editMode: boolean | undefined setEditMode: (e: boolean) => void @@ -427,4 +440,55 @@ const EditableSingleValueTime = ({ ); }; +const EditableCronValue = ({ + field, + form: { initialValues, setFieldValue }, + text, + editMode, + setEditMode, + showCheck, + handleKeyDown, +} : { + field: FieldProps["field"] + form: FieldProps["form"] + text: string + editMode: boolean | undefined + setEditMode: (e: boolean) => void + showCheck?: boolean, + handleKeyDown: (event: React.KeyboardEvent, type: string) => void +}) => { + + return editMode ? ( + // TODO: Figure out a way to set EditMode to false again + // As of now, selecting a value in one of the dropdowns will cause EditMode + // to be set to false, without the selected value actually being set. +
setEditMode(false)} + onKeyDown={(e) => handleKeyDown(e, "cron")} + // ref={childRef} + > + setFieldValue(field.name, value)} + /> +
+ ) : ( +
setEditMode(true)} className="show-edit"> + {text || ""} +
+ + {showCheck && ( + + )} +
+
+ ) +}; + + export default RenderField; diff --git a/src/components/shared/wizard/RenderMultiField.tsx b/src/components/shared/wizard/RenderMultiField.tsx index 303d5f7598..4357f40ce1 100644 --- a/src/components/shared/wizard/RenderMultiField.tsx +++ b/src/components/shared/wizard/RenderMultiField.tsx @@ -28,7 +28,7 @@ const RenderMultiField = ({ // Temporary storage for value user currently types in const [inputValue, setInputValue] = useState(""); - let fieldValue = [...field.value]; + let fieldValue = field.value ? [...field.value] : []; // Handle change of value user currently types in const handleChange = (e: React.ChangeEvent) => { diff --git a/src/configs/modalConfig.ts b/src/configs/modalConfig.ts index a9c4ba1901..5922dae1db 100644 --- a/src/configs/modalConfig.ts +++ b/src/configs/modalConfig.ts @@ -5,6 +5,7 @@ import { TobiraPage } from "../slices/seriesSlice"; import { initArray } from "../utils/utils"; import { EditedEvents, Event, UploadAssetsTrack } from "../slices/eventSlice"; import { Role } from "../slices/aclSlice"; +import { TargetFilter } from "../slices/lifeCycleSlice"; // Context for notifications shown in modals export const NOTIFICATION_CONTEXT = "modal-form"; @@ -210,3 +211,33 @@ export const initialFormValuesEditScheduledEvents: { editedEvents: [], changedEvents: [], }; + +export const initialFormValuesNewLifeCyclePolicy: { + title: string, + isActive: boolean, + isCreatedFromConfig: boolean, + targetType: string, + timing: string, + action: string, + actionDate: string, + cronTrigger: string, + actionParameters: { [key: string]: unknown } + acls: TransformedAcl[] + targetFiltersArray: (TargetFilter & { filter: string })[], +} = { + title: "", + isActive: true, + isCreatedFromConfig: false, + targetType: "EVENT", + timing: "SPECIFIC_DATE", + action: "START_WORKFLOW", + actionDate: "", + cronTrigger: "", + actionParameters: { + workflowId: "noop", + workflowParameters: `{"straightToPublishing": true}` + }, + + acls: [], + targetFiltersArray: [], +}; diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index cd16368d29..8bfeeff89a 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -119,7 +119,8 @@ "GROUP": "The following group will be deleted", "USER": "The following user will be deleted", "THEME": "The following theme will be deleted", - "LOCATION": "The following location will be deleted" + "LOCATION": "The following location will be deleted", + "LIFECYCLE_POLICY": "The following lifeCycle policy will be deleted" }, "NAME": "Name" }, @@ -190,6 +191,10 @@ "EVENTS_NOT_DELETED_NOT_AUTHORIZED": "The event(s) could not be deleted, because you don't have the permission to do so.", "SERIES_DELETED": "The series has been deleted", "SERIES_NOT_DELETED": "The series could not be deleted", + "LIFECYCLE_POLICY_ADDED": "The lifeCycle policy has been created", + "LIFECYCLE_POLICY_NOT_SAVED": "The lifeCycle policy could not be saved", + "LIFECYCLE_POLICY_DELETED": "The lifeCycle policy has been deleted", + "LIFECYCLE_POLICY_NOT_DELETED": "The lifeCycle policy could not be deleted", "LOCATION_DELETED": "The location has been deleted", "LOCATION_NOT_DELETED": "The location could not be deleted", "LOCATION_NOT_DELETED_NOT_AUTHORIZED": "The location could not be deleted, because you don't have the permission to do so.", @@ -1261,7 +1266,15 @@ "TIMING": "Timing", "TITLE": "Title", "TOOLTIP": { - "DETAILS": "LifeCycle Policy Details" + "DETAILS": "LifeCycle Policy Details", + "DELETE": "Delete LifeCycle Policy" + }, + "ADD_POLICY": "Add LifeCycle Policy" + }, + "NEW": { + "CAPTION": "Create LifeCycle Policy", + "GENERAL": { + "CAPTION": "General" } }, "DETAILS": { @@ -1269,16 +1282,31 @@ "GENERAL": { "ACTION": "Action", "ACTIONDATE": "Action Date", - "ACTIONPARAMETERS": "Action Parameters", + "ACTIONPARAMETERS": { + "CAPTION": "Action Parameters", + "WORKFLOW_ID": "Workflow ID", + "WORKFLOW_PARAMETERS": "Workflow Parameters" + }, "CAPTION": "LifeCycle Policy Details", "CRONTRIGGER": "Cron Trigger", "ID": "Identifier", "ISACTIVE": "Active", "ISCREATEDFROMCONFIG": "Created from Config", "TARGETTYPE": "Target Type", - "TARGETFILTERS": "Target Filters", + "TARGETFILTERS": { + "CAPTION": "Target Filters", + "FILTER": "Filter", + "VALUE": "Value", + "TYPE": "Type", + "MUST": "Must", + "NEW": "New Filter" + }, "TIMING": "Timing", - "TITLE": "Title" + "TITLE": "Title", + "NOTE": { + "TITLE": "A note on editing LifeCycle Policies", + "MESSAGE": "The same policy cannot affect the same target multiple times. Depending on your goals, creating a new policy may be required." + } }, "ACCESS": { "LABEL": "Select a template", diff --git a/src/selectors/lifeCycleDetailsSelectors.ts b/src/selectors/lifeCycleDetailsSelectors.ts index 364368819a..8b279abb40 100644 --- a/src/selectors/lifeCycleDetailsSelectors.ts +++ b/src/selectors/lifeCycleDetailsSelectors.ts @@ -5,3 +5,6 @@ import { RootState } from "../store"; */ export const getLifeCyclePolicyDetails = (state: RootState) => state.lifeCyclePolicyDetails; export const getLifeCyclePolicyDetailsAcl = (state: RootState) => state.lifeCyclePolicyDetails.accessControlEntries; +export const getLifeCyclePolicyActions = (state: RootState) => state.lifeCyclePolicyDetails.actionsEnum; +export const getLifeCyclePolicyTargetTypes = (state: RootState) => state.lifeCyclePolicyDetails.targetTypesEnum; +export const getLifeCyclePolicyTimings = (state: RootState) => state.lifeCyclePolicyDetails.timingsEnum; diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts index 2bba3cda56..447254d3ef 100644 --- a/src/slices/lifeCycleDetailsSlice.ts +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -5,6 +5,8 @@ import { LifeCyclePolicy } from './lifeCycleSlice'; import { TransformedAcl } from './aclDetailsSlice'; import { createPolicy } from '../utils/resourceUtils'; import { Ace } from './aclSlice'; +import { addNotification } from './notificationSlice'; + /** * This file contains redux reducer for actions affecting the state of a lifeCyclePolicy/capture agent @@ -12,6 +14,10 @@ import { Ace } from './aclSlice'; interface LifeCyclePolicyDetailsState extends LifeCyclePolicy { statusLifeCyclePolicyDetails: 'uninitialized' | 'loading' | 'succeeded' | 'failed', errorLifeCyclePolicyDetails: SerializedError | null, + + actionsEnum: string[], + targetTypesEnum: string[], + timingsEnum: string[], } // Initial state of lifeCyclePolicy details in redux store @@ -29,7 +35,11 @@ const initialState: LifeCyclePolicyDetailsState = { actionDate: "", cronTrigger: "", targetFilters: {}, - accessControlEntries: [] + accessControlEntries: [], + + actionsEnum: [], + targetTypesEnum: [], + timingsEnum: [], }; // fetch details of certain lifeCyclePolicy from server @@ -70,6 +80,27 @@ export const fetchLifeCyclePolicyDetails = createAppAsyncThunk('lifeCyclePolicyD return data; }); +export const fetchLifeCyclePolicyActions = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyActions', async () => { + const res = await axios.get(`/api/lifecyclemanagement/policies/actions`); + const data = res.data; + + return data; +}); + +export const fetchLifeCyclePolicyTargetTypes = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyTargetTypes', async () => { + const res = await axios.get(`/api/lifecyclemanagement/policies/targettypes`); + const data = res.data; + + return data; +}); + +export const fetchLifeCyclePolicyTimings = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyTimings', async () => { + const res = await axios.get(`/api/lifecyclemanagement/policies/timings`); + const data = res.data; + + return data; +}); + // Dummy function for compatability export const fetchLifeCyclePolicyDetailsAcls = createAppAsyncThunk('lifeCyclePolicyDetails/fetchLifeCyclePolicyDetailsAcls', async (id: string, {getState}) => { const state = getState(); @@ -81,7 +112,48 @@ export const updateLifeCyclePolicyAccess = createAppAsyncThunk('lifeCyclePolicyD id: string, policies: { acl: { ace: Ace[] } } }, {dispatch}) => { - return false; + const { id, policies } = params; + + let data = new URLSearchParams(); + data.append("accessControlEntries", JSON.stringify(policies.acl.ace)); + + axios.put(`/api/lifecyclemanagement/policies/${id}`, data) + .then((response) => { + console.info(response); + dispatch(addNotification({type: "success", key: "LIFECYCLEPOLICY_ADDED"})); + return true; + }) + .catch((response) => { + console.error(response); + dispatch(addNotification({type: "error", key: "LIFECYCLEPOLICY_NOT_SAVED"})); + return false; + }); +}); + +export const updateLifeCyclePolicy = createAppAsyncThunk('lifeCyclePolicyDetails/updateLifeCyclePolicy', async (policy: LifeCyclePolicy, {dispatch}) => { + let data = new URLSearchParams(); + + Object.entries(policy).forEach(([key, value]) => { + let stringified = value + if (stringified instanceof Date) { + stringified = stringified.toJSON() + } + else if (stringified === Object(stringified)) { + stringified = JSON.stringify(stringified) + } + // @ts-ignore + data.append(key, stringified); + }) + + axios.put(`/api/lifecyclemanagement/policies/${policy.id}`, data) + .then((response) => { + console.info(response); + dispatch(addNotification({type: "success", key: "LIFECYCLEPOLICY_ADDED"})); + }) + .catch((response) => { + console.error(response); + dispatch(addNotification({type: "error", key: "LIFECYCLEPOLICY_NOT_SAVED"})); + }); }); const lifeCyclePolicyDetailsSlice = createSlice({ @@ -126,7 +198,25 @@ const lifeCyclePolicyDetailsSlice = createSlice({ .addCase(fetchLifeCyclePolicyDetails.rejected, (state, action) => { state.statusLifeCyclePolicyDetails = 'failed'; state.errorLifeCyclePolicyDetails = action.error; - }); + }) + .addCase(fetchLifeCyclePolicyActions.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const actionsEnum = action.payload; + state.actionsEnum = actionsEnum; + }) + .addCase(fetchLifeCyclePolicyTargetTypes.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const targetTypesEnum = action.payload; + state.targetTypesEnum = targetTypesEnum; + }) + .addCase(fetchLifeCyclePolicyTimings.fulfilled, (state, action: PayloadAction< + LifeCyclePolicyDetailsState["actionsEnum"] + >) => { + const timingsEnum = action.payload; + state.timingsEnum = timingsEnum; + }) } }); diff --git a/src/slices/lifeCycleSlice.ts b/src/slices/lifeCycleSlice.ts index cfa4e78192..6be65c607d 100644 --- a/src/slices/lifeCycleSlice.ts +++ b/src/slices/lifeCycleSlice.ts @@ -2,30 +2,35 @@ import { PayloadAction, SerializedError, createSlice } from '@reduxjs/toolkit' import { TableConfig } from "../configs/tableConfigs/aclsTableConfig"; import { lifeCyclePolicyTableConfig } from "../configs/tableConfigs/lifeCyclePoliciesTableConfig"; import axios from 'axios'; -import { getURLParams } from '../utils/resourceUtils'; +import { getURLParams, prepareAccessPolicyRulesForPost } from '../utils/resourceUtils'; import { createAppAsyncThunk } from '../createAsyncThunkWithTypes'; import { TransformedAcl } from './aclDetailsSlice'; +import { addNotification } from './notificationSlice'; -type LifeCyclePolicyTiming = "SPECIFIC_DATE" | "REPEATING" | "ALWAYS"; -type LifeCyclePolicyAction = "START_WORKFLOW" -type LifeCyclePolicyTargetType = "EVENT" +// type LifeCyclePolicyTiming = "SPECIFIC_DATE" | "REPEATING" | "ALWAYS"; +// type LifeCyclePolicyAction = "START_WORKFLOW" +// type LifeCyclePolicyTargetType = "EVENT" +export type TargetFilter = { + value: string | string[], + type: TargetFiltersType, + must: boolean +} +export const ALL_TARGET_FILTER_TYPES = ['SEARCH', 'WILDCARD', 'GREATER_THAN', 'LESS_THAN'] as const; +type TargetFilterTypesTuple = typeof ALL_TARGET_FILTER_TYPES; +type TargetFiltersType = TargetFilterTypesTuple[number]; export type LifeCyclePolicy = { actionParameters: { [key: string]: unknown }, // JSON. Variable, depends on action - timing: LifeCyclePolicyTiming, - action: LifeCyclePolicyAction, - targetType: LifeCyclePolicyTargetType, + timing: string, + action: string, + targetType: string, id: string, title: string, isActive: boolean, isCreatedFromConfig: boolean, actionDate: string, // Date cronTrigger: string, - targetFilters: { [key: string]: { - value: string, - type: "SEARCH" | "WILDCARD" | "GREATER_THAN" | "LESS_THAN", - must: boolean - }}, + targetFilters: { [key: string]: TargetFilter }, accessControlEntries: TransformedAcl[] } @@ -65,6 +70,72 @@ export const fetchLifeCyclePolicies = createAppAsyncThunk('lifeCycle/fetchLifeCy return res.data; }); +export const postNewLifeCyclePolicy = createAppAsyncThunk('lifeCycle/postNewLifeCyclePolicy', async ( + policy: { + actionParameters: { [key: string]: unknown }, + timing: string, + action: string, + targetType: string, + title: string, + isActive: boolean, + actionDate: string, + cronTrigger: string, + targetFilters: { [key: string]: TargetFilter }, + accessControlEntries: TransformedAcl[] + }, + { dispatch } +) => { + let data = new URLSearchParams(); + + // Format filter collections + // for (const filterName in policy.targetFilters) { + // // policy.targetFilters[filterName] + // if (hasOwnProperty(TARGET_FILTER_KEYS_EVENTS, filterName) + // && TARGET_FILTER_KEYS_EVENTS[filterName].collection) { + // policy.targetFilters[filterName].value = policy.targetFilters[filterName].value.toString() + // } + // } + + // Stringify + Object.entries(policy).forEach(([key, value]) => { + let stringified = value + if (stringified instanceof Date) { + stringified = stringified.toJSON() + } + else if (stringified === Object(stringified)) { + stringified = JSON.stringify(stringified) + } + // @ts-ignore + data.append(key, stringified); + }) + + data.delete("accessControlEntries"); + data.append("accessControlEntries", JSON.stringify(prepareAccessPolicyRulesForPost(policy.accessControlEntries).acl.ace)) + + axios.post(`/api/lifecyclemanagement/policies`, data) + .then((res) => { + console.info(res); + dispatch(addNotification({type: "success", key: "LIFECYCLE_POLICY_ADDED"})); + }) + .catch((res) => { + console.error(res); + dispatch(addNotification({type: "error", key: "LIFECYCLE_POLICY_NOT_SAVED"})); + }); +}); + +export const deleteLifeCyclePolicy = createAppAsyncThunk('lifeCycle/fetchLifeCyclePolicies', async (id: string, { dispatch }) => { + axios + .delete(`/api/lifecyclemanagement/policies/${id}`) + .then((res) => { + console.info(res); + dispatch(addNotification({type: "success", key: "LIFECYCLE_POLICY_DELETED"})); + }) + .catch((res) => { + console.error(res); + dispatch(addNotification({type: "error", key: "LIFECYCLE_POLICY_NOT_DELETED"})); + }); +}); + const lifeCycleSlice = createSlice({ name: 'lifeCycle', initialState, diff --git a/src/slices/workflowSlice.ts b/src/slices/workflowSlice.ts index e6a9db5b46..a0c8a688b5 100644 --- a/src/slices/workflowSlice.ts +++ b/src/slices/workflowSlice.ts @@ -15,7 +15,7 @@ export type FieldSetField = { [key: string]: unknown } -type ConfigurationPanelField = { +export type ConfigurationPanelField = { // We could potentially specify 'fieldset' more, but I cannot find a definition // for which key value pairs are allowed fieldset?: FieldSetField[] // Values can be anything diff --git a/src/styles/main.scss b/src/styles/main.scss index 083aaa90c8..d880fef953 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -625,3 +625,8 @@ tr.info { overflow: hidden; text-overflow: ellipsis; } + +// React-JS-Cron +.my-project-cron-select-dropdown { + z-index: 10000; +} \ No newline at end of file diff --git a/src/utils/componentStyles.ts b/src/utils/componentStyles.ts index 599d0c68e6..8bee3a5c71 100644 --- a/src/utils/componentStyles.ts +++ b/src/utils/componentStyles.ts @@ -19,6 +19,8 @@ export function dropDownStyle(type: DropDownType): StylesConfig { ? 360 : type === "aclTemplate" || type === "comment" || type === "filter" ? 200 + : type === "policyAction" + ? 150 : 250; return { diff --git a/src/utils/dropDownUtils.ts b/src/utils/dropDownUtils.ts index c3c1b052e7..b80e040379 100644 --- a/src/utils/dropDownUtils.ts +++ b/src/utils/dropDownUtils.ts @@ -31,6 +31,10 @@ export const filterBySearch = (filterText: string, type: DropDownType, options: return options.filter((item) => t(item.label).toLowerCase().includes(filterText) ); + } else if (type === "policyAction") { + return options.filter((item) => + t(item).toLowerCase().includes(filterText) + ); } else { return options.filter((item) => item.value.toLowerCase().includes(filterText) @@ -127,7 +131,14 @@ export const formatDropDownOptions = ( label: item.label, }); } - } else { + } else if (type === "policyAction") { + for (const item of unformattedOptions) { + formattedOptions.push({ + value: item, + label: item, + }); + } + }else { for (const item of unformattedOptions) { formattedOptions.push({ value: item.value, diff --git a/src/utils/lifeCycleUtils.ts b/src/utils/lifeCycleUtils.ts new file mode 100644 index 0000000000..f39117dde7 --- /dev/null +++ b/src/utils/lifeCycleUtils.ts @@ -0,0 +1,16 @@ +import { LifeCyclePolicy, TargetFilter } from "../slices/lifeCycleSlice"; + +export const parseTargetFiltersForSubmit = ( + targetFiltersArray: (TargetFilter & { filter: string })[] +) => { + const targetFilters: LifeCyclePolicy["targetFilters"] = {} + for (const filter of targetFiltersArray) { + targetFilters[filter.filter] = { + value: filter.value, + type: filter.type, + must: filter.must + } + } + + return targetFilters; +} diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 8e6857d36b..a5e0948c82 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -165,3 +165,13 @@ export const translateOverrideFallback = (asset: UploadAssetOption, t: TFunction return result; } + +/** + * (Hopefully) Typesafe way of checking if an object has a specific property + */ +export function hasOwnProperty( + obj: O, + key: K, +): obj is O & Record { + return Object.prototype.hasOwnProperty.call(obj, key); +} diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 7d1829bdea..0cc0eb2346 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -225,3 +225,30 @@ export const EditGroupSchema = Yup.object().shape({ export const AdopterRegistrationSchema = Yup.object().shape({ email: Yup.string().email(), }); + +// Validation Schema used in lifecycle policy modal +export const LifeCyclePolicySchema = [ + Yup.object().shape({ + title: Yup.string().required("Required"), + isActive: Yup.bool().required("Required"), + targetType: Yup.string().required("Required"), + timing: Yup.string().required("Required"), + action: Yup.string().required("Required"), + actionParameters: Yup.object().shape({ + // Property only required if it actually exists on the object + workflowId: Yup.string().required("Required"), + // workflowId: Yup.string().when("workflowId", { + // is: (exists: any) => !!exists, + // then: Yup.string().required("Required"), + // }), + }), + actionDate: Yup.date().when("timing", { + is: (timing: string) => timing === "SPECIFIC_DATE", + then: () => Yup.date().required("Required"), + }), + cronTrigger: Yup.string().when("timing", { + is: (timing: string) => timing === "REPEATING", + then: () => Yup.string().required("Required"), + }), + }), +]; From 865e34c76c698330e2d8419a1286e6e2e70557e7 Mon Sep 17 00:00:00 2001 From: Arnei Date: Fri, 31 Jan 2025 16:19:18 +0100 Subject: [PATCH 4/6] Fix modal usage errors --- src/components/events/LifeCyclePolicies.tsx | 20 +++++++------- .../partials/LifeCyclePolicyActionCell.tsx | 26 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx index 476c455dc5..3cfd870c33 100644 --- a/src/components/events/LifeCyclePolicies.tsx +++ b/src/components/events/LifeCyclePolicies.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import MainNav from "../shared/MainNav"; import { useTranslation } from "react-i18next"; import { Link } from "react-router"; @@ -25,6 +25,7 @@ import { setOffset } from "../../slices/tableSlice"; import { fetchSeries } from "../../slices/seriesSlice"; import NewResourceModal from "../shared/NewResourceModal"; import { fetchLifeCyclePolicyActions, fetchLifeCyclePolicyTargetTypes, fetchLifeCyclePolicyTimings } from "../../slices/lifeCycleDetailsSlice"; +import { ModalHandle } from "../shared/modals/Modal"; /** * This component renders the table view of policies @@ -33,7 +34,7 @@ const LifeCyclePolicies = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const [displayNavigation, setNavigation] = useState(false); - const [displayNewPolicyModal, setNewPolicyModal] = useState(false); + const newPolicyModalRef = useRef(null); const user = useAppSelector(state => getUserInformation(state)); const policiesTotal = useAppSelector(state => getTotalLifeCyclePolicies(state)); @@ -96,11 +97,11 @@ const LifeCyclePolicies = () => { await dispatch(fetchLifeCyclePolicyTargetTypes()); await dispatch(fetchLifeCyclePolicyTimings()); - setNewPolicyModal(true); + newPolicyModalRef.current?.open() }; const hideNewPolicyModal = () => { - setNewPolicyModal(false); + newPolicyModalRef.current?.close?.() }; return ( @@ -109,12 +110,11 @@ const LifeCyclePolicies = () => { { /* Display modal for new event if add event button is clicked */ - displayNewPolicyModal && ( - - ) + } {/* Include Burger-button menu*/} diff --git a/src/components/events/partials/LifeCyclePolicyActionCell.tsx b/src/components/events/partials/LifeCyclePolicyActionCell.tsx index 78de162c74..e3f459cbf1 100644 --- a/src/components/events/partials/LifeCyclePolicyActionCell.tsx +++ b/src/components/events/partials/LifeCyclePolicyActionCell.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAppDispatch, useAppSelector } from "../../../store"; import { Tooltip } from "../../shared/Tooltip"; @@ -9,6 +9,7 @@ import { hasAccess } from "../../../utils/utils"; import { getUserInformation } from "../../../selectors/userInfoSelectors"; import { fetchLifeCyclePolicyDetails } from "../../../slices/lifeCycleDetailsSlice"; import ConfirmModal from "../../shared/ConfirmModal"; +import { ModalHandle } from "../../shared/modals/Modal"; /** * This component renders the title cells of series in the table view @@ -22,7 +23,7 @@ const LifeCyclePolicyActionCell = ({ const dispatch = useAppDispatch(); const [displayLifeCyclePolicyDetails, setLifeCyclePolicyDetails] = useState(false); - const [displayDeleteConfirmation, setDeleteConfirmation] = useState(false); + const deleteConfirmationModalRef = useRef(null); const user = useAppSelector(state => getUserInformation(state)); @@ -37,11 +38,11 @@ const LifeCyclePolicyActionCell = ({ }; const hideDeleteConfirmation = () => { - setDeleteConfirmation(false); + deleteConfirmationModalRef.current?.close?.() }; const showDeleteConfirmation = async () => { - setDeleteConfirmation(true); + deleteConfirmationModalRef.current?.open() }; const deletingPolicy = (id: string) => { @@ -81,15 +82,14 @@ const LifeCyclePolicyActionCell = ({ )} - {displayDeleteConfirmation && ( - - )} + ); }; From c3c8672188aa4b510d994851ab68c9a875602970 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 2 Apr 2025 09:25:23 +0200 Subject: [PATCH 5/6] Fix various eslint complaints --- .../ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx | 3 +-- .../ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx | 3 +-- .../partials/wizards/LifeCyclePolicyGeneralFields.tsx | 10 +++++----- .../partials/wizards/NewLifeCyclePolicySummary.tsx | 10 +++++----- src/slices/lifeCycleDetailsSlice.ts | 5 ++--- src/slices/lifeCycleSlice.ts | 5 ++--- src/thunks/tableThunks.ts | 2 +- src/utils/lifeCycleUtils.ts | 2 +- 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx index bb5957f982..f18d56afb2 100644 --- a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyAccessTab.tsx @@ -40,8 +40,7 @@ const LifeCyclePolicyDetailsAccessTab = ({ descriptionText={t("LIFECYCLE.POLICIES.DETAILS.ACCESS.DESCRIPTION")} policies={acl} fetchAccessPolicies={fetchLifeCyclePolicyDetailsAcls} - // TODO: Figure out why typescript is being funky here - // @ts-ignore + // @ts-expect-error: TODO: Figure out why typescript is being funky here saveNewAccessPolicies={updateLifeCyclePolicyAccess} editAccessRole={"ROLE_UI_LIFECYCLEPOLICY_DETAILS_ACL_EDIT"} policyChanged={policyChanged} diff --git a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx index 1682a6cb51..a93fdac59b 100644 --- a/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx +++ b/src/components/events/partials/ModalTabsAndPages/LifeCyclePolicyGeneralTab.tsx @@ -69,8 +69,7 @@ const LifeCyclePolicyGeneralTab = ({ // Access policies are handled in a different tab // Remove them here, else they will delete the ACL due to their formatting - // TODO: Find a typesafe (or straight up better) way to do this - // @ts-ignore + // @ts-expect-error: TODO: Find a typesafe (or straight up better) way to do this delete initialValues.accessControlEntries // Transform filters into something more editable diff --git a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx index ddb910deb1..3b002cdca8 100644 --- a/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx +++ b/src/components/events/partials/wizards/LifeCyclePolicyGeneralFields.tsx @@ -167,7 +167,7 @@ const LifeCyclePolicyGeneralFields = ({ value: element, name: element }) ), + collection: targetTypes.map((element) => ({ value: element, name: element })), id: "language", }} component={RenderField} @@ -182,7 +182,7 @@ const LifeCyclePolicyGeneralFields = ({ value: element, name: element }) ), + collection: timings.map((element) => ({ value: element, name: element })), id: "language", }} component={RenderField} @@ -197,7 +197,7 @@ const LifeCyclePolicyGeneralFields = ({ value: element, name: element }) ), + collection: actions.map((element) => ({ value: element, name: element })), id: "language" }} component={RenderField} @@ -457,7 +457,7 @@ const DropdownField = ({ ) }; -const getTargetFilterRenderType = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[] ) => { +const getTargetFilterRenderType = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[]) => { const option = targetFilterOptions.find(e => e.id === filterName); if (option === undefined) { return "text"; @@ -469,7 +469,7 @@ const getTargetFilterRenderType = (filterName: string, targetFilterOptions: { id return option.type; } -const getTargetFilterRenderCollection = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[] ) => { +const getTargetFilterRenderCollection = (filterName: string, targetFilterOptions: { id: string, type: string, collection?: unknown }[]) => { const option = targetFilterOptions.find(e => e.id === filterName); return option !== undefined ? option.collection : undefined } diff --git a/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx b/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx index ddf79b8a47..00a9485074 100644 --- a/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx +++ b/src/components/events/partials/wizards/NewLifeCyclePolicySummary.tsx @@ -55,7 +55,7 @@ const NewLifeCyclePolicySummary = {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.ACTIONDATE")} - {t("dateFormats.dateTime.medium", { dateTime: renderValidDate(formik.values.actionDate) } )} + {t("dateFormats.dateTime.medium", { dateTime: renderValidDate(formik.values.actionDate) })} {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.CRONTRIGGER")} @@ -64,8 +64,8 @@ const NewLifeCyclePolicySummary = {t("LIFECYCLE.POLICIES.DETAILS.GENERAL.TARGETFILTERS.CAPTION")} - {formik.values.targetFiltersArray.map((filter) => ( - + {formik.values.targetFiltersArray.map((filter, key) => ( + {filter.filter} {filter.value} {filter.type} @@ -79,9 +79,9 @@ const NewLifeCyclePolicySummary = {formik.values.action === "START_WORKFLOW" && - {/* @ts-ignore */} + {/* @ts-expect-error: Potentially unknown */} {formik.values.actionParameters.workflowId} - {/* @ts-ignore */} + {/* @ts-expect-error: Potentially unknown */} {formik.values.actionParameters.workflowParameters} } diff --git a/src/slices/lifeCycleDetailsSlice.ts b/src/slices/lifeCycleDetailsSlice.ts index 447254d3ef..1cce3d158e 100644 --- a/src/slices/lifeCycleDetailsSlice.ts +++ b/src/slices/lifeCycleDetailsSlice.ts @@ -137,11 +137,10 @@ export const updateLifeCyclePolicy = createAppAsyncThunk('lifeCyclePolicyDetails let stringified = value if (stringified instanceof Date) { stringified = stringified.toJSON() - } - else if (stringified === Object(stringified)) { + } else if (stringified === Object(stringified)) { stringified = JSON.stringify(stringified) } - // @ts-ignore + // @ts-expect-error: ??? data.append(key, stringified); }) diff --git a/src/slices/lifeCycleSlice.ts b/src/slices/lifeCycleSlice.ts index 860da2037d..cd1461e691 100644 --- a/src/slices/lifeCycleSlice.ts +++ b/src/slices/lifeCycleSlice.ts @@ -101,11 +101,10 @@ export const postNewLifeCyclePolicy = createAppAsyncThunk('lifeCycle/postNewLife let stringified = value if (stringified instanceof Date) { stringified = stringified.toJSON() - } - else if (stringified === Object(stringified)) { + } else if (stringified === Object(stringified)) { stringified = JSON.stringify(stringified) } - // @ts-ignore + // @ts-expect-error: ??? data.append(key, stringified); }) diff --git a/src/thunks/tableThunks.ts b/src/thunks/tableThunks.ts index 77c82bb7fa..4ed43a3876 100644 --- a/src/thunks/tableThunks.ts +++ b/src/thunks/tableThunks.ts @@ -120,7 +120,7 @@ export const loadSeriesIntoTable = (): AppThunk => (dispatch, getState) => { }; export const loadLifeCyclePoliciesIntoTable = (): AppThunk => (dispatch, getState) => { - const { lifeCycle, table } = getState() as RootState; + const { lifeCycle, table } = getState(); const pagination = table.pagination; const resource = lifeCycle.results; const total = lifeCycle.total; diff --git a/src/utils/lifeCycleUtils.ts b/src/utils/lifeCycleUtils.ts index f39117dde7..4b29e2bab8 100644 --- a/src/utils/lifeCycleUtils.ts +++ b/src/utils/lifeCycleUtils.ts @@ -3,7 +3,7 @@ import { LifeCyclePolicy, TargetFilter } from "../slices/lifeCycleSlice"; export const parseTargetFiltersForSubmit = ( targetFiltersArray: (TargetFilter & { filter: string })[] ) => { - const targetFilters: LifeCyclePolicy["targetFilters"] = {} + const targetFilters: LifeCyclePolicy["targetFilters"] = {} for (const filter of targetFiltersArray) { targetFilters[filter.filter] = { value: filter.value, From 8815f373611598a7d21ef783cafae69574ea7717 Mon Sep 17 00:00:00 2001 From: Arnei Date: Wed, 9 Apr 2025 14:05:14 +0200 Subject: [PATCH 6/6] Fix undefined string --- src/components/events/LifeCyclePolicies.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/events/LifeCyclePolicies.tsx b/src/components/events/LifeCyclePolicies.tsx index dcebf9c8f8..8636121697 100644 --- a/src/components/events/LifeCyclePolicies.tsx +++ b/src/components/events/LifeCyclePolicies.tsx @@ -88,8 +88,6 @@ const LifeCyclePolicies = () => { onShowModal: showNewPolicyModal, text: "LIFECYCLE.POLICIES.TABLE.ADD_POLICY", resource: "lifecyclepolicy", - hotkeySequence: availableHotkeys.general.NEW_LIFECYCLEPOLICY.sequence, - hotkeyDescription: availableHotkeys.general.NEW_LIFECYCLEPOLICY.description, }} >