diff options
-rw-r--r-- | frontend/src/@redux/actions/site.ts | 9 | ||||
-rw-r--r-- | frontend/src/@redux/reducers/site.ts | 36 | ||||
-rw-r--r-- | frontend/src/@socketio/reducer.ts | 6 | ||||
-rw-r--r-- | frontend/src/App/Notification.tsx | 2 | ||||
-rw-r--r-- | frontend/src/apis/index.ts | 6 | ||||
-rw-r--r-- | frontend/src/utilites/async.ts | 6 |
6 files changed, 46 insertions, 19 deletions
diff --git a/frontend/src/@redux/actions/site.ts b/frontend/src/@redux/actions/site.ts index 8fa4cd077..89f89c0c7 100644 --- a/frontend/src/@redux/actions/site.ts +++ b/frontend/src/@redux/actions/site.ts @@ -1,5 +1,6 @@ import { createAction, createAsyncThunk } from "@reduxjs/toolkit"; import { BadgesApi } from "../../apis"; +import { waitFor } from "../../utilites"; import { systemUpdateAllSettings } from "./system"; export const siteBootstrap = createAsyncThunk( @@ -29,8 +30,12 @@ export const siteRemoveNotifications = createAction<string>( export const siteAddProgress = createAction<Server.Progress[]>("site/progress/add"); -export const siteRemoveProgress = createAction<string[]>( - "site/progress/remove" +export const siteRemoveProgress = createAsyncThunk( + "site/progress/remove", + async (ids: string[]) => { + await waitFor(3 * 1000); + return ids; + } ); export const siteChangeSidebar = createAction<string>("site/sidebar/update"); diff --git a/frontend/src/@redux/reducers/site.ts b/frontend/src/@redux/reducers/site.ts index 54aedc3d0..2cf860674 100644 --- a/frontend/src/@redux/reducers/site.ts +++ b/frontend/src/@redux/reducers/site.ts @@ -1,5 +1,5 @@ import { createReducer } from "@reduxjs/toolkit"; -import { pullAllWith, remove, uniqBy } from "lodash"; +import { intersectionWith, pullAllWith, remove, sortBy, uniqBy } from "lodash"; import apis from "../../apis"; import { siteAddNotifications, @@ -50,31 +50,49 @@ const reducer = createReducer(defaultSite, (builder) => { }) .addCase(siteRedirectToAuth, (state) => { if (process.env.NODE_ENV !== "production") { - apis.danger_resetApi("NEED_AUTH"); + apis._resetApi("NEED_AUTH"); } state.auth = false; }) .addCase(siteUpdateInitialization, (state, action) => { state.initialized = action.payload; - }) + }); + + builder .addCase(siteAddNotifications, (state, action) => { state.notifications = uniqBy( - [...action.payload.reverse(), ...state.notifications], - (n) => n.id + [...action.payload, ...state.notifications], + (v) => v.id ); + state.notifications = sortBy(state.notifications, (v) => v.id); }) .addCase(siteRemoveNotifications, (state, action) => { remove(state.notifications, (n) => n.id === action.payload); - }) + }); + + builder .addCase(siteAddProgress, (state, action) => { state.progress = uniqBy( - [...action.payload.reverse(), ...state.progress], + [...action.payload, ...state.progress], (n) => n.id ); + state.progress = sortBy(state.progress, (v) => v.id); }) - .addCase(siteRemoveProgress, (state, action) => { - pullAllWith(state.progress, action.payload, (l, r) => l.id === r); + .addCase(siteRemoveProgress.pending, (state, action) => { + // Mark completed + intersectionWith( + state.progress, + action.meta.arg, + (l, r) => l.id === r + ).forEach((v) => { + v.value = v.count + 1; + }); }) + .addCase(siteRemoveProgress.fulfilled, (state, action) => { + pullAllWith(state.progress, action.payload, (l, r) => l.id === r); + }); + + builder .addCase(siteChangeSidebar, (state, action) => { state.sidebar = action.payload; }) diff --git a/frontend/src/@socketio/reducer.ts b/frontend/src/@socketio/reducer.ts index 153915939..b13112abf 100644 --- a/frontend/src/@socketio/reducer.ts +++ b/frontend/src/@socketio/reducer.ts @@ -83,11 +83,7 @@ export function createDefaultReducer(): SocketIO.Reducer[] { { key: "progress", update: bindReduxAction(siteAddProgress), - delete: (ids) => { - setTimeout(() => { - reduxStore.dispatch(siteRemoveProgress(ids)); - }, 3 * 1000); - }, + delete: bindReduxAction(siteRemoveProgress), }, { key: "series", diff --git a/frontend/src/App/Notification.tsx b/frontend/src/App/Notification.tsx index 6c1727c60..8c62caa37 100644 --- a/frontend/src/App/Notification.tsx +++ b/frontend/src/App/Notification.tsx @@ -202,7 +202,7 @@ const Progress: FunctionComponent<Server.Progress> = ({ count, header, }) => { - const isCompleted = value / count >= 1; + const isCompleted = value / count > 1; return ( <div className="notification-center-progress d-flex flex-column"> <p className="progress-header m-0 h-6 text-dark font-weight-bold"> diff --git a/frontend/src/apis/index.ts b/frontend/src/apis/index.ts index eb91fe87c..9c66aa4ab 100644 --- a/frontend/src/apis/index.ts +++ b/frontend/src/apis/index.ts @@ -52,8 +52,10 @@ class Api { ); } - danger_resetApi(apikey: string) { - this.axios.defaults.headers.common["X-API-KEY"] = apikey; + _resetApi(apikey: string) { + if (process.env.NODE_ENV !== "production") { + this.axios.defaults.headers.common["X-API-KEY"] = apikey; + } } handleError(code: number) { diff --git a/frontend/src/utilites/async.ts b/frontend/src/utilites/async.ts index 97eaeb42a..de363de32 100644 --- a/frontend/src/utilites/async.ts +++ b/frontend/src/utilites/async.ts @@ -3,6 +3,12 @@ import { useEffect, useMemo, useState } from "react"; import { useEffectOnceWhen } from "rooks"; import { useEntityIdByRange, useEntityToItem } from "./entity"; +export async function waitFor(time: number) { + return new Promise((resolved) => { + setTimeout(resolved, time); + }); +} + export function useNewEntityIds(entity: Async.Entity<any>) { return useMemo(() => { const dirtyEntities = entity.dirtyEntities; |