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 DataTable from '@/components/common/DataTable';
|
||||
import { useWebsites } from '@/components/hooks';
|
||||
import { useWebsites, useModified } from '@/components/hooks';
|
||||
|
||||
export function UserWebsites({ userId }) {
|
||||
const queryResult = useWebsites({ userId });
|
||||
|
||||
const { touch } = useModified('websites');
|
||||
return (
|
||||
<DataTable queryResult={queryResult}>
|
||||
{({ data }) => (
|
||||
<WebsitesTable data={data} showActions={true} allowEdit={true} allowView={true} />
|
||||
<WebsitesTable
|
||||
data={data}
|
||||
showActions={true}
|
||||
allowEdit={true}
|
||||
allowView={true}
|
||||
updateChildren={() => {
|
||||
touch();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</DataTable>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { ReactNode } from 'react';
|
||||
import WebsitesTable from '@/app/(main)/settings/websites/WebsitesTable';
|
||||
import DataTable from '@/components/common/DataTable';
|
||||
import { useWebsites } from '@/components/hooks';
|
||||
|
||||
import { useWebsites, useModified } from '@/components/hooks';
|
||||
export function WebsitesDataTable({
|
||||
teamId,
|
||||
allowEdit = true,
|
||||
|
|
@ -17,7 +16,7 @@ export function WebsitesDataTable({
|
|||
children?: ReactNode;
|
||||
}) {
|
||||
const queryResult = useWebsites({ teamId });
|
||||
|
||||
const { touch } = useModified('websites');
|
||||
return (
|
||||
<DataTable queryResult={queryResult} renderEmpty={() => children}>
|
||||
{({ data }) => (
|
||||
|
|
@ -27,6 +26,7 @@ export function WebsitesDataTable({
|
|||
showActions={showActions}
|
||||
allowEdit={allowEdit}
|
||||
allowView={allowView}
|
||||
updateChildren={() => touch()}
|
||||
/>
|
||||
)}
|
||||
</DataTable>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Text, Icon, Icons, GridTable, GridColumn } from 'react-basics';
|
||||
import { ReactNode, useState } from 'react';
|
||||
import { Text, Icon, Icons, GridTable, GridColumn, Checkbox, Modal } from 'react-basics';
|
||||
import { useMessages, useTeamUrl } from '@/components/hooks';
|
||||
import WebsiteDeleteForm from './[websiteId]/WebsiteDeleteForm';
|
||||
import LinkButton from '@/components/common/LinkButton';
|
||||
|
||||
export interface WebsitesTableProps {
|
||||
data: any[];
|
||||
showActions?: boolean;
|
||||
|
|
@ -10,6 +10,7 @@ export interface WebsitesTableProps {
|
|||
allowView?: boolean;
|
||||
teamId?: string;
|
||||
children?: ReactNode;
|
||||
updateChildren?: () => void;
|
||||
}
|
||||
|
||||
export function WebsitesTable({
|
||||
|
|
@ -18,47 +19,106 @@ export function WebsitesTable({
|
|||
allowEdit,
|
||||
allowView,
|
||||
children,
|
||||
updateChildren,
|
||||
}: WebsitesTableProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { renderTeamUrl } = useTeamUrl();
|
||||
const [deleteIds, setDeleteIds] = useState([]);
|
||||
const [showConf, setShowConf] = useState(false);
|
||||
|
||||
if (!data?.length) {
|
||||
return children;
|
||||
}
|
||||
const checked = (websiteId: string) => {
|
||||
if (deleteIds.includes(websiteId)) {
|
||||
setDeleteIds(deleteIds.filter(prev => prev != websiteId));
|
||||
} else {
|
||||
setDeleteIds(prev => [...prev, websiteId]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<GridTable data={data}>
|
||||
<GridColumn name="name" label={formatMessage(labels.name)} />
|
||||
<GridColumn name="domain" label={formatMessage(labels.domain)} />
|
||||
{showActions && (
|
||||
<GridColumn name="action" label=" " alignment="end">
|
||||
<>
|
||||
<GridTable data={data}>
|
||||
<GridColumn
|
||||
width="40px"
|
||||
name="delete"
|
||||
label={
|
||||
deleteIds.length != 0 ? (
|
||||
<Icon
|
||||
style={{ color: 'red' }}
|
||||
onClick={() => {
|
||||
setShowConf(true);
|
||||
}}
|
||||
size={'lg'}
|
||||
>
|
||||
<Icons.Trash />
|
||||
</Icon>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
}
|
||||
>
|
||||
{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>
|
||||
)}
|
||||
</>
|
||||
<Checkbox
|
||||
defaultChecked={false}
|
||||
onChange={() => {
|
||||
checked(websiteId);
|
||||
}}
|
||||
value={websiteId}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</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>
|
||||
<Modal title={formatMessage(labels.deleteWebsite)}>
|
||||
{(close: () => void) => (
|
||||
<WebsiteDeleteForm websiteId={websiteId} onSave={handleSave} onClose={close} />
|
||||
<WebsiteDeleteForm
|
||||
CONFIRM_VALUE={'DELETE'}
|
||||
websiteId={websiteId}
|
||||
onSave={handleSave}
|
||||
onClose={close}
|
||||
/>
|
||||
)}
|
||||
</Modal>
|
||||
</ModalTrigger>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,28 @@
|
|||
import { useApi, useMessages } from '@/components/hooks';
|
||||
import TypeConfirmationForm from '@/components/common/TypeConfirmationForm';
|
||||
|
||||
const CONFIRM_VALUE = 'DELETE';
|
||||
|
||||
export function WebsiteDeleteForm({
|
||||
websiteId,
|
||||
CONFIRM_VALUE,
|
||||
onSave,
|
||||
onClose,
|
||||
}: {
|
||||
websiteId: string;
|
||||
websiteId: string | string[];
|
||||
CONFIRM_VALUE: string;
|
||||
onSave?: () => void;
|
||||
onClose?: () => void;
|
||||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { del, useMutation } = useApi();
|
||||
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 () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue