Skip to content

Commit

Permalink
Change collection stats links, update deps (#1160)
Browse files Browse the repository at this point in the history
* Use searchParams for release management options, change collection stats links

* Upgrade react-toastify

* Update deps
  • Loading branch information
harshithmohan authored Dec 17, 2024
1 parent 97132b4 commit 9c1f70c
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 318 deletions.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
"@microsoft/signalr": "^8.0.7",
"@monaco-editor/react": "^4.6.0",
"@reduxjs/toolkit": "^2.5.0",
"@sentry/browser": "^8.45.0",
"@sentry/react": "^8.45.0",
"@sentry/browser": "^8.46.0",
"@sentry/react": "^8.46.0",
"@tanstack/react-query": "^5.62.7",
"@tanstack/react-query-devtools": "^5.62.7",
"@tanstack/react-virtual": "^3.11.1",
"@tanstack/react-virtual": "^3.11.2",
"axios": "^1.7.9",
"classnames": "^2.5.1",
"copy-to-clipboard": "^3.3.3",
Expand All @@ -37,12 +37,12 @@
"react-avatar-editor": "^13.0.2",
"react-dom": "^19.0.0",
"react-grid-layout": "^1.5.0",
"react-modal": "^3.16.1",
"react-modal": "^3.16.3",
"react-redux": "^9.2.0",
"react-resizable": "^3.0.5",
"react-responsive": "^10.0.0",
"react-router": "^7.0.2",
"react-toastify": "^10.0.6",
"react-toastify": "^11.0.0",
"react-tooltip": "^5.28.0",
"react-use-measure": "^2.1.1",
"redux": "^5.0.1",
Expand Down Expand Up @@ -88,7 +88,7 @@
"postcss-import": "^16.1.0",
"postcss-load-config": "^6.0.1",
"postcss-preset-env": "^10.1.2",
"stylelint": "^16.11.0",
"stylelint": "^16.12.0",
"stylelint-config-standard": "^36.0.1",
"stylelint-config-tailwindcss": "^0.0.7",
"tailwindcss": "^3.4.16",
Expand Down
455 changes: 229 additions & 226 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/components/Dialogs/ActionsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ const Action = ({ actionKey, length }: { actionKey: string, length: number }) =>
runAction(functionName, {
onSuccess: () => toast.success(`Running action "${name}"`),
});
setTimeout(() => {
}, 2000);
});

return (
Expand Down
90 changes: 36 additions & 54 deletions src/components/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,52 @@
import React from 'react';
import type React from 'react';
import { toast } from 'react-toastify';
import type { ToastContentProps, ToastOptions } from 'react-toastify';
import {
mdiAlertCircleOutline,
mdiCheckboxMarkedCircleOutline,
mdiCloseCircleOutline,
mdiInformationOutline,
} from '@mdi/js';
import { Icon } from '@mdi/react';
import type { ToastOptions } from 'react-toastify';
import { mdiAlertCircleOutline, mdiCheckboxMarkedCircleOutline, mdiInformationOutline } from '@mdi/js';

type Props = Partial<ToastContentProps> & {
header: string;
message?: React.ReactNode;
icon: string;
};

const colorClass = {
success: 'text-panel-text-important',
error: 'text-panel-text-danger',
info: 'text-panel-text-primary',
warning: 'text-panel-text-warning',
};

const isColorClass = (type: string): type is keyof typeof colorClass => type in colorClass;

// eslint-disable-next-line react-refresh/only-export-components
function Toast(props: Props) {
const { closeToast, header, icon, message, toastProps } = props;
const color = toastProps && 'type' in toastProps && isColorClass(toastProps.type) ? toastProps?.type : 'info';

return (
<div className="flex">
<span>
<Icon path={icon} size={1} className={colorClass[color]} />
</span>
<div className="ml-4 mr-8 flex grow flex-col">
<div className="font-semibold">{header}</div>
<div className="text-panel-text">{message}</div>
</div>
{toastProps?.autoClose && (
<span onClick={closeToast}>
<Icon path={mdiCloseCircleOutline} size={1} className="text-panel-text opacity-65" />
</span>
)}
</div>
);
}
import ToastComponent from '@/components/ToastComponent';

const success = (header: string, message?: React.ReactNode, options?: ToastOptions) =>
toast.success(<Toast header={header} message={message} icon={mdiCheckboxMarkedCircleOutline} />, options);
toast.success(ToastComponent, {
data: {
header,
message,
icon: mdiCheckboxMarkedCircleOutline,
},
...options,
});

const error = (header: string, message?: React.ReactNode, options?: ToastOptions) =>
toast.error(<Toast header={header} message={message} icon={mdiAlertCircleOutline} />, options);
toast.error(ToastComponent, {
data: {
header,
message,
icon: mdiAlertCircleOutline,
},
...options,
});

const warning = (header: string, message?: React.ReactNode, options?: ToastOptions) =>
toast.warning(<Toast header={header} message={message} icon={mdiAlertCircleOutline} />, options);
toast.warning(ToastComponent, {
data: {
header,
message,
icon: mdiAlertCircleOutline,
},
...options,
});

const info = (header: string, message?: React.ReactNode, options?: ToastOptions) =>
toast.info(<Toast header={header} message={message} icon={mdiInformationOutline} />, options);
toast.info(ToastComponent, {
data: {
header,
message,
icon: mdiInformationOutline,
},
...options,
});

const dismiss = (id: number | string) => toast.dismiss(id);

const infoUpdate = (id: number | string, header: string, message?: React.ReactNode) =>
toast.update(id, { render: <Toast header={header} message={message} icon={mdiInformationOutline} /> });

const isActive = (id: number | string) => toast.isActive(id);

export default {
Expand All @@ -72,6 +55,5 @@ export default {
warning,
info,
dismiss,
infoUpdate,
isActive,
};
43 changes: 43 additions & 0 deletions src/components/ToastComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import type { ToastContentProps } from 'react-toastify';
import { mdiCloseCircleOutline } from '@mdi/js';
import { Icon } from '@mdi/react';

type Props = ToastContentProps<{
header: string;
message?: React.ReactNode;
icon: string;
}>;

const colorClass = {
success: 'text-panel-text-important',
error: 'text-panel-text-danger',
info: 'text-panel-text-primary',
warning: 'text-panel-text-warning',
};

const isColorClass = (type: string): type is keyof typeof colorClass => type in colorClass;

const ToastComponent = (props: Props) => {
const { closeToast, data, toastProps } = props;
const color = isColorClass(toastProps.type) ? toastProps?.type : 'info';

return (
<div className="flex bg-panel-background">
<span>
<Icon path={data.icon} size={1} className={colorClass[color]} />
</span>
<div className="ml-4 mr-8 flex grow flex-col">
<div className="font-semibold">{data.header}</div>
<div className="text-panel-text">{data.message}</div>
</div>
{toastProps.autoClose && (
<span onClick={closeToast}>
<Icon path={mdiCloseCircleOutline} size={1} className="text-panel-text opacity-65" />
</span>
)}
</div>
);
};

export default ToastComponent;
4 changes: 2 additions & 2 deletions src/pages/dashboard/panels/CollectionStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ function CollectionStats() {
key="missing-episodes-collecting"
title="Missing Episodes (Collecting)"
value={statsQuery.data?.MissingEpisodesCollecting}
filter="HasMissingEpisodesCollecting"
link="/webui/utilities/release-management/missing-episodes?onlyCollecting=true"
/>,
<Item
key="missing-episodes"
title="Missing Episodes (Total)"
value={statsQuery.data?.MissingEpisodes}
filter="HasMissingEpisodes"
link="/webui/utilities/release-management/missing-episodes"
/>,
];

Expand Down
1 change: 0 additions & 1 deletion src/pages/login/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
} from '@mdi/js';
import { Icon } from '@mdi/react';
import cx from 'classnames';
import 'react-toastify/dist/ReactToastify.min.css';
import { siDiscord } from 'simple-icons';

import Button from '@/components/Input/Button';
Expand Down
1 change: 0 additions & 1 deletion src/pages/main/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { Outlet } from 'react-router';
import { Slide, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';
import { Tooltip } from 'react-tooltip';
import { mdiLoading } from '@mdi/js';
import { Icon } from '@mdi/react';
Expand Down
55 changes: 29 additions & 26 deletions src/pages/utilities/ReleaseManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router';
import { useParams, useSearchParams } from 'react-router';
import {
mdiCloseCircleOutline,
mdiEyeOffOutline,
Expand Down Expand Up @@ -45,16 +45,28 @@ const titleMap = {

const ReleaseManagement = () => {
const { itemType } = useParams();
const [searchParams, setSearchParams] = useSearchParams();

const type = useMemo(() => {
if (itemType === 'duplicates') return ReleaseManagementItemType.DuplicateFiles;
if (itemType === 'missing-episodes') return ReleaseManagementItemType.MissingEpisodes;
return ReleaseManagementItemType.MultipleReleases;
}, [itemType]);

const [ignoreVariations, toggleIgnoreVariations, setIgnoreVariations] = useToggle(true);
const [onlyCollecting, toggleOnlyCollecting, setOnlyCollecting] = useToggle(false);
const [onlyFinishedSeries, toggleOnlyFinishedSeries, setOnlyFinishedSeries] = useToggle(false);
const filterOptions = useMemo(() => ({
ignoreVariations: (searchParams.get('ignoreVariations') ?? 'true') === 'true',
onlyCollecting: searchParams.get('onlyCollecting') === 'true',
onlyFinishedSeries: searchParams.get('onlyFinishedSeries') === 'true',
}), [searchParams]);

const handleFilterChange = useEventCallback((event: React.ChangeEvent<HTMLInputElement>) => {
setSearchParams((currentParams) => {
const newParams = new URLSearchParams(currentParams);
newParams.set(event.target.id, String(event.target.checked));
return newParams;
});
});

const [seriesCount, setSeriesCount] = useState(0);
const [selectedSeries, setSelectedSeries] = useState(0);
const [selectedEpisode, setSelectedEpisode] = useState<EpisodeType>();
Expand All @@ -64,25 +76,16 @@ const ReleaseManagement = () => {
const [showQuickSelectModal, toggleShowQuickSelectModal] = useToggle(false);

useEffect(() => {
setIgnoreVariations(true);
setOnlyCollecting(false);
setOnlyFinishedSeries(false);
setSelectedSeries(0);
setSelectedEpisode(undefined);
setSelectedEpisodes([]);
}, [itemType, setIgnoreVariations, setOnlyCollecting, setOnlyFinishedSeries]);
}, [itemType]);

const { mutateAsync: deleteFile } = useDeleteFileMutation();
const { mutateAsync: markVariation } = useMarkVariationMutation();
const { mutateAsync: deleteFileLocation } = useDeleteFileLocationMutation();
const { mutateAsync: hideEpisode } = useHideEpisodeMutation();

const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.id === 'ignore-variations') toggleIgnoreVariations();
if (event.target.id === 'only-collecting') toggleOnlyCollecting();
if (event.target.id === 'only-finished-series') toggleOnlyFinishedSeries();
};

const confirmChanges = useEventCallback(() => {
setOperationsPending(true);

Expand Down Expand Up @@ -151,28 +154,28 @@ const ReleaseManagement = () => {

{type === ReleaseManagementItemType.MultipleReleases && (
<Checkbox
id="ignore-variations"
isChecked={ignoreVariations}
onChange={handleCheckboxChange}
id="ignoreVariations"
isChecked={filterOptions.ignoreVariations}
onChange={handleFilterChange}
label="Ignore Variations"
labelRight
/>
)}

{type === ReleaseManagementItemType.MissingEpisodes && (
<Checkbox
id="only-collecting"
isChecked={onlyCollecting}
onChange={handleCheckboxChange}
id="onlyCollecting"
isChecked={filterOptions.onlyCollecting}
onChange={handleFilterChange}
label="Only Collecting"
labelRight
/>
)}

<Checkbox
id="only-finished-series"
isChecked={onlyFinishedSeries}
onChange={handleCheckboxChange}
id="onlyFinishedSeries"
isChecked={filterOptions.onlyFinishedSeries}
onChange={handleFilterChange}
label="Only Finished Series"
labelRight
/>
Expand Down Expand Up @@ -242,9 +245,9 @@ const ReleaseManagement = () => {
<TransitionDiv show={!selectedEpisode} className="absolute flex size-full gap-x-3">
<SeriesList
type={type}
ignoreVariations={ignoreVariations}
onlyCollecting={onlyCollecting}
onlyFinishedSeries={onlyFinishedSeries}
ignoreVariations={filterOptions.ignoreVariations}
onlyCollecting={filterOptions.onlyCollecting}
onlyFinishedSeries={filterOptions.onlyFinishedSeries}
setSelectedEpisode={setSelectedEpisode}
setSelectedEpisodes={setSelectedEpisodes}
setSelectedSeriesId={setSelectedSeries}
Expand Down

0 comments on commit 9c1f70c

Please sign in to comment.