mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
fixed cyclic dependencies for dialogs
This commit is contained in:
parent
d7ed0cbe54
commit
c0c832d158
19 changed files with 399 additions and 263 deletions
|
@ -34,6 +34,7 @@ const INITIAL_STATE: IAuthState = {
|
|||
|
||||
restore: {
|
||||
code: '',
|
||||
user: null,
|
||||
is_loading: false,
|
||||
is_succesfull: false,
|
||||
errors: {},
|
||||
|
|
|
@ -1,17 +1,5 @@
|
|||
import {
|
||||
call,
|
||||
put,
|
||||
takeEvery,
|
||||
takeLatest,
|
||||
select,
|
||||
delay
|
||||
} from "redux-saga/effects";
|
||||
import {
|
||||
AUTH_USER_ACTIONS,
|
||||
EMPTY_USER,
|
||||
USER_ERRORS,
|
||||
USER_ROLES
|
||||
} from "~/redux/auth/constants";
|
||||
import { call, put, takeEvery, takeLatest, select, delay } from 'redux-saga/effects';
|
||||
import { AUTH_USER_ACTIONS, EMPTY_USER, USER_ERRORS, USER_ROLES } from '~/redux/auth/constants';
|
||||
import {
|
||||
authSetToken,
|
||||
userSetLoginError,
|
||||
|
@ -25,8 +13,10 @@ import {
|
|||
authSetUpdates,
|
||||
authLoggedIn,
|
||||
authSetLastSeenMessages,
|
||||
authPatchUser
|
||||
} from "~/redux/auth/actions";
|
||||
authPatchUser,
|
||||
authRestorePassword,
|
||||
authSetRestore,
|
||||
} from '~/redux/auth/actions';
|
||||
import {
|
||||
apiUserLogin,
|
||||
apiAuthGetUser,
|
||||
|
@ -34,31 +24,19 @@ import {
|
|||
apiAuthGetUserMessages,
|
||||
apiAuthSendMessage,
|
||||
apiAuthGetUpdates,
|
||||
apiUpdateUser
|
||||
} from "~/redux/auth/api";
|
||||
import { modalSetShown, modalShowDialog } from "~/redux/modal/actions";
|
||||
import {
|
||||
selectToken,
|
||||
selectAuthProfile,
|
||||
selectAuthUser,
|
||||
selectAuthUpdates
|
||||
} from "./selectors";
|
||||
import {
|
||||
IResultWithStatus,
|
||||
INotification,
|
||||
IMessageNotification
|
||||
} from "../types";
|
||||
import { IUser, IAuthState } from "./types";
|
||||
import { REHYDRATE, RehydrateAction } from "redux-persist";
|
||||
import { selectModal } from "../modal/selectors";
|
||||
import { IModalState } from "../modal/reducer";
|
||||
import { DIALOGS } from "../modal/constants";
|
||||
import { ERRORS } from "~/constants/errors";
|
||||
apiUpdateUser,
|
||||
} from '~/redux/auth/api';
|
||||
import { modalSetShown, modalShowDialog } from '~/redux/modal/actions';
|
||||
import { selectToken, selectAuthProfile, selectAuthUser, selectAuthUpdates } from './selectors';
|
||||
import { IResultWithStatus, INotification, IMessageNotification } from '../types';
|
||||
import { IUser, IAuthState } from './types';
|
||||
import { REHYDRATE, RehydrateAction } from 'redux-persist';
|
||||
import { selectModal } from '~/redux/modal/selectors';
|
||||
import { IModalState } from '~/redux/modal/reducer';
|
||||
import { DIALOGS } from '~/redux/modal/constants';
|
||||
import { ERRORS } from '~/constants/errors';
|
||||
|
||||
export function* reqWrapper(
|
||||
requestAction,
|
||||
props = {}
|
||||
): ReturnType<typeof requestAction> {
|
||||
export function* reqWrapper(requestAction, props = {}): ReturnType<typeof requestAction> {
|
||||
const access = yield select(selectToken);
|
||||
|
||||
const result = yield call(requestAction, { access, ...props });
|
||||
|
@ -70,22 +48,16 @@ export function* reqWrapper(
|
|||
return result;
|
||||
}
|
||||
|
||||
function* sendLoginRequestSaga({
|
||||
username,
|
||||
password
|
||||
}: ReturnType<typeof userSendLoginRequest>) {
|
||||
function* sendLoginRequestSaga({ username, password }: ReturnType<typeof userSendLoginRequest>) {
|
||||
if (!username || !password) return;
|
||||
|
||||
const {
|
||||
error,
|
||||
data: { token, user }
|
||||
}: IResultWithStatus<{ token: string; user: IUser }> = yield call(
|
||||
apiUserLogin,
|
||||
{
|
||||
username,
|
||||
password
|
||||
}
|
||||
);
|
||||
data: { token, user },
|
||||
}: IResultWithStatus<{ token: string; user: IUser }> = yield call(apiUserLogin, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
yield put(userSetLoginError(error));
|
||||
|
@ -101,17 +73,14 @@ function* sendLoginRequestSaga({
|
|||
function* refreshUser() {
|
||||
const {
|
||||
error,
|
||||
data: { user }
|
||||
}: IResultWithStatus<{ user: IUser }> = yield call(
|
||||
reqWrapper,
|
||||
apiAuthGetUser
|
||||
);
|
||||
data: { user },
|
||||
}: IResultWithStatus<{ user: IUser }> = yield call(reqWrapper, apiAuthGetUser);
|
||||
|
||||
if (error) {
|
||||
yield put(
|
||||
authSetUser({
|
||||
...EMPTY_USER,
|
||||
is_user: false
|
||||
is_user: false,
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -122,7 +91,7 @@ function* refreshUser() {
|
|||
}
|
||||
|
||||
function* checkUserSaga({ key }: RehydrateAction) {
|
||||
if (key !== "auth") return;
|
||||
if (key !== 'auth') return;
|
||||
yield call(refreshUser);
|
||||
// yield put(authOpenProfile("gvorcek", "settings"));
|
||||
}
|
||||
|
@ -142,21 +111,18 @@ function* logoutSaga() {
|
|||
yield put(
|
||||
authSetUpdates({
|
||||
last: null,
|
||||
notifications: []
|
||||
notifications: [],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function* openProfile({
|
||||
username,
|
||||
tab = "profile"
|
||||
}: ReturnType<typeof authOpenProfile>) {
|
||||
function* openProfile({ username, tab = 'profile' }: ReturnType<typeof authOpenProfile>) {
|
||||
yield put(modalShowDialog(DIALOGS.PROFILE));
|
||||
yield put(authSetProfile({ is_loading: true, tab }));
|
||||
|
||||
const {
|
||||
error,
|
||||
data: { user }
|
||||
data: { user },
|
||||
} = yield call(reqWrapper, apiAuthGetUserProfile, { username });
|
||||
|
||||
if (error || !user) {
|
||||
|
@ -176,16 +142,15 @@ function* getMessages({ username }: ReturnType<typeof authGetMessages>) {
|
|||
messages:
|
||||
messages &&
|
||||
messages.length > 0 &&
|
||||
(messages[0].to.username === username ||
|
||||
messages[0].from.username === username)
|
||||
(messages[0].to.username === username || messages[0].from.username === username)
|
||||
? messages
|
||||
: []
|
||||
: [],
|
||||
})
|
||||
);
|
||||
|
||||
const {
|
||||
error,
|
||||
data
|
||||
data,
|
||||
// data: { messages },
|
||||
} = yield call(reqWrapper, apiAuthGetUserMessages, { username });
|
||||
|
||||
|
@ -193,21 +158,19 @@ function* getMessages({ username }: ReturnType<typeof authGetMessages>) {
|
|||
return yield put(
|
||||
authSetProfile({
|
||||
is_loading_messages: false,
|
||||
messages_error: ERRORS.EMPTY_RESPONSE
|
||||
messages_error: ERRORS.EMPTY_RESPONSE,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
yield put(
|
||||
authSetProfile({ is_loading_messages: false, messages: data.messages })
|
||||
);
|
||||
yield put(authSetProfile({ is_loading_messages: false, messages: data.messages }));
|
||||
|
||||
const { notifications } = yield select(selectAuthUpdates);
|
||||
|
||||
// clear viewed message from notifcation list
|
||||
const filtered = notifications.filter(
|
||||
notification =>
|
||||
notification.type !== "message" ||
|
||||
notification.type !== 'message' ||
|
||||
(notification as IMessageNotification).content.from.username !== username
|
||||
);
|
||||
|
||||
|
@ -216,23 +179,18 @@ function* getMessages({ username }: ReturnType<typeof authGetMessages>) {
|
|||
}
|
||||
}
|
||||
|
||||
function* sendMessage({
|
||||
message,
|
||||
onSuccess
|
||||
}: ReturnType<typeof authSendMessage>) {
|
||||
function* sendMessage({ message, onSuccess }: ReturnType<typeof authSendMessage>) {
|
||||
const {
|
||||
user: { username }
|
||||
user: { username },
|
||||
} = yield select(selectAuthProfile);
|
||||
|
||||
if (!username) return;
|
||||
|
||||
yield put(
|
||||
authSetProfile({ is_sending_messages: true, messages_error: null })
|
||||
);
|
||||
yield put(authSetProfile({ is_sending_messages: true, messages_error: null }));
|
||||
|
||||
const { error, data } = yield call(reqWrapper, apiAuthSendMessage, {
|
||||
username,
|
||||
message
|
||||
message,
|
||||
});
|
||||
|
||||
console.log({ error, data });
|
||||
|
@ -241,7 +199,7 @@ function* sendMessage({
|
|||
return yield put(
|
||||
authSetProfile({
|
||||
is_sending_messages: false,
|
||||
messages_error: error || ERRORS.EMPTY_RESPONSE
|
||||
messages_error: error || ERRORS.EMPTY_RESPONSE,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -255,7 +213,7 @@ function* sendMessage({
|
|||
yield put(
|
||||
authSetProfile({
|
||||
is_sending_messages: false,
|
||||
messages: [data.message, ...messages]
|
||||
messages: [data.message, ...messages],
|
||||
})
|
||||
);
|
||||
|
||||
|
@ -265,35 +223,28 @@ function* sendMessage({
|
|||
function* getUpdates() {
|
||||
const user = yield select(selectAuthUser);
|
||||
|
||||
if (!user || !user.is_user || user.role === USER_ROLES.GUEST || !user.id)
|
||||
return;
|
||||
if (!user || !user.is_user || user.role === USER_ROLES.GUEST || !user.id) return;
|
||||
|
||||
const modal: IModalState = yield select(selectModal);
|
||||
const profile: IAuthState["profile"] = yield select(selectAuthProfile);
|
||||
const { last }: IAuthState["updates"] = yield select(selectAuthUpdates);
|
||||
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;
|
||||
modal.is_shown && modal.dialog === DIALOGS.PROFILE && profile.user.id ? profile.user.id : null;
|
||||
|
||||
const {
|
||||
error,
|
||||
data
|
||||
}: IResultWithStatus<{ notifications: INotification[] }> = yield call(
|
||||
const { error, data }: IResultWithStatus<{ notifications: INotification[] }> = yield call(
|
||||
reqWrapper,
|
||||
apiAuthGetUpdates,
|
||||
{ exclude_dialogs, last: last || user.last_seen_messages }
|
||||
);
|
||||
|
||||
if (error || !data || !data.notifications || !data.notifications.length)
|
||||
return;
|
||||
if (error || !data || !data.notifications || !data.notifications.length) return;
|
||||
|
||||
const { notifications } = data;
|
||||
|
||||
yield put(
|
||||
authSetUpdates({
|
||||
last: notifications[0].created_at,
|
||||
notifications
|
||||
notifications,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -305,9 +256,7 @@ function* startPollingSaga() {
|
|||
}
|
||||
}
|
||||
|
||||
function* setLastSeenMessages({
|
||||
last_seen_messages
|
||||
}: ReturnType<typeof authSetLastSeenMessages>) {
|
||||
function* setLastSeenMessages({ last_seen_messages }: ReturnType<typeof authSetLastSeenMessages>) {
|
||||
if (!Date.parse(last_seen_messages)) return;
|
||||
|
||||
yield call(reqWrapper, apiUpdateUser, { user: { last_seen_messages } });
|
||||
|
@ -323,7 +272,19 @@ function* patchUser({ user }: ReturnType<typeof authPatchUser>) {
|
|||
}
|
||||
|
||||
yield put(authSetUser({ ...me, ...data.user }));
|
||||
yield put(authSetProfile({ user: { ...me, ...data.user }, tab: "profile" }));
|
||||
yield put(authSetProfile({ user: { ...me, ...data.user }, tab: 'profile' }));
|
||||
}
|
||||
|
||||
function* restorePassword({ code }: ReturnType<typeof authRestorePassword>) {
|
||||
if (!code && !code.length) {
|
||||
return yield put(
|
||||
authSetRestore({
|
||||
errors: { code: ERRORS.CODE_IS_INVALID },
|
||||
is_loading: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
console.log({ code });
|
||||
}
|
||||
|
||||
function* authSaga() {
|
||||
|
@ -336,11 +297,9 @@ function* authSaga() {
|
|||
yield takeLatest(AUTH_USER_ACTIONS.OPEN_PROFILE, openProfile);
|
||||
yield takeLatest(AUTH_USER_ACTIONS.GET_MESSAGES, getMessages);
|
||||
yield takeLatest(AUTH_USER_ACTIONS.SEND_MESSAGE, sendMessage);
|
||||
yield takeLatest(
|
||||
AUTH_USER_ACTIONS.SET_LAST_SEEN_MESSAGES,
|
||||
setLastSeenMessages
|
||||
);
|
||||
yield takeLatest(AUTH_USER_ACTIONS.SET_LAST_SEEN_MESSAGES, setLastSeenMessages);
|
||||
yield takeLatest(AUTH_USER_ACTIONS.PATCH_USER, patchUser);
|
||||
yield takeLatest(AUTH_USER_ACTIONS.RESTORE_PASSWORD, restorePassword);
|
||||
}
|
||||
|
||||
export default authSaga;
|
||||
|
|
|
@ -52,6 +52,7 @@ export type IAuthState = Readonly<{
|
|||
|
||||
restore: {
|
||||
code: string;
|
||||
user: Pick<IUser, 'username' | 'photo'>;
|
||||
is_loading: boolean;
|
||||
is_succesfull: boolean;
|
||||
errors: Record<string, string>;
|
||||
|
|
|
@ -8,12 +8,7 @@ import { EditorDialogAudio } from '~/containers/editors/EditorDialogAudio';
|
|||
import { NODE_TYPES } from '../node/constants';
|
||||
import { TestDialog } from '~/containers/dialogs/TestDialog';
|
||||
import { ProfileDialog } from '~/containers/dialogs/ProfileDialog';
|
||||
|
||||
export const MODAL_ACTIONS = {
|
||||
SET_SHOWN: 'MODAL.SET_SHOWN',
|
||||
SET_DIALOG: 'SET_DIALOG',
|
||||
SHOW_DIALOG: 'SHOW_DIALOG',
|
||||
};
|
||||
import { RestoreRequestDialog } from '~/containers/dialogs/RestoreRequestDialog';
|
||||
|
||||
export const DIALOGS = {
|
||||
EDITOR_IMAGE: 'EDITOR_IMAGE',
|
||||
|
@ -23,25 +18,14 @@ export const DIALOGS = {
|
|||
LOGIN: 'LOGIN',
|
||||
LOADING: 'LOADING',
|
||||
PROFILE: 'PROFILE',
|
||||
RESTORE_REQUEST: 'RESTORE_REQUEST',
|
||||
TEST: 'TEST',
|
||||
};
|
||||
|
||||
export const DIALOG_CONTENT = {
|
||||
[DIALOGS.EDITOR_IMAGE]: EditorDialogImage,
|
||||
[DIALOGS.EDITOR_TEXT]: EditorDialogText,
|
||||
[DIALOGS.EDITOR_VIDEO]: EditorDialogVideo,
|
||||
[DIALOGS.EDITOR_AUDIO]: EditorDialogAudio,
|
||||
[DIALOGS.LOGIN]: LoginDialog,
|
||||
[DIALOGS.LOADING]: LoadingDialog,
|
||||
[DIALOGS.TEST]: TestDialog,
|
||||
[DIALOGS.PROFILE]: ProfileDialog,
|
||||
};
|
||||
|
||||
export const NODE_EDITOR_DIALOGS = {
|
||||
[NODE_TYPES.IMAGE]: DIALOGS.EDITOR_IMAGE,
|
||||
[NODE_TYPES.TEXT]: DIALOGS.EDITOR_TEXT,
|
||||
[NODE_TYPES.VIDEO]: DIALOGS.EDITOR_VIDEO,
|
||||
[NODE_TYPES.AUDIO]: DIALOGS.EDITOR_AUDIO,
|
||||
export const MODAL_ACTIONS = {
|
||||
SET_SHOWN: 'MODAL.SET_SHOWN',
|
||||
SET_DIALOG: 'SET_DIALOG',
|
||||
SHOW_DIALOG: 'SHOW_DIALOG',
|
||||
};
|
||||
|
||||
export interface IDialogProps {
|
||||
|
|
|
@ -40,7 +40,8 @@ import { selectFlowNodes, selectFlow } from '../flow/selectors';
|
|||
import { URLS } from '~/constants/urls';
|
||||
import { selectNode } from './selectors';
|
||||
import { IResultWithStatus, INode } from '../types';
|
||||
import { NODE_EDITOR_DIALOGS, DIALOGS } from '../modal/constants';
|
||||
import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs';
|
||||
import { DIALOGS } from '~/redux/modal/constants';
|
||||
import { INodeState } from './reducer';
|
||||
import { IFlowState } from '../flow/reducer';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DetailedHTMLProps, InputHTMLAttributes } from "react";
|
||||
import { DIALOGS } from "~/redux/modal/constants";
|
||||
import { ERRORS } from "~/constants/errors";
|
||||
import { IUser } from "./auth/types";
|
||||
import { DetailedHTMLProps, InputHTMLAttributes } from 'react';
|
||||
import { DIALOGS } from '~/redux/modal/constants';
|
||||
import { ERRORS } from '~/constants/errors';
|
||||
import { IUser } from './auth/types';
|
||||
|
||||
export interface ITag {
|
||||
id: number;
|
||||
|
@ -55,7 +55,7 @@ export interface IResultWithStatus<T> {
|
|||
|
||||
export type UUID = string;
|
||||
|
||||
export type IUploadType = "image" | "text" | "audio" | "video" | "other";
|
||||
export type IUploadType = 'image' | 'text' | 'audio' | 'video' | 'other';
|
||||
|
||||
export interface IFile {
|
||||
id?: number;
|
||||
|
@ -96,12 +96,12 @@ export interface IFileWithUUID {
|
|||
}
|
||||
|
||||
export interface IBlockText {
|
||||
type: "text";
|
||||
type: 'text';
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface IBlockEmbed {
|
||||
type: "video";
|
||||
type: 'video';
|
||||
url: string;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ export interface INode {
|
|||
is_heroic?: boolean;
|
||||
|
||||
flow: {
|
||||
display: "single" | "vertical" | "horizontal" | "quadro";
|
||||
display: 'single' | 'vertical' | 'horizontal' | 'quadro';
|
||||
show_description: boolean;
|
||||
};
|
||||
|
||||
|
@ -147,7 +147,7 @@ export interface IComment {
|
|||
update_at?: string;
|
||||
}
|
||||
|
||||
export type IMessage = Omit<IComment, "user" | "node"> & {
|
||||
export type IMessage = Omit<IComment, 'user' | 'node'> & {
|
||||
from: IUser;
|
||||
to: IUser;
|
||||
};
|
||||
|
@ -155,7 +155,7 @@ export type IMessage = Omit<IComment, "user" | "node"> & {
|
|||
export interface ICommentGroup {
|
||||
user: IUser;
|
||||
comments: IComment[];
|
||||
ids: IComment["id"][];
|
||||
ids: IComment['id'][];
|
||||
}
|
||||
|
||||
export type IUploadProgressHandler = (progress: ProgressEvent) => void;
|
||||
|
@ -164,25 +164,25 @@ export type IValidationErrors = Record<string, IError>;
|
|||
export type InputHandler<T = string> = (val: T) => void;
|
||||
|
||||
export const NOTIFICATION_TYPES = {
|
||||
message: "message",
|
||||
comment: "comment",
|
||||
node: "node"
|
||||
message: 'message',
|
||||
comment: 'comment',
|
||||
node: 'node',
|
||||
};
|
||||
|
||||
export type IMessageNotification = {
|
||||
type: typeof NOTIFICATION_TYPES["message"];
|
||||
type: typeof NOTIFICATION_TYPES['message'];
|
||||
content: Partial<IMessage>;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type ICommentNotification = {
|
||||
type: typeof NOTIFICATION_TYPES["comment"];
|
||||
type: typeof NOTIFICATION_TYPES['comment'];
|
||||
content: Partial<IComment>;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type INodeNotification = {
|
||||
type: typeof NOTIFICATION_TYPES["node"];
|
||||
type: typeof NOTIFICATION_TYPES['node'];
|
||||
content: Partial<INode>;
|
||||
created_at: string;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue