1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-08 07:15:23 +02:00

refactor(ui): remove global providers [EE-4128] (#7578)

This commit is contained in:
Chaim Lev-Ari 2022-09-20 21:14:24 +03:00 committed by GitHub
parent d3f094cb18
commit fad376b415
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 372 additions and 214 deletions

View file

@ -6,7 +6,6 @@ import settingsModule from './settings';
import featureFlagModule from './feature-flags';
import userActivityModule from './user-activity';
import servicesModule from './services';
import homeModule from './home';
import { reactModule } from './react';
import { sidebarModule } from './react/views/sidebar';
import environmentsModule from './environments';
@ -29,7 +28,6 @@ async function initAuthentication(authManager, Authentication, $rootScope, $stat
angular
.module('portainer.app', [
homeModule,
'portainer.oauth',
'portainer.rbac',
componentsModule,

View file

@ -1,8 +1,6 @@
import { useRouter } from '@uirouter/react';
import { useState } from 'react';
import { r2a } from '@/react-tools/react2angular';
import { PageHeader } from '@@/PageHeader';
import * as notifications from '../services/notifications';
@ -73,8 +71,6 @@ export function HomeView() {
}
}
export const HomeViewAngular = r2a(HomeView, []);
async function confirmEndpointSnapshot() {
return confirmAsync({
title: buildTitle('Are you sure?'),

View file

@ -1,7 +1,7 @@
import { useQuery } from 'react-query';
import _ from 'lodash';
import { useUIState } from '@/portainer/hooks/UIStateProvider';
import { useUIState } from '@/portainer/hooks/useUIState';
import { InformationPanel } from '@@/InformationPanel';
@ -10,9 +10,13 @@ import { getMotd } from './home.service';
export function MotdPanel() {
const motd = useMotd();
const [uiState, setUIState] = useUIState();
const uiStateStore = useUIState();
if (!motd || motd.Message === '' || motd.Hash === uiState.dismissedInfoHash) {
if (
!motd ||
motd.Message === '' ||
motd.Hash === uiStateStore.dismissedInfoHash
) {
return null;
}
@ -34,10 +38,7 @@ export function MotdPanel() {
);
function onDismiss(hash: string) {
setUIState({
...uiState,
dismissedInfoHash: hash,
});
uiStateStore.dismissMotd(hash);
}
}

View file

@ -1,9 +1 @@
import angular from 'angular';
import { EnvironmentListAngular } from './EnvironmentList';
import { HomeViewAngular } from './HomeView';
export default angular
.module('portainer.app.home', [])
.component('homeView', HomeViewAngular)
.component('environmentList', EnvironmentListAngular).name;
export { HomeView } from './HomeView';

View file

@ -1,29 +0,0 @@
import { createContext, PropsWithChildren, useContext } from 'react';
import { useLocalStorage } from '@/portainer/hooks/useLocalStorage';
interface UIState {
dismissedInfoPanels: Record<string, string>;
dismissedInfoHash: string;
dismissedUpdateVersion: string;
}
type UIStateService = [UIState, (state: UIState) => void];
const Context = createContext<null | UIStateService>(null);
export function useUIState() {
const context = useContext(Context);
if (context == null) {
throw new Error('Should be nested under a UIStateProvider component');
}
return context;
}
export function UIStateProvider({ children }: PropsWithChildren<unknown>) {
const service = useLocalStorage<UIState>('UI_STATE', {} as UIState);
return <Context.Provider value={service}>{children}</Context.Provider>;
}

View file

@ -0,0 +1,37 @@
import create from 'zustand';
import { persist } from 'zustand/middleware';
import { keyBuilder } from '@/portainer/hooks/useLocalStorage';
interface UIState {
dismissedInfoPanels: Record<string, boolean>;
dismissInfoPanel(id: string): void;
dismissedInfoHash: string;
dismissMotd(hash: string): void;
dismissedUpdateVersion: string;
dismissUpdateVersion(version: string): void;
}
export const useUIState = create<UIState>()(
persist(
(set) => ({
dismissedInfoPanels: {},
dismissInfoPanel(id: string) {
set((state) => ({
dismissedInfoPanels: { ...state.dismissedInfoPanels, [id]: true },
}));
},
dismissedInfoHash: '',
dismissMotd(hash: string) {
set({ dismissedInfoHash: hash });
},
dismissedUpdateVersion: '',
dismissUpdateVersion(version: string) {
set({ dismissedUpdateVersion: version });
},
}),
{ name: keyBuilder('NEW_UI_STATE') }
)
);

View file

@ -23,6 +23,7 @@ interface State {
}
export const UserContext = createContext<State | null>(null);
UserContext.displayName = 'UserContext';
export function useUser() {
const context = useContext(UserContext);

View file

@ -1,10 +1,19 @@
import angular from 'angular';
import { react2angular } from 'react2angular';
import { r2a } from '@/react-tools/react2angular';
import { CreateAccessToken } from '@/react/portainer/account/CreateAccessTokenView';
import {
DefaultRegistryAction,
DefaultRegistryDomain,
DefaultRegistryName,
} from '@/react/portainer/registries/ListView/DefaultRegistry';
import { Icon } from '@/react/components/Icon';
import { ReactQueryDevtoolsWrapper } from '@/react/components/ReactQueryDevtoolsWrapper';
import { AccessControlPanel } from '@/react/portainer/access-control';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { withI18nSuspense } from '@/react-tools/withI18nSuspense';
import { PageHeader } from '@@/PageHeader';
import { TagSelector } from '@@/TagSelector';
@ -26,22 +35,25 @@ export const componentsModule = angular
.module('portainer.app.react.components', [customTemplatesModule])
.component(
'tagSelector',
r2a(TagSelector, ['allowCreate', 'onChange', 'value'])
r2a(withReactQuery(TagSelector), ['allowCreate', 'onChange', 'value'])
)
.component(
'portainerTooltip',
react2angular(Tooltip, ['message', 'position', 'className'])
r2a(Tooltip, ['message', 'position', 'className'])
)
.component('fileUploadField', fileUploadField)
.component('porSwitchField', switchField)
.component(
'passwordCheckHint',
r2a(PasswordCheckHint, ['forceChangePassword', 'passwordValid'])
r2a(withReactQuery(PasswordCheckHint), [
'forceChangePassword',
'passwordValid',
])
)
.component('rdLoading', r2a(Loading, []))
.component(
'tableColumnHeader',
react2angular(TableColumnHeaderAngular, [
r2a(TableColumnHeaderAngular, [
'colTitle',
'canSort',
'isSorted',
@ -51,13 +63,13 @@ export const componentsModule = angular
.component('viewLoading', r2a(ViewLoading, ['message']))
.component(
'pageHeader',
r2a(PageHeader, [
'id',
r2a(withUIRouter(withReactQuery(withCurrentUser(PageHeader))), [
'title',
'breadcrumbs',
'loading',
'onReload',
'reload',
'id',
])
)
.component(
@ -75,7 +87,7 @@ export const componentsModule = angular
)
.component(
'prIcon',
react2angular(Icon, ['className', 'feather', 'icon', 'mode', 'size'])
r2a(Icon, ['className', 'feather', 'icon', 'mode', 'size'])
)
.component('reactQueryDevTools', r2a(ReactQueryDevtoolsWrapper, []))
.component(
@ -86,13 +98,10 @@ export const componentsModule = angular
'datatableSearchbar',
r2a(SearchBar, ['data-cy', 'onChange', 'value', 'placeholder'])
)
.component(
'boxSelectorBadgeIcon',
react2angular(BadgeIcon, ['featherIcon', 'icon'])
)
.component('boxSelectorBadgeIcon', r2a(BadgeIcon, ['featherIcon', 'icon']))
.component(
'accessControlPanel',
r2a(AccessControlPanel, [
r2a(withReactQuery(withCurrentUser(AccessControlPanel)), [
'disableOwnershipChange',
'onUpdateSuccess',
'resourceControl',
@ -100,4 +109,23 @@ export const componentsModule = angular
'resourceType',
'environmentId',
])
)
.component(
'defaultRegistryName',
r2a(withReactQuery(DefaultRegistryName), [])
)
.component(
'defaultRegistryAction',
r2a(withReactQuery(DefaultRegistryAction), [])
)
.component(
'defaultRegistryDomain',
r2a(withReactQuery(DefaultRegistryDomain), [])
)
.component(
'createAccessToken',
r2a(withI18nSuspense(withUIRouter(CreateAccessToken)), [
'onSubmit',
'onError',
])
).name;

View file

@ -1,12 +1,10 @@
import angular from 'angular';
import { HomeView } from '@/portainer/home';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { r2a } from '@/react-tools/react2angular';
import { CreateAccessToken } from '@/react/portainer/account/CreateAccessTokenView';
import {
DefaultRegistryAction,
DefaultRegistryDomain,
DefaultRegistryName,
} from '@/react/portainer/registries/ListView/DefaultRegistry';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { wizardModule } from './wizard';
import { teamsModule } from './teams';
@ -18,10 +16,7 @@ export const viewsModule = angular
teamsModule,
updateSchedulesModule,
])
.component('defaultRegistryName', r2a(DefaultRegistryName, []))
.component('defaultRegistryAction', r2a(DefaultRegistryAction, []))
.component('defaultRegistryDomain', r2a(DefaultRegistryDomain, []))
.component(
'createAccessToken',
r2a(CreateAccessToken, ['onSubmit', 'onError'])
'homeView',
r2a(withUIRouter(withReactQuery(withCurrentUser(HomeView))), [])
).name;

View file

@ -3,8 +3,14 @@ import angular from 'angular';
import { AngularSidebarService } from '@/react/sidebar/useSidebarState';
import { Sidebar } from '@/react/sidebar/Sidebar';
import { r2a } from '@/react-tools/react2angular';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const sidebarModule = angular
.module('portainer.app.sidebar', [])
.component('sidebar', r2a(Sidebar, []))
.component(
'sidebar',
r2a(withUIRouter(withReactQuery(withCurrentUser(Sidebar))), [])
)
.factory('SidebarService', AngularSidebarService).name;

View file

@ -3,12 +3,21 @@ import { StateRegistry } from '@uirouter/angularjs';
import { ItemView, ListView } from '@/react/portainer/users/teams';
import { r2a } from '@/react-tools/react2angular';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const teamsModule = angular
.module('portainer.app.teams', [])
.config(config)
.component('teamView', r2a(ItemView, []))
.component('teamsView', r2a(ListView, [])).name;
.component(
'teamView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ItemView))), [])
)
.component(
'teamsView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ListView))), [])
).name;
/* @ngInject */
function config($stateRegistryProvider: StateRegistry) {

View file

@ -7,12 +7,24 @@ import {
CreateView,
ItemView,
} from '@/react/portainer/environments/update-schedules';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
export const updateSchedulesModule = angular
.module('portainer.edge.updateSchedules', [])
.component('updateSchedulesListView', r2a(ListView, []))
.component('updateSchedulesCreateView', r2a(CreateView, []))
.component('updateSchedulesItemView', r2a(ItemView, []))
.component(
'updateSchedulesListView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ListView))), [])
)
.component(
'updateSchedulesCreateView',
r2a(withUIRouter(withReactQuery(withCurrentUser(CreateView))), [])
)
.component(
'updateSchedulesItemView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ItemView))), [])
)
.config(config).name;
function config($stateRegistryProvider: StateRegistry) {

View file

@ -7,15 +7,30 @@ import {
EnvironmentTypeSelectView,
HomeView,
} from '@/react/portainer/environments/wizard';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const wizardModule = angular
.module('portainer.app.react.views.wizard', [])
.component('wizardEnvironmentCreationView', r2a(EnvironmentCreationView, []))
.component(
'wizardEnvironmentCreationView',
r2a(
withUIRouter(withReactQuery(withCurrentUser(EnvironmentCreationView))),
[]
)
)
.component(
'wizardEnvironmentTypeSelectView',
r2a(EnvironmentTypeSelectView, [])
r2a(
withUIRouter(withReactQuery(withCurrentUser(EnvironmentTypeSelectView))),
[]
)
)
.component(
'wizardMainView',
r2a(withUIRouter(withReactQuery(withCurrentUser(HomeView))), [])
)
.component('wizardMainView', r2a(HomeView, []))
.config(config).name;
function config($stateRegistryProvider: StateRegistry) {

View file

@ -1,4 +1,6 @@
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { r2a } from '@/react-tools/react2angular';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { Settings } from '../types';
@ -20,7 +22,7 @@ export function EdgeComputeSettingsView({ settings, onSubmit }: Props) {
);
}
export const EdgeComputeSettingsViewAngular = r2a(EdgeComputeSettingsView, [
'settings',
'onSubmit',
]);
export const EdgeComputeSettingsViewAngular = r2a(
withReactQuery(withCurrentUser(EdgeComputeSettingsView)),
['settings', 'onSubmit']
);

View file

@ -1,6 +1,11 @@
import { react2angular } from '@/react-tools/react2angular';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { SettingsFDO } from './SettingsFDO';
const SettingsFDOAngular = react2angular(SettingsFDO, ['settings', 'onSubmit']);
const SettingsFDOAngular = react2angular(
withUIRouter(withReactQuery(SettingsFDO)),
['settings', 'onSubmit']
);
export { SettingsFDO, SettingsFDOAngular };