mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
fork refine
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
import { IUndoableQueue } from "../../interfaces";
|
||||
|
||||
export interface IUndoableQueueContext {
|
||||
notifications: IUndoableQueue[];
|
||||
notificationDispatch: React.Dispatch<any>;
|
||||
}
|
||||
5
packages/core/src/contexts/undoableQueue/actionTypes.ts
Normal file
5
packages/core/src/contexts/undoableQueue/actionTypes.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum ActionTypes {
|
||||
ADD = "ADD",
|
||||
REMOVE = "REMOVE",
|
||||
DECREASE_NOTIFICATION_SECOND = "DECREASE_NOTIFICATION_SECOND",
|
||||
}
|
||||
86
packages/core/src/contexts/undoableQueue/index.spec.tsx
Normal file
86
packages/core/src/contexts/undoableQueue/index.spec.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import * as React from "react";
|
||||
import { act, waitFor } from "@test";
|
||||
import { renderHook } from "@testing-library/react";
|
||||
|
||||
import { undoableQueueReducer } from "./undoableQueueContext";
|
||||
|
||||
describe("Notification Reducer", () => {
|
||||
const notificationDispatch = jest.fn();
|
||||
|
||||
const providerProps = {
|
||||
notifications: [
|
||||
{
|
||||
id: "1",
|
||||
resource: "posts",
|
||||
seconds: 5000,
|
||||
isRunning: true,
|
||||
},
|
||||
],
|
||||
notificationDispatch: notificationDispatch,
|
||||
};
|
||||
|
||||
it("should render notification item with ADD action", () => {
|
||||
const { result } = renderHook(() =>
|
||||
React.useReducer(undoableQueueReducer, []),
|
||||
);
|
||||
|
||||
const [, dispatch] = result.current;
|
||||
|
||||
act(() => {
|
||||
dispatch({ type: "ADD", payload: providerProps.notifications[0] });
|
||||
});
|
||||
|
||||
const [state] = result.current;
|
||||
|
||||
expect(state).toEqual([
|
||||
{
|
||||
id: "1",
|
||||
resource: "posts",
|
||||
seconds: 5000,
|
||||
isRunning: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("remove notification item with DELETE action", async () => {
|
||||
const { result } = renderHook(() =>
|
||||
React.useReducer(undoableQueueReducer, providerProps.notifications),
|
||||
);
|
||||
const [, dispatch] = result.current;
|
||||
|
||||
act(() => {
|
||||
dispatch({
|
||||
type: "REMOVE",
|
||||
payload: providerProps.notifications[0],
|
||||
});
|
||||
});
|
||||
|
||||
const [state] = result.current;
|
||||
|
||||
expect(state).toEqual([]);
|
||||
});
|
||||
|
||||
it("decrease notification item by 1 second with DECREASE_NOTIFICATION_SECOND action", async () => {
|
||||
const { result } = renderHook(() =>
|
||||
React.useReducer(undoableQueueReducer, providerProps.notifications),
|
||||
);
|
||||
const [, dispatch] = result.current;
|
||||
|
||||
act(() => {
|
||||
dispatch({
|
||||
type: "DECREASE_NOTIFICATION_SECOND",
|
||||
payload: {
|
||||
id: providerProps.notifications[0].id,
|
||||
seconds: providerProps.notifications[0].seconds,
|
||||
resource: providerProps.notifications[0].resource,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const [state] = result.current;
|
||||
|
||||
expect(state[0].seconds).toEqual(
|
||||
providerProps.notifications[0].seconds - 1000,
|
||||
);
|
||||
});
|
||||
});
|
||||
5
packages/core/src/contexts/undoableQueue/index.ts
Normal file
5
packages/core/src/contexts/undoableQueue/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export { ActionTypes } from "./actionTypes";
|
||||
export {
|
||||
UndoableQueueContextProvider,
|
||||
UndoableQueueContext,
|
||||
} from "./undoableQueueContext";
|
||||
@@ -0,0 +1,83 @@
|
||||
import React, { ReactNode, useReducer } from "react";
|
||||
import isEqual from "lodash/isEqual";
|
||||
|
||||
import { UndoableQueue } from "@components";
|
||||
|
||||
import { IUndoableQueue, IUndoableQueueContext } from "../../interfaces";
|
||||
import { ActionTypes } from "./actionTypes";
|
||||
|
||||
export const UndoableQueueContext = React.createContext<IUndoableQueueContext>({
|
||||
notifications: [],
|
||||
notificationDispatch: () => false,
|
||||
});
|
||||
|
||||
const initialState: IUndoableQueue[] = [];
|
||||
|
||||
export const undoableQueueReducer = (state: IUndoableQueue[], action: any) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.ADD:
|
||||
const newState = state.filter(
|
||||
(notificationItem: IUndoableQueue) => {
|
||||
return !(
|
||||
isEqual(notificationItem.id, action.payload.id) &&
|
||||
notificationItem.resource == action.payload.resource
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return [
|
||||
...newState,
|
||||
{
|
||||
...action.payload,
|
||||
isRunning: true,
|
||||
},
|
||||
];
|
||||
case ActionTypes.REMOVE:
|
||||
return state.filter(
|
||||
(notificationItem: IUndoableQueue) =>
|
||||
!(
|
||||
isEqual(notificationItem.id, action.payload.id) &&
|
||||
notificationItem.resource == action.payload.resource
|
||||
),
|
||||
);
|
||||
case ActionTypes.DECREASE_NOTIFICATION_SECOND:
|
||||
return state.map((notificationItem: IUndoableQueue) => {
|
||||
if (
|
||||
isEqual(notificationItem.id, action.payload.id) &&
|
||||
notificationItem.resource == action.payload.resource
|
||||
) {
|
||||
return {
|
||||
...notificationItem,
|
||||
seconds: action.payload.seconds - 1000,
|
||||
};
|
||||
}
|
||||
return notificationItem;
|
||||
});
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export const UndoableQueueContextProvider: React.FC<{
|
||||
children: ReactNode;
|
||||
}> = ({ children }) => {
|
||||
const [notifications, notificationDispatch] = useReducer(
|
||||
undoableQueueReducer,
|
||||
initialState,
|
||||
);
|
||||
|
||||
const notificationData = { notifications, notificationDispatch };
|
||||
|
||||
return (
|
||||
<UndoableQueueContext.Provider value={notificationData}>
|
||||
{children}
|
||||
{typeof window !== "undefined" &&
|
||||
notifications.map((notification) => (
|
||||
<UndoableQueue
|
||||
key={`${notification.id}-${notification.resource}-queue`}
|
||||
notification={notification}
|
||||
/>
|
||||
))}
|
||||
</UndoableQueueContext.Provider>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user