Skip to content
Snippets Groups Projects

feat(alert): extra time for alerts and allow cancel operation by user click

Merged Leonardo Christino requested to merge feat/alert_click into main
3 files
+ 61
41
Compare changes
  • Side-by-side
  • Inline
Files
3
import React, { ReactNode, useEffect, useState } from 'react';
import React, { ReactNode, useEffect, useState, useImperativeHandle, useRef } from 'react';
import Broker from '@graphpolaris/shared/lib/data-access/socket/broker';
import { useImmer } from 'use-immer';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import { useAppDispatch, useConfig } from '../store';
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
import { removeLastError, removeLastWarning } from '../store/configSlice';
import { includes } from 'lodash-es';
type Message = {
message: ReactNode;
@@ -12,32 +13,52 @@ type Message = {
};
export const DashboardAlerts = (props: { timer?: number }) => {
const [messages, setMessages] = useImmer<{ data: any; routingKey: string; message: Message; showing: boolean }[]>([]);
const timer = props.timer || 1200;
const [messages, setMessages] = useImmer<{ data: any; routingKey: string; message: Message; showing: boolean; key: string }[]>([]);
const timer = props.timer || 4000;
const config = useConfig();
const dispatch = useAppDispatch();
const ref = useRef<any>(null);
async function processMessage(message: Message | undefined, data: any, routingKey: string) {
// Queue the message to be shown for props.time time, then fade it out matching the animation of animate-closemenu fade out time
if (message) {
useImperativeHandle(ref, () => ({
onAdd: (message: Message, data: any, routingKey: string) => {
let newMessage = { data, routingKey, message: message as Message, showing: true, key: `${Date.now()}-${Math.random()}` };
setMessages((draft) => {
draft.unshift(newMessage);
return draft;
});
return newMessage.key;
},
onTimeout: (key: string) => {
setMessages((draft) => {
const idx = draft.findIndex((m) => m.key === key);
if (idx === -1) return draft;
draft.splice(idx, 1);
return draft;
});
},
onShowTimeout: (key: string) => {
setMessages((draft) => {
draft.unshift({ data, routingKey, message: message as Message, showing: true });
const idx = draft.findIndex((m) => m.key === key);
if (idx === -1) return draft;
draft[idx].showing = false;
return draft;
});
setTimeout(() => {
setMessages((draft) => {
draft[draft.length - 1].showing = false;
// draft.pop();
return draft;
});
ref.current.onTimeout(key);
return true;
}, 300); // matches the animation of animate-closemenu
},
}));
setTimeout(() => {
setMessages((draft) => {
draft.pop();
return draft;
});
return true;
}, 300); // matches the animation of animate-closemenu
async function processMessage(message: Message | undefined, data: any, routingKey: string) {
// Queue the message to be shown for props.time time, then fade it out matching the animation of animate-closemenu fade out time
if (message && ref?.current) {
const key = ref.current.onAdd(message, data, routingKey);
setTimeout(() => {
ref.current.onShowTimeout(key);
return true;
}, timer);
}
}
@@ -125,13 +146,18 @@ export const DashboardAlerts = (props: { timer?: number }) => {
<div
key={i}
className={
`absolute bottom-5 right-5 w-fit min-w-[20rem] alert z-50 ` +
`absolute bottom-5 right-5 w-fit min-w-[20rem] cursor-pointer alert z-50 ` +
(m.showing ? 'animate-openmenu ' : 'animate-closemenu ') +
(m.message?.className || '')
}
style={{
transform: `translateY(-${i * 5}rem)`,
}}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
ref.current.onShowTimeout(m.key);
}}
>
<span className="flex flex-row content-center gap-3 text-white">{m.message.message}</span>
{/* {!message && (m.data?.status ? m.data.status : m.routingKey)} */}
Loading