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

refactor(apps): migrate applications view to react [r8s-124] (#28)

This commit is contained in:
Ali 2024-10-25 12:28:05 +13:00 committed by GitHub
parent cc75167437
commit 959c527be7
42 changed files with 1378 additions and 1293 deletions

View file

@ -1,52 +1,44 @@
import { List } from 'lucide-react';
import { useRouter } from '@uirouter/react';
import { useAuthorizations } from '@/react/hooks/useUser';
import { Authorized, useAuthorizations } from '@/react/hooks/useUser';
import { SystemResourceDescription } from '@/react/kubernetes/datatables/SystemResourceDescription';
import { createStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { isSystemNamespace } from '@/react/kubernetes/namespaces/queries/useIsSystemNamespace';
import { useNamespacesQuery } from '@/react/kubernetes/namespaces/queries/useNamespacesQuery';
import { DefaultDatatableSettings } from '@/react/kubernetes/datatables/DefaultDatatableSettings';
import { ExpandableDatatable } from '@@/datatables/ExpandableDatatable';
import { useTableState } from '@@/datatables/useTableState';
import { TableSettingsMenu } from '@@/datatables';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { useApplications } from '../../application.queries';
import { useApplications } from '../../queries/useApplications';
import { ApplicationsTableSettings } from '../useKubeAppsTableStore';
import { useDeleteApplicationsMutation } from '../../queries/useDeleteApplicationsMutation';
import { columns } from './columns';
import { SubRows } from './SubRows';
import { Namespace, Stack } from './types';
import { NamespaceFilter } from './NamespaceFilter';
import { TableActions } from './TableActions';
import { getStacksFromApplications } from './getStacksFromApplications';
const storageKey = 'kubernetes.applications.stacks';
const settingsStore = createStore(storageKey);
interface Props {
onRemove(selectedItems: Array<Stack>): void;
namespace?: string;
namespaces: Array<Namespace>;
onNamespaceChange(namespace: string): void;
}
import { Stack } from './types';
export function ApplicationsStacksDatatable({
onRemove,
namespace = '',
namespaces,
onNamespaceChange,
}: Props) {
const tableState = useTableState(settingsStore, storageKey);
const envId = useEnvironmentId();
const applicationsQuery = useApplications(envId, {
tableState,
}: {
tableState: ApplicationsTableSettings & {
setSearch: (value: string) => void;
search: string;
};
}) {
const router = useRouter();
const environmentId = useEnvironmentId();
const namespaceListQuery = useNamespacesQuery(environmentId);
const { authorized: hasWriteAuth } = useAuthorizations('K8sApplicationsW');
const applicationsQuery = useApplications(environmentId, {
refetchInterval: tableState.autoRefreshRate * 1000,
namespace,
namespace: tableState.namespace,
withDependencies: true,
});
const namespaceListQuery = useNamespacesQuery(envId);
const applications = applicationsQuery.data ?? [];
const filteredApplications = tableState.showSystemResources
? applications
@ -54,10 +46,12 @@ export function ApplicationsStacksDatatable({
(item) =>
!isSystemNamespace(item.ResourcePool, namespaceListQuery.data ?? [])
);
const { authorized } = useAuthorizations('K8sApplicationsW');
const stacks = getStacksFromApplications(filteredApplications);
const removeApplicationsMutation = useDeleteApplicationsMutation({
environmentId,
stacks,
reportStacks: true,
});
return (
<ExpandableDatatable
@ -68,18 +62,17 @@ export function ApplicationsStacksDatatable({
isLoading={applicationsQuery.isLoading || namespaceListQuery.isLoading}
columns={columns}
settingsManager={tableState}
disableSelect={!authorized}
disableSelect={!hasWriteAuth}
renderSubRow={(row) => (
<SubRows stack={row.original} span={row.getVisibleCells().length} />
)}
noWidget
description={
<div className="w-full">
<div className="float-right mr-2 min-w-[140px]">
<NamespaceFilter
namespaces={namespaces}
value={namespace}
onChange={onNamespaceChange}
namespaces={namespaceListQuery.data ?? []}
value={tableState.namespace}
onChange={tableState.setNamespace}
showSystem={tableState.showSystemResources}
/>
</div>
@ -92,7 +85,14 @@ export function ApplicationsStacksDatatable({
</div>
}
renderTableActions={(selectedItems) => (
<TableActions selectedItems={selectedItems} onRemove={onRemove} />
<Authorized authorizations="K8sApplicationsW">
<DeleteButton
confirmMessage="Are you sure that you want to remove the selected stack(s) ? This will remove all the applications associated to the stack(s)."
disabled={selectedItems.length === 0}
onConfirmed={() => handleRemoveStacks(selectedItems)}
data-cy="k8sApp-removeStackButton"
/>
</Authorized>
)}
renderTableSettings={() => (
<TableSettingsMenu>
@ -103,4 +103,13 @@ export function ApplicationsStacksDatatable({
data-cy="applications-stacks-datatable"
/>
);
function handleRemoveStacks(selectedItems: Stack[]) {
const applications = selectedItems.flatMap((stack) => stack.Applications);
removeApplicationsMutation.mutate(applications, {
onSuccess: () => {
router.stateService.reload();
},
});
}
}

View file

@ -1,13 +1,16 @@
import { Filter } from 'lucide-react';
import { useEffect } from 'react';
import { PortainerNamespace } from '@/react/kubernetes/namespaces/types';
import { Icon } from '@@/Icon';
import { Select } from '@@/form-components/Input';
import { InputGroup } from '@@/form-components/InputGroup';
import { Namespace } from './types';
function transformNamespaces(namespaces: Namespace[], showSystem?: boolean) {
function transformNamespaces(
namespaces: PortainerNamespace[],
showSystem?: boolean
) {
const transformedNamespaces = namespaces.map(({ Name, IsSystem }) => ({
label: IsSystem ? `${Name} - system` : Name,
value: Name,
@ -26,7 +29,7 @@ export function NamespaceFilter({
onChange,
showSystem,
}: {
namespaces: Namespace[];
namespaces: PortainerNamespace[];
value: string;
onChange: (value: string) => void;
showSystem?: boolean;

View file

@ -1,24 +0,0 @@
import { Authorized } from '@/react/hooks/useUser';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { Stack } from './types';
export function TableActions({
selectedItems,
onRemove,
}: {
selectedItems: Array<Stack>;
onRemove: (selectedItems: Array<Stack>) => void;
}) {
return (
<Authorized authorizations="K8sApplicationsW">
<DeleteButton
confirmMessage="Are you sure that you want to remove the selected stack(s) ? This will remove all the applications associated to the stack(s)."
disabled={selectedItems.length === 0}
onConfirmed={() => onRemove(selectedItems)}
data-cy="k8sApp-removeStackButton"
/>
</Authorized>
);
}

View file

@ -12,13 +12,6 @@ export interface TableSettings
RefreshableTableSettings,
SystemResourcesTableSettings {}
export interface Namespace {
Id: string;
Name: string;
Yaml: string;
IsSystem?: boolean;
}
export type Stack = {
Name: string;
ResourcePool: string;