From 859cbb71febfa970656dac3ed283716fbd35a7c8 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 17 Nov 2022 14:48:16 -0700 Subject: [PATCH] Refactored notifcations --- ui/src/app/App.js | 137 +++++++++--------- .../app/admin/container/EditConfiguration.js | 6 +- ui/src/app/admin/container/EditGroup.js | 7 +- ui/src/app/admin/container/EditRole.js | 5 +- ui/src/app/admin/container/MetadataActions.js | 13 +- .../app/admin/container/NewConfiguration.js | 5 +- ui/src/app/admin/container/NewGroup.js | 5 +- ui/src/app/admin/container/NewRole.js | 5 +- ui/src/app/admin/container/UserManagement.js | 3 - .../app/admin/hoc/ConfigurationsProvider.js | 5 +- ui/src/app/admin/hoc/GroupsProvider.js | 5 +- ui/src/app/admin/hoc/RolesProvider.js | 5 +- ui/src/app/admin/hoc/RolesProvider.test.js | 7 +- ui/src/app/dashboard/view/ActionsTab.js | 4 +- ui/src/app/dashboard/view/Dashboard.js | 16 +- .../dashboard/view/DynamicRegistrationsTab.js | 48 +++--- ui/src/app/dashboard/view/SourcesTab.js | 3 - ui/src/app/dynamic-registration/api.js | 2 +- .../hoc/DynamicRegistrationActions.js | 14 +- .../app/metadata/component/MetadataHeader.js | 5 +- .../filter/component/MetadataFilters.js | 5 +- ui/src/app/metadata/editor/MetadataEditor.js | 5 +- ui/src/app/metadata/hoc/MetadataAttributes.js | 5 +- ui/src/app/metadata/hoc/MetadataSelector.js | 21 ++- .../hoc/attribute/AttributeBundleApi.js | 5 +- ui/src/app/metadata/new/NewAttribute.js | 5 +- ui/src/app/metadata/new/NewFilter.js | 5 +- ui/src/app/metadata/view/EditFilter.js | 5 +- .../metadata/view/MetadataAttributeEdit.js | 5 +- ui/src/app/metadata/view/MetadataCopy.js | 5 +- ui/src/app/metadata/view/MetadataOptions.js | 6 +- ui/src/app/metadata/view/MetadataUpload.js | 5 +- ui/src/app/metadata/view/MetadataWizard.js | 5 +- .../component/NotificationList.js | 13 +- .../DynamicRegistrationSlice.js | 39 ++++- ui/src/app/store/index.js | 2 + ui/src/app/store/metadata/SourceSlice.js | 45 +++++- .../store/notifications/NotificationSlice.js | 56 +++++++ ui/src/app/store/user/CurrentUserSlice.js | 22 +++ ui/src/app/store/user/UserSlice.js | 30 +++- 40 files changed, 408 insertions(+), 181 deletions(-) create mode 100644 ui/src/app/store/notifications/NotificationSlice.js create mode 100644 ui/src/app/store/user/CurrentUserSlice.js diff --git a/ui/src/app/App.js b/ui/src/app/App.js index f30e09884..77a41a73e 100644 --- a/ui/src/app/App.js +++ b/ui/src/app/App.js @@ -22,7 +22,6 @@ import Header from './core/components/Header'; import { UserProvider } from './core/user/UserContext'; import { Metadata } from './metadata/Metadata'; import { Attribute } from './metadata/Attribute'; -import { Notifications } from './notifications/hoc/Notifications'; import { NotificationList } from './notifications/component/NotificationList'; import { UserConfirmation, ConfirmWindow } from './core/components/UserConfirmation'; import { NewSource } from './metadata/new/NewSource'; @@ -63,75 +62,73 @@ function App() { return (
- - - - - - - - - {(message, confirm, confirmCallback, setConfirm, getConfirmation) => - - - -
-
- - - - - - - - - } /> - - - - - } /> - - - - - } /> - - - - - } /> - - - - - - } /> - - - - - } /> - - - - - } /> - - - - - -
-
- - - } - - - - - + + + + + + + + {(message, confirm, confirmCallback, setConfirm, getConfirmation) => + + + +
+
+ + + + + + + + + } /> + + + + + } /> + + + + + } /> + + + + + } /> + + + + + + } /> + + + + + } /> + + + + + } /> + + + + + +
+
+ + + } + + + +
); diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index dfa90aa8e..d1950afdf 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -1,11 +1,11 @@ import React from 'react'; - +import { useDispatch } from 'react-redux'; import { Prompt, useHistory, useParams } from 'react-router-dom'; import Translate from '../../i18n/components/translate'; import { useConfiguration } from '../hooks'; import { ConfigurationForm } from '../component/ConfigurationForm'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { PropertiesProvider } from '../hoc/PropertiesProvider'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -13,7 +13,7 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons'; export function EditConfiguration({ configurations }) { const history = useHistory(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { id } = useParams(); diff --git a/ui/src/app/admin/container/EditGroup.js b/ui/src/app/admin/container/EditGroup.js index 175ac4e69..7e2d72acf 100644 --- a/ui/src/app/admin/container/EditGroup.js +++ b/ui/src/app/admin/container/EditGroup.js @@ -1,5 +1,5 @@ import React from 'react'; - +import { useDispatch } from 'react-redux'; import { Prompt, useHistory } from 'react-router-dom'; import { useParams } from 'react-router-dom'; import Translate from '../../i18n/components/translate'; @@ -9,15 +9,16 @@ import { FormManager } from '../../form/FormManager'; import { GroupForm } from '../component/GroupForm'; import { GroupProvider } from '../hoc/GroupProvider'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; + export function EditGroup({ groups }) { const { id } = useParams(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const history = useHistory(); diff --git a/ui/src/app/admin/container/EditRole.js b/ui/src/app/admin/container/EditRole.js index 75ab0a93b..d3a4e43fb 100644 --- a/ui/src/app/admin/container/EditRole.js +++ b/ui/src/app/admin/container/EditRole.js @@ -9,15 +9,16 @@ import { FormManager } from '../../form/FormManager'; import { RoleForm } from '../component/RoleForm'; import { RoleProvider } from '../hoc/RoleProvider'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; +import { useDispatch } from 'react-redux'; export function EditRole() { const { id } = useParams(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const history = useHistory(); diff --git a/ui/src/app/admin/container/MetadataActions.js b/ui/src/app/admin/container/MetadataActions.js index d90eb803f..80adbf8ec 100644 --- a/ui/src/app/admin/container/MetadataActions.js +++ b/ui/src/app/admin/container/MetadataActions.js @@ -1,13 +1,14 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { DeleteConfirmation } from '../../core/components/DeleteConfirmation'; import { useMetadataActivator, useMetadataApprover, useMetadataEntity } from '../../metadata/hooks/api'; -import { NotificationContext, createNotificationAction, NotificationTypes } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useApproveSourceMutation, useDeleteSourceMutation, useEnableSourceMutation } from '../../store/metadata/SourceSlice'; +import { useDispatch } from 'react-redux'; export function MetadataActions ({type, children}) { - const { dispatch } = React.useContext(NotificationContext); + const dispatch = useDispatch(); const { del, response } = useMetadataEntity(type, { cachePolicy: 'no-cache' @@ -50,7 +51,7 @@ export function MetadataActions ({type, children}) { } } - const toast = (message, type) => dispatch(createNotificationAction(message, type)); + const toast = useCallback((message, type) => dispatch(createNotificationAction(message, type)), [dispatch]); const toastApproveSuccess = (type, enabled) => toast(`Metadata ${type} has been ${enabled ? 'approved' : 'unapproved'}.`); const toastEnableSuccess = (type, enabled) => toast(`Metadata ${type} has been ${enabled ? 'enabled' : 'disabled'}.`); @@ -62,7 +63,9 @@ export function MetadataActions ({type, children}) { const [deleteSource] = useDeleteSourceMutation(); const remove = type === 'source' ? - (id) => deleteSource({id}) : + (id, cb) => { + deleteSource({id}).then(() => cb()); + } : deleteEntity; const enable = type === 'source' ? ({id}, enabled) => enableSource({id, enabled}) : diff --git a/ui/src/app/admin/container/NewConfiguration.js b/ui/src/app/admin/container/NewConfiguration.js index d9a1bf33c..bc3131c6a 100644 --- a/ui/src/app/admin/container/NewConfiguration.js +++ b/ui/src/app/admin/container/NewConfiguration.js @@ -6,14 +6,15 @@ import { useConfiguration } from '../hooks'; import { Schema } from '../../form/Schema'; import { ConfigurationForm } from '../component/ConfigurationForm'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; import { PropertiesProvider } from '../hoc/PropertiesProvider'; +import { useDispatch } from 'react-redux'; export function NewConfiguration({ configurations }) { const history = useHistory(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { post, response, loading } = useConfiguration({}); diff --git a/ui/src/app/admin/container/NewGroup.js b/ui/src/app/admin/container/NewGroup.js index c24f4f516..7bebbe49e 100644 --- a/ui/src/app/admin/container/NewGroup.js +++ b/ui/src/app/admin/container/NewGroup.js @@ -7,13 +7,14 @@ import { Schema } from '../../form/Schema'; import { FormManager } from '../../form/FormManager'; import { GroupForm } from '../component/GroupForm'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; +import { useDispatch } from 'react-redux'; export function NewGroup({ groups }) { const history = useHistory(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { post, response, loading } = useGroups({}); diff --git a/ui/src/app/admin/container/NewRole.js b/ui/src/app/admin/container/NewRole.js index 4a323c9c9..19b6a04d7 100644 --- a/ui/src/app/admin/container/NewRole.js +++ b/ui/src/app/admin/container/NewRole.js @@ -7,13 +7,14 @@ import { Schema } from '../../form/Schema'; import { FormManager } from '../../form/FormManager'; import { RoleForm } from '../component/RoleForm'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; +import { useDispatch } from 'react-redux'; export function NewRole() { const history = useHistory(); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { post, response, loading } = useRoles({}); diff --git a/ui/src/app/admin/container/UserManagement.js b/ui/src/app/admin/container/UserManagement.js index b4cb51d67..40545b1a2 100644 --- a/ui/src/app/admin/container/UserManagement.js +++ b/ui/src/app/admin/container/UserManagement.js @@ -8,15 +8,12 @@ import Button from 'react-bootstrap/Button'; import Translate from '../../i18n/components/translate'; import API_BASE_PATH from '../../App.constant'; -import { NotificationContext, createNotificationAction} from '../../notifications/hoc/Notifications'; import { useRemoveUserMutation, useSetUserGroupRequestMutation, useSetUserRoleRequestMutation } from '../../store/user/UserSlice'; export default function UserManagement({ users, children, reload}) { const [roles, setRoles] = React.useState([]); - const { dispatch } = React.useContext(NotificationContext); - const { get, response, loading } = useFetch(`${API_BASE_PATH}`, {}); async function loadRoles() { diff --git a/ui/src/app/admin/hoc/ConfigurationsProvider.js b/ui/src/app/admin/hoc/ConfigurationsProvider.js index 99220c94c..0a710a579 100644 --- a/ui/src/app/admin/hoc/ConfigurationsProvider.js +++ b/ui/src/app/admin/hoc/ConfigurationsProvider.js @@ -1,13 +1,14 @@ import React from 'react'; import { useConfigurations } from '../hooks'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; +import { useDispatch } from 'react-redux'; export function ConfigurationsProvider({ children, cache = 'no-cache' }) { const [configurations, setConfigurations] = React.useState([]); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { get, del, response, loading } = useConfigurations({ diff --git a/ui/src/app/admin/hoc/GroupsProvider.js b/ui/src/app/admin/hoc/GroupsProvider.js index 016bcee13..33a5395c3 100644 --- a/ui/src/app/admin/hoc/GroupsProvider.js +++ b/ui/src/app/admin/hoc/GroupsProvider.js @@ -1,13 +1,14 @@ import React from 'react'; import { useGroups } from '../hooks'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; +import { useDispatch } from 'react-redux'; export function GroupsProvider({ children, cache = 'no-cache' }) { const [groups, setGroups] = React.useState([]); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { get, del, response, loading } = useGroups({ diff --git a/ui/src/app/admin/hoc/RolesProvider.js b/ui/src/app/admin/hoc/RolesProvider.js index e87d96539..aff8dca1e 100644 --- a/ui/src/app/admin/hoc/RolesProvider.js +++ b/ui/src/app/admin/hoc/RolesProvider.js @@ -1,13 +1,14 @@ import React from 'react'; import { useRoles } from '../hooks'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; +import { useDispatch } from 'react-redux'; export function RolesProvider({ children, cache = 'no-cache' }) { const [roles, setRoles] = React.useState([]); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); const translator = useTranslator(); const { get, del, response, loading } = useRoles({ diff --git a/ui/src/app/admin/hoc/RolesProvider.test.js b/ui/src/app/admin/hoc/RolesProvider.test.js index 65cc3ee22..fe1119c82 100644 --- a/ui/src/app/admin/hoc/RolesProvider.test.js +++ b/ui/src/app/admin/hoc/RolesProvider.test.js @@ -4,7 +4,6 @@ import React from 'react'; import { RolesProvider } from './RolesProvider'; import { useRoles } from '../hooks'; -import { useNotificationDispatcher } from "../../notifications/hoc/Notifications"; jest.mock('../../App.constant', () => ({ get API_BASE_PATH() { @@ -14,16 +13,12 @@ jest.mock('../../App.constant', () => ({ jest.mock('../hooks'); -jest.mock('../../notifications/hoc/Notifications'); +jest.mock('../../store/notifications/NotificationSlice'); describe('RolesProvider component', () => { beforeEach(() => { - useNotificationDispatcher.mockImplementation(() => { - return {}; - }); - useRoles.mockImplementation(() => { return { get: jest.fn().mockResolvedValue([]), diff --git a/ui/src/app/dashboard/view/ActionsTab.js b/ui/src/app/dashboard/view/ActionsTab.js index c3ac1d4ac..96daf8535 100644 --- a/ui/src/app/dashboard/view/ActionsTab.js +++ b/ui/src/app/dashboard/view/ActionsTab.js @@ -63,6 +63,7 @@ export function ActionsTab({ registrations }) { Approve Metadata Sources + { unApprovedSources.length ? {unApprovedSources.length} : '' } {disabledRegistrations && @@ -76,6 +77,7 @@ export function ActionsTab({ registrations }) { Approve Dynamic Registrations + { unApprovedRegistrations.length ? {unApprovedRegistrations.length} : '' } {users !== null && @@ -88,7 +90,7 @@ export function ActionsTab({ registrations }) { } - + diff --git a/ui/src/app/dashboard/view/Dashboard.js b/ui/src/app/dashboard/view/Dashboard.js index 8424ca579..2404c6c6f 100644 --- a/ui/src/app/dashboard/view/Dashboard.js +++ b/ui/src/app/dashboard/view/Dashboard.js @@ -1,7 +1,7 @@ import React from 'react'; import Nav from 'react-bootstrap/Nav'; -import { Switch, Route, Redirect, useRouteMatch, useLocation } from 'react-router-dom'; +import { Switch, Route, Redirect, useRouteMatch } from 'react-router-dom'; import { NavLink } from 'react-router-dom'; import Translate from '../../i18n/components/translate'; @@ -13,12 +13,12 @@ import { AdminTab } from './AdminTab'; import { ActionsTab } from './ActionsTab'; import { useCurrentUserLoading, useIsAdmin, useIsApprover } from '../../core/user/UserContext'; import { DynamicRegistrationsTab } from './DynamicRegistrationsTab'; -import { useUnapprovedSources} from '../../metadata/hooks/api'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import Badge from 'react-bootstrap/Badge'; import { useGetNewUsersQuery } from '../../store/user/UserSlice'; import { useGetDisabledSourcesQuery, useGetUnapprovedSourcesQuery } from '../../store/metadata/SourceSlice'; +import { useGetDisabledRegistrationsQuery, useGetUnapprovedRegistrationsQuery } from '../../store/dynamic-registration/DynamicRegistrationSlice'; export function Dashboard () { @@ -34,10 +34,18 @@ export function Dashboard () { const {data: users = []} = useGetNewUsersQuery(); const {data: disabledSources = []} = useGetDisabledSourcesQuery(); const {data: unApprovedSources = []} = useGetUnapprovedSourcesQuery(); + const {data: unApprovedRegistrations = []} = useGetUnapprovedRegistrationsQuery(); + const {data: disabledRegistrations = []} = useGetDisabledRegistrationsQuery(); React.useEffect(() => { - setActions((users?.length || 0) + (disabledSources?.length || 0) + unApprovedSources.length); - }, [users, disabledSources, unApprovedSources]); + const count = + (users?.length || 0) + + (disabledSources?.length || 0) + + (unApprovedRegistrations?.length || 0) + + (disabledSources?.length || 0) + + (disabledRegistrations.length || 0) + setActions(count); + }, [users, disabledSources, unApprovedSources, disabledRegistrations, unApprovedRegistrations]); return (
diff --git a/ui/src/app/dashboard/view/DynamicRegistrationsTab.js b/ui/src/app/dashboard/view/DynamicRegistrationsTab.js index de22cfba3..7a299da31 100644 --- a/ui/src/app/dashboard/view/DynamicRegistrationsTab.js +++ b/ui/src/app/dashboard/view/DynamicRegistrationsTab.js @@ -4,11 +4,9 @@ import { Search } from '../component/Search'; import {DynamicRegistrationList} from '../../dynamic-registration/component/DynamicRegistrationList'; import { - useChangeDynamicRegistrationGroupMutation, - useDeleteDynamicRegistrationMutation, - useEnableDynamicRegistrationMutation, useGetDynamicRegistrationsQuery } from '../../store/dynamic-registration/DynamicRegistrationSlice'; +import { DynamicRegistrationActions } from '../../dynamic-registration/hoc/DynamicRegistrationActions'; const searchProps = ['name']; @@ -16,30 +14,32 @@ export function DynamicRegistrationsTab () { const {data: registrations = [], isLoading: loading} = useGetDynamicRegistrationsQuery(); - const [remove] = useDeleteDynamicRegistrationMutation(); - const [enable] = useEnableDynamicRegistrationMutation(); - const [changeGroup] = useChangeDynamicRegistrationGroupMutation(); - return (
- <> -
- - Dynamic Registrations - -
-
- - {(searched) => - remove({id})} - onEnable={(id, enabled) => enable({id, enabled}) } - onChangeGroup={(registration, group) => changeGroup({ registration, group })}/> - } - -
- + + {({enable, remove, changeGroup}) => ( + +
+ + Dynamic Registrations + +
+
+ + {(searched) => + remove({id})} + onEnable={(id, enabled) => enable({id, enabled}) } + onChangeGroup={(registration, group) => changeGroup({ registration, group })}/> + } + +
+
+ )} +
) diff --git a/ui/src/app/dashboard/view/SourcesTab.js b/ui/src/app/dashboard/view/SourcesTab.js index d5e3ff7cb..d997cb4ba 100644 --- a/ui/src/app/dashboard/view/SourcesTab.js +++ b/ui/src/app/dashboard/view/SourcesTab.js @@ -6,15 +6,12 @@ import SourceList from '../../metadata/domain/source/component/SourceList'; import { Search } from '../component/Search'; import { Spinner } from '../../core/components/Spinner'; -import { NotificationContext, createNotificationAction, NotificationTypes } from '../../notifications/hoc/Notifications'; import { useChangeSourceGroupMutation, useGetSourcesQuery } from '../../store/metadata/SourceSlice'; const searchProps = ['serviceProviderName', 'entityId', 'createdBy', 'protocol']; export function SourcesTab () { - const { dispatch } = React.useContext(NotificationContext); - const [changeSourceGroup] = useChangeSourceGroupMutation(); const { data: sources = [], isLoading: loading } = useGetSourcesQuery(); diff --git a/ui/src/app/dynamic-registration/api.js b/ui/src/app/dynamic-registration/api.js index fc7b41508..a99a4091e 100644 --- a/ui/src/app/dynamic-registration/api.js +++ b/ui/src/app/dynamic-registration/api.js @@ -1,6 +1,6 @@ import useFetch from 'use-http'; -import {API_BASE_PATH, BASE_PATH} from '../App.constant'; +import {API_BASE_PATH} from '../App.constant'; import DynamicConfigurationDefinition from './hoc/DynamicConfigurationDefinition'; export const DYNAMIC_REGISTRATION_JSONSCHEMA_PATH = DynamicConfigurationDefinition.schema; diff --git a/ui/src/app/dynamic-registration/hoc/DynamicRegistrationActions.js b/ui/src/app/dynamic-registration/hoc/DynamicRegistrationActions.js index e872665b7..ce1d89420 100644 --- a/ui/src/app/dynamic-registration/hoc/DynamicRegistrationActions.js +++ b/ui/src/app/dynamic-registration/hoc/DynamicRegistrationActions.js @@ -1,4 +1,5 @@ import React, { Fragment, useMemo } from 'react'; +import { DeleteConfirmation } from '../../core/components/DeleteConfirmation'; import { useDeleteDynamicRegistrationMutation, @@ -9,11 +10,14 @@ import { export function DynamicRegistrationActions ({ children }) { + // const toast = useCallback((message, type) => dispatch(createNotificationAction(message, type)), [dispatch]); + const [remove] = useDeleteDynamicRegistrationMutation(); const [approve] = useApproveDynamicRegistrationMutation(); const [enable] = useEnableDynamicRegistrationMutation(); const [changeGroup] = useChangeDynamicRegistrationGroupMutation(); + const api = useMemo(() => ({ remove, approve, @@ -22,6 +26,14 @@ export function DynamicRegistrationActions ({ children }) { }), [remove, approve, enable, changeGroup]); return ( - {children(api)} + + {(block) => + {children({ + ...api, + remove: (id, cb) => block(() => remove(id, cb)) + })} + } + + ) } \ No newline at end of file diff --git a/ui/src/app/metadata/component/MetadataHeader.js b/ui/src/app/metadata/component/MetadataHeader.js index 94308eddf..7ab4571a2 100644 --- a/ui/src/app/metadata/component/MetadataHeader.js +++ b/ui/src/app/metadata/component/MetadataHeader.js @@ -5,11 +5,12 @@ import { useIsAdmin } from '../../core/user/UserContext'; import Translate from '../../i18n/components/translate'; import { GroupsProvider } from '../../admin/hoc/GroupsProvider'; import { useMetadataEntity } from '../hooks/api'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useTranslator } from '../../i18n/hooks'; import { useMetadataLoader } from '../hoc/MetadataSelector'; import Form from 'react-bootstrap/Form'; import Badge from 'react-bootstrap/Badge'; +import { useDispatch } from 'react-redux'; export function MetadataHeader ({ showGroup, model, current = true, enabled = true, children, ...props }) { @@ -20,7 +21,7 @@ export function MetadataHeader ({ showGroup, model, current = true, enabled = tr cachePolicy: 'no-cache' }); - const notifier = useNotificationDispatcher(); + const notifier = useDispatch(); async function changeSourceGroup(s, group) { let toast; diff --git a/ui/src/app/metadata/domain/filter/component/MetadataFilters.js b/ui/src/app/metadata/domain/filter/component/MetadataFilters.js index d8a1d8242..2bfae6858 100644 --- a/ui/src/app/metadata/domain/filter/component/MetadataFilters.js +++ b/ui/src/app/metadata/domain/filter/component/MetadataFilters.js @@ -1,13 +1,14 @@ import React from 'react'; import { useMetadataFilters, useFilterActivator } from '../../../hooks/api'; import { DeleteConfirmation } from '../../../../core/components/DeleteConfirmation'; -import { NotificationContext, createNotificationAction } from '../../../../notifications/hoc/Notifications'; +import { createNotificationAction } from '../../../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export const MetadataFiltersContext = React.createContext(); export function MetadataFilters ({ providerId, types = [], filters, children }) { - const { dispatch } = React.useContext(NotificationContext); + const dispatch = useDispatch(); const { put, del, get, response, loading } = useMetadataFilters(providerId, { cachePolicy: 'no-cache' diff --git a/ui/src/app/metadata/editor/MetadataEditor.js b/ui/src/app/metadata/editor/MetadataEditor.js index 6918d3627..0ae86bf51 100644 --- a/ui/src/app/metadata/editor/MetadataEditor.js +++ b/ui/src/app/metadata/editor/MetadataEditor.js @@ -18,8 +18,9 @@ import API_BASE_PATH from '../../App.constant'; import { MetadataObjectContext } from '../hoc/MetadataSelector'; import { FilterableProviders } from '../domain/provider'; import { checkChanges } from '../hooks/utility'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useUserGroup } from '../../core/user/UserContext'; +import { useDispatch } from 'react-redux'; export function MetadataEditor ({ restore, current, reload }) { @@ -30,7 +31,7 @@ export function MetadataEditor ({ restore, current, reload }) { const { update, loading } = useMetadataUpdater(`${ API_BASE_PATH }${getMetadataPath(type)}`, current, reload); - const notificationDispatch = useNotificationDispatcher(); + const notificationDispatch = useDispatch(); const { data } = useMetadataEntities(type, {}, []); const history = useHistory(); diff --git a/ui/src/app/metadata/hoc/MetadataAttributes.js b/ui/src/app/metadata/hoc/MetadataAttributes.js index e4cf57a2d..c554279f8 100644 --- a/ui/src/app/metadata/hoc/MetadataAttributes.js +++ b/ui/src/app/metadata/hoc/MetadataAttributes.js @@ -1,10 +1,11 @@ import React from 'react'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { useDispatch } from 'react-redux'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; import { useMetadataAttribute, useMetadataAttributes } from '../hooks/api'; export function MetadataAttributes ({children}) { - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const { get, response } = useMetadataAttributes({ cachePolicy: 'no-cache' diff --git a/ui/src/app/metadata/hoc/MetadataSelector.js b/ui/src/app/metadata/hoc/MetadataSelector.js index 5518cd7cd..5fffb7c63 100644 --- a/ui/src/app/metadata/hoc/MetadataSelector.js +++ b/ui/src/app/metadata/hoc/MetadataSelector.js @@ -1,6 +1,7 @@ import React from 'react'; import { useLocation, useParams } from 'react-router'; import Spinner from '../../core/components/Spinner'; +import { useLazySelectSourceQuery } from '../../store/metadata/SourceSlice'; import { useMetadataEntity } from '../hooks/api'; export const MetadataTypeContext = React.createContext(); @@ -26,6 +27,8 @@ export function MetadataSelector({ children, ...props }) { const { get, response } = useMetadataEntity(type); + const [getSource, result] = useLazySelectSourceQuery(); + const [metadata, setMetadata] = React.useState(); async function loadMetadata(id) { @@ -36,13 +39,29 @@ export function MetadataSelector({ children, ...props }) { } } + async function loadSource(id) { + const {data: source, isSuccess} = await getSource({id}); + if (isSuccess) { + setMetadata(source); + setLoading(false); + } + } + function reload() { setLoading(true); - loadMetadata(id); + if (type === 'source') { + loadSource(id); + } else { + loadMetadata(id); + } } React.useEffect(() => reload(), [id]); + React.useEffect(() => { + setMetadata(result.currentData); + }, [result.currentData]); + return ( {loading &&
diff --git a/ui/src/app/metadata/hoc/attribute/AttributeBundleApi.js b/ui/src/app/metadata/hoc/attribute/AttributeBundleApi.js index a32ebd271..bb51663b3 100644 --- a/ui/src/app/metadata/hoc/attribute/AttributeBundleApi.js +++ b/ui/src/app/metadata/hoc/attribute/AttributeBundleApi.js @@ -1,13 +1,14 @@ import React from 'react'; +import { useDispatch } from 'react-redux'; import useFetch from 'use-http'; import API_BASE_PATH from '../../../App.constant'; import { DeleteConfirmation } from '../../../core/components/DeleteConfirmation'; -import { createNotificationAction, NotificationContext } from '../../../notifications/hoc/Notifications'; +import { createNotificationAction } from '../../../store/notifications/NotificationSlice'; export function AttributeBundleApi({ id, children }) { - const { dispatch } = React.useContext(NotificationContext); + const dispatch = useDispatch(); const { get, put, post, del, response, loading } = useFetch(`${API_BASE_PATH}/custom/entity/bundles`, { cachePolicy: 'no-cache' diff --git a/ui/src/app/metadata/new/NewAttribute.js b/ui/src/app/metadata/new/NewAttribute.js index 0db6847cb..01b9c8fae 100644 --- a/ui/src/app/metadata/new/NewAttribute.js +++ b/ui/src/app/metadata/new/NewAttribute.js @@ -11,12 +11,13 @@ import { useMetadataAttribute } from '../hooks/api'; import {CustomAttributeDefinition} from '../domain/attribute/CustomAttributeDefinition'; import MetadataSchema from '../hoc/MetadataSchema'; import { MetadataForm } from '../hoc/MetadataFormContext'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export function NewAttribute() { const history = useHistory(); - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const definition = CustomAttributeDefinition; diff --git a/ui/src/app/metadata/new/NewFilter.js b/ui/src/app/metadata/new/NewFilter.js index 72da363b9..197d2534d 100644 --- a/ui/src/app/metadata/new/NewFilter.js +++ b/ui/src/app/metadata/new/NewFilter.js @@ -9,14 +9,15 @@ import { MetadataForm } from '../hoc/MetadataFormContext'; import { MetadataSchema } from '../hoc/MetadataSchema'; import { useMetadataFilters, useMetadataFilterTypes } from '../hooks/api'; import { MetadataFilterTypeSelector } from '../wizard/MetadataFilterTypeSelector'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export function NewFilter() { const { id } = useParams(); const history = useHistory(); const types = useMetadataFilterTypes(); - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const { post, response, loading } = useMetadataFilters(id, {}); diff --git a/ui/src/app/metadata/view/EditFilter.js b/ui/src/app/metadata/view/EditFilter.js index ac8ce11c3..204c72f55 100644 --- a/ui/src/app/metadata/view/EditFilter.js +++ b/ui/src/app/metadata/view/EditFilter.js @@ -11,11 +11,12 @@ import { MetadataSchema } from '../hoc/MetadataSchema'; import { getMetadataPath, useMetadataUpdater } from '../hooks/api'; import { useMetadataFilterObject } from '../hoc/MetadataFilterSelector'; import API_BASE_PATH from '../../App.constant'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export function EditFilter() { - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const { id, filterId } = useParams(); const filter = useMetadataFilterObject(); diff --git a/ui/src/app/metadata/view/MetadataAttributeEdit.js b/ui/src/app/metadata/view/MetadataAttributeEdit.js index 84670d467..dc617d523 100644 --- a/ui/src/app/metadata/view/MetadataAttributeEdit.js +++ b/ui/src/app/metadata/view/MetadataAttributeEdit.js @@ -11,7 +11,8 @@ import { useMetadataAttribute } from '../hooks/api'; import { CustomAttributeDefinition, CustomAttributeEditor } from '../domain/attribute/CustomAttributeDefinition'; import MetadataSchema from '../hoc/MetadataSchema'; import { MetadataForm } from '../hoc/MetadataFormContext'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export function MetadataAttributeEdit() { const { id } = useParams(); @@ -19,7 +20,7 @@ export function MetadataAttributeEdit() { const definition = CustomAttributeDefinition; - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const { get, put, response, loading } = useMetadataAttribute({ cachePolicy: 'no-cache' diff --git a/ui/src/app/metadata/view/MetadataCopy.js b/ui/src/app/metadata/view/MetadataCopy.js index 29df9ef3b..5156fc6a2 100644 --- a/ui/src/app/metadata/view/MetadataCopy.js +++ b/ui/src/app/metadata/view/MetadataCopy.js @@ -3,14 +3,15 @@ import { CopySource } from '../copy/CopySource'; import { SaveCopy } from '../copy/SaveCopy'; import { useMetadataEntity } from '../hooks/api'; import { useHistory } from 'react-router-dom'; -import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; +import { createNotificationAction, NotificationTypes } from '../../store/notifications/NotificationSlice'; +import { useDispatch } from 'react-redux'; export function MetadataCopy ({ onShowNav }) { const { post, response, loading } = useMetadataEntity('source'); const history = useHistory(); - const dispatch = useNotificationDispatcher(); + const dispatch = useDispatch(); const [copy, setCopy] = React.useState({ target: null, diff --git a/ui/src/app/metadata/view/MetadataOptions.js b/ui/src/app/metadata/view/MetadataOptions.js index 35a0977ac..9d0f5e8d5 100644 --- a/ui/src/app/metadata/view/MetadataOptions.js +++ b/ui/src/app/metadata/view/MetadataOptions.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { faArrowDown, faArrowUp, faHistory, faPlus, faToggleOff, faToggleOn, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Link, useHistory, useParams } from 'react-router-dom'; @@ -50,14 +50,14 @@ export function MetadataOptions ({reload}) { const canFilter = FilterableProviders.indexOf(definition.type) > -1; - const enabled = type === 'source' ? metadata.serviceEnabled : metadata.enabled; + const enabled = useMemo(() => type === 'source' ? metadata.serviceEnabled : metadata.enabled, [type, metadata]); const canEnable = useCanEnable()(metadata.approved); const isAdmin = useIsAdmin(); return ( - {({enable, remove, approve}) => + {({enable, remove}) => <>