mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
refactor(groups): migrate groups selectors to react [EE-3842] (#8936)
This commit is contained in:
parent
2018529add
commit
e91b4f5c83
38 changed files with 543 additions and 627 deletions
|
@ -0,0 +1,63 @@
|
|||
import { EdgeTypes, EnvironmentId } from '@/react/portainer/environments/types';
|
||||
|
||||
import { EdgeGroupAssociationTable } from './EdgeGroupAssociationTable';
|
||||
|
||||
export function AssociatedEdgeEnvironmentsSelector({
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
onChange: (
|
||||
value: EnvironmentId[],
|
||||
meta: { type: 'add' | 'remove'; value: EnvironmentId }
|
||||
) => void;
|
||||
value: EnvironmentId[];
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<div className="col-sm-12 small text-muted">
|
||||
You can select which environment should be part of this group by moving
|
||||
them to the associated environments table. Simply click on any
|
||||
environment entry to move it from one table to the other.
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 mt-4">
|
||||
<div className="flex">
|
||||
<div className="w-1/2">
|
||||
<EdgeGroupAssociationTable
|
||||
title="Available environments"
|
||||
emptyContentLabel="No environment available"
|
||||
query={{
|
||||
types: EdgeTypes,
|
||||
}}
|
||||
onClickRow={(env) => {
|
||||
if (!value.includes(env.Id)) {
|
||||
onChange([...value, env.Id], { type: 'add', value: env.Id });
|
||||
}
|
||||
}}
|
||||
data-cy="edgeGroupCreate-availableEndpoints"
|
||||
hideEnvironmentIds={value}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-1/2">
|
||||
<EdgeGroupAssociationTable
|
||||
title="Associated environments"
|
||||
emptyContentLabel="No associated environment'"
|
||||
query={{
|
||||
types: EdgeTypes,
|
||||
endpointIds: value,
|
||||
}}
|
||||
onClickRow={(env) => {
|
||||
if (value.includes(env.Id)) {
|
||||
onChange(
|
||||
value.filter((id) => id !== env.Id),
|
||||
{ type: 'remove', value: env.Id }
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
117
app/react/edge/components/EdgeGroupAssociationTable.tsx
Normal file
117
app/react/edge/components/EdgeGroupAssociationTable.tsx
Normal file
|
@ -0,0 +1,117 @@
|
|||
import { createColumnHelper } from '@tanstack/react-table';
|
||||
import { truncate } from 'lodash';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { useEnvironmentList } from '@/react/portainer/environments/queries';
|
||||
import {
|
||||
Environment,
|
||||
EnvironmentId,
|
||||
} from '@/react/portainer/environments/types';
|
||||
import { useGroups } from '@/react/portainer/environments/environment-groups/queries';
|
||||
import { useTags } from '@/portainer/tags/queries';
|
||||
import { EnvironmentsQueryParams } from '@/react/portainer/environments/environment.service';
|
||||
import { AutomationTestingProps } from '@/types';
|
||||
|
||||
import { useTableStateWithoutStorage } from '@@/datatables/useTableState';
|
||||
import { Datatable, TableRow } from '@@/datatables';
|
||||
|
||||
type DecoratedEnvironment = Environment & {
|
||||
Tags: string[];
|
||||
Group: string;
|
||||
};
|
||||
|
||||
const columHelper = createColumnHelper<DecoratedEnvironment>();
|
||||
|
||||
const columns = [
|
||||
columHelper.accessor('Name', {
|
||||
header: 'Name',
|
||||
id: 'Name',
|
||||
cell: ({ getValue }) => truncate(getValue(), { length: 64 }),
|
||||
}),
|
||||
columHelper.accessor('Group', {
|
||||
header: 'Group',
|
||||
id: 'Group',
|
||||
cell: ({ getValue }) => truncate(getValue(), { length: 64 }),
|
||||
}),
|
||||
columHelper.accessor((row) => row.Tags.join(','), {
|
||||
header: 'Tags',
|
||||
id: 'tags',
|
||||
enableSorting: false,
|
||||
cell: ({ getValue }) => truncate(getValue(), { length: 64 }),
|
||||
}),
|
||||
];
|
||||
|
||||
export function EdgeGroupAssociationTable({
|
||||
title,
|
||||
query,
|
||||
emptyContentLabel,
|
||||
onClickRow,
|
||||
'data-cy': dataCy,
|
||||
hideEnvironmentIds = [],
|
||||
}: {
|
||||
title: string;
|
||||
query: EnvironmentsQueryParams;
|
||||
emptyContentLabel: string;
|
||||
onClickRow: (env: Environment) => void;
|
||||
hideEnvironmentIds?: EnvironmentId[];
|
||||
} & AutomationTestingProps) {
|
||||
const tableState = useTableStateWithoutStorage('Name');
|
||||
const [page, setPage] = useState(1);
|
||||
const environmentsQuery = useEnvironmentList({
|
||||
pageLimit: tableState.pageSize,
|
||||
page,
|
||||
search: tableState.search,
|
||||
sort: tableState.sortBy.id as 'Group' | 'Name',
|
||||
order: tableState.sortBy.desc ? 'desc' : 'asc',
|
||||
...query,
|
||||
});
|
||||
const groupsQuery = useGroups({
|
||||
enabled: environmentsQuery.environments.length > 0,
|
||||
});
|
||||
const tagsQuery = useTags({
|
||||
enabled: environmentsQuery.environments.length > 0,
|
||||
});
|
||||
|
||||
const environments: Array<DecoratedEnvironment> = useMemo(
|
||||
() =>
|
||||
environmentsQuery.environments
|
||||
.filter((e) => !hideEnvironmentIds.includes(e.Id))
|
||||
.map((env) => ({
|
||||
...env,
|
||||
Group:
|
||||
groupsQuery.data?.find((g) => g.Id === env.GroupId)?.Name || '',
|
||||
Tags: env.TagIds.map(
|
||||
(tagId) => tagsQuery.data?.find((t) => t.ID === tagId)?.Name || ''
|
||||
),
|
||||
})),
|
||||
[
|
||||
environmentsQuery.environments,
|
||||
groupsQuery.data,
|
||||
hideEnvironmentIds,
|
||||
tagsQuery.data,
|
||||
]
|
||||
);
|
||||
|
||||
const totalCount = environmentsQuery.totalCount - hideEnvironmentIds.length;
|
||||
|
||||
return (
|
||||
<Datatable<DecoratedEnvironment>
|
||||
title={title}
|
||||
columns={columns}
|
||||
settingsManager={tableState}
|
||||
dataset={environments}
|
||||
onPageChange={setPage}
|
||||
pageCount={Math.ceil(totalCount / tableState.pageSize)}
|
||||
renderRow={(row) => (
|
||||
<TableRow<DecoratedEnvironment>
|
||||
cells={row.getVisibleCells()}
|
||||
onClick={() => onClickRow(row.original)}
|
||||
/>
|
||||
)}
|
||||
emptyContentLabel={emptyContentLabel}
|
||||
data-cy={dataCy}
|
||||
disableSelect
|
||||
totalCount={totalCount}
|
||||
/>
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue