mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-25 12:56:41 +07:00
refactored component errors
This commit is contained in:
parent
7031084b09
commit
d4c2e7ee09
79 changed files with 573 additions and 462 deletions
|
@ -31,7 +31,7 @@ export type IStatBackend = {
|
|||
export type IBorisState = Readonly<{
|
||||
stats: {
|
||||
git: Partial<IStatGitRow>[];
|
||||
backend: IStatBackend;
|
||||
backend?: IStatBackend;
|
||||
is_loading: boolean;
|
||||
};
|
||||
}>;
|
||||
|
@ -39,7 +39,7 @@ export type IBorisState = Readonly<{
|
|||
const BORIS_INITIAL_STATE: IBorisState = {
|
||||
stats: {
|
||||
git: [],
|
||||
backend: null,
|
||||
backend: undefined,
|
||||
is_loading: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ export const nodeSetSaveErrors = (errors: IValidationErrors) => ({
|
|||
type: NODE_ACTIONS.SET_SAVE_ERRORS,
|
||||
});
|
||||
|
||||
export const nodeGotoNode = (id: number, node_type: INode['type']) => ({
|
||||
export const nodeGotoNode = (id: INode['id'], node_type: INode['type']) => ({
|
||||
id,
|
||||
node_type,
|
||||
type: NODE_ACTIONS.GOTO_NODE,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { FC } from 'react';
|
||||
import { FC, ReactElement } from 'react';
|
||||
import { IComment, INode, ValueOf } from '../types';
|
||||
import { NodeImageSlideBlock } from '~/components/node/NodeImageSlideBlock';
|
||||
import { NodeTextBlock } from '~/components/node/NodeTextBlock';
|
||||
|
@ -13,7 +13,7 @@ import { EditorImageUploadButton } from '~/components/editors/EditorImageUploadB
|
|||
import { EditorAudioUploadButton } from '~/components/editors/EditorAudioUploadButton';
|
||||
import { EditorUploadCoverButton } from '~/components/editors/EditorUploadCoverButton';
|
||||
import { modalShowPhotoswipe } from '../modal/actions';
|
||||
import { IEditorComponentProps } from '~/redux/node/types';
|
||||
import { IEditorComponentProps, NodeEditorProps } from '~/redux/node/types';
|
||||
import { EditorFiller } from '~/components/editors/EditorFiller';
|
||||
|
||||
const prefix = 'NODE.';
|
||||
|
@ -50,15 +50,13 @@ export const NODE_ACTIONS = {
|
|||
};
|
||||
|
||||
export const EMPTY_NODE: INode = {
|
||||
id: null,
|
||||
|
||||
user: null,
|
||||
|
||||
id: 0,
|
||||
user: undefined,
|
||||
title: '',
|
||||
files: [],
|
||||
|
||||
cover: null,
|
||||
type: null,
|
||||
cover: undefined,
|
||||
type: undefined,
|
||||
|
||||
blocks: [],
|
||||
tags: [],
|
||||
|
@ -102,13 +100,16 @@ export const NODE_INLINES: INodeComponents = {
|
|||
};
|
||||
|
||||
export const EMPTY_COMMENT: IComment = {
|
||||
id: null,
|
||||
id: 0,
|
||||
text: '',
|
||||
files: [],
|
||||
user: null,
|
||||
user: undefined,
|
||||
};
|
||||
|
||||
export const NODE_EDITORS = {
|
||||
export const NODE_EDITORS: Record<
|
||||
typeof NODE_TYPES[keyof typeof NODE_TYPES],
|
||||
FC<NodeEditorProps>
|
||||
> = {
|
||||
[NODE_TYPES.IMAGE]: ImageEditor,
|
||||
[NODE_TYPES.TEXT]: TextEditor,
|
||||
[NODE_TYPES.VIDEO]: VideoEditor,
|
||||
|
|
|
@ -8,12 +8,12 @@ export type INodeState = Readonly<{
|
|||
current: INode;
|
||||
comments: IComment[];
|
||||
related: {
|
||||
albums: Record<string, Partial<INode[]>>;
|
||||
similar: Partial<INode[]>;
|
||||
albums: Record<string, INode[]>;
|
||||
similar: INode[];
|
||||
};
|
||||
comment_data: Record<number, IComment>;
|
||||
comment_count: number;
|
||||
current_cover_image: IFile;
|
||||
current_cover_image?: IFile;
|
||||
|
||||
error: string;
|
||||
errors: Record<string, string>;
|
||||
|
@ -38,14 +38,17 @@ const INITIAL_STATE: INodeState = {
|
|||
},
|
||||
comment_count: 0,
|
||||
comments: [],
|
||||
related: null,
|
||||
current_cover_image: null,
|
||||
related: {
|
||||
albums: {},
|
||||
similar: [],
|
||||
},
|
||||
current_cover_image: undefined,
|
||||
|
||||
is_loading: false,
|
||||
is_loading_comments: false,
|
||||
is_sending_comment: false,
|
||||
|
||||
error: null,
|
||||
error: '',
|
||||
errors: {},
|
||||
};
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ import { selectNode } from './selectors';
|
|||
import { Unwrap } from '../types';
|
||||
import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs';
|
||||
import { DIALOGS } from '~/redux/modal/constants';
|
||||
import { has } from 'ramda';
|
||||
|
||||
export function* updateNodeEverywhere(node) {
|
||||
const {
|
||||
|
@ -103,6 +104,9 @@ function* onNodeSave({ node }: ReturnType<typeof nodeSave>) {
|
|||
}
|
||||
|
||||
function* onNodeGoto({ id, node_type }: ReturnType<typeof nodeGotoNode>) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
if (node_type) yield put(nodeSetCurrent({ ...EMPTY_NODE, type: node_type }));
|
||||
|
||||
yield put(nodeLoadNode(id));
|
||||
|
@ -224,7 +228,7 @@ function* onUpdateTags({ id, tags }: ReturnType<typeof nodeUpdateTags>) {
|
|||
}
|
||||
|
||||
function* onCreateSaga({ node_type: type }: ReturnType<typeof nodeCreate>) {
|
||||
if (!NODE_EDITOR_DIALOGS[type]) return;
|
||||
if (!type || !has(type, NODE_EDITOR_DIALOGS)) return;
|
||||
|
||||
yield put(nodeSetEditor({ ...EMPTY_NODE, ...(NODE_EDITOR_DATA[type] || {}), type }));
|
||||
yield put(modalShowDialog(NODE_EDITOR_DIALOGS[type]));
|
||||
|
@ -240,6 +244,8 @@ function* onEditSaga({ id }: ReturnType<typeof nodeEdit>) {
|
|||
|
||||
const { node }: Unwrap<typeof apiGetNode> = yield call(apiGetNode, { id });
|
||||
|
||||
if (!node.type || !has(node.type, NODE_EDITOR_DIALOGS)) return;
|
||||
|
||||
if (!NODE_EDITOR_DIALOGS[node?.type]) {
|
||||
throw new Error('Unknown node type');
|
||||
}
|
||||
|
|
|
@ -83,3 +83,9 @@ export type ApiLockCommentRequest = {
|
|||
export type ApiLockcommentResult = {
|
||||
deleted_at: string;
|
||||
};
|
||||
export type NodeEditorProps = {
|
||||
data: INode;
|
||||
setData: (val: INode) => void;
|
||||
temp: string[];
|
||||
setTemp: (val: string[]) => void;
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ export interface IFile {
|
|||
url: string;
|
||||
size: number;
|
||||
|
||||
type: IUploadType;
|
||||
type?: IUploadType;
|
||||
mime: string;
|
||||
metadata?: {
|
||||
id3title?: string;
|
||||
|
@ -92,7 +92,7 @@ export interface IFileWithUUID {
|
|||
file: File;
|
||||
subject?: string;
|
||||
target: string;
|
||||
type: string;
|
||||
type?: string;
|
||||
onSuccess?: (file: IFile) => void;
|
||||
onFail?: () => void;
|
||||
}
|
||||
|
@ -111,13 +111,13 @@ export type IBlock = IBlockText | IBlockEmbed;
|
|||
|
||||
export interface INode {
|
||||
id?: number;
|
||||
user: Partial<IUser>;
|
||||
user?: Partial<IUser>;
|
||||
|
||||
title: string;
|
||||
files: IFile[];
|
||||
|
||||
cover: IFile;
|
||||
type: string;
|
||||
cover?: IFile;
|
||||
type?: string;
|
||||
|
||||
blocks: IBlock[];
|
||||
thumbnail?: string;
|
||||
|
@ -143,7 +143,7 @@ export interface IComment {
|
|||
id: number;
|
||||
text: string;
|
||||
files: IFile[];
|
||||
user: IUser;
|
||||
user?: IUser;
|
||||
|
||||
created_at?: string;
|
||||
update_at?: string;
|
||||
|
|
|
@ -15,9 +15,9 @@ export const UPLOAD_ACTIONS = {
|
|||
};
|
||||
|
||||
export const EMPTY_FILE: IFile = {
|
||||
id: null,
|
||||
user_id: null,
|
||||
node_id: null,
|
||||
id: undefined,
|
||||
user_id: undefined,
|
||||
node_id: undefined,
|
||||
|
||||
name: '',
|
||||
orig_name: '',
|
||||
|
@ -25,21 +25,21 @@ export const EMPTY_FILE: IFile = {
|
|||
full_path: '',
|
||||
url: '',
|
||||
size: 0,
|
||||
type: null,
|
||||
type: undefined,
|
||||
mime: '',
|
||||
};
|
||||
|
||||
export const EMPTY_UPLOAD_STATUS: IUploadStatus = {
|
||||
is_uploading: false,
|
||||
preview: null,
|
||||
error: null,
|
||||
uuid: null,
|
||||
url: null,
|
||||
preview: '',
|
||||
error: '',
|
||||
uuid: 0,
|
||||
url: '',
|
||||
progress: 0,
|
||||
thumbnail_url: null,
|
||||
type: null,
|
||||
temp_id: null,
|
||||
name: null,
|
||||
thumbnail_url: '',
|
||||
type: '',
|
||||
temp_id: '',
|
||||
name: '',
|
||||
};
|
||||
|
||||
// for targeted cancellation
|
||||
|
|
|
@ -2,38 +2,41 @@ import { assocPath } from 'ramda';
|
|||
import { omit } from 'ramda';
|
||||
|
||||
import { UPLOAD_ACTIONS, EMPTY_UPLOAD_STATUS } from './constants';
|
||||
import {
|
||||
uploadAddStatus, uploadDropStatus, uploadSetStatus, uploadAddFile
|
||||
} from './actions';
|
||||
import { uploadAddStatus, uploadDropStatus, uploadSetStatus, uploadAddFile } from './actions';
|
||||
import { IUploadState } from './reducer';
|
||||
|
||||
const addStatus = (
|
||||
state: IUploadState,
|
||||
{ temp_id, status, }: ReturnType<typeof uploadAddStatus>
|
||||
): IUploadState => assocPath(
|
||||
['statuses'],
|
||||
{ ...state.statuses, [temp_id]: { ...EMPTY_UPLOAD_STATUS, ...status, }, },
|
||||
state
|
||||
);
|
||||
{ temp_id, status }: ReturnType<typeof uploadAddStatus>
|
||||
): IUploadState =>
|
||||
assocPath(
|
||||
['statuses'],
|
||||
{ ...state.statuses, [temp_id]: { ...EMPTY_UPLOAD_STATUS, ...status } },
|
||||
state
|
||||
);
|
||||
|
||||
const dropStatus = (
|
||||
state: IUploadState,
|
||||
{ temp_id, }: ReturnType<typeof uploadDropStatus>
|
||||
{ temp_id }: ReturnType<typeof uploadDropStatus>
|
||||
): IUploadState => assocPath(['statuses'], omit([temp_id], state.statuses), state);
|
||||
|
||||
const setStatus = (
|
||||
state: IUploadState,
|
||||
{ temp_id, status, }: ReturnType<typeof uploadSetStatus>
|
||||
): IUploadState => assocPath(
|
||||
['statuses'],
|
||||
{
|
||||
...state.statuses,
|
||||
[temp_id]: { ...(state.statuses[temp_id] || EMPTY_UPLOAD_STATUS), ...status, },
|
||||
},
|
||||
state
|
||||
);
|
||||
{ temp_id, status }: ReturnType<typeof uploadSetStatus>
|
||||
): IUploadState =>
|
||||
assocPath(
|
||||
['statuses'],
|
||||
{
|
||||
...state.statuses,
|
||||
[temp_id]: { ...(state.statuses[temp_id] || EMPTY_UPLOAD_STATUS), ...status },
|
||||
},
|
||||
state
|
||||
);
|
||||
|
||||
const addFile = (state: IUploadState, { file, }: ReturnType<typeof uploadAddFile>): IUploadState => assocPath(['files'], { ...state.files, [file.id]: file, }, state);
|
||||
const addFile = (state: IUploadState, { file }: ReturnType<typeof uploadAddFile>): IUploadState => {
|
||||
if (!file.id) return state;
|
||||
return assocPath(['files', file.id], file, state);
|
||||
};
|
||||
|
||||
export const UPLOAD_HANDLERS = {
|
||||
[UPLOAD_ACTIONS.ADD_STATUS]: addStatus,
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import uuid from 'uuid4';
|
||||
import { IResultWithStatus, IFile, UUID } from '../types';
|
||||
import { HTTP_RESPONSES } from '~/utils/api';
|
||||
import { EMPTY_FILE } from './constants';
|
||||
|
||||
export const uploadMock = ({ temp_id, file }: { temp_id: UUID; file: File }): Promise<IResultWithStatus<IFile>> => (
|
||||
Promise.resolve({
|
||||
status: HTTP_RESPONSES.CREATED,
|
||||
data: {
|
||||
...EMPTY_FILE,
|
||||
id: uuid(),
|
||||
temp_id,
|
||||
},
|
||||
error: null,
|
||||
}));
|
|
@ -73,7 +73,7 @@ function* uploadFile({ file, temp_id, type, target, onSuccess, onFail }: IFileWi
|
|||
if (!temp_id) return;
|
||||
|
||||
try {
|
||||
if (!file.type || !FILE_MIMES[type] || !FILE_MIMES[type].includes(file.type)) {
|
||||
if (!file.type || !type || !FILE_MIMES[type] || !FILE_MIMES[type].includes(file.type)) {
|
||||
return {
|
||||
error: 'File_Not_Image',
|
||||
status: HTTP_RESPONSES.BAD_REQUEST,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue