mirror of
https://github.com/umami-software/umami.git
synced 2026-02-18 19:45:35 +01:00
Added Batch Website Deletion Along With Confirmation of Deletion Of the Batch
This commit is contained in:
parent
b04077db02
commit
87cf22530c
5 changed files with 119 additions and 39 deletions
|
|
@ -1,14 +1,22 @@
|
||||||
import WebsitesTable from '@/app/(main)/settings/websites/WebsitesTable';
|
import WebsitesTable from '@/app/(main)/settings/websites/WebsitesTable';
|
||||||
import DataTable from '@/components/common/DataTable';
|
import DataTable from '@/components/common/DataTable';
|
||||||
import { useWebsites } from '@/components/hooks';
|
import { useWebsites, useModified } from '@/components/hooks';
|
||||||
|
|
||||||
export function UserWebsites({ userId }) {
|
export function UserWebsites({ userId }) {
|
||||||
const queryResult = useWebsites({ userId });
|
const queryResult = useWebsites({ userId });
|
||||||
|
const { touch } = useModified('websites');
|
||||||
return (
|
return (
|
||||||
<DataTable queryResult={queryResult}>
|
<DataTable queryResult={queryResult}>
|
||||||
{({ data }) => (
|
{({ data }) => (
|
||||||
<WebsitesTable data={data} showActions={true} allowEdit={true} allowView={true} />
|
<WebsitesTable
|
||||||
|
data={data}
|
||||||
|
showActions={true}
|
||||||
|
allowEdit={true}
|
||||||
|
allowView={true}
|
||||||
|
updateChildren={() => {
|
||||||
|
touch();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</DataTable>
|
</DataTable>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import WebsitesTable from '@/app/(main)/settings/websites/WebsitesTable';
|
import WebsitesTable from '@/app/(main)/settings/websites/WebsitesTable';
|
||||||
import DataTable from '@/components/common/DataTable';
|
import DataTable from '@/components/common/DataTable';
|
||||||
import { useWebsites } from '@/components/hooks';
|
import { useWebsites, useModified } from '@/components/hooks';
|
||||||
|
|
||||||
export function WebsitesDataTable({
|
export function WebsitesDataTable({
|
||||||
teamId,
|
teamId,
|
||||||
allowEdit = true,
|
allowEdit = true,
|
||||||
|
|
@ -17,7 +16,7 @@ export function WebsitesDataTable({
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
const queryResult = useWebsites({ teamId });
|
const queryResult = useWebsites({ teamId });
|
||||||
|
const { touch } = useModified('websites');
|
||||||
return (
|
return (
|
||||||
<DataTable queryResult={queryResult} renderEmpty={() => children}>
|
<DataTable queryResult={queryResult} renderEmpty={() => children}>
|
||||||
{({ data }) => (
|
{({ data }) => (
|
||||||
|
|
@ -27,6 +26,7 @@ export function WebsitesDataTable({
|
||||||
showActions={showActions}
|
showActions={showActions}
|
||||||
allowEdit={allowEdit}
|
allowEdit={allowEdit}
|
||||||
allowView={allowView}
|
allowView={allowView}
|
||||||
|
updateChildren={() => touch()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DataTable>
|
</DataTable>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode, useState } from 'react';
|
||||||
import { Text, Icon, Icons, GridTable, GridColumn } from 'react-basics';
|
import { Text, Icon, Icons, GridTable, GridColumn, Checkbox, Modal } from 'react-basics';
|
||||||
import { useMessages, useTeamUrl } from '@/components/hooks';
|
import { useMessages, useTeamUrl } from '@/components/hooks';
|
||||||
|
import WebsiteDeleteForm from './[websiteId]/WebsiteDeleteForm';
|
||||||
import LinkButton from '@/components/common/LinkButton';
|
import LinkButton from '@/components/common/LinkButton';
|
||||||
|
|
||||||
export interface WebsitesTableProps {
|
export interface WebsitesTableProps {
|
||||||
data: any[];
|
data: any[];
|
||||||
showActions?: boolean;
|
showActions?: boolean;
|
||||||
|
|
@ -10,6 +10,7 @@ export interface WebsitesTableProps {
|
||||||
allowView?: boolean;
|
allowView?: boolean;
|
||||||
teamId?: string;
|
teamId?: string;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
updateChildren?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WebsitesTable({
|
export function WebsitesTable({
|
||||||
|
|
@ -18,47 +19,106 @@ export function WebsitesTable({
|
||||||
allowEdit,
|
allowEdit,
|
||||||
allowView,
|
allowView,
|
||||||
children,
|
children,
|
||||||
|
updateChildren,
|
||||||
}: WebsitesTableProps) {
|
}: WebsitesTableProps) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const { renderTeamUrl } = useTeamUrl();
|
const { renderTeamUrl } = useTeamUrl();
|
||||||
|
const [deleteIds, setDeleteIds] = useState([]);
|
||||||
|
const [showConf, setShowConf] = useState(false);
|
||||||
|
|
||||||
if (!data?.length) {
|
if (!data?.length) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
const checked = (websiteId: string) => {
|
||||||
|
if (deleteIds.includes(websiteId)) {
|
||||||
|
setDeleteIds(deleteIds.filter(prev => prev != websiteId));
|
||||||
|
} else {
|
||||||
|
setDeleteIds(prev => [...prev, websiteId]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GridTable data={data}>
|
<>
|
||||||
<GridColumn name="name" label={formatMessage(labels.name)} />
|
<GridTable data={data}>
|
||||||
<GridColumn name="domain" label={formatMessage(labels.domain)} />
|
<GridColumn
|
||||||
{showActions && (
|
width="40px"
|
||||||
<GridColumn name="action" label=" " alignment="end">
|
name="delete"
|
||||||
|
label={
|
||||||
|
deleteIds.length != 0 ? (
|
||||||
|
<Icon
|
||||||
|
style={{ color: 'red' }}
|
||||||
|
onClick={() => {
|
||||||
|
setShowConf(true);
|
||||||
|
}}
|
||||||
|
size={'lg'}
|
||||||
|
>
|
||||||
|
<Icons.Trash />
|
||||||
|
</Icon>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
{row => {
|
{row => {
|
||||||
const { id: websiteId } = row;
|
const { id: websiteId } = row;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Checkbox
|
||||||
{allowEdit && (
|
defaultChecked={false}
|
||||||
<LinkButton href={renderTeamUrl(`/settings/websites/${websiteId}`)}>
|
onChange={() => {
|
||||||
<Icon data-test="link-button-edit">
|
checked(websiteId);
|
||||||
<Icons.Edit />
|
}}
|
||||||
</Icon>
|
value={websiteId}
|
||||||
<Text>{formatMessage(labels.edit)}</Text>
|
/>
|
||||||
</LinkButton>
|
|
||||||
)}
|
|
||||||
{allowView && (
|
|
||||||
<LinkButton href={renderTeamUrl(`/websites/${websiteId}`)}>
|
|
||||||
<Icon>
|
|
||||||
<Icons.ArrowRight />
|
|
||||||
</Icon>
|
|
||||||
<Text>{formatMessage(labels.view)}</Text>
|
|
||||||
</LinkButton>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</GridColumn>
|
</GridColumn>
|
||||||
|
<GridColumn name="name" label={formatMessage(labels.name)} />
|
||||||
|
<GridColumn name="domain" label={formatMessage(labels.domain)} />
|
||||||
|
{showActions && (
|
||||||
|
<GridColumn name="action" label=" " alignment="end">
|
||||||
|
{row => {
|
||||||
|
const { id: websiteId } = row;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{allowEdit && (
|
||||||
|
<LinkButton href={renderTeamUrl(`/settings/websites/${websiteId}`)}>
|
||||||
|
<Icon data-test="link-button-edit">
|
||||||
|
<Icons.Edit />
|
||||||
|
</Icon>
|
||||||
|
<Text>{formatMessage(labels.edit)}</Text>
|
||||||
|
</LinkButton>
|
||||||
|
)}
|
||||||
|
{allowView && (
|
||||||
|
<LinkButton href={renderTeamUrl(`/websites/${websiteId}`)}>
|
||||||
|
<Icon>
|
||||||
|
<Icons.ArrowRight />
|
||||||
|
</Icon>
|
||||||
|
<Text>{formatMessage(labels.view)}</Text>
|
||||||
|
</LinkButton>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</GridColumn>
|
||||||
|
)}
|
||||||
|
</GridTable>
|
||||||
|
{showConf && (
|
||||||
|
<Modal title={formatMessage(labels.deleteWebsite)}>
|
||||||
|
{
|
||||||
|
<WebsiteDeleteForm
|
||||||
|
websiteId={deleteIds}
|
||||||
|
CONFIRM_VALUE={'DELETE MULTIPLE'}
|
||||||
|
onClose={() => {
|
||||||
|
setShowConf(false);
|
||||||
|
updateChildren();
|
||||||
|
setDeleteIds([]);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</Modal>
|
||||||
)}
|
)}
|
||||||
</GridTable>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,12 @@ export function WebsiteData({ websiteId, onSave }: { websiteId: string; onSave?:
|
||||||
</Button>
|
</Button>
|
||||||
<Modal title={formatMessage(labels.deleteWebsite)}>
|
<Modal title={formatMessage(labels.deleteWebsite)}>
|
||||||
{(close: () => void) => (
|
{(close: () => void) => (
|
||||||
<WebsiteDeleteForm websiteId={websiteId} onSave={handleSave} onClose={close} />
|
<WebsiteDeleteForm
|
||||||
|
CONFIRM_VALUE={'DELETE'}
|
||||||
|
websiteId={websiteId}
|
||||||
|
onSave={handleSave}
|
||||||
|
onClose={close}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Modal>
|
</Modal>
|
||||||
</ModalTrigger>
|
</ModalTrigger>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,28 @@
|
||||||
import { useApi, useMessages } from '@/components/hooks';
|
import { useApi, useMessages } from '@/components/hooks';
|
||||||
import TypeConfirmationForm from '@/components/common/TypeConfirmationForm';
|
import TypeConfirmationForm from '@/components/common/TypeConfirmationForm';
|
||||||
|
|
||||||
const CONFIRM_VALUE = 'DELETE';
|
|
||||||
|
|
||||||
export function WebsiteDeleteForm({
|
export function WebsiteDeleteForm({
|
||||||
websiteId,
|
websiteId,
|
||||||
|
CONFIRM_VALUE,
|
||||||
onSave,
|
onSave,
|
||||||
onClose,
|
onClose,
|
||||||
}: {
|
}: {
|
||||||
websiteId: string;
|
websiteId: string | string[];
|
||||||
|
CONFIRM_VALUE: string;
|
||||||
onSave?: () => void;
|
onSave?: () => void;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}) {
|
}) {
|
||||||
const { formatMessage, labels } = useMessages();
|
const { formatMessage, labels } = useMessages();
|
||||||
const { del, useMutation } = useApi();
|
const { del, useMutation } = useApi();
|
||||||
const { mutate, isPending, error } = useMutation({
|
const { mutate, isPending, error } = useMutation({
|
||||||
mutationFn: () => del(`/websites/${websiteId}`),
|
mutationFn: async () => {
|
||||||
|
if (typeof websiteId === 'string') {
|
||||||
|
return del(`/websites/${websiteId}`);
|
||||||
|
} else {
|
||||||
|
const ids = Array.isArray(websiteId) ? websiteId : [websiteId];
|
||||||
|
return Promise.all(ids.map(id => del(`/websites/${id}`)));
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue