1
0
Fork 0
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:
Fedor Katurov 2023-03-18 16:09:53 +06:00
parent d56bfe968d
commit 2ecda12513
13 changed files with 61 additions and 22 deletions

View file

@ -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;

View file

@ -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>

View file

@ -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 {

View file

@ -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>

View file

@ -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 {

View file

@ -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>

View file

@ -1,7 +0,0 @@
@import 'src/styles/variables';
.grid {
display: grid;
grid-auto-flow: row;
row-gap: $gap;
}

View file

@ -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;
}

View file

@ -54,5 +54,7 @@ export const useNotificationSettings = () => {
update,
loading: isLoading,
toggleEnabled,
lastSeen,
lastDate,
};
};

View file

@ -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),

View file

@ -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;

View file

@ -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,

View file

@ -14,6 +14,7 @@ const defaultValue = {
toggleEnabled: () => {},
markAsRead: () => {},
refresh: () => Promise.resolve() as Promise<unknown>,
lastSeen: null as Date | null | undefined,
};
const NotificationContext = createContext(defaultValue);