mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
feat(edge): sort waiting room table [EE-6259] (#10577)
This commit is contained in:
parent
32d8dc311b
commit
25741e8c4c
10 changed files with 306 additions and 106 deletions
|
@ -22,6 +22,7 @@ export function Datatable() {
|
|||
} = useEnvironments({
|
||||
pageLimit: tableState.pageSize,
|
||||
search: tableState.search,
|
||||
sortBy: tableState.sortBy,
|
||||
});
|
||||
|
||||
return (
|
||||
|
|
|
@ -8,27 +8,32 @@ const columnHelper = createColumnHelper<WaitingRoomEnvironment>();
|
|||
export const columns = [
|
||||
columnHelper.accessor('Name', {
|
||||
header: 'Name',
|
||||
id: 'name',
|
||||
id: 'Name',
|
||||
}),
|
||||
columnHelper.accessor('EdgeID', {
|
||||
header: 'Edge ID',
|
||||
id: 'edge-id',
|
||||
id: 'EdgeID',
|
||||
}),
|
||||
columnHelper.accessor((row) => row.EdgeGroups.join(', ') || '-', {
|
||||
columnHelper.accessor((row) => row.EdgeGroups.join(', '), {
|
||||
header: 'Edge Groups',
|
||||
id: 'edge-groups',
|
||||
enableSorting: false,
|
||||
cell: ({ getValue }) => getValue() || '-',
|
||||
}),
|
||||
columnHelper.accessor((row) => row.Group || '-', {
|
||||
columnHelper.accessor((row) => row.Group, {
|
||||
header: 'Group',
|
||||
id: 'group',
|
||||
id: 'Group',
|
||||
cell: ({ getValue }) => getValue() || '-',
|
||||
}),
|
||||
columnHelper.accessor((row) => row.Tags.join(', ') || '-', {
|
||||
columnHelper.accessor((row) => row.Tags.join(', '), {
|
||||
header: 'Tags',
|
||||
id: 'tags',
|
||||
enableSorting: false,
|
||||
cell: ({ getValue }) => getValue() || '-',
|
||||
}),
|
||||
columnHelper.accessor((row) => row.LastCheckInDate, {
|
||||
header: 'Last Check-in',
|
||||
id: 'last-check-in',
|
||||
id: 'LastCheckIn',
|
||||
cell: ({ getValue }) => {
|
||||
const value = getValue();
|
||||
return value ? moment(value * 1000).fromNow() : '-';
|
||||
|
|
|
@ -6,6 +6,10 @@ import { useEdgeGroups } from '@/react/edge/edge-groups/queries/useEdgeGroups';
|
|||
import { useGroups } from '@/react/portainer/environments/environment-groups/queries';
|
||||
import { useEnvironmentList } from '@/react/portainer/environments/queries';
|
||||
import { EdgeTypes } from '@/react/portainer/environments/types';
|
||||
import {
|
||||
Query,
|
||||
getSortType,
|
||||
} from '@/react/portainer/environments/queries/useEnvironmentList';
|
||||
|
||||
import { WaitingRoomEnvironment } from '../types';
|
||||
|
||||
|
@ -14,9 +18,11 @@ import { useFilterStore } from './filter-store';
|
|||
export function useEnvironments({
|
||||
pageLimit = 10,
|
||||
search,
|
||||
sortBy,
|
||||
}: {
|
||||
pageLimit: number;
|
||||
search: string;
|
||||
sortBy: { id: string; desc: boolean } | undefined;
|
||||
}) {
|
||||
const [page, setPage] = useState(0);
|
||||
const filterStore = useFilterStore();
|
||||
|
@ -35,7 +41,7 @@ export function useEnvironments({
|
|||
[edgeGroupsQuery.data, filterStore.edgeGroups]
|
||||
);
|
||||
|
||||
const query = useMemo(
|
||||
const query: Partial<Query> = useMemo(
|
||||
() => ({
|
||||
pageLimit,
|
||||
edgeDeviceUntrusted: true,
|
||||
|
@ -46,6 +52,8 @@ export function useEnvironments({
|
|||
endpointIds: filterByEnvironmentsIds,
|
||||
edgeCheckInPassedSeconds: filterStore.checkIn,
|
||||
search,
|
||||
sort: getSortType(sortBy?.id),
|
||||
order: sortBy?.desc ? 'desc' : 'asc',
|
||||
}),
|
||||
[
|
||||
filterByEnvironmentsIds,
|
||||
|
@ -54,6 +62,7 @@ export function useEnvironments({
|
|||
filterStore.tags,
|
||||
pageLimit,
|
||||
search,
|
||||
sortBy,
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
import { EnvironmentGroupId } from '@/react/portainer/environments/environment-groups/types';
|
||||
import {
|
||||
refetchIfAnyOffline,
|
||||
SortType,
|
||||
useEnvironmentList,
|
||||
} from '@/react/portainer/environments/queries/useEnvironmentList';
|
||||
import { useGroups } from '@/react/portainer/environments/environment-groups/queries';
|
||||
|
@ -37,6 +36,7 @@ import { NoEnvironmentsInfoPanel } from './NoEnvironmentsInfoPanel';
|
|||
import { UpdateBadge } from './UpdateBadge';
|
||||
import { EnvironmentListFilters } from './EnvironmentListFilters';
|
||||
import { AMTButton } from './AMTButton/AMTButton';
|
||||
import { ListSortType } from './SortbySelector';
|
||||
|
||||
interface Props {
|
||||
onClickBrowse(environment: Environment): void;
|
||||
|
@ -70,7 +70,7 @@ export function EnvironmentList({ onClickBrowse, onRefresh }: Props) {
|
|||
[]
|
||||
);
|
||||
const [sortByFilter, setSortByFilter] = useHomePageFilter<
|
||||
SortType | undefined
|
||||
ListSortType | undefined
|
||||
>('sortBy', undefined);
|
||||
const [sortByDescending, setSortByDescending] = useHomePageFilter(
|
||||
'sortOrder',
|
||||
|
|
|
@ -5,13 +5,9 @@ import { useTags } from '@/portainer/tags/queries';
|
|||
import { useAgentVersionsList } from '../../environments/queries/useAgentVersionsList';
|
||||
import { EnvironmentStatus, PlatformType } from '../../environments/types';
|
||||
import { useGroups } from '../../environments/environment-groups/queries';
|
||||
import {
|
||||
SortOptions,
|
||||
SortType,
|
||||
} from '../../environments/queries/useEnvironmentList';
|
||||
|
||||
import { HomepageFilter } from './HomepageFilter';
|
||||
import { SortbySelector } from './SortbySelector';
|
||||
import { ListSortType, SortbySelector } from './SortbySelector';
|
||||
import { ConnectionType } from './types';
|
||||
import styles from './EnvironmentList.module.css';
|
||||
|
||||
|
@ -20,11 +16,6 @@ const status = [
|
|||
{ value: EnvironmentStatus.Down, label: 'Down' },
|
||||
];
|
||||
|
||||
const sortByOptions = SortOptions.map((v) => ({
|
||||
value: v,
|
||||
label: v,
|
||||
}));
|
||||
|
||||
export function EnvironmentListFilters({
|
||||
agentVersions,
|
||||
clearFilter,
|
||||
|
@ -63,8 +54,8 @@ export function EnvironmentListFilters({
|
|||
setAgentVersions: (value: string[]) => void;
|
||||
agentVersions: string[];
|
||||
|
||||
sortByState?: SortType;
|
||||
sortOnChange: (value: SortType) => void;
|
||||
sortByState?: ListSortType;
|
||||
sortOnChange: (value: ListSortType) => void;
|
||||
|
||||
sortOnDescending: () => void;
|
||||
sortByDescending: boolean;
|
||||
|
@ -160,7 +151,6 @@ export function EnvironmentListFilters({
|
|||
|
||||
<div className={styles.filterRight}>
|
||||
<SortbySelector
|
||||
filterOptions={sortByOptions}
|
||||
onChange={sortOnChange}
|
||||
onDescending={sortOnDescending}
|
||||
placeHolder="Sort By"
|
||||
|
|
|
@ -1,24 +1,34 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { Option, PortainerSelect } from '@@/form-components/PortainerSelect';
|
||||
import { PortainerSelect } from '@@/form-components/PortainerSelect';
|
||||
import { TableHeaderSortIcons } from '@@/datatables/TableHeaderSortIcons';
|
||||
|
||||
import { SortType } from '../../environments/queries/useEnvironmentList';
|
||||
import {
|
||||
SortOptions,
|
||||
SortType,
|
||||
} from '../../environments/queries/useEnvironmentList';
|
||||
|
||||
import styles from './SortbySelector.module.css';
|
||||
|
||||
export type ListSortType = Exclude<SortType, 'LastCheckIn' | 'EdgeID'>;
|
||||
|
||||
const sortByOptions = SortOptions.filter(
|
||||
(v): v is ListSortType => !['LastCheckIn', 'EdgeID'].includes(v)
|
||||
).map((v) => ({
|
||||
value: v,
|
||||
label: v,
|
||||
}));
|
||||
|
||||
interface Props {
|
||||
filterOptions: Option<SortType>[];
|
||||
onChange: (value: SortType) => void;
|
||||
onChange: (value: ListSortType) => void;
|
||||
onDescending: () => void;
|
||||
placeHolder: string;
|
||||
sortByDescending: boolean;
|
||||
sortByButton: boolean;
|
||||
value?: SortType;
|
||||
value?: ListSortType;
|
||||
}
|
||||
|
||||
export function SortbySelector({
|
||||
filterOptions,
|
||||
onChange,
|
||||
onDescending,
|
||||
placeHolder,
|
||||
|
@ -31,8 +41,8 @@ export function SortbySelector({
|
|||
<div className="flex items-center justify-end gap-1">
|
||||
<PortainerSelect
|
||||
placeholder={placeHolder}
|
||||
options={filterOptions}
|
||||
onChange={(option: SortType) => onChange(option || '')}
|
||||
options={sortByOptions}
|
||||
onChange={(option: ListSortType) => onChange(option)}
|
||||
isClearable
|
||||
value={value}
|
||||
/>
|
||||
|
|
|
@ -12,12 +12,22 @@ import { environmentQueryKeys } from './query-keys';
|
|||
|
||||
export const ENVIRONMENTS_POLLING_INTERVAL = 30000; // in ms
|
||||
|
||||
export const SortOptions = ['Name', 'Group', 'Status'] as const;
|
||||
export const SortOptions = [
|
||||
'Name',
|
||||
'Group',
|
||||
'Status',
|
||||
'LastCheckIn',
|
||||
'EdgeID',
|
||||
] as const;
|
||||
export type SortType = (typeof SortOptions)[number];
|
||||
export function isSortType(value?: string): value is SortType {
|
||||
return SortOptions.includes(value as SortType);
|
||||
}
|
||||
|
||||
export function getSortType(value?: string): SortType | undefined {
|
||||
return isSortType(value) ? value : undefined;
|
||||
}
|
||||
|
||||
export type Query = EnvironmentsQueryParams & {
|
||||
page?: number;
|
||||
pageLimit?: number;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue