Fix snapshot mode should not be editable
Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
167
apps/console/src/components/assets/AssetsTable.tsx
Normal file
167
apps/console/src/components/assets/AssetsTable.tsx
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
import { getAssetTypeVariant, promisifyMutation, sprintf } from "@probo/helpers";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { ActionDropdown, Badge, DropdownItem, IconPencil, IconTrashCan, SelectCell, TextCell, useConfirm } from "@probo/ui";
|
||||||
|
import { useMutation } from "react-relay";
|
||||||
|
import type { usePaginationFragmentHookType } from "react-relay/relay-hooks/usePaginationFragment";
|
||||||
|
import { Link } from "react-router";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { EditableTable } from "../table/EditableTable";
|
||||||
|
import { PeopleCell } from "../table/PeopleCell";
|
||||||
|
import { VendorsCell } from "../table/VendorsCell";
|
||||||
|
import { createAssetMutation, deleteAssetMutation, updateAssetMutation } from "/hooks/graph/AssetGraph";
|
||||||
|
import type { AssetGraphDeleteMutation } from "/hooks/graph/__generated__/AssetGraphDeleteMutation.graphql";
|
||||||
|
import type { AssetsPageFragment$data, AssetsPageFragment$key } from "/pages/organizations/assets/__generated__/AssetsPageFragment.graphql";
|
||||||
|
import type { OperationType } from "relay-runtime";
|
||||||
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
connectionId: string;
|
||||||
|
pagination: usePaginationFragmentHookType<
|
||||||
|
OperationType,
|
||||||
|
AssetsPageFragment$key,
|
||||||
|
AssetsPageFragment$data
|
||||||
|
>;
|
||||||
|
assets: AssetsPageFragment$data["assets"]["edges"][0]["node"][];
|
||||||
|
hasAnyAction: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
name: z.string().trim().min(1, "Name is required"),
|
||||||
|
amount: z.coerce.number().min(1, "Amount is required"),
|
||||||
|
assetType: z.enum(["PHYSICAL", "VIRTUAL"]),
|
||||||
|
ownerId: z.string().trim().min(1, "Owner is required"),
|
||||||
|
vendorIds: z.array(z.string()).optional(),
|
||||||
|
dataTypesStored: z.string().trim().min(1, "Data types stored is required"),
|
||||||
|
organizationId: z.string().trim().min(1, "Organization is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultValue = {
|
||||||
|
name: "",
|
||||||
|
amount: 0,
|
||||||
|
assetType: "VIRTUAL",
|
||||||
|
ownerId: "",
|
||||||
|
vendorIds: [],
|
||||||
|
dataTypesStored: "",
|
||||||
|
organizationId: "",
|
||||||
|
} satisfies z.infer<typeof schema>;
|
||||||
|
|
||||||
|
export function AssetsTable(props: Props) {
|
||||||
|
const { connectionId, pagination, assets, hasAnyAction } = props;
|
||||||
|
|
||||||
|
const organizationId = useOrganizationId();
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const deleteAsset = useDeleteAsset(connectionId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditableTable
|
||||||
|
connectionId={connectionId}
|
||||||
|
pagination={pagination}
|
||||||
|
items={assets}
|
||||||
|
columns={[
|
||||||
|
__("Name"),
|
||||||
|
__("Type"),
|
||||||
|
__("Data Types stored"),
|
||||||
|
__("Amount"),
|
||||||
|
__("Owner"),
|
||||||
|
__("Vendors"),
|
||||||
|
]}
|
||||||
|
schema={schema}
|
||||||
|
updateMutation={updateAssetMutation}
|
||||||
|
createMutation={createAssetMutation}
|
||||||
|
addLabel={__("Add a new asset")}
|
||||||
|
defaultValue={{
|
||||||
|
...defaultValue,
|
||||||
|
organizationId,
|
||||||
|
}}
|
||||||
|
action={({ item }) =>
|
||||||
|
hasAnyAction ? (
|
||||||
|
<ActionDropdown>
|
||||||
|
<DropdownItem asChild>
|
||||||
|
<Link to={`/organizations/${organizationId}/assets/${item.id}`}>
|
||||||
|
<IconPencil size={16} />
|
||||||
|
{__("Edit")}
|
||||||
|
</Link>
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
onClick={() => deleteAsset(item)}
|
||||||
|
variant="danger"
|
||||||
|
icon={IconTrashCan}
|
||||||
|
>
|
||||||
|
{__("Delete")}
|
||||||
|
</DropdownItem>
|
||||||
|
</ActionDropdown>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
row={({ item }) => (
|
||||||
|
<>
|
||||||
|
<TextCell name="name" defaultValue={item?.name ?? ""} required />
|
||||||
|
<SelectCell
|
||||||
|
name="assetType"
|
||||||
|
items={["VIRTUAL", "PHYSICAL"]}
|
||||||
|
itemRenderer={({ item }) => (
|
||||||
|
<Badge variant={getAssetTypeVariant(item ?? "VIRTUAL")}>
|
||||||
|
{item === "PHYSICAL" ? __("Physical") : __("Virtual")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
defaultValue={item?.assetType ?? defaultValue.assetType}
|
||||||
|
/>
|
||||||
|
<TextCell
|
||||||
|
name="dataTypesStored"
|
||||||
|
defaultValue={
|
||||||
|
item?.dataTypesStored ?? defaultValue.dataTypesStored
|
||||||
|
}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<TextCell
|
||||||
|
name="amount"
|
||||||
|
defaultValue={(item?.amount ?? defaultValue.amount).toString()}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<PeopleCell
|
||||||
|
name="ownerId"
|
||||||
|
defaultValue={item?.owner}
|
||||||
|
organizationId={organizationId}
|
||||||
|
/>
|
||||||
|
<VendorsCell
|
||||||
|
name="vendorIds"
|
||||||
|
organizationId={organizationId}
|
||||||
|
defaultValue={
|
||||||
|
item?.vendors?.edges?.map((edge) => edge.node) ?? []
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const useDeleteAsset = (connectionId: string) => {
|
||||||
|
const [mutate] = useMutation<AssetGraphDeleteMutation>(deleteAssetMutation);
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
return (asset: { id: string; name: string }) => {
|
||||||
|
if (!asset.id || !asset.name) {
|
||||||
|
return alert(__("Failed to delete asset: missing id or name"));
|
||||||
|
}
|
||||||
|
confirm(
|
||||||
|
() =>
|
||||||
|
promisifyMutation(mutate)({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
assetId: asset.id!,
|
||||||
|
},
|
||||||
|
connections: [connectionId],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
message: sprintf(
|
||||||
|
__(
|
||||||
|
'This will permanently delete "%s". This action cannot be undone.',
|
||||||
|
),
|
||||||
|
asset.name,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
99
apps/console/src/components/assets/SnapshotAssetsTable.tsx
Normal file
99
apps/console/src/components/assets/SnapshotAssetsTable.tsx
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { Avatar, Badge, Tbody, Td, Th, Thead, Tr } from "@probo/ui";
|
||||||
|
import { SortableTable } from "../SortableTable";
|
||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import type { usePaginationFragmentHookType } from "react-relay/relay-hooks/usePaginationFragment";
|
||||||
|
import type { AssetsPageFragment$data, AssetsPageFragment$key } from "/pages/organizations/assets/__generated__/AssetsPageFragment.graphql";
|
||||||
|
import type { OperationType } from "relay-runtime";
|
||||||
|
import type { NodeOf } from "/types";
|
||||||
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
|
import { useParams } from "react-router";
|
||||||
|
import { faviconUrl, getAssetTypeVariant } from "@probo/helpers";
|
||||||
|
|
||||||
|
type AssetEntry = NodeOf<AssetsPageFragment$data["assets"]>;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
pagination: usePaginationFragmentHookType<
|
||||||
|
OperationType,
|
||||||
|
AssetsPageFragment$key,
|
||||||
|
AssetsPageFragment$data
|
||||||
|
>;
|
||||||
|
assets: AssetEntry[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SnapshotAssetsTable(props: Props) {
|
||||||
|
const { pagination, assets } = props;
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SortableTable {...pagination}>
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>{__("Name")}</Th>
|
||||||
|
<Th>{__("Type")}</Th>
|
||||||
|
<Th>{__("Amount")}</Th>
|
||||||
|
<Th>{__("Owner")}</Th>
|
||||||
|
<Th>{__("Vendors")}</Th>
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{assets.map((entry) => (
|
||||||
|
<AssetRow
|
||||||
|
key={entry.id}
|
||||||
|
entry={entry}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
</SortableTable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AssetRow({
|
||||||
|
entry,
|
||||||
|
}: {
|
||||||
|
entry: AssetEntry;
|
||||||
|
}) {
|
||||||
|
const organizationId = useOrganizationId();
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
|
const vendors = entry.vendors?.edges.map((edge) => edge.node) ?? [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tr to={`/organizations/${organizationId}/snapshots/${snapshotId}/assets/${entry.id}`}>
|
||||||
|
<Td>{entry.name}</Td>
|
||||||
|
<Td>
|
||||||
|
<Badge variant={getAssetTypeVariant(entry.assetType)}>
|
||||||
|
{entry.assetType === "PHYSICAL" ? __("Physical") : __("Virtual")}
|
||||||
|
</Badge>
|
||||||
|
</Td>
|
||||||
|
<Td>{entry.amount}</Td>
|
||||||
|
<Td>{entry.owner?.fullName ?? __("Unassigned")}</Td>
|
||||||
|
<Td>
|
||||||
|
{vendors.length > 0 ? (
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
|
{vendors.slice(0, 3).map((vendor) => (
|
||||||
|
<Badge
|
||||||
|
key={vendor.id}
|
||||||
|
variant="neutral"
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
name={vendor.name}
|
||||||
|
src={faviconUrl(vendor.websiteUrl)}
|
||||||
|
size="s"
|
||||||
|
/>
|
||||||
|
<span className="text-xs">{vendor.name}</span>
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
{vendors.length > 3 && (
|
||||||
|
<Badge variant="neutral" className="text-xs">
|
||||||
|
+{vendors.length - 3}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<span className="text-txt-secondary text-sm">{__("None")}</span>
|
||||||
|
)}
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,47 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
ActionDropdown,
|
|
||||||
Badge,
|
|
||||||
Button,
|
Button,
|
||||||
DropdownItem,
|
|
||||||
IconPencil,
|
|
||||||
IconPlusLarge,
|
IconPlusLarge,
|
||||||
IconTrashCan,
|
|
||||||
PageHeader,
|
PageHeader,
|
||||||
SelectCell,
|
|
||||||
TextCell,
|
|
||||||
useConfirm,
|
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { usePageTitle } from "@probo/hooks";
|
import { usePageTitle } from "@probo/hooks";
|
||||||
import {
|
import {
|
||||||
graphql,
|
graphql,
|
||||||
type PreloadedQuery,
|
type PreloadedQuery,
|
||||||
useMutation,
|
|
||||||
usePaginationFragment,
|
usePaginationFragment,
|
||||||
usePreloadedQuery,
|
usePreloadedQuery,
|
||||||
} from "react-relay";
|
} from "react-relay";
|
||||||
import { useOrganizationId } from "/hooks/useOrganizationId";
|
import { useOrganizationId } from "/hooks/useOrganizationId";
|
||||||
import { Link, useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
import {
|
import {
|
||||||
assetsQuery,
|
assetsQuery,
|
||||||
createAssetMutation,
|
|
||||||
deleteAssetMutation,
|
|
||||||
updateAssetMutation,
|
|
||||||
} from "/hooks/graph/AssetGraph";
|
} from "/hooks/graph/AssetGraph";
|
||||||
import type { AssetGraphListQuery } from "/hooks/graph/__generated__/AssetGraphListQuery.graphql";
|
import type { AssetGraphListQuery } from "/hooks/graph/__generated__/AssetGraphListQuery.graphql";
|
||||||
import {
|
|
||||||
getAssetTypeVariant,
|
|
||||||
promisifyMutation,
|
|
||||||
sprintf,
|
|
||||||
} from "@probo/helpers";
|
|
||||||
import type { AssetsPageFragment$key } from "./__generated__/AssetsPageFragment.graphql";
|
import type { AssetsPageFragment$key } from "./__generated__/AssetsPageFragment.graphql";
|
||||||
import { SnapshotBanner } from "/components/SnapshotBanner";
|
import { SnapshotBanner } from "/components/SnapshotBanner";
|
||||||
import z from "zod";
|
|
||||||
import { EditableTable } from "/components/table/EditableTable.tsx";
|
|
||||||
import { PeopleCell } from "/components/table/PeopleCell.tsx";
|
|
||||||
import { VendorsCell } from "/components/table/VendorsCell.tsx";
|
|
||||||
import { CreateAssetDialog } from "./dialogs/CreateAssetDialog";
|
import { CreateAssetDialog } from "./dialogs/CreateAssetDialog";
|
||||||
import { Authorized, isAuthorized } from "/permissions";
|
import { Authorized, isAuthorized } from "/permissions";
|
||||||
|
import { AssetsTable } from "../../../components/assets/AssetsTable";
|
||||||
|
import { SnapshotAssetsTable } from "/components/assets/SnapshotAssetsTable";
|
||||||
|
|
||||||
const paginatedAssetsFragment = graphql`
|
const paginatedAssetsFragment = graphql`
|
||||||
fragment AssetsPageFragment on Organization
|
fragment AssetsPageFragment on Organization
|
||||||
@@ -95,45 +76,19 @@ type Props = {
|
|||||||
queryRef: PreloadedQuery<AssetGraphListQuery>;
|
queryRef: PreloadedQuery<AssetGraphListQuery>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = z.object({
|
|
||||||
name: z.string().trim().min(1, "Name is required"),
|
|
||||||
amount: z.coerce.number().min(1, "Amount is required"),
|
|
||||||
assetType: z.enum(["PHYSICAL", "VIRTUAL"]),
|
|
||||||
ownerId: z.string().trim().min(1, "Owner is required"),
|
|
||||||
vendorIds: z.array(z.string()).optional(),
|
|
||||||
dataTypesStored: z.string().trim().min(1, "Data types stored is required"),
|
|
||||||
organizationId: z.string().trim().min(1, "Organization is required"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const defaultValue = {
|
|
||||||
name: "",
|
|
||||||
amount: 0,
|
|
||||||
assetType: "VIRTUAL",
|
|
||||||
ownerId: "",
|
|
||||||
vendorIds: [],
|
|
||||||
dataTypesStored: "",
|
|
||||||
organizationId: "",
|
|
||||||
} satisfies z.infer<typeof schema>;
|
|
||||||
|
|
||||||
export default function AssetsPage(props: Props) {
|
export default function AssetsPage(props: Props) {
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const organizationId = useOrganizationId();
|
const organizationId = useOrganizationId();
|
||||||
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
const { snapshotId } = useParams<{ snapshotId?: string }>();
|
||||||
const isSnapshotMode = Boolean(snapshotId);
|
const isSnapshotMode = Boolean(snapshotId);
|
||||||
|
|
||||||
const assetUrl = (entry: { id: string }) =>
|
const data = usePreloadedQuery<AssetGraphListQuery>(assetsQuery, props.queryRef);
|
||||||
isSnapshotMode && snapshotId
|
|
||||||
? `/organizations/${organizationId}/snapshots/${snapshotId}/assets/${entry.id}`
|
|
||||||
: `/organizations/${organizationId}/assets/${entry.id}`;
|
|
||||||
|
|
||||||
const data = usePreloadedQuery(assetsQuery, props.queryRef);
|
|
||||||
const pagination = usePaginationFragment(
|
const pagination = usePaginationFragment(
|
||||||
paginatedAssetsFragment,
|
paginatedAssetsFragment,
|
||||||
data.node as AssetsPageFragment$key,
|
data.node as AssetsPageFragment$key,
|
||||||
);
|
);
|
||||||
const assets = pagination.data.assets?.edges.map((edge) => edge.node);
|
const assets = pagination.data.assets?.edges.map((edge) => edge.node);
|
||||||
const connectionId = pagination.data.assets.__id;
|
const connectionId = pagination.data.assets.__id;
|
||||||
const deleteAsset = useDeleteAsset(connectionId);
|
|
||||||
|
|
||||||
const hasAnyAction =
|
const hasAnyAction =
|
||||||
!isSnapshotMode &&
|
!isSnapshotMode &&
|
||||||
@@ -161,116 +116,16 @@ export default function AssetsPage(props: Props) {
|
|||||||
</Authorized>
|
</Authorized>
|
||||||
)}
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<EditableTable
|
{isSnapshotMode ?
|
||||||
connectionId={connectionId}
|
<SnapshotAssetsTable pagination={pagination} assets={assets} />
|
||||||
pagination={pagination}
|
:
|
||||||
items={assets}
|
<AssetsTable
|
||||||
columns={[
|
connectionId={connectionId}
|
||||||
__("Name"),
|
pagination={pagination}
|
||||||
__("Type"),
|
assets={assets}
|
||||||
__("Data Types stored"),
|
hasAnyAction={hasAnyAction}
|
||||||
__("Amount"),
|
/>
|
||||||
__("Owner"),
|
}
|
||||||
__("Vendors"),
|
|
||||||
]}
|
|
||||||
schema={schema}
|
|
||||||
updateMutation={updateAssetMutation}
|
|
||||||
createMutation={createAssetMutation}
|
|
||||||
addLabel={__("Add a new asset")}
|
|
||||||
defaultValue={{
|
|
||||||
...defaultValue,
|
|
||||||
organizationId,
|
|
||||||
}}
|
|
||||||
action={({ item }) =>
|
|
||||||
hasAnyAction ? (
|
|
||||||
<ActionDropdown>
|
|
||||||
<DropdownItem asChild>
|
|
||||||
<Link to={assetUrl(item)}>
|
|
||||||
<IconPencil size={16} />
|
|
||||||
{__("Edit")}
|
|
||||||
</Link>
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
onClick={() => deleteAsset(item)}
|
|
||||||
variant="danger"
|
|
||||||
icon={IconTrashCan}
|
|
||||||
>
|
|
||||||
{__("Delete")}
|
|
||||||
</DropdownItem>
|
|
||||||
</ActionDropdown>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
row={({ item }) => (
|
|
||||||
<>
|
|
||||||
<TextCell name="name" defaultValue={item?.name ?? ""} required />
|
|
||||||
<SelectCell
|
|
||||||
name="assetType"
|
|
||||||
items={["VIRTUAL", "PHYSICAL"]}
|
|
||||||
itemRenderer={({ item }) => (
|
|
||||||
<Badge variant={getAssetTypeVariant(item ?? "VIRTUAL")}>
|
|
||||||
{item === "PHYSICAL" ? __("Physical") : __("Virtual")}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
defaultValue={item?.assetType ?? defaultValue.assetType}
|
|
||||||
/>
|
|
||||||
<TextCell
|
|
||||||
name="dataTypesStored"
|
|
||||||
defaultValue={
|
|
||||||
item?.dataTypesStored ?? defaultValue.dataTypesStored
|
|
||||||
}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<TextCell
|
|
||||||
name="amount"
|
|
||||||
defaultValue={(item?.amount ?? defaultValue.amount).toString()}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<PeopleCell
|
|
||||||
name="ownerId"
|
|
||||||
defaultValue={item?.owner}
|
|
||||||
organizationId={organizationId}
|
|
||||||
/>
|
|
||||||
<VendorsCell
|
|
||||||
name="vendorIds"
|
|
||||||
organizationId={organizationId}
|
|
||||||
defaultValue={
|
|
||||||
item?.vendors?.edges?.map((edge) => edge.node) ?? []
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const useDeleteAsset = (connectionId: string) => {
|
|
||||||
const [mutate] = useMutation(deleteAssetMutation);
|
|
||||||
const confirm = useConfirm();
|
|
||||||
const { __ } = useTranslate();
|
|
||||||
|
|
||||||
return (asset: { id: string; name: string }) => {
|
|
||||||
if (!asset.id || !asset.name) {
|
|
||||||
return alert(__("Failed to delete asset: missing id or name"));
|
|
||||||
}
|
|
||||||
confirm(
|
|
||||||
() =>
|
|
||||||
promisifyMutation(mutate)({
|
|
||||||
variables: {
|
|
||||||
input: {
|
|
||||||
assetId: asset.id!,
|
|
||||||
},
|
|
||||||
connections: [connectionId],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
message: sprintf(
|
|
||||||
__(
|
|
||||||
'This will permanently delete "%s". This action cannot be undone.',
|
|
||||||
),
|
|
||||||
asset.name,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user