You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
portainer/app/react/edge/edge-stacks/ItemView/EnvironmentsDatatable/EnvironmentsDatatable.tsx

161 lines
4.7 KiB

import { useCurrentStateAndParams } from '@uirouter/react';
import { HardDrive } from 'lucide-react';
import { useMemo, useState } from 'react';
import { EdgeStackStatus, StatusType } from '@/react/edge/edge-stacks/types';
import { useEnvironmentList } from '@/react/portainer/environments/queries';
import { useParamState } from '@/react/hooks/useParamState';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
import { Datatable } from '@@/datatables';
import { PortainerSelect } from '@@/form-components/PortainerSelect';
import { createPersistedStore } from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import { useEdgeStack } from '../../queries/useEdgeStack';
import { EdgeStackEnvironment } from './types';
import { columns } from './columns';
const tableKey = 'edge-stacks-environment';
const settingsStore = createPersistedStore(tableKey);
export function EnvironmentsDatatable() {
const {
params: { stackId },
} = useCurrentStateAndParams();
const edgeStackQuery = useEdgeStack(stackId, {
refetchInterval(data) {
if (!data) {
return 0;
}
return Object.values(data.Status).some((status) =>
status.Status.every((s) => s.Type === StatusType.Running)
)
? 0
: 10000;
},
});
const [page, setPage] = useState(0);
const [statusFilter, setStatusFilter] = useParamState<StatusType>(
'status',
(value) => (value ? parseInt(value, 10) : undefined)
);
const tableState = useTableState(settingsStore, tableKey);
const environmentsQuery = useEnvironmentList({
pageLimit: tableState.pageSize,
page: page + 1,
search: tableState.search,
sort: tableState.sortBy?.id as 'Group' | 'Name',
order: tableState.sortBy?.desc ? 'desc' : 'asc',
edgeStackId: stackId,
edgeStackStatus: statusFilter,
});
const currentFileVersion =
edgeStackQuery.data?.StackFileVersion?.toString() || '';
const gitConfigURL = edgeStackQuery.data?.GitConfig?.URL || '';
const gitConfigCommitHash = edgeStackQuery.data?.GitConfig?.ConfigHash || '';
const environments: Array<EdgeStackEnvironment> = useMemo(
() =>
environmentsQuery.environments.map(
(env) =>
({
...env,
TargetFileVersion: currentFileVersion,
GitConfigURL: gitConfigURL,
TargetCommitHash: gitConfigCommitHash,
StackStatus: getEnvStackStatus(
env.Id,
edgeStackQuery.data?.Status[env.Id]
),
}) satisfies EdgeStackEnvironment
),
[
currentFileVersion,
edgeStackQuery.data?.Status,
environmentsQuery.environments,
gitConfigCommitHash,
gitConfigURL,
]
);
const envStatusSelectOptions = [
{ value: StatusType.Pending, label: 'Pending' },
{ value: StatusType.Acknowledged, label: 'Acknowledged' },
{ value: StatusType.ImagesPulled, label: 'Images pre-pulled' },
{ value: StatusType.Running, label: 'Deployed' },
{ value: StatusType.Error, label: 'Failed' },
];
if (isBE) {
envStatusSelectOptions.concat([
{ value: StatusType.PausedDeploying, label: 'Paused' },
{ value: StatusType.RollingBack, label: 'Rolling back' },
{ value: StatusType.RolledBack, label: 'Rolled back' },
]);
}
return (
<Datatable
columns={columns}
isLoading={environmentsQuery.isLoading}
dataset={environments}
settingsManager={tableState}
title="Environments Status"
titleIcon={HardDrive}
isServerSidePagination
page={page}
onPageChange={setPage}
totalCount={environmentsQuery.totalCount}
disableSelect
description={
<div className="w-1/4">
<PortainerSelect<StatusType | undefined>
isClearable
bindToBody
value={statusFilter}
onChange={(e) => setStatusFilter(e ?? undefined)}
options={envStatusSelectOptions}
data-cy="edge-stacks-environments-status-filter"
/>
</div>
}
data-cy="edge-stacks-environments-datatable"
/>
);
}
function getEnvStackStatus(
envId: EnvironmentId,
envStatus: EdgeStackStatus | undefined
) {
const pendingStatus = {
Type: StatusType.Pending,
Error: '',
Time: new Date().valueOf() / 1000,
};
let status = envStatus;
if (!status) {
status = {
EndpointID: envId,
DeploymentInfo: {
Version: 0,
ConfigHash: '',
FileVersion: 0,
},
Status: [],
};
}
if (status.Status.length === 0) {
status.Status.push(pendingStatus);
}
return status;
}