mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 21:06:42 +07:00
notification menu
This commit is contained in:
parent
6c1f8967e8
commit
9b0c3dd1fb
20 changed files with 371 additions and 39 deletions
|
@ -54,3 +54,15 @@ export const authSendMessage = (message: Partial<IMessage>, onSuccess) => ({
|
|||
message,
|
||||
onSuccess,
|
||||
});
|
||||
|
||||
export const authSetUpdates = (updates: Partial<IAuthState['updates']>) => ({
|
||||
type: AUTH_USER_ACTIONS.SET_UPDATES,
|
||||
updates,
|
||||
});
|
||||
|
||||
export const authSetLastSeenMessages = (
|
||||
last_seen_messages: IAuthState['user']['last_seen_messages']
|
||||
) => ({
|
||||
type: AUTH_USER_ACTIONS.SET_LAST_SEEN_MESSAGES,
|
||||
last_seen_messages,
|
||||
});
|
||||
|
|
|
@ -54,8 +54,9 @@ export const apiAuthSendMessage = ({
|
|||
export const apiAuthGetUpdates = ({
|
||||
access,
|
||||
exclude_dialogs,
|
||||
last,
|
||||
}): Promise<IResultWithStatus<{ message: IMessage }>> =>
|
||||
api
|
||||
.get(API.USER.GET_UPDATES, configWithToken(access, { params: { exclude_dialogs } }))
|
||||
.get(API.USER.GET_UPDATES, configWithToken(access, { params: { exclude_dialogs, last } }))
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware);
|
||||
|
|
|
@ -13,6 +13,9 @@ export const AUTH_USER_ACTIONS = {
|
|||
SET_PROFILE: 'SET_PROFILE',
|
||||
GET_MESSAGES: 'GET_MESSAGES',
|
||||
SEND_MESSAGE: 'SEND_MESSAGE',
|
||||
|
||||
SET_UPDATES: 'SET_UPDATES',
|
||||
SET_LAST_SEEN_MESSAGES: 'SET_LAST_SEEN_MESSAGES',
|
||||
};
|
||||
|
||||
export const USER_ERRORS = {
|
||||
|
@ -46,9 +49,11 @@ export const EMPTY_USER: IUser = {
|
|||
cover: null,
|
||||
is_activated: false,
|
||||
is_user: false,
|
||||
last_seen: null,
|
||||
fullname: null,
|
||||
description: null,
|
||||
|
||||
last_seen: null,
|
||||
last_seen_messages: null,
|
||||
};
|
||||
|
||||
export interface IApiUser {
|
||||
|
|
|
@ -37,9 +37,31 @@ const setProfile: ActionHandler<typeof ActionCreators.authSetProfile> = (state,
|
|||
...profile,
|
||||
},
|
||||
});
|
||||
|
||||
const setUpdates: ActionHandler<typeof ActionCreators.authSetUpdates> = (state, { updates }) => ({
|
||||
...state,
|
||||
updates: {
|
||||
...state.updates,
|
||||
...updates,
|
||||
},
|
||||
});
|
||||
|
||||
const setLastSeenMessages: ActionHandler<typeof ActionCreators.authSetLastSeenMessages> = (
|
||||
state,
|
||||
{ last_seen_messages }
|
||||
) => ({
|
||||
...state,
|
||||
user: {
|
||||
...state.user,
|
||||
last_seen_messages,
|
||||
},
|
||||
});
|
||||
|
||||
export const AUTH_USER_HANDLERS = {
|
||||
[AUTH_USER_ACTIONS.SET_LOGIN_ERROR]: setLoginError,
|
||||
[AUTH_USER_ACTIONS.SET_USER]: setUser,
|
||||
[AUTH_USER_ACTIONS.SET_TOKEN]: setToken,
|
||||
[AUTH_USER_ACTIONS.SET_PROFILE]: setProfile,
|
||||
[AUTH_USER_ACTIONS.SET_UPDATES]: setUpdates,
|
||||
[AUTH_USER_ACTIONS.SET_LAST_SEEN_MESSAGES]: setLastSeenMessages,
|
||||
};
|
||||
|
|
|
@ -12,7 +12,8 @@ const INITIAL_STATE: IAuthState = {
|
|||
user: { ...EMPTY_USER },
|
||||
|
||||
updates: {
|
||||
messages: [],
|
||||
last: null,
|
||||
notifications: [],
|
||||
},
|
||||
|
||||
login: {
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
authSetProfile,
|
||||
authGetMessages,
|
||||
authSendMessage,
|
||||
authSetUpdates,
|
||||
} from '~/redux/auth/actions';
|
||||
import {
|
||||
apiUserLogin,
|
||||
|
@ -20,8 +21,8 @@ import {
|
|||
apiAuthGetUpdates,
|
||||
} from '~/redux/auth/api';
|
||||
import { modalSetShown, modalShowDialog } from '~/redux/modal/actions';
|
||||
import { selectToken, selectAuthProfile, selectAuthUser } from './selectors';
|
||||
import { IResultWithStatus } from '../types';
|
||||
import { selectToken, selectAuthProfile, selectAuthUser, selectAuthUpdates } from './selectors';
|
||||
import { IResultWithStatus, INotification } from '../types';
|
||||
import { IUser, IAuthState } from './types';
|
||||
import { REHYDRATE, RehydrateAction } from 'redux-persist';
|
||||
import { selectModal } from '../modal/selectors';
|
||||
|
@ -197,19 +198,32 @@ function* getUpdates() {
|
|||
|
||||
const modal: IModalState = yield select(selectModal);
|
||||
const profile: IAuthState['profile'] = yield select(selectAuthProfile);
|
||||
|
||||
const { last }: IAuthState['updates'] = yield select(selectAuthUpdates);
|
||||
const exclude_dialogs =
|
||||
modal.is_shown && modal.dialog === DIALOGS.PROFILE && profile.user.id ? profile.user.id : null;
|
||||
|
||||
const { error, data } = yield call(reqWrapper, apiAuthGetUpdates, { exclude_dialogs });
|
||||
const { error, data }: IResultWithStatus<{ notifications: INotification[] }> = yield call(
|
||||
reqWrapper,
|
||||
apiAuthGetUpdates,
|
||||
{ exclude_dialogs, last }
|
||||
);
|
||||
|
||||
if (error || !data) return;
|
||||
if (error || !data || !data.notifications || !data.notifications.length) return;
|
||||
|
||||
const { notifications } = data;
|
||||
|
||||
yield put(
|
||||
authSetUpdates({
|
||||
last: notifications[0].created_at,
|
||||
notifications,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function* startPollingSaga() {
|
||||
while (true) {
|
||||
yield call(getUpdates);
|
||||
yield delay(30000);
|
||||
yield delay(60000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,3 +6,4 @@ export const selectToken = (state: IState): IState['auth']['token'] => state.aut
|
|||
export const selectAuthLogin = (state: IState): IState['auth']['login'] => state.auth.login;
|
||||
export const selectAuthProfile = (state: IState): IState['auth']['profile'] => state.auth.profile;
|
||||
export const selectAuthUser = (state: IState): IState['auth']['user'] => state.auth.user;
|
||||
export const selectAuthUpdates = (state: IState): IState['auth']['updates'] => state.auth.updates;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IFile, IMessage } from '../types';
|
||||
import { IFile, IMessage, INotification } from '../types';
|
||||
|
||||
export interface IToken {
|
||||
access: string;
|
||||
|
@ -13,10 +13,12 @@ export interface IUser {
|
|||
photo: IFile;
|
||||
cover: IFile;
|
||||
name: string;
|
||||
last_seen: string;
|
||||
fullname: string;
|
||||
description: string;
|
||||
|
||||
last_seen: string;
|
||||
last_seen_messages: string;
|
||||
|
||||
is_activated: boolean;
|
||||
is_user: boolean;
|
||||
}
|
||||
|
@ -26,7 +28,8 @@ export type IAuthState = Readonly<{
|
|||
token: string;
|
||||
|
||||
updates: {
|
||||
messages: IMessage[];
|
||||
last: string;
|
||||
notifications: INotification[];
|
||||
};
|
||||
|
||||
login: {
|
||||
|
|
|
@ -29,7 +29,7 @@ import { gotAuthPostMessage, authOpenProfile } from './auth/actions';
|
|||
|
||||
const authPersistConfig: PersistConfig = {
|
||||
key: 'auth',
|
||||
whitelist: ['token', 'user'],
|
||||
whitelist: ['token', 'user', 'updates'],
|
||||
storage,
|
||||
};
|
||||
|
||||
|
@ -50,8 +50,6 @@ history.listen(({ pathname }) => {
|
|||
console.log({ pathname });
|
||||
|
||||
if (pathname.match(/~([\wа-яА-Я]+)/)) {
|
||||
console.log('hi!', pathname.match(/~([\wа-яА-Я]+)/));
|
||||
|
||||
const [, username] = pathname.match(/~([\wа-яА-Я]+)/);
|
||||
window.postMessage({ type: 'username', username }, '*');
|
||||
}
|
||||
|
|
|
@ -161,3 +161,28 @@ export type IUploadProgressHandler = (progress: ProgressEvent) => void;
|
|||
export type IError = ValueOf<typeof ERRORS>;
|
||||
export type IValidationErrors = Record<string, IError>;
|
||||
export type InputHandler<T = string> = (val: T) => void;
|
||||
|
||||
export const NOTIFICATION_TYPES = {
|
||||
message: 'message',
|
||||
comment: 'comment',
|
||||
node: 'node',
|
||||
};
|
||||
|
||||
export type IMessageNotification = {
|
||||
type: typeof NOTIFICATION_TYPES['message'];
|
||||
content: Partial<IMessage>;
|
||||
};
|
||||
|
||||
export type ICommentNotification = {
|
||||
type: typeof NOTIFICATION_TYPES['comment'];
|
||||
content: Partial<IComment>;
|
||||
};
|
||||
|
||||
export type INodeNotification = {
|
||||
type: typeof NOTIFICATION_TYPES['node'];
|
||||
content: Partial<INode>;
|
||||
};
|
||||
|
||||
export type INotification = (IMessageNotification | ICommentNotification) & {
|
||||
created_at: string;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue