mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
notifications: added boris notifications
This commit is contained in:
parent
d56bfe968d
commit
2ecda12513
13 changed files with 61 additions and 22 deletions
|
@ -3,6 +3,7 @@ import { NotificationItem } from '~/types/notifications';
|
|||
export interface ApiGetNotificationSettingsResponse {
|
||||
enabled: boolean;
|
||||
flow: boolean;
|
||||
boris: boolean;
|
||||
comments: boolean;
|
||||
send_telegram: boolean;
|
||||
show_indicator: boolean;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { FC } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Anchor } from '~/components/common/Anchor';
|
||||
import { Avatar } from '~/components/common/Avatar';
|
||||
import { InlineUsername } from '~/components/common/InlineUsername';
|
||||
|
@ -11,11 +13,12 @@ import styles from './styles.module.scss';
|
|||
|
||||
interface NotificationCommentProps {
|
||||
item: NotificationItem;
|
||||
isNew?: boolean;
|
||||
}
|
||||
|
||||
const NotificationComment: FC<NotificationCommentProps> = ({ item }) => (
|
||||
const NotificationComment: FC<NotificationCommentProps> = ({ item, isNew }) => (
|
||||
<Anchor href={item.url} className={styles.link}>
|
||||
<div className={styles.message}>
|
||||
<div className={classNames(styles.message, { [styles.new]: isNew })}>
|
||||
<div className={styles.icon}>
|
||||
<Avatar
|
||||
size={32}
|
||||
|
@ -31,11 +34,13 @@ const NotificationComment: FC<NotificationCommentProps> = ({ item }) => (
|
|||
<InlineUsername>{item.user.username}</InlineUsername>
|
||||
</span>
|
||||
<span>-</span>
|
||||
<Square
|
||||
className={styles.item_image}
|
||||
size={16}
|
||||
image={getURLFromString(item.thumbnail, 'avatar')}
|
||||
/>
|
||||
{!!item.thumbnail && (
|
||||
<Square
|
||||
className={styles.item_image}
|
||||
size={16}
|
||||
image={getURLFromString(item.thumbnail, 'avatar')}
|
||||
/>
|
||||
)}
|
||||
<div className={styles.item_title}>{item.title}</div>
|
||||
</b>
|
||||
|
||||
|
|
|
@ -12,6 +12,18 @@
|
|||
display: grid;
|
||||
grid-template-columns: 32px auto;
|
||||
column-gap: 0;
|
||||
position: relative;
|
||||
|
||||
&.new::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: $gap;
|
||||
right: $gap;
|
||||
background: $color_danger;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
|
@ -49,7 +61,6 @@
|
|||
|
||||
.item_title {
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
@ -58,6 +69,7 @@
|
|||
.item_image {
|
||||
flex: 0 0 16px;
|
||||
border-radius: 2px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.time {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { FC, useMemo } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { NodeThumbnail } from '~/components/node/NodeThumbnail';
|
||||
import { NotificationItem } from '~/types/notifications';
|
||||
import { getPrettyDate } from '~/utils/dom';
|
||||
|
@ -8,9 +10,10 @@ import styles from './styles.module.scss';
|
|||
|
||||
interface NotificationNodeProps {
|
||||
item: NotificationItem;
|
||||
isNew?: boolean;
|
||||
}
|
||||
|
||||
const NotificationNode: FC<NotificationNodeProps> = ({ item }) => {
|
||||
const NotificationNode: FC<NotificationNodeProps> = ({ item, isNew }) => {
|
||||
const thumbnail = useMemo(
|
||||
() => ({
|
||||
title: item.title,
|
||||
|
@ -21,7 +24,7 @@ const NotificationNode: FC<NotificationNodeProps> = ({ item }) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className={styles.card}>
|
||||
<div className={classNames(styles.card, { [styles.new]: isNew })}>
|
||||
<div className={styles.image}>
|
||||
<NodeThumbnail item={thumbnail} />
|
||||
</div>
|
||||
|
|
|
@ -8,6 +8,17 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: $gap/2;
|
||||
|
||||
&.new::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: $gap;
|
||||
right: $gap;
|
||||
background: $color_danger;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
|
|
|
@ -9,8 +9,6 @@ import { Toggle } from '~/components/input/Toggle';
|
|||
import { useNotificationSettingsForm } from '~/hooks/notifications/useNotificationSettingsForm';
|
||||
import { NotificationSettings } from '~/types/notifications';
|
||||
|
||||
import styles from './styles.module.scss';
|
||||
|
||||
interface NotificationSettingsFormProps {
|
||||
value: NotificationSettings;
|
||||
onSubmit: (val: Partial<NotificationSettings>) => Promise<unknown>;
|
||||
|
@ -65,6 +63,8 @@ const NotificationSettingsForm: FC<NotificationSettingsFormProps> = ({
|
|||
<InputRow input={toggle('comments', !values.enabled)}>
|
||||
Комментарии
|
||||
</InputRow>
|
||||
|
||||
<InputRow input={toggle('boris', !values.enabled)}>Борис</InputRow>
|
||||
</Group>
|
||||
</Zone>
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
row-gap: $gap;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import { FC, useCallback, useEffect } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { isAfter, parseISO } from 'date-fns';
|
||||
|
||||
import { Button } from '~/components/input/Button';
|
||||
import { InputRow } from '~/components/input/InputRow';
|
||||
|
@ -17,7 +18,7 @@ interface NotificationListProps {}
|
|||
|
||||
const NotificationList: FC<NotificationListProps> = () => {
|
||||
const { isLoading, items } = useNotificationsList();
|
||||
const { enabled, toggleEnabled } = useNotifications();
|
||||
const { enabled, toggleEnabled, lastSeen } = useNotifications();
|
||||
const { markAsRead } = useNotifications();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -25,11 +26,16 @@ const NotificationList: FC<NotificationListProps> = () => {
|
|||
}, []);
|
||||
|
||||
const renderItem = useCallback((item: NotificationItem) => {
|
||||
const isNew =
|
||||
!lastSeen ||
|
||||
!item.created_at ||
|
||||
isAfter(parseISO(item.created_at), lastSeen);
|
||||
switch (item.type) {
|
||||
case NotificationType.Comment:
|
||||
return <NotificationComment item={item} />;
|
||||
case NotificationType.Boris:
|
||||
return <NotificationComment item={item} isNew={isNew} />;
|
||||
case NotificationType.Node:
|
||||
return <NotificationNode item={item} />;
|
||||
return <NotificationNode item={item} isNew={isNew} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -54,5 +54,7 @@ export const useNotificationSettings = () => {
|
|||
update,
|
||||
loading: isLoading,
|
||||
toggleEnabled,
|
||||
lastSeen,
|
||||
lastDate,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useFormAutoSubmit } from '../useFormAutosubmit';
|
|||
const validationSchema = object({
|
||||
enabled: boolean().default(false),
|
||||
flow: boolean().default(false),
|
||||
boris: boolean().default(false),
|
||||
comments: boolean().default(false),
|
||||
sendTelegram: boolean().default(false),
|
||||
showIndicator: boolean().default(false),
|
||||
|
|
|
@ -14,11 +14,13 @@ export interface NotificationItem {
|
|||
export enum NotificationType {
|
||||
Node = 'node',
|
||||
Comment = 'comment',
|
||||
Boris = 'boris',
|
||||
}
|
||||
|
||||
export interface NotificationSettings {
|
||||
enabled: boolean;
|
||||
flow: boolean;
|
||||
boris: boolean;
|
||||
comments: boolean;
|
||||
sendTelegram: boolean;
|
||||
showIndicator: boolean;
|
||||
|
|
|
@ -8,6 +8,7 @@ export const notificationSettingsFromRequest = (
|
|||
): NotificationSettings => ({
|
||||
enabled: req.enabled,
|
||||
flow: req.flow,
|
||||
boris: req.boris,
|
||||
comments: req.comments,
|
||||
sendTelegram: req.send_telegram,
|
||||
showIndicator: req.show_indicator,
|
||||
|
@ -20,6 +21,7 @@ export const notificationSettingsToRequest = (
|
|||
): ApiUpdateNotificationSettingsRequest => ({
|
||||
enabled: req.enabled,
|
||||
flow: req.flow,
|
||||
boris: req.boris,
|
||||
comments: req.comments,
|
||||
send_telegram: req.sendTelegram,
|
||||
show_indicator: req.showIndicator,
|
||||
|
|
|
@ -14,6 +14,7 @@ const defaultValue = {
|
|||
toggleEnabled: () => {},
|
||||
markAsRead: () => {},
|
||||
refresh: () => Promise.resolve() as Promise<unknown>,
|
||||
lastSeen: null as Date | null | undefined,
|
||||
};
|
||||
|
||||
const NotificationContext = createContext(defaultValue);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue