mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
rating notification
This commit is contained in:
parent
416ba8d5da
commit
d4ee83dcb7
@ -6,6 +6,7 @@ import { FloatingPortal, useFloating, useInteractions } from "@floating-ui/react
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useEffect, useState } from "react";
|
||||
import { NotificationItem } from "./notificationitem";
|
||||
import { RatingBubble } from "./ratingbubble";
|
||||
import { useNotification } from "./usenotification";
|
||||
|
||||
import clsx from "clsx";
|
||||
@ -16,6 +17,7 @@ const NotificationBubbles = () => {
|
||||
notifications,
|
||||
hoveredId,
|
||||
hideNotification,
|
||||
removeNotification,
|
||||
copyNotification,
|
||||
handleActionClick,
|
||||
formatTimestamp,
|
||||
@ -60,6 +62,15 @@ const NotificationBubbles = () => {
|
||||
>
|
||||
{notifications.map((notif) => {
|
||||
if (notif.hidden) return null;
|
||||
if (notif.componentType === "rating") {
|
||||
return (
|
||||
<RatingBubble
|
||||
key={notif.id}
|
||||
notification={notif}
|
||||
onRemove={removeNotification}
|
||||
></RatingBubble>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NotificationItem
|
||||
key={notif.id}
|
||||
|
@ -29,8 +29,8 @@ const NotificationItem = ({
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
}: NotificationItemProps) => {
|
||||
const { id, title, message, icon, type, timestamp, persistent, actions } = notification;
|
||||
const color = type === "error" ? "red" : type === "warning" ? "yellow" : "green";
|
||||
const { id, title, message, icon, statusType, timestamp, persistent, actions } = notification;
|
||||
const color = statusType === "error" ? "red" : statusType === "warning" ? "yellow" : "green";
|
||||
const nIcon = icon ? icon : "bell";
|
||||
|
||||
const renderCloseButton = () => {
|
||||
|
@ -37,8 +37,8 @@ const NotificationPopover = () => {
|
||||
setNotificationPopoverMode(!notificationPopoverMode);
|
||||
}, [notificationPopoverMode]);
|
||||
|
||||
const hasErrors = notifications.some((n) => n.type === "error");
|
||||
const hasUpdate = notifications.some((n) => n.type === "update");
|
||||
const hasErrors = notifications.some((n) => n.statusType === "error");
|
||||
const hasUpdate = notifications.some((n) => n.statusType === "update");
|
||||
|
||||
const addOnClassNames = hasUpdate ? "solid green" : hasErrors ? "solid red" : "ghost grey";
|
||||
|
||||
|
48
frontend/app/notification/ratingbubble.less
Normal file
48
frontend/app/notification/ratingbubble.less
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.notification-title {
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
margin-bottom: 3px;
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
.notification-message {
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.rating-bubble {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 380px;
|
||||
padding: 16px 24px 16px 16px;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
border-radius: 8px;
|
||||
border: 0.5px solid rgba(255, 255, 255, 0.12);
|
||||
background: #232323;
|
||||
box-shadow: 0px 8px 32px 0px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.notification-inner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
column-gap: 6px;
|
||||
}
|
||||
|
||||
&.hovered {
|
||||
background: #292929;
|
||||
}
|
65
frontend/app/notification/ratingbubble.tsx
Normal file
65
frontend/app/notification/ratingbubble.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { Button } from "@/element/button";
|
||||
import { makeIconClass } from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import { useState } from "react";
|
||||
|
||||
import "./ratingbubble.less";
|
||||
|
||||
interface RatingBubbleProps {
|
||||
notification: NotificationType;
|
||||
onRemove: (id: string) => void;
|
||||
}
|
||||
|
||||
const RatingBubble = ({ notification, onRemove }: RatingBubbleProps) => {
|
||||
const { id, title, message } = notification;
|
||||
const [hoveredButtons, setHoveredButtons] = useState<{ [key: number]: boolean }>({});
|
||||
|
||||
const handleRatingClick = (rating: number) => {
|
||||
console.log("rating clicked");
|
||||
};
|
||||
|
||||
const handleMouseEnter = (buttonIndex: number) => {
|
||||
setHoveredButtons((prev) => ({ ...prev, [buttonIndex]: true }));
|
||||
};
|
||||
|
||||
const handleMouseLeave = (buttonIndex: number) => {
|
||||
setHoveredButtons((prev) => ({ ...prev, [buttonIndex]: false }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx("rating-bubble")} title="Click to Copy Notification Message">
|
||||
<Button
|
||||
className="close-btn ghost grey vertical-padding-10"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onRemove(id);
|
||||
}}
|
||||
aria-label="Close"
|
||||
>
|
||||
<i className={clsx(makeIconClass("close", false))}></i>
|
||||
</Button>
|
||||
<div className="notification-inner">
|
||||
<div className="notification-text">
|
||||
{title && <div className={clsx("notification-title green")}>{title}</div>}
|
||||
{message && <div className="notification-message">{message}</div>}
|
||||
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((rating) => (
|
||||
<Button
|
||||
key={rating}
|
||||
className={clsx(hoveredButtons[rating] ? "green" : "grey")}
|
||||
onClick={() => handleRatingClick(rating)}
|
||||
onMouseEnter={() => handleMouseEnter(rating)}
|
||||
onMouseLeave={() => handleMouseLeave(rating)}
|
||||
>
|
||||
{rating}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { RatingBubble };
|
3
frontend/types/custom.d.ts
vendored
3
frontend/types/custom.d.ts
vendored
@ -320,7 +320,8 @@ declare global {
|
||||
hidden?: boolean;
|
||||
actions?: NotificationActionType[];
|
||||
persistent?: boolean;
|
||||
type?: "error" | "update" | "info" | "warning";
|
||||
componentType?: "rating";
|
||||
statusType?: "error" | "update" | "info" | "warning";
|
||||
};
|
||||
|
||||
interface AbstractWshClient {
|
||||
|
Loading…
Reference in New Issue
Block a user