1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-24 15:59:41 +02:00

refactor(docker/stacks): migrate table to react [EE-4705] (#9956)

This commit is contained in:
Chaim Lev-Ari 2023-09-07 15:59:59 +01:00 committed by GitHub
parent c3d266931f
commit c8a1f0fa77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 1127 additions and 492 deletions

View file

@ -0,0 +1,85 @@
import { useQuery } from 'react-query';
import { Loader } from 'lucide-react';
import {
getContainerImagesStatus,
getServiceImagesStatus,
} from '@/react/docker/images/image.service';
import { useEnvironment } from '@/react/portainer/environments/queries';
import { statusIcon } from '@/react/docker/components/ImageStatus/helpers';
import { ResourceID, ResourceType } from '@/react/docker/images/types';
import { EnvironmentId } from '@/react/portainer/environments/types';
import { Icon } from '@@/Icon';
export interface Props {
environmentId: EnvironmentId;
resourceId: ResourceID;
resourceType?: ResourceType;
nodeName?: string;
}
export function ImageStatus({
environmentId,
resourceId,
resourceType = ResourceType.CONTAINER,
nodeName = '',
}: Props) {
const enableImageNotificationQuery = useEnvironment(
environmentId,
(environment) => environment?.EnableImageNotification
);
const { data, isLoading, isError } = useImageNotification(
environmentId,
resourceId,
resourceType,
nodeName,
enableImageNotificationQuery.data
);
if (!enableImageNotificationQuery.data || isError) {
return null;
}
if (isLoading || !data) {
return (
<Icon
icon={Loader}
size="sm"
className="!mr-1 animate-spin-slow align-middle"
/>
);
}
return (
<Icon icon={statusIcon(data)} size="sm" className="!mr-1 align-middle" />
);
}
export function useImageNotification(
environmentId: number,
resourceId: ResourceID,
resourceType: ResourceType,
nodeName: string,
enabled = false
) {
return useQuery(
[
'environments',
environmentId,
'docker',
'images',
resourceType,
resourceId,
'status',
],
() =>
resourceType === ResourceType.SERVICE
? getServiceImagesStatus(environmentId, resourceId)
: getContainerImagesStatus(environmentId, resourceId, nodeName),
{
enabled,
}
);
}

View file

@ -0,0 +1,20 @@
import { Loader } from 'lucide-react';
import UpdatesAvailable from '@/assets/ico/icon_updates-available.svg?c';
import UpToDate from '@/assets/ico/icon_up-to-date.svg?c';
import UpdatesUnknown from '@/assets/ico/icon_updates-unknown.svg?c';
import { ImageStatus } from '../../images/types';
export function statusIcon(status: ImageStatus) {
switch (status.Status) {
case 'outdated':
return UpdatesAvailable;
case 'updated':
return UpToDate;
case 'processing':
return Loader;
default:
return UpdatesUnknown;
}
}

View file

@ -0,0 +1 @@
export { ImageStatus } from './ImageStatus';

View file

@ -0,0 +1,65 @@
import UpdatesAvailable from '@/assets/ico/icon_updates-available.svg?c';
import UpToDate from '@/assets/ico/icon_up-to-date.svg?c';
import UpdatesUnknown from '@/assets/ico/icon_updates-unknown.svg?c';
import { useEnvironment } from '@/react/portainer/environments/queries';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { Icon } from '@@/Icon';
import { Tooltip } from '@@/Tip/Tooltip';
import {
TableColumnHeaderAngular,
TableColumnHeaderAngularProps,
} from '@@/datatables/TableHeaderCell';
export function TableColumnHeaderImageUpToDate({
canSort,
isSorted,
colTitle,
isSortedDesc = true,
}: TableColumnHeaderAngularProps) {
return (
<TableColumnHeaderAngular
canSort={canSort}
isSorted={isSorted}
colTitle={colTitle}
isSortedDesc={isSortedDesc}
>
<ImageUpToDateTooltip />
</TableColumnHeaderAngular>
);
}
export function ImageUpToDateTooltip() {
const environmentId = useEnvironmentId();
const enableImageNotificationQuery = useEnvironment(
environmentId,
(environment) => environment?.EnableImageNotification
);
if (!enableImageNotificationQuery.data) {
return null;
}
return (
<Tooltip
position="top"
message={
<div className="flex flex-col gap-y-2 p-2">
<div className="flex items-center gap-2">
<Icon icon={UpToDate} />
Images are up to date
</div>
<div className="flex items-center gap-2">
<Icon icon={UpdatesAvailable} />
Updates are available
</div>
<div className="flex items-center gap-2">
<Icon icon={UpdatesUnknown} />
Updates availability unknown
</div>
</div>
}
/>
);
}

View file

@ -11,16 +11,16 @@ export interface IResource {
};
}
export function createOwnershipColumn<D extends IResource>(): ColumnDef<
D,
ResourceControlOwnership
> {
export function createOwnershipColumn<D extends IResource>(
enableHiding = true
): ColumnDef<D, ResourceControlOwnership> {
return {
accessorFn: (row) =>
row.ResourceControl?.Ownership || ResourceControlOwnership.ADMINISTRATORS,
header: 'Ownership',
id: 'ownership',
cell: OwnershipCell,
enableHiding,
};
function OwnershipCell({