1
0
Fork 0
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:
Fedor Katurov 2019-11-13 12:11:47 +07:00
parent 6c1f8967e8
commit 9b0c3dd1fb
20 changed files with 371 additions and 39 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -12,7 +12,8 @@ const INITIAL_STATE: IAuthState = {
user: { ...EMPTY_USER },
updates: {
messages: [],
last: null,
notifications: [],
},
login: {

View file

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

View file

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

View file

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

View file

@ -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 }, '*');
}

View file

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