diff --git a/web/src/App.tsx b/web/src/App.tsx index 695de26c36..58166e5808 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,7 +1,8 @@ import * as Sentry from '@sentry/react'; import {HistoryRouter} from 'redux-first-history/rr6'; -import DashboardWrapper from 'components/DashboardWrapper/DashboardWrapper'; +import CustomizationWrapper from 'components/CustomizationWrapper'; +import DashboardWrapper from 'components/DashboardWrapper'; import ErrorBoundary from 'components/ErrorBoundary'; import {theme} from 'constants/Theme.constants'; import {ReduxWrapperProvider} from 'redux/ReduxWrapperProvider'; @@ -18,9 +19,11 @@ const App = () => ( }> - - - + + + + + diff --git a/web/src/BaseApp.tsx b/web/src/BaseApp.tsx index 1d0d7412c3..f7340fe151 100644 --- a/web/src/BaseApp.tsx +++ b/web/src/BaseApp.tsx @@ -1,14 +1,9 @@ import Router from 'components/Router'; import SettingsValuesProvider from 'providers/SettingsValues'; -import {TCustomHeader} from 'components/Layout/Layout'; -interface IProps { - customHeader?: TCustomHeader; -} - -const BaseApp = ({customHeader}: IProps) => ( +const BaseApp = () => ( - + ); diff --git a/web/src/components/AllowButton/AllowButton.tsx b/web/src/components/AllowButton/AllowButton.tsx new file mode 100644 index 0000000000..6e90d73f46 --- /dev/null +++ b/web/src/components/AllowButton/AllowButton.tsx @@ -0,0 +1,19 @@ +import {Button, ButtonProps, Tooltip} from 'antd'; +import {Operation, useCustomization} from 'providers/Customization/Customization.provider'; + +interface IProps extends ButtonProps { + operation: Operation; +} + +const AllowButton = ({operation, ...props}: IProps) => { + const {getIsAllowed} = useCustomization(); + const isAllowed = getIsAllowed(operation); + + return ( + + - + diff --git a/web/src/providers/Customization/Customization.provider.tsx b/web/src/providers/Customization/Customization.provider.tsx new file mode 100644 index 0000000000..1453e0c0b4 --- /dev/null +++ b/web/src/providers/Customization/Customization.provider.tsx @@ -0,0 +1,30 @@ +import {createContext, useContext} from 'react'; + +export enum Operation { + Configure = 'configure', + Edit = 'edit', + View = 'view', +} + +interface IContext { + getComponent(name: string, fallback: React.ComponentType): React.ComponentType; + getIsAllowed(operation: Operation): boolean; +} + +export const Context = createContext({ + getComponent: (name, fallback) => fallback, + getIsAllowed: () => true, +}); + +export const useCustomization = () => useContext(Context); + +interface IProps { + children: React.ReactNode; + value: IContext; +} + +const CustomizationProvider = ({children, value}: IProps) => { + return {children}; +}; + +export default CustomizationProvider; diff --git a/web/src/providers/Customization/WithCustomization.tsx b/web/src/providers/Customization/WithCustomization.tsx new file mode 100644 index 0000000000..d71cc9c009 --- /dev/null +++ b/web/src/providers/Customization/WithCustomization.tsx @@ -0,0 +1,14 @@ +import {useCustomization} from './Customization.provider'; + +const withCustomization =

(Component: React.ComponentType

, id: string) => { + const WrappedComponent = (props: P) => { + const {getComponent} = useCustomization(); + const CustomizedComponent = getComponent(id, Component); + + return ; + }; + + return WrappedComponent; +}; + +export default withCustomization; diff --git a/web/src/providers/Customization/index.ts b/web/src/providers/Customization/index.ts new file mode 100644 index 0000000000..5e2ae6b66e --- /dev/null +++ b/web/src/providers/Customization/index.ts @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-restricted-exports +export {default, useCustomization, Operation} from './Customization.provider'; +export {default as withCustomization} from './WithCustomization';