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

refactor(tables): use add and delete buttons [EE-6297] (#10668)

Co-authored-by: Chaim Lev-Ari <chaim.levi-ari@portaienr.io>
This commit is contained in:
Chaim Lev-Ari 2024-04-08 17:21:41 +03:00 committed by GitHub
parent d88ef03ddb
commit 9600eb6fa1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 369 additions and 727 deletions

View file

@ -1,13 +1,13 @@
import { Clipboard, Plus, Trash2 } from 'lucide-react';
import { Clipboard } from 'lucide-react';
import { Authorized, useAuthorizations } from '@/react/hooks/useUser';
import { Datatable, TableSettingsMenu } from '@@/datatables';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useRepeater } from '@@/datatables/useRepeater';
import { Button } from '@@/buttons';
import { Link } from '@@/Link';
import { AddButton } from '@@/buttons';
import { useTableState } from '@@/datatables/useTableState';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { DockerConfig } from '../../types';
@ -17,7 +17,7 @@ import { createStore } from './store';
interface Props {
dataset: Array<DockerConfig>;
onRemoveClick: (configs: Array<DockerConfig>) => void;
onRefresh: () => Promise<void>;
onRefresh: () => void;
}
const storageKey = 'docker_configs';
@ -54,24 +54,15 @@ export function ConfigsDatatable({ dataset, onRefresh, onRemoveClick }: Props) {
hasWriteAccessQuery.authorized && (
<div className="flex items-center gap-3">
<Authorized authorizations="DockerConfigDelete">
<Button
icon={Trash2}
color="dangerlight"
onClick={() => onRemoveClick(selectedRows)}
<DeleteButton
disabled={selectedRows.length === 0}
>
Remove
</Button>
onConfirmed={() => onRemoveClick(selectedRows)}
confirmMessage="Do you want to remove the selected config(s)?"
/>
</Authorized>
<Authorized authorizations="DockerConfigCreate">
<Button
icon={Plus}
as={Link}
props={{ to: 'docker.configs.new' }}
>
Add config
</Button>
<AddButton>Add config</AddButton>
</Authorized>
</div>
)

View file

@ -1,13 +1,5 @@
import { useRouter } from '@uirouter/react';
import {
Pause,
Play,
Plus,
RefreshCw,
Slash,
Square,
Trash2,
} from 'lucide-react';
import { Pause, Play, RefreshCw, Slash, Square, Trash2 } from 'lucide-react';
import * as notifications from '@/portainer/services/notifications';
import { useAuthorizations, Authorized } from '@/react/hooks/useUser';
@ -29,8 +21,7 @@ import {
} from '@/react/docker/containers/containers.service';
import type { EnvironmentId } from '@/react/portainer/environments/types';
import { Link } from '@@/Link';
import { ButtonGroup, Button } from '@@/buttons';
import { ButtonGroup, Button, AddButton } from '@@/buttons';
type ContainerServiceAction = (
endpointId: EnvironmentId,
@ -166,11 +157,11 @@ export function ContainersDatatableActions({
</Authorized>
</ButtonGroup>
{isAddActionVisible && (
<Authorized authorizations="DockerContainerCreate">
<Link to="docker.containers.new" className="space-left">
<Button icon={Plus}>Add container</Button>
</Link>
</Authorized>
<div className="space-left">
<Authorized authorizations="DockerContainerCreate">
<AddButton>Add container</AddButton>
</Authorized>
</div>
)}
</div>
);

View file

@ -1,11 +1,4 @@
import {
ChevronDown,
Download,
List,
Plus,
Trash2,
Upload,
} from 'lucide-react';
import { ChevronDown, Download, List, Trash2, Upload } from 'lucide-react';
import { Menu, MenuButton, MenuItem, MenuPopover } from '@reach/menu-button';
import { positionRight } from '@reach/popover';
import { useMemo } from 'react';
@ -21,7 +14,7 @@ import {
RefreshableTableSettings,
} from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import { Button, ButtonGroup, LoadingButton } from '@@/buttons';
import { AddButton, Button, ButtonGroup, LoadingButton } from '@@/buttons';
import { Link } from '@@/Link';
import { ButtonWithRef } from '@@/buttons/Button';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
@ -82,14 +75,12 @@ export function ImagesDatatable({
/>
<Authorized authorizations="DockerImageBuild">
<Button
as={Link}
props={{ to: 'docker.images.build' }}
<AddButton
to="docker.images.build"
data-cy="image-buildImageButton"
icon={Plus}
>
Build a new image
</Button>
</AddButton>
</Authorized>
</div>
)}

View file

@ -8,7 +8,6 @@ import { DockerContainer } from '@/react/docker/containers/types';
import { ResourceControlViewModel } from '@/react/portainer/access-control/models/ResourceControlViewModel';
import { useContainers } from '@/react/docker/containers/queries/containers';
import { confirmDelete } from '@@/modals/confirm';
import { PageHeader } from '@@/PageHeader';
import { useNetwork, useDeleteNetwork } from '../queries';
@ -95,19 +94,14 @@ export function ItemView() {
);
async function onRemoveNetworkClicked() {
const message = 'Do you want to delete the network?';
const confirmed = await confirmDelete(message);
if (confirmed) {
deleteNetworkMutation.mutate(
{ environmentId, networkId },
{
onSuccess: () => {
router.stateService.go('docker.networks');
},
}
);
}
deleteNetworkMutation.mutate(
{ environmentId, networkId },
{
onSuccess: () => {
router.stateService.go('docker.networks');
},
}
);
}
}

View file

@ -1,13 +1,12 @@
import { Fragment } from 'react';
import { Network, Trash2 } from 'lucide-react';
import { Network } from 'lucide-react';
import DockerNetworkHelper from '@/docker/helpers/networkHelper';
import { Authorized } from '@/react/hooks/useUser';
import { TableContainer, TableTitle } from '@@/datatables';
import { DetailsTable } from '@@/DetailsTable';
import { Button } from '@@/buttons';
import { Icon } from '@@/Icon';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { isSystemNetwork } from '../network.helper';
import { DockerNetwork, IPConfig } from '../types';
@ -38,21 +37,18 @@ export function NetworkDetailsTable({
<DetailsTable.Row label="Id">
{network.Id}
{allowRemoveNetwork && (
<Authorized authorizations="DockerNetworkDelete">
<Button
data-cy="networkDetails-deleteNetwork"
size="xsmall"
color="danger"
onClick={() => onRemoveNetworkClicked()}
>
<Icon
icon={Trash2}
className="space-right"
aria-hidden="true"
/>
Delete this network
</Button>
</Authorized>
<span className="ml-2">
<Authorized authorizations="DockerNetworkDelete">
<DeleteButton
data-cy="networkDetails-deleteNetwork"
size="xsmall"
onConfirmed={onRemoveNetworkClicked}
confirmMessage="Do you want to delete the network?"
>
Delete this network
</DeleteButton>
</Authorized>
</span>
)}
</DetailsTable.Row>
<DetailsTable.Row label="Driver">{network.Driver}</DetailsTable.Row>

View file

@ -1,4 +1,4 @@
import { Plus, Network, Trash2 } from 'lucide-react';
import { Network } from 'lucide-react';
import { Authorized } from '@/react/hooks/useUser';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
@ -10,12 +10,12 @@ import {
refreshableSettings,
RefreshableTableSettings,
} from '@@/datatables/types';
import { Button } from '@@/buttons';
import { AddButton } from '@@/buttons';
import { TableSettingsMenu } from '@@/datatables';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useRepeater } from '@@/datatables/useRepeater';
import { useTableState } from '@@/datatables/useTableState';
import { Link } from '@@/Link';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { useIsSwarm } from '../../proxy/queries/useInfo';
@ -80,22 +80,16 @@ export function NetworksDatatable({ dataset, onRemove, onRefresh }: Props) {
<Authorized
authorizations={['DockerNetworkDelete', 'DockerNetworkCreate']}
>
<Button
<DeleteButton
disabled={selectedRows.length === 0}
color="dangerlight"
onClick={() => onRemove(selectedRows)}
icon={Trash2}
>
Remove
</Button>
confirmMessage="Do you want to remove the selected network(s)?"
onConfirmed={() => onRemove(selectedRows)}
/>
</Authorized>
<Authorized
authorizations="DockerNetworkCreate"
data-cy="network-addNetworkButton"
>
<Button icon={Plus} as={Link} props={{ to: '.new' }}>
<Authorized authorizations="DockerNetworkCreate">
<AddButton data-cy="network-addNetworkButton">
Add network
</Button>
</AddButton>
</Authorized>
</div>
)}

View file

@ -1,5 +1,5 @@
import { createColumnHelper } from '@tanstack/react-table';
import { Lock, Plus, Trash2 } from 'lucide-react';
import { Lock } from 'lucide-react';
import { SecretViewModel } from '@/docker/models/secret';
import { isoDate } from '@/portainer/filters/filters';
@ -15,9 +15,9 @@ import {
} from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { Button } from '@@/buttons';
import { Link } from '@@/Link';
import { AddButton } from '@@/buttons';
import { useRepeater } from '@@/datatables/useRepeater';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { createOwnershipColumn } from '../../components/datatable/createOwnershipColumn';
@ -96,28 +96,16 @@ function TableActions({
return (
<div className="flex items-center gap-2">
<Authorized authorizations="DockerSecretDelete">
<Button
color="dangerlight"
<DeleteButton
disabled={selectedItems.length === 0}
onClick={() => onRemove(selectedItems)}
icon={Trash2}
className="!m-0"
onConfirmed={() => onRemove(selectedItems)}
confirmMessage="Do you want to remove the selected secret(s)?"
data-cy="secret-removeSecretButton"
>
Remove
</Button>
/>
</Authorized>
<Authorized authorizations="DockerSecretCreate">
<Button
as={Link}
props={{ to: '.new' }}
icon={Plus}
className="!m-0"
data-cy="secret-addSecretButton"
>
Add secret
</Button>
<AddButton data-cy="secret-addSecretButton">Add secret</AddButton>
</Authorized>
</div>
);

View file

@ -1,4 +1,4 @@
import { Trash2, Plus, RefreshCw } from 'lucide-react';
import { RefreshCw } from 'lucide-react';
import { useRouter } from '@uirouter/react';
import { ServiceViewModel } from '@/docker/models/service';
@ -6,9 +6,8 @@ import { Authorized } from '@/react/hooks/useUser';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { notifySuccess } from '@/portainer/services/notifications';
import { Link } from '@@/Link';
import { Button, ButtonGroup } from '@@/buttons';
import { confirmDelete } from '@@/modals/confirm';
import { AddButton, Button, ButtonGroup } from '@@/buttons';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { confirmServiceForceUpdate } from '../../common/update-service-modal';
@ -46,28 +45,18 @@ export function TableActions({
</Authorized>
)}
<Authorized authorizations="DockerServiceDelete">
<Button
color="dangerlight"
<DeleteButton
disabled={selectedItems.length === 0}
onClick={() => handleRemove(selectedItems)}
icon={Trash2}
onConfirmed={() => handleRemove(selectedItems)}
confirmMessage="Do you want to remove the selected service(s)? All the containers associated to the selected service(s) will be removed too."
data-cy="service-removeServiceButton"
>
Remove
</Button>
/>
</Authorized>
</ButtonGroup>
{isAddActionVisible && (
<Authorized authorizations="DockerServiceCreate">
<Button
as={Link}
props={{ to: '.new' }}
icon={Plus}
className="!ml-0"
>
Add service
</Button>
<AddButton>Add service</AddButton>
</Authorized>
)}
</div>
@ -97,14 +86,6 @@ export function TableActions({
}
async function handleRemove(selectedItems: Array<ServiceViewModel>) {
const confirmed = await confirmDelete(
'Do you want to remove the selected service(s)? All the containers associated to the selected service(s) will be removed too.'
);
if (!confirmed) {
return;
}
removeMutation.mutate(
selectedItems.map((service) => service.Id),
{

View file

@ -1,9 +1,7 @@
import { Trash2, Plus } from 'lucide-react';
import { Authorized } from '@/react/hooks/useUser';
import { Link } from '@@/Link';
import { Button } from '@@/buttons';
import { AddButton } from '@@/buttons';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { DecoratedStack } from './types';
@ -17,28 +15,18 @@ export function TableActions({
return (
<div className="flex items-center gap-2">
<Authorized authorizations="PortainerStackDelete">
<Button
color="dangerlight"
<DeleteButton
disabled={selectedItems.length === 0}
onClick={() => onRemove(selectedItems)}
icon={Trash2}
className="!m-0"
onConfirmed={() => onRemove(selectedItems)}
confirmMessage="Do you want to remove the selected stack(s)? Associated services will be removed as well."
data-cy="stack-removeStackButton"
>
Remove
</Button>
/>
</Authorized>
<Authorized authorizations="PortainerStackCreate">
<Button
as={Link}
props={{ to: '.newstack' }}
icon={Plus}
className="!m-0"
data-cy="stack-addStackButton"
>
<AddButton data-cy="stack-addStackButton" to=".newstack">
Add stack
</Button>
</AddButton>
</Authorized>
</div>
);

View file

@ -1,9 +1,7 @@
import { Plus, Trash2 } from 'lucide-react';
import { Authorized } from '@/react/hooks/useUser';
import { Link } from '@@/Link';
import { Button } from '@@/buttons';
import { AddButton } from '@@/buttons';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { DecoratedVolume } from '../types';
@ -17,27 +15,15 @@ export function TableActions({
return (
<div className="flex items-center gap-2">
<Authorized authorizations="DockerVolumeDelete">
<Button
color="dangerlight"
<DeleteButton
disabled={selectedItems.length === 0}
onClick={() => onRemove(selectedItems)}
icon={Trash2}
className="!m-0"
onConfirmed={() => onRemove(selectedItems)}
confirmMessage="Do you want to remove the selected volume(s)?"
data-cy="volume-removeVolumeButton"
>
Remove
</Button>
/>
</Authorized>
<Authorized authorizations="DockerVolumeCreate">
<Button
as={Link}
props={{ to: '.new' }}
icon={Plus}
className="!m-0"
data-cy="volume-addVolumeButton"
>
Add volume
</Button>
<AddButton data-cy="volume-addVolumeButton">Add volume</AddButton>
</Authorized>
</div>
);