Compare commits

...

11 Commits

Author SHA1 Message Date
Chaim Lev-Ari
fe2340b8a0 feat(ui/r2a): add is destroyed check 2022-08-28 10:50:55 +03:00
Chaim Lev-Ari
6c34eeb2ea fix(ui/r2a): fix props 2022-08-28 10:50:55 +03:00
Chaim Lev-Ari
baea1e5c56 fix(services): show quick actions 2022-08-28 10:50:55 +03:00
Chaim Lev-Ari
c8f91e92e9 refactor(ui): remove react2angular package 2022-08-28 10:50:52 +03:00
Chaim Lev-Ari
4f45d02dca refactor(ui): remove RootProvider 2022-08-28 10:50:12 +03:00
Chaim Lev-Ari
0a05cf7da5 refactor(ui): move user provider HOC 2022-08-28 10:48:51 +03:00
Chaim Lev-Ari
fd67620703 refactor(ui): remove UIRouterProvider 2022-08-28 10:47:35 +03:00
Chaim Lev-Ari
998160a163 refactor(ui): remove QueryProvider 2022-08-28 10:46:18 +03:00
Chaim Lev-Ari
5f2bb12816 refactor(ui): remove user provider from r2a 2022-08-28 10:43:35 +03:00
Chaim Lev-Ari
edb01c63a0 feat(ui): create withUser hoc 2022-08-28 04:09:44 +03:00
Chaim Lev-Ari
96c2158ac9 refactor(ui): remove global ui state context 2022-08-28 04:09:44 +03:00
33 changed files with 298 additions and 171 deletions

View File

@@ -5,10 +5,25 @@ import { CreateView } from '@/react/azure/container-instances/CreateView';
import { ItemView } from '@/react/azure/container-instances/ItemView';
import { ListView } from '@/react/azure/container-instances/ListView';
import { DashboardView } from '@/react/azure/DashboardView';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const viewsModule = angular
.module('portainer.azure.react.views', [])
.component('containerInstanceView', r2a(ItemView, []))
.component('createContainerInstanceView', r2a(CreateView, []))
.component('containerInstancesView', r2a(ListView, []))
.component('dashboardView', r2a(DashboardView, [])).name;
.component(
'containerInstanceView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ItemView))), [])
)
.component(
'createContainerInstanceView',
r2a(withUIRouter(withReactQuery(withCurrentUser(CreateView))), [])
)
.component(
'containerInstancesView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ListView))), [])
)
.component(
'dashboardView',
r2a(withUIRouter(withReactQuery(withCurrentUser(DashboardView))), [])
).name;

View File

@@ -5,12 +5,16 @@ import { StackContainersDatatable } from '@/react/docker/stacks/ItemView/StackCo
import { ContainerQuickActions } from '@/react/docker/containers/components/ContainerQuickActions';
import { TemplateListDropdownAngular } from '@/react/docker/app-templates/TemplateListDropdown';
import { TemplateListSortAngular } from '@/react/docker/app-templates/TemplateListSort';
import { Gpu } from '@/react/docker/containers/CreateView/Gpu';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const componentsModule = angular
.module('portainer.docker.react.components', [])
.component(
'containerQuickActions',
r2a(ContainerQuickActions, [
r2a(withUIRouter(withCurrentUser(ContainerQuickActions)), [
'containerId',
'nodeName',
'state',
@@ -22,5 +26,12 @@ export const componentsModule = angular
.component('templateListSort', TemplateListSortAngular)
.component(
'stackContainersDatatable',
r2a(StackContainersDatatable, ['environment', 'stackName'])
r2a(withReactQuery(withCurrentUser(StackContainersDatatable)), [
'environment',
'stackName',
])
)
.component(
'gpu',
r2a(Gpu, ['values', 'onChange', 'gpus', 'usedGpus', 'usedAllGpus'])
).name;

View File

@@ -3,10 +3,16 @@ import angular from 'angular';
import { r2a } from '@/react-tools/react2angular';
import { ListView } from '@/react/docker/containers/ListView';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const containersModule = angular
.module('portainer.docker.containers', [])
.component('containersView', r2a(ListView, ['endpoint']))
.component(
'containersView',
r2a(withUIRouter(withReactQuery(withCurrentUser(ListView))), ['endpoint'])
)
.config(config).name;

View File

@@ -1,15 +1,17 @@
import angular from 'angular';
import { Gpu } from 'Docker/react/views/gpu';
import { ItemView as NetworksItemView } from '@/react/docker/networks/ItemView';
import { r2a } from '@/react-tools/react2angular';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { containersModule } from './containers';
export const viewsModule = angular
.module('portainer.docker.react.views', [containersModule])
.component(
'gpu',
r2a(Gpu, ['values', 'onChange', 'gpus', 'usedGpus', 'usedAllGpus'])
)
.component('networkDetailsView', r2a(NetworksItemView, [])).name;
'networkDetailsView',
r2a(withUIRouter(withReactQuery(withCurrentUser(NetworksItemView))), [])
).name;

View File

@@ -2,7 +2,6 @@ import { useState } from 'react';
import { useSettings } from '@/portainer/settings/queries';
import { useGroups } from '@/portainer/environment-groups/queries';
import { r2a } from '@/react-tools/react2angular';
import { PageHeader } from '@@/PageHeader';
import { ViewLoading } from '@@/ViewLoading';
@@ -55,5 +54,3 @@ export function EdgeDevicesView() {
</>
);
}
export const EdgeDevicesViewAngular = r2a(EdgeDevicesView, []);

View File

@@ -1 +1 @@
export { EdgeDevicesView, EdgeDevicesViewAngular } from './EdgeDevicesView';
export { EdgeDevicesView } from './EdgeDevicesView';

View File

@@ -1,7 +1,6 @@
import { useRouter } from '@uirouter/react';
import { useEnvironmentList } from '@/portainer/environments/queries/useEnvironmentList';
import { r2a } from '@/react-tools/react2angular';
import { EdgeTypes } from '@/portainer/environments/types';
import { InformationPanel } from '@@/InformationPanel';
@@ -58,5 +57,3 @@ export function WaitingRoomView() {
</>
);
}
export const WaitingRoomViewAngular = r2a(WaitingRoomView, []);

View File

@@ -1 +1 @@
export { WaitingRoomView, WaitingRoomViewAngular } from './WaitingRoomView';
export { WaitingRoomView } from './WaitingRoomView';

View File

@@ -1,15 +1,17 @@
import angular from 'angular';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { r2a } from '@/react-tools/react2angular';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
import edgeStackModule from './views/edge-stacks';
import { componentsModule } from './components';
import { WaitingRoomViewAngular } from './EdgeDevices/WaitingRoomView';
import { WaitingRoomView } from './EdgeDevices/WaitingRoomView';
import { reactModule } from './react';
import { EdgeDevicesViewAngular } from './EdgeDevices/EdgeDevicesView';
angular
.module('portainer.edge', [edgeStackModule, componentsModule, reactModule])
.component('waitingRoomView', WaitingRoomViewAngular)
.component('edgeDevicesView', EdgeDevicesViewAngular)
.component('waitingRoomView', r2a(withUIRouter(withReactQuery(withCurrentUser(WaitingRoomView))), []))
.config(function config($stateRegistryProvider) {
const edge = {
name: 'edge',

View File

@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { useSettings } from '@/portainer/settings/queries';
import { r2a } from '@/react-tools/react2angular';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { FormControl } from '@@/form-components/FormControl';
import { Select } from '@@/form-components/Input';
@@ -58,14 +59,10 @@ export function EdgeCheckinIntervalField({
);
}
export const EdgeCheckinIntervalFieldAngular = r2a(EdgeCheckinIntervalField, [
'value',
'onChange',
'isDefaultHidden',
'tooltip',
'label',
'readonly',
]);
export const EdgeCheckinIntervalFieldAngular = r2a(
withReactQuery(EdgeCheckinIntervalField),
['value', 'onChange', 'isDefaultHidden', 'tooltip', 'label', 'readonly']
);
function useOptions(isDefaultHidden: boolean) {
const [options, setOptions] = useState(checkinIntervalOptions);

View File

@@ -2,6 +2,7 @@ import angular from 'angular';
import { r2a } from '@/react-tools/react2angular';
import { EdgeScriptForm } from '@/react/edge/components/EdgeScriptForm';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { EdgeCheckinIntervalFieldAngular } from './EdgeCheckInIntervalField';
@@ -9,6 +10,10 @@ export const componentsModule = angular
.module('app.edge.components', [])
.component(
'edgeScriptForm',
r2a(EdgeScriptForm, ['edgeInfo', 'commands', 'isNomadTokenVisible'])
r2a(withReactQuery(EdgeScriptForm), [
'edgeInfo',
'commands',
'isNomadTokenVisible',
])
)
.component('edgeCheckinIntervalField', EdgeCheckinIntervalFieldAngular).name;

View File

@@ -1,6 +1,14 @@
import angular from 'angular';
export const viewsModule = angular.module(
'portainer.edge.react.views',
[]
).name;
import { EdgeDevicesView } from '@/edge/EdgeDevices/EdgeDevicesView';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { r2a } from '@/react-tools/react2angular';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { withUIRouter } from '@/react-tools/withUIRouter';
export const viewsModule = angular
.module('portainer.edge.react.views', [])
.component(
'edgeDevicesView',
r2a(withUIRouter(withReactQuery(withCurrentUser(EdgeDevicesView))), [])
).name;

View File

@@ -7,7 +7,6 @@ import featureFlagModule from './feature-flags';
import userActivityModule from './user-activity';
import servicesModule from './services';
import teamsModule from './teams';
import homeModule from './home';
import { accessControlModule } from './access-control';
import { reactModule } from './react';
import { sidebarModule } from './react/views/sidebar';
@@ -31,7 +30,6 @@ async function initAuthentication(authManager, Authentication, $rootScope, $stat
angular
.module('portainer.app', [
homeModule,
'portainer.oauth',
'portainer.rbac',
componentsModule,

View File

@@ -1,10 +1,12 @@
import { useReducer } from 'react';
import { useUser } from '@/portainer/hooks/useUser';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { Icon } from '@/react/components/Icon';
import { r2a } from '@/react-tools/react2angular';
import { TeamMembership, Role } from '@/portainer/teams/types';
import { useUserMembership } from '@/portainer/users/queries';
import { withReactQuery } from '@/react-tools/withReactQuery';
import { TableContainer, TableTitle } from '@@/datatables';
import { Button } from '@@/buttons';
@@ -143,10 +145,13 @@ function isLeaderOfAnyRestrictedTeams(
);
}
export const AccessControlPanelAngular = r2a(AccessControlPanel, [
'resourceControl',
'resourceType',
'disableOwnershipChange',
'resourceId',
'onUpdateSuccess',
]);
export const AccessControlPanelAngular = r2a(
withReactQuery(withCurrentUser(AccessControlPanel)),
[
'resourceControl',
'resourceType',
'disableOwnershipChange',
'resourceId',
'onUpdateSuccess',
]
);

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';
@@ -11,6 +9,7 @@ import { snapshotEndpoints } from '../environments/environment.service';
import { isEdgeEnvironment } from '../environments/utils';
import { confirmAsync } from '../services/modal.service/confirm';
import { buildTitle } from '../services/modal.service/utils';
import { UIStateProvider } from '../hooks/UIStateProvider';
import { EnvironmentList } from './EnvironmentList';
import { EdgeLoadingSpinner } from './EdgeLoadingSpinner';
@@ -24,7 +23,7 @@ export function HomeView() {
const router = useRouter();
return (
<>
<UIStateProvider>
<PageHeader
reload
title="Home"
@@ -45,7 +44,7 @@ export function HomeView() {
onRefresh={confirmTriggerSnapshot}
/>
)}
</>
</UIStateProvider>
);
async function confirmTriggerSnapshot() {
@@ -73,8 +72,6 @@ export function HomeView() {
}
}
export const HomeViewAngular = r2a(HomeView, []);
async function confirmEndpointSnapshot() {
return confirmAsync({
title: buildTitle('Are you sure?'),

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

@@ -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,9 +1,18 @@
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 { 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';
@@ -25,22 +34,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',
@@ -50,13 +62,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(
@@ -74,7 +86,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(
@@ -85,7 +97,24 @@ export const componentsModule = angular
'datatableSearchbar',
r2a(SearchBar, ['data-cy', 'onChange', 'value', 'placeholder'])
)
.component('boxSelectorBadgeIcon', r2a(BadgeIcon, ['featherIcon', 'icon']))
.component(
'boxSelectorBadgeIcon',
react2angular(BadgeIcon, ['featherIcon', 'icon'])
'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,21 +1,16 @@
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';
export const viewsModule = angular
.module('portainer.app.react.views', [wizardModule])
.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

@@ -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 };

View File

@@ -1,24 +0,0 @@
import { QueryClientProvider } from 'react-query';
import { UIRouterContextComponent } from '@uirouter/react-hybrid';
import { PropsWithChildren, StrictMode } from 'react';
import { UserProvider } from '@/portainer/hooks/useUser';
import { UIStateProvider } from '@/portainer/hooks/UIStateProvider';
import { createQueryClient } from './react-query';
const queryClient = createQueryClient();
export function RootProvider({ children }: PropsWithChildren<unknown>) {
return (
<StrictMode>
<QueryClientProvider client={queryClient}>
<UIStateProvider>
<UIRouterContextComponent>
<UserProvider>{children}</UserProvider>
</UIRouterContextComponent>
</UIStateProvider>
</QueryClientProvider>
</StrictMode>
);
}

View File

@@ -93,3 +93,5 @@ function handleError(error: unknown, errorMeta?: unknown) {
notifyError(title, error as Error, message);
}
}
export const queryClient = createQueryClient();

View File

@@ -1,10 +1,8 @@
import ReactDOM from 'react-dom';
import { IComponentOptions, IController } from 'angular';
import { Suspense } from 'react';
import { StrictMode } from 'react';
import _ from 'lodash';
import { RootProvider } from './RootProvider';
function toProps(
propNames: string[],
controller: IController,
@@ -54,20 +52,29 @@ export function react2angular<T, U extends PropNames<T>[]>(
$element: HTMLElement[],
$q: ng.IQService
) {
let isDestroyed = false;
const el = $element[0];
this.$onChanges = () => {
const props = toProps(propNames, this, $q);
ReactDOM.render(
<Suspense fallback="loading translations">
<RootProvider>
if (!isDestroyed) {
const props = toProps(propNames, this, $q);
ReactDOM.render(
<StrictMode>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<Component {...(props as T)} />
</RootProvider>
</Suspense>,
el
);
</StrictMode>,
el
);
}
};
this.$onDestroy = () => {
if (!isDestroyed) {
isDestroyed = true;
ReactDOM.unmountComponentAtNode(el);
}
};
this.$onDestroy = () => ReactDOM.unmountComponentAtNode(el);
}
}

View File

@@ -0,0 +1,24 @@
import { ComponentType } from 'react';
import { UserProvider } from '@/portainer/hooks/useUser';
export function withCurrentUser<T>(
WrappedComponent: ComponentType<T>
): ComponentType<T> {
// Try to create a nice displayName for React Dev Tools.
const displayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
function WrapperComponent(props: T) {
return (
<UserProvider>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<WrappedComponent {...props} />
</UserProvider>
);
}
WrapperComponent.displayName = displayName;
return WrapperComponent;
}

View File

@@ -0,0 +1,22 @@
import { ComponentType, Suspense } from 'react';
export function withI18nSuspense<T>(
WrappedComponent: ComponentType<T>
): ComponentType<T> {
// Try to create a nice displayName for React Dev Tools.
const displayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
function WrapperComponent(props: T) {
return (
<Suspense fallback="Loading translations...">
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<WrappedComponent {...props} />
</Suspense>
);
}
WrapperComponent.displayName = displayName;
return WrapperComponent;
}

View File

@@ -0,0 +1,26 @@
import { ComponentType } from 'react';
import { QueryClientProvider } from 'react-query';
import { queryClient as defaultQueryClient } from './react-query';
export function withReactQuery<T>(
WrappedComponent: ComponentType<T>,
queryClient = defaultQueryClient
): ComponentType<T> {
// Try to create a nice displayName for React Dev Tools.
const displayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
function WrapperComponent(props: T) {
return (
<QueryClientProvider client={queryClient}>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<WrappedComponent {...props} />
</QueryClientProvider>
);
}
WrapperComponent.displayName = displayName;
return WrapperComponent;
}

View File

@@ -0,0 +1,23 @@
import { ComponentType } from 'react';
import { UIRouterContextComponent } from '@uirouter/react-hybrid';
export function withUIRouter<T>(
WrappedComponent: ComponentType<T>
): ComponentType<T> {
// Try to create a nice displayName for React Dev Tools.
const displayName =
WrappedComponent.displayName || WrappedComponent.name || 'Component';
function WrapperComponent(props: T) {
return (
<UIRouterContextComponent>
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<WrappedComponent {...props} />
</UIRouterContextComponent>
);
}
WrapperComponent.displayName = displayName;
return WrapperComponent;
}

View File

@@ -132,7 +132,6 @@
"react-select": "^5.2.1",
"react-table": "^7.7.0",
"react-tooltip": "^4.2.21",
"react2angular": "^4.0.6",
"sanitize-html": "^2.5.3",
"spinkit": "^2.0.1",
"splitargs": "github:deviantony/splitargs#semver:~0.2.0",

View File

@@ -4397,10 +4397,10 @@
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
"@types/angular@^1.6.39", "@types/angular@^1.8.3":
version "1.8.4"
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.8.4.tgz#a2cc163e508389c51d4c4119ebff6b9395cec472"
integrity sha512-wPS/ncJWhyxJsndsW1B6Ta8D4mi97x1yItSu+rkLDytU3oRIh2CFAjMuJceYwFAh9+DIohndWM0QBA9OU2Hv0g==
"@types/angular@^1.8.3":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.8.3.tgz#97602244b685113ce9dc27823471b67d28f5ba3e"
integrity sha512-vgc5Z+TD07DT7NEUjFm6XMp0kEbGXIa95XmOL5IiHXR9LdrJpcdDh3jl1nCuZbWyzFn5/1OqtMfomcnA1sUFXQ==
"@types/aria-query@^4.2.0":
version "4.2.2"
@@ -4678,14 +4678,7 @@
"@types/interpret" "*"
"@types/node" "*"
"@types/lodash.frompairs@^4.0.5":
version "4.0.7"
resolved "https://registry.yarnpkg.com/@types/lodash.frompairs/-/lodash.frompairs-4.0.7.tgz#ee9b800b4dab37cd063dcc652a2bd86f7ff984b7"
integrity sha512-7UeH2+GF9yop4AqnPwae5/2TE+eY0WRDy0RRQtNGHjzIgdUhilRskMXvXqUcCSazvbkxasjqydXrIE1OB6bPKA==
dependencies:
"@types/lodash" "*"
"@types/lodash@*", "@types/lodash@^4.14.167", "@types/lodash@^4.14.85":
"@types/lodash@^4.14.167":
version "4.14.182"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2"
integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
@@ -5670,11 +5663,6 @@ angular@1.8.2, angular@^1.3:
resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.2.tgz#5983bbb5a9fa63e213cb7749199e0d352de3a2f1"
integrity sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw==
angular@>=1.5, angular@>=1.5.0:
version "1.8.3"
resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.3.tgz#851ad75d5163c105a7e329555ef70c90aa706894"
integrity sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==
angularjs-scroll-glue@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/angularjs-scroll-glue/-/angularjs-scroll-glue-2.2.0.tgz#07d3399ac16ca874c63b6b5ee2ee30558b37e5d1"
@@ -12822,11 +12810,6 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.frompairs@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.frompairs/-/lodash.frompairs-4.0.1.tgz#bc4e5207fa2757c136e573614e9664506b2b1bd2"
integrity sha512-dvqe2I+cO5MzXCMhUnfYFa9MD+/760yx2aTAN1lqEcEkf896TxgrX373igVdqSJj6tQd0jnSLE1UMuKufqqxFw==
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
@@ -12857,7 +12840,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@^3.10.0, lodash@^3.6.0, lodash@^4.0.0, lodash@^4.11.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.7.0, lodash@~2.4.1, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.21:
lodash@^3.10.0, lodash@^3.6.0, lodash@^4.0.0, lodash@^4.11.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.3.0, lodash@^4.7.0, lodash@~2.4.1, lodash@~4.17.15, lodash@~4.17.19, lodash@~4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -13562,16 +13545,6 @@ ng-file-upload@~12.2.13:
resolved "https://registry.yarnpkg.com/ng-file-upload/-/ng-file-upload-12.2.13.tgz#01800f3872e526f95310f8477e99e4f12d0d8d14"
integrity sha1-AYAPOHLlJvlTEPhHfpnk8S0NjRQ=
ngcomponent@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ngcomponent/-/ngcomponent-4.1.0.tgz#793e379138f552ea0cd2c767ad0aa7057678e228"
integrity sha512-cGL3iVoqMWTpCfaIwgRKhdaGqiy2Z+CCG0cVfjlBvdqE8saj8xap9B4OTf+qwObxLVZmDTJPDgx3bN6Q/lZ7BQ==
dependencies:
"@types/angular" "^1.6.39"
"@types/lodash" "^4.14.85"
angular ">=1.5.0"
lodash "^4.17.4"
ngtemplate-loader@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ngtemplate-loader/-/ngtemplate-loader-2.1.0.tgz#fb71c614c509b114b3bb28a828cb608757531e96"
@@ -15608,16 +15581,6 @@ react-transition-group@^4.3.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react2angular@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/react2angular/-/react2angular-4.0.6.tgz#ec49ef834d101c9a320e25229fc5afa5b29edc4f"
integrity sha512-MDl2WRoTyu7Gyh4+FAIlmsM2mxIa/DjSz6G/d90L1tK8ZRubqVEayKF6IPyAruC5DMhGDVJ7tlAIcu/gMNDjXg==
dependencies:
"@types/lodash.frompairs" "^4.0.5"
angular ">=1.5"
lodash.frompairs "^4.0.1"
ngcomponent "^4.1.0"
react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"