mirror of https://github.com/morpheus65535/bazarr
Add progress notifications
This commit is contained in:
parent
d5112d365c
commit
4513c4f676
|
@ -8,6 +8,8 @@ import {
|
|||
SITE_NOTIFICATIONS_ADD,
|
||||
SITE_NOTIFICATIONS_REMOVE,
|
||||
SITE_OFFLINE_UPDATE,
|
||||
SITE_PROGRESS_ADD,
|
||||
SITE_PROGRESS_REMOVE,
|
||||
SITE_SIDEBAR_UPDATE,
|
||||
} from "../constants";
|
||||
import { createAsyncAction, createCallbackAction } from "./factory";
|
||||
|
@ -32,7 +34,7 @@ export const badgeUpdateAll = createAsyncAction(SITE_BADGE_UPDATE, () =>
|
|||
|
||||
export const siteAddNotifications = createAction(
|
||||
SITE_NOTIFICATIONS_ADD,
|
||||
(err: ReduxStore.Notification[]) => err
|
||||
(notification: ReduxStore.Notification[]) => notification
|
||||
);
|
||||
|
||||
export const siteRemoveNotifications = createAction(
|
||||
|
@ -40,6 +42,16 @@ export const siteRemoveNotifications = createAction(
|
|||
(id: string) => id
|
||||
);
|
||||
|
||||
export const siteAddProgress = createAction(
|
||||
SITE_PROGRESS_ADD,
|
||||
(progress: ReduxStore.Progress[]) => progress
|
||||
);
|
||||
|
||||
export const siteRemoveProgress = createAction(
|
||||
SITE_PROGRESS_REMOVE,
|
||||
(id: string) => id
|
||||
);
|
||||
|
||||
export const siteChangeSidebar = createAction(
|
||||
SITE_SIDEBAR_UPDATE,
|
||||
(id: string) => id
|
||||
|
|
|
@ -36,6 +36,8 @@ export const SITE_INITIALIZED = "SITE_SYSTEM_INITIALIZED";
|
|||
export const SITE_INITIALIZE_FAILED = "SITE_INITIALIZE_FAILED";
|
||||
export const SITE_NOTIFICATIONS_ADD = "SITE_NOTIFICATIONS_ADD";
|
||||
export const SITE_NOTIFICATIONS_REMOVE = "SITE_NOTIFICATIONS_REMOVE";
|
||||
export const SITE_PROGRESS_ADD = "SITE_PROGRESS_ADD";
|
||||
export const SITE_PROGRESS_REMOVE = "SITE_PROGRESS_REMOVE";
|
||||
export const SITE_SIDEBAR_UPDATE = "SITE_SIDEBAR_UPDATE";
|
||||
export const SITE_BADGE_UPDATE = "SITE_BADGE_UPDATE";
|
||||
export const SITE_OFFLINE_UPDATE = "SITE_OFFLINE_UPDATE";
|
||||
|
|
|
@ -9,6 +9,8 @@ import {
|
|||
SITE_NOTIFICATIONS_ADD,
|
||||
SITE_NOTIFICATIONS_REMOVE,
|
||||
SITE_OFFLINE_UPDATE,
|
||||
SITE_PROGRESS_ADD,
|
||||
SITE_PROGRESS_REMOVE,
|
||||
SITE_SIDEBAR_UPDATE,
|
||||
} from "../constants";
|
||||
import { AsyncAction } from "../types";
|
||||
|
@ -47,6 +49,18 @@ const reducer = handleActions<ReduxStore.Site, any>(
|
|||
remove(notifications, (n) => n.id === action.payload);
|
||||
return { ...state, notifications };
|
||||
},
|
||||
[SITE_PROGRESS_ADD]: (state, action: Action<ReduxStore.Progress[]>) => {
|
||||
const progress = uniqBy(
|
||||
[...action.payload, ...state.progress],
|
||||
(n) => n.id
|
||||
);
|
||||
return { ...state, progress };
|
||||
},
|
||||
[SITE_PROGRESS_REMOVE]: (state, action: Action<string>) => {
|
||||
const progress = [...state.progress];
|
||||
remove(progress, (n) => n.id === action.payload);
|
||||
return { ...state, progress };
|
||||
},
|
||||
[SITE_SIDEBAR_UPDATE]: (state, action: Action<string>) => {
|
||||
return {
|
||||
...state,
|
||||
|
@ -70,6 +84,7 @@ const reducer = handleActions<ReduxStore.Site, any>(
|
|||
{
|
||||
initialized: false,
|
||||
auth: true,
|
||||
progress: [],
|
||||
notifications: [],
|
||||
sidebar: "",
|
||||
badges: {
|
||||
|
|
|
@ -13,10 +13,18 @@ namespace ReduxStore {
|
|||
timeout: number;
|
||||
}
|
||||
|
||||
interface Progress {
|
||||
id: string;
|
||||
name: string;
|
||||
value: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
interface Site {
|
||||
// Initialization state or error message
|
||||
initialized: boolean | string;
|
||||
auth: boolean;
|
||||
progress: Progress[];
|
||||
notifications: Notification[];
|
||||
sidebar: string;
|
||||
badges: Badge;
|
||||
|
|
|
@ -37,4 +37,8 @@ namespace SocketIO {
|
|||
EventType,
|
||||
OptionalRecord<ActionType, any[]>
|
||||
>;
|
||||
|
||||
namespace CustomEvent {
|
||||
type Progress = ReduxStore.Progress;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,35 @@
|
|||
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
|
||||
import {
|
||||
faExclamationTriangle,
|
||||
faPaperPlane,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { capitalize } from "lodash";
|
||||
import React, { FunctionComponent, useCallback, useMemo } from "react";
|
||||
import { Toast } from "react-bootstrap";
|
||||
import { ProgressBar, Toast } from "react-bootstrap";
|
||||
import { useTimeoutWhen } from "rooks";
|
||||
import { siteRemoveNotifications } from "../../@redux/actions";
|
||||
import {
|
||||
siteRemoveNotifications,
|
||||
siteRemoveProgress,
|
||||
} from "../../@redux/actions";
|
||||
import { useReduxAction, useReduxStore } from "../../@redux/hooks/base";
|
||||
import "./style.scss";
|
||||
|
||||
export interface NotificationContainerProps {}
|
||||
|
||||
const NotificationContainer: FunctionComponent<NotificationContainerProps> = () => {
|
||||
const list = useReduxStore((s) => s.site.notifications);
|
||||
const { progress, notifications } = useReduxStore((s) => s.site);
|
||||
|
||||
const items = useMemo(
|
||||
() =>
|
||||
list.map((v) => (
|
||||
<NotificationToast key={v.id} {...v}></NotificationToast>
|
||||
)),
|
||||
[list]
|
||||
);
|
||||
const items = useMemo(() => {
|
||||
const progressItems = progress.map((v) => (
|
||||
<ProgressToast key={v.id} {...v}></ProgressToast>
|
||||
));
|
||||
|
||||
const notificationItems = notifications.map((v) => (
|
||||
<NotificationToast key={v.id} {...v}></NotificationToast>
|
||||
));
|
||||
|
||||
return [...progressItems, ...notificationItems];
|
||||
}, [notifications, progress]);
|
||||
return (
|
||||
<div className="alert-container">
|
||||
<div className="toast-container">{items}</div>
|
||||
|
@ -54,4 +64,39 @@ const NotificationToast: FunctionComponent<MessageHolderProps> = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
type ProgressHolderProps = ReduxStore.Progress & {};
|
||||
|
||||
const ProgressToast: FunctionComponent<ProgressHolderProps> = ({
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
count,
|
||||
}) => {
|
||||
const removeProgress = useReduxAction(siteRemoveProgress);
|
||||
const remove = useCallback(() => removeProgress(id), [removeProgress, id]);
|
||||
|
||||
// TODO: Auto remove
|
||||
|
||||
return (
|
||||
<Toast onClose={remove}>
|
||||
<Toast.Body>
|
||||
<div className="mb-2 mt-1">
|
||||
<FontAwesomeIcon
|
||||
className="mr-2"
|
||||
icon={faPaperPlane}
|
||||
></FontAwesomeIcon>
|
||||
<span>{name}</span>
|
||||
</div>
|
||||
<ProgressBar
|
||||
className="my-1"
|
||||
animated
|
||||
now={value / count}
|
||||
max={1}
|
||||
label={`${value}/${count}`}
|
||||
></ProgressBar>
|
||||
</Toast.Body>
|
||||
</Toast>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationContainer;
|
||||
|
|
Loading…
Reference in New Issue