1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 05:45:22 +02:00

feat(docker/images): show used tag correctly [EE-5396] (#10305)

This commit is contained in:
Chaim Lev-Ari 2023-10-03 15:55:23 +03:00 committed by GitHub
parent b895e88075
commit 9bf2957ea7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 383 additions and 287 deletions

View file

@ -10,8 +10,8 @@ import { Menu, MenuButton, MenuItem, MenuPopover } from '@reach/menu-button';
import { positionRight } from '@reach/popover';
import { useMemo } from 'react';
import { Environment } from '@/react/portainer/environments/types';
import { Authorized } from '@/react/hooks/useUser';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { Datatable, TableSettingsMenu } from '@@/datatables';
import {
@ -24,14 +24,12 @@ import { useTableState } from '@@/datatables/useTableState';
import { Button, ButtonGroup, LoadingButton } from '@@/buttons';
import { Link } from '@@/Link';
import { ButtonWithRef } from '@@/buttons/Button';
import { useRepeater } from '@@/datatables/useRepeater';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { DockerImage } from '../../types';
import { ImagesListResponse, useImages } from '../../queries/useImages';
import { columns as defColumns } from './columns';
import { host as hostColumn } from './columns/host';
import { RowProvider } from './RowContext';
const tableKey = 'images';
@ -48,76 +46,67 @@ const settingsStore = createPersistedStore<TableSettings>(
);
export function ImagesDatatable({
dataset,
environment,
isHostColumnVisible,
isExportInProgress,
onDownload,
onRefresh,
onRemove,
}: {
dataset: Array<DockerImage>;
environment: Environment;
isHostColumnVisible: boolean;
onDownload: (images: Array<DockerImage>) => void;
onRemove: (images: Array<DockerImage>, force: true) => void;
onRefresh: () => Promise<void>;
onDownload: (images: Array<ImagesListResponse>) => void;
onRemove: (images: Array<ImagesListResponse>, force: true) => void;
isExportInProgress: boolean;
}) {
const environmentId = useEnvironmentId();
const tableState = useTableState(settingsStore, tableKey);
const columns = useMemo(
() => (isHostColumnVisible ? [...defColumns, hostColumn] : defColumns),
[isHostColumnVisible]
);
useRepeater(tableState.autoRefreshRate, onRefresh);
const imagesQuery = useImages(environmentId, true, {
refetchInterval: tableState.autoRefreshRate * 1000,
});
return (
<RowProvider context={{ environment }}>
<Datatable
title="Images"
titleIcon={List}
renderTableActions={(selectedItems) => (
<div className="flex items-center gap-2">
<RemoveButtonMenu
selectedItems={selectedItems}
onRemove={onRemove}
/>
<Datatable
title="Images"
titleIcon={List}
renderTableActions={(selectedItems) => (
<div className="flex items-center gap-2">
<RemoveButtonMenu selectedItems={selectedItems} onRemove={onRemove} />
<ImportExportButtons
isExportInProgress={isExportInProgress}
onExportClick={onDownload}
selectedItems={selectedItems}
/>
<ImportExportButtons
isExportInProgress={isExportInProgress}
onExportClick={onDownload}
selectedItems={selectedItems}
/>
<Authorized authorizations="DockerImageBuild">
<Button
as={Link}
props={{ to: 'docker.images.build' }}
data-cy="image-buildImageButton"
icon={Plus}
>
Build a new image
</Button>
</Authorized>
</div>
)}
dataset={dataset}
settingsManager={tableState}
columns={columns}
emptyContentLabel="No images found"
renderTableSettings={() => (
<TableSettingsMenu>
<TableSettingsMenuAutoRefresh
value={tableState.autoRefreshRate}
onChange={(value) => tableState.setAutoRefreshRate(value)}
/>
</TableSettingsMenu>
)}
/>
</RowProvider>
<Authorized authorizations="DockerImageBuild">
<Button
as={Link}
props={{ to: 'docker.images.build' }}
data-cy="image-buildImageButton"
icon={Plus}
>
Build a new image
</Button>
</Authorized>
</div>
)}
dataset={imagesQuery.data || []}
isLoading={imagesQuery.isLoading}
settingsManager={tableState}
columns={columns}
emptyContentLabel="No images found"
renderTableSettings={() => (
<TableSettingsMenu>
<TableSettingsMenuAutoRefresh
value={tableState.autoRefreshRate}
onChange={(value) => tableState.setAutoRefreshRate(value)}
/>
</TableSettingsMenu>
)}
/>
);
}
@ -125,8 +114,8 @@ function RemoveButtonMenu({
onRemove,
selectedItems,
}: {
selectedItems: Array<DockerImage>;
onRemove(selectedItems: Array<DockerImage>, force: boolean): void;
selectedItems: Array<ImagesListResponse>;
onRemove(selectedItems: Array<ImagesListResponse>, force: boolean): void;
}) {
return (
<Authorized authorizations="DockerImageDelete">
@ -176,8 +165,8 @@ function ImportExportButtons({
onExportClick,
}: {
isExportInProgress: boolean;
selectedItems: Array<DockerImage>;
onExportClick(selectedItems: Array<DockerImage>): void;
selectedItems: Array<ImagesListResponse>;
onExportClick(selectedItems: Array<ImagesListResponse>): void;
}) {
return (
<ButtonGroup>

View file

@ -1,11 +0,0 @@
import { Environment } from '@/react/portainer/environments/types';
import { createRowContext } from '@@/datatables/RowContext';
interface RowContextState {
environment: Environment;
}
const { RowProvider, useRowContext } = createRowContext<RowContextState>();
export { RowProvider, useRowContext };

View file

@ -2,7 +2,7 @@ import { isoDateFromTimestamp } from '@/portainer/filters/filters';
import { columnHelper } from './helper';
export const created = columnHelper.accessor('Created', {
export const created = columnHelper.accessor('created', {
id: 'created',
header: 'Created',
cell: ({ getValue }) => {

View file

@ -1,16 +1,5 @@
import { createColumnHelper } from '@tanstack/react-table';
import { DockerImage } from '@/react/docker/images/types';
import { ImagesListResponse } from '@/react/docker/images/queries/useImages';
export const columnHelper = createColumnHelper<
DockerImage & { NodeName?: string }
>();
/**
* Docker response from proxy (with added portainer metadata)
* images view model
* images snapshot
* snapshots view model
*
*
*/
export const columnHelper = createColumnHelper<ImagesListResponse>();

View file

@ -1,6 +1,6 @@
import { columnHelper } from './helper';
export const host = columnHelper.accessor('NodeName', {
export const host = columnHelper.accessor('nodeName', {
header: 'Host',
cell: ({ getValue }) => {
const value = getValue();

View file

@ -1,21 +1,21 @@
import { CellContext, Column } from '@tanstack/react-table';
import { useSref } from '@uirouter/react';
import { DockerImage } from '@/react/docker/images/types';
import { truncate } from '@/portainer/filters/filters';
import { getValueAsArrayOfStrings } from '@/portainer/helpers/array';
import { ImagesListResponse } from '@/react/docker/images/queries/useImages';
import { MultipleSelectionFilter } from '@@/datatables/Filter';
import { columnHelper } from './helper';
export const id = columnHelper.accessor('Id', {
export const id = columnHelper.accessor('id', {
id: 'id',
header: 'Id',
cell: Cell,
enableColumnFilter: true,
filterFn: (
{ original: { Used } },
{ original: { used } },
columnId,
filterValue: Array<'Used' | 'Unused'>
) => {
@ -23,11 +23,11 @@ export const id = columnHelper.accessor('Id', {
return true;
}
if (filterValue.includes('Used') && Used) {
if (filterValue.includes('Used') && used) {
return true;
}
if (filterValue.includes('Unused') && !Used) {
if (filterValue.includes('Unused') && !used) {
return true;
}
@ -63,12 +63,12 @@ function FilterByUsage<TData extends { Used: boolean }>({
function Cell({
getValue,
row: { original: image },
}: CellContext<DockerImage, string>) {
}: CellContext<ImagesListResponse, string>) {
const name = getValue();
const linkProps = useSref('.image', {
id: image.Id,
imageId: image.Id,
id: image.id,
imageId: image.id,
});
return (
@ -76,7 +76,7 @@ function Cell({
<a href={linkProps.href} onClick={linkProps.onClick} title={name}>
{truncate(name, 40)}
</a>
{!image.Used && (
{!image.used && (
<span className="label label-warning image-tag ml-2">Unused</span>
)}
</>

View file

@ -2,7 +2,7 @@ import { humanize } from '@/portainer/filters/filters';
import { columnHelper } from './helper';
export const size = columnHelper.accessor('VirtualSize', {
export const size = columnHelper.accessor('size', {
id: 'size',
header: 'Size',
cell: ({ getValue }) => {

View file

@ -1,16 +1,16 @@
import { CellContext } from '@tanstack/react-table';
import { DockerImage } from '@/react/docker/images/types';
import { ImagesListResponse } from '@/react/docker/images/queries/useImages';
import { columnHelper } from './helper';
export const tags = columnHelper.accessor('RepoTags', {
export const tags = columnHelper.accessor('tags', {
id: 'tags',
header: 'Tags',
cell: Cell,
});
function Cell({ getValue }: CellContext<DockerImage, string[]>) {
function Cell({ getValue }: CellContext<ImagesListResponse, string[]>) {
const repoTags = getValue();
return (