Skip to content

Commit

Permalink
Add delete series actions (#806)
Browse files Browse the repository at this point in the history
  • Loading branch information
harshithmohan authored Jan 30, 2024
1 parent e03e5f3 commit a317eac
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 46 deletions.
20 changes: 14 additions & 6 deletions src/components/Collection/Series/EditSeriesModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React, { useState } from 'react';
import cx from 'classnames';
import { map } from 'lodash';

import DeleteActionsTab from '@/components/Collection/Series/EditSeriesTabs/DeleteActionsTab';
import FileActionsTab from '@/components/Collection/Series/EditSeriesTabs/FileActionsTab';
import NameTab from '@/components/Collection/Series/EditSeriesTabs/NameTab';
import SeriesActionsTab from '@/components/Collection/Series/EditSeriesTabs/SeriesActionsTab';
import UpdateActionsTab from '@/components/Collection/Series/EditSeriesTabs/UpdateActionsTab';
import ModalPanel from '@/components/Panels/ModalPanel';

// TODO: Add tabs after implementing back-end endpoint for GroupTab and PersonalStats
Expand All @@ -20,13 +22,19 @@ const tabs = {
// name: 'Name',
// group: 'Group',
// stats: 'Personal Stats',
actions: 'Series Actions',
update_actions: 'Update Actions',
file_actions: 'File Actions',
delete_actions: 'Delete Actions',
};

const renderTab = (activeTab: string, seriesId: number) => {
switch (activeTab) {
case 'actions':
return <SeriesActionsTab seriesId={seriesId} />;
case 'update_actions':
return <UpdateActionsTab seriesId={seriesId} />;
case 'file_actions':
return <FileActionsTab seriesId={seriesId} />;
case 'delete_actions':
return <DeleteActionsTab seriesId={seriesId} />;
// case 'group':
// return <GroupTab seriesId={seriesId} />;
// case 'stats':
Expand All @@ -40,12 +48,12 @@ const renderTab = (activeTab: string, seriesId: number) => {
const EditSeriesModal = (props: Props) => {
const { onClose, seriesId, show } = props;

const [activeTab, setActiveTab] = useState('actions');
const [activeTab, setActiveTab] = useState('update_actions');

return (
<ModalPanel show={show} onRequestClose={onClose} header="Edit Series" noPadding>
<div className="flex">
<div className="flex w-[12rem] shrink-0 flex-col gap-y-8 border-r border-panel-border p-8 font-semibold">
<div className="flex w-[12.5rem] shrink-0 flex-col gap-y-8 border-r border-panel-border p-8 font-semibold">
{map(tabs, (value, key) => (
<div
className={cx('font-semibold cursor-pointer', activeTab === key && 'text-panel-text-primary')}
Expand Down
19 changes: 19 additions & 0 deletions src/components/Collection/Series/EditSeriesTabs/Action.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { mdiPlayCircleOutline } from '@mdi/js';
import { Icon } from '@mdi/react';

import Button from '@/components/Input/Button';

const Action = ({ description, name, onClick }: { name: string, description: string, onClick: () => void }) => (
<div className="mr-4 flex flex-row justify-between gap-y-2 border-b border-panel-border pb-4 last:border-0">
<div className="flex w-full max-w-[35rem] flex-col gap-y-2">
<div>{name}</div>
<div className="text-sm opacity-65">{description}</div>
</div>
<Button onClick={onClick} className="text-panel-text-primary">
<Icon path={mdiPlayCircleOutline} size={1} />
</Button>
</div>
);

export default Action;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';

import Action from '@/components/Collection/Series/EditSeriesTabs/Action';
import toast from '@/components/Toast';
import { useDeleteSeriesMutation } from '@/core/react-query/series/mutations';

type Props = {
seriesId: number;
};

const DeleteActionsTab = ({ seriesId }: Props) => {
const navigate = useNavigate();

const { mutate: deleteSeries } = useDeleteSeriesMutation();

const navigateToCollection = () => navigate('/webui/collection');

return (
<div className="flex h-[22rem] grow flex-col gap-y-4 overflow-y-auto">
<Action
name="Delete Series - Keep Files"
description="Deletes the series from Shoko but does not delete the files"
onClick={() =>
deleteSeries({ seriesId, deleteFiles: false }, {
onSuccess: () => {
toast.success('Series deleted!');
navigateToCollection();
},
})}
/>
<Action
name="Delete Series - Remove Files"
description="Deletes the series from Shoko along with the files"
onClick={() =>
deleteSeries({ seriesId, deleteFiles: true }, {
onSuccess: () => {
toast.success('Series and files deleted!');
navigateToCollection();
},
})}
/>
<Action
name="Delete Series - Complete"
description="Removes all records relating to the series. Use with caution, as you may get banned if it's abused"
onClick={() =>
deleteSeries({ seriesId, deleteFiles: true, completelyRemove: true }, {
onSuccess: () => {
toast.success('Series deleted completely!');
navigateToCollection();
},
})}
/>
</div>
);
};

export default DeleteActionsTab;
37 changes: 37 additions & 0 deletions src/components/Collection/Series/EditSeriesTabs/FileActionsTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import Action from '@/components/Collection/Series/EditSeriesTabs/Action';
import toast from '@/components/Toast';
import { useRehashSeriesFilesMutation, useRescanSeriesFilesMutation } from '@/core/react-query/series/mutations';

type Props = {
seriesId: number;
};

const FileActionsTab = ({ seriesId }: Props) => {
const { mutate: rehashSeriesFiles } = useRehashSeriesFilesMutation();
const { mutate: rescanSeriesFiles } = useRescanSeriesFilesMutation();

return (
<div className="flex h-[22rem] grow flex-col gap-y-4 overflow-y-auto">
<Action
name="Rescan Files"
description="Rescans every file associated with the series."
onClick={() =>
rescanSeriesFiles(seriesId, {
onSuccess: () => toast.success('Series files rescan queued!'),
})}
/>
<Action
name="Rehash Files"
description="Rehashes every file associated with the series."
onClick={() =>
rehashSeriesFiles(seriesId, {
onSuccess: () => toast.success('Series files rehash queued!'),
})}
/>
</div>
);
};

export default FileActionsTab;
Original file line number Diff line number Diff line change
@@ -1,37 +1,19 @@
import React from 'react';
import { mdiPlayCircleOutline } from '@mdi/js';
import { Icon } from '@mdi/react';

import Button from '@/components/Input/Button';
import Action from '@/components/Collection/Series/EditSeriesTabs/Action';
import toast from '@/components/Toast';
import {
useRefreshSeriesAniDBInfoMutation,
useRefreshSeriesTvdbInfoMutatation,
useRehashSeriesFilesMutation,
useRescanSeriesFilesMutation,
} from '@/core/react-query/series/mutations';

type Props = {
seriesId: number;
};

const Action = ({ description, name, onClick }: { name: string, description: string, onClick: () => void }) => (
<div className="mr-4 flex flex-row justify-between gap-y-2 border-b border-panel-border pb-4 last:border-0">
<div className="flex w-full max-w-[35rem] flex-col gap-y-2">
<div>{name}</div>
<div className="text-sm opacity-65">{description}</div>
</div>
<Button onClick={onClick} className="text-panel-text-primary">
<Icon path={mdiPlayCircleOutline} size={1} />
</Button>
</div>
);

const SeriesActionsTab = ({ seriesId }: Props) => {
const UpdateActionsTab = ({ seriesId }: Props) => {
const { mutate: refreshAnidb } = useRefreshSeriesAniDBInfoMutation();
const { mutate: refreshTvdb } = useRefreshSeriesTvdbInfoMutatation();
const { mutate: rehashSeriesFiles } = useRehashSeriesFilesMutation();
const { mutate: rescanSeriesFiles } = useRescanSeriesFilesMutation();

const triggerAnidbRefresh = (force: boolean, cacheOnly: boolean) => {
refreshAnidb({ seriesId, force, cacheOnly }, {
Expand All @@ -40,23 +22,7 @@ const SeriesActionsTab = ({ seriesId }: Props) => {
};

return (
<div className="flex h-[22rem] grow flex-col gap-y-4 overflow-y-scroll">
<Action
name="Rescan Files"
description="Rescans every file associated with the series."
onClick={() =>
rescanSeriesFiles(seriesId, {
onSuccess: () => toast.success('Series files rescan queued!'),
})}
/>
<Action
name="Rehash Files"
description="Rehashes every file associated with the series."
onClick={() =>
rehashSeriesFiles(seriesId, {
onSuccess: () => toast.success('Series files rehash queued!'),
})}
/>
<div className="flex h-[22rem] grow flex-col gap-y-4 overflow-y-auto">
<Action
name="Update TVDB Info"
description="Gets the latest series information from TheTVDB database."
Expand Down Expand Up @@ -84,4 +50,4 @@ const SeriesActionsTab = ({ seriesId }: Props) => {
);
};

export default SeriesActionsTab;
export default UpdateActionsTab;
5 changes: 4 additions & 1 deletion src/core/react-query/series/mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export const useChangeSeriesImageMutation = () =>
export const useDeleteSeriesMutation = () =>
useMutation({
mutationFn: ({ seriesId, ...data }: DeleteSeriesRequestType) => axios.delete(`Series/${seriesId}`, { data }),
onSuccess: () => invalidateQueries(['series', 'without-files']),
onSuccess: () => {
invalidateQueries(['filter']);
invalidateQueries(['series', 'without-files']);
},
});

export const useDeleteSeriesTvdbLinkMutation = () =>
Expand Down
3 changes: 2 additions & 1 deletion src/core/react-query/series/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export type ChangeSeriesImageRequestType = {

export type DeleteSeriesRequestType = {
seriesId: number;
deleteFiles: boolean;
deleteFiles?: boolean;
completelyRemove?: boolean;
};

export type SeriesRequestType = {
Expand Down

0 comments on commit a317eac

Please sign in to comment.