mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
eslint fix
This commit is contained in:
parent
dfaac877fb
commit
fa4d51360b
81 changed files with 741 additions and 972 deletions
27
.eslintrc.js
27
.eslintrc.js
|
@ -1,26 +1,27 @@
|
|||
module.exports = {
|
||||
extends: ['airbnb', 'airbnb-base', 'plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
extends: ['airbnb', 'airbnb-base', 'prettier/@typescript-eslint', 'plugin:@typescript-eslint/recommended'],
|
||||
// "parser": "babel-eslint",
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
jsx: true,
|
||||
},
|
||||
project: './tsconfig.json'
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'react', 'jsx-a11y', 'import', 'react-hooks', 'prettier'],
|
||||
plugins: ['@typescript-eslint', 'react', 'jsx-a11y', 'import', 'react-hooks'],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
// node: {
|
||||
// extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
// },
|
||||
typescript: {}
|
||||
}
|
||||
typescript: {},
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
indent: ['error', 2],
|
||||
'@typescript-eslint/explicit-function-return-type': 0,
|
||||
'@typescript-eslint/indent': ['error', 2],
|
||||
'@typescript-eslint/indent': ['warn', 2],
|
||||
"indent": "off",
|
||||
'comma-dangle': 0,
|
||||
'no-restricted-syntax': 1,
|
||||
'react/prop-types': 0,
|
||||
|
@ -44,16 +45,16 @@ module.exports = {
|
|||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
'no-nested-ternary': 1,
|
||||
'arrow-parens': 0,
|
||||
'import/prefer-default-export': 0,
|
||||
'no-return-await': 0,
|
||||
'prefer-promise-reject-errors': 0,
|
||||
'import/order': 0
|
||||
'max-line-length': [true, 100],
|
||||
// 'max-len': 100,
|
||||
// 'max-len': { "code": 100 },
|
||||
'max-len': ["warn", { "code": 100 }]
|
||||
},
|
||||
globals: {
|
||||
document: false,
|
||||
window: false,
|
||||
HTMLInputElement: false,
|
||||
HTMLDivElement: false
|
||||
}
|
||||
HTMLDivElement: false,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"printWidth": 120,
|
||||
"printWidth": 100,
|
||||
"singleQuote": true
|
||||
}
|
20
.vscode/settings.json
vendored
Normal file
20
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
|
||||
"editor.rulers": [100],
|
||||
"prettier.eslintIntegration": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveTimeout": 750,
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveTimeout": 750,
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveTimeout": 750,
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveTimeout": 750,
|
||||
},
|
||||
}
|
518
package-lock.json
generated
518
package-lock.json
generated
File diff suppressed because it is too large
Load diff
27
package.json
27
package.json
|
@ -27,18 +27,6 @@
|
|||
"babel-preset-react": "^6.24.1",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"css-loader": "^0.28.11",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-airbnb": "^17.1.1",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-import-resolver-babel-module": "^4.0.0",
|
||||
"eslint-import-resolver-typescript": "^1.1.1",
|
||||
"eslint-import-resolver-webpack": "^0.9.0",
|
||||
"eslint-loader": "^2.2.1",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"eslint-plugin-react": "^7.14.3",
|
||||
"file-loader": "^1.1.11",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
|
@ -51,7 +39,6 @@
|
|||
"style-loader": "^0.21.0",
|
||||
"ts-node": "^8.0.1",
|
||||
"typescript": "^3.2.4",
|
||||
"typescript-eslint-parser": "^22.0.0",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"webpack": "^4.6.0",
|
||||
"webpack-cli": "^3.2.3",
|
||||
|
@ -74,7 +61,19 @@
|
|||
"date-fns": "^2.0.0-alpha.27",
|
||||
"dotenv": "^8.0.0",
|
||||
"dotenv-webpack": "^1.7.0",
|
||||
"eslint-plugin-react-hooks": "^1.6.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-airbnb": "^17.1.1",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-import-resolver-babel-module": "^4.0.0",
|
||||
"eslint-import-resolver-typescript": "^1.1.1",
|
||||
"eslint-import-resolver-webpack": "^0.9.0",
|
||||
"eslint-loader": "^2.2.1",
|
||||
"eslint-plugin-babel": "^5.3.0",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"eslint-plugin-react": "^7.14.3",
|
||||
"eslint-plugin-react-hooks": "^1.7.0",
|
||||
"history": "^4.7.2",
|
||||
"http-errors": "~1.6.2",
|
||||
"less": "^3.8.1",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { AllHTMLAttributes, FC } from "react";
|
||||
import * as styles from "./styles.scss";
|
||||
import React, { AllHTMLAttributes, FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
type IProps = AllHTMLAttributes<HTMLDivElement> & { is_blurred: boolean };
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { FC } from 'react';
|
||||
import classNames = require("classnames");
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
seamless?: boolean;
|
||||
}
|
||||
|
@ -12,12 +13,12 @@ const Card: FC<IProps> = ({
|
|||
seamless,
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.card, className, { seamless })}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.card, className, { seamless })}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { Card };
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import React, { FC, HTMLAttributes, ReactChild, ReactChildren } from 'react';
|
||||
import React, {
|
||||
FC, HTMLAttributes, ReactChild, ReactChildren
|
||||
} from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||
children: any;
|
||||
|
@ -13,13 +16,13 @@ const CellGrid: FC<IProps> = ({
|
|||
className,
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.grid, className)}
|
||||
style={{ gridTemplateColumns: `repeat(auto-fit, minmax(${size}px, 1fr))` }}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.grid, className)}
|
||||
style={{ gridTemplateColumns: `repeat(auto-fit, minmax(${size}px, 1fr))` }}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { CellGrid };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { FC } from "react";
|
||||
import classNames from "classnames";
|
||||
import * as styles from "./styles.scss";
|
||||
import React, { FC } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
horizontal?: boolean;
|
||||
|
@ -15,14 +15,14 @@ type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
|||
|
||||
const Grid: FC<IProps> = ({
|
||||
children,
|
||||
className = "",
|
||||
className = '',
|
||||
horizontal = false,
|
||||
vertical = false,
|
||||
square = false,
|
||||
size = "auto",
|
||||
size = 'auto',
|
||||
style = {},
|
||||
columns = "auto",
|
||||
rows = "auto",
|
||||
columns = 'auto',
|
||||
rows = 'auto',
|
||||
gap = 10,
|
||||
stretchy,
|
||||
...props
|
||||
|
@ -37,10 +37,10 @@ const Grid: FC<IProps> = ({
|
|||
style={{
|
||||
...style,
|
||||
gridTemplateColumns: square
|
||||
? `repeat(auto-fill, ${(columns !== "auto" && columns) || size})`
|
||||
? `repeat(auto-fill, ${(columns !== 'auto' && columns) || size})`
|
||||
: columns,
|
||||
gridTemplateRows: square
|
||||
? `repeat(auto-fill, ${(rows !== "auto" && rows) || size})`
|
||||
? `repeat(auto-fill, ${(rows !== 'auto' && rows) || size})`
|
||||
: rows,
|
||||
gridAutoRows: rows,
|
||||
gridAutoColumns: columns,
|
||||
|
|
|
@ -18,7 +18,7 @@ const Group: FC<IProps> = ({
|
|||
bottom = false,
|
||||
wrap = false,
|
||||
seamless = false,
|
||||
...props
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
import classNames = require('classnames');
|
||||
|
||||
type IProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
padding?: number;
|
||||
vertical?: boolean;
|
||||
horizontal?: boolean;
|
||||
|
@ -17,13 +18,13 @@ const Padder: FC<IProps> = ({
|
|||
horizontal,
|
||||
...props
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.padder, className, { vertical, horizontal })}
|
||||
style={padding ? { ...style, padding } : style}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.padder, className, { vertical, horizontal })}
|
||||
style={padding ? { ...style, padding } : style}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { Padder };
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||
seamless?: boolean;
|
||||
stretchy?: boolean
|
||||
stretchy?: boolean;
|
||||
}
|
||||
|
||||
const Panel: FC<IProps> = ({
|
||||
|
@ -14,9 +15,9 @@ const Panel: FC<IProps> = ({
|
|||
stretchy,
|
||||
...props
|
||||
}) => (
|
||||
<div className={classNames(styles.panel, className, { seamless, stretchy })} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={classNames(styles.panel, className, { seamless, stretchy })} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { Panel };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { MouseEventHandler, useEffect, useState } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Scrollbars } from 'tt-react-custom-scrollbars';
|
||||
import classNames from 'classnames';
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
interface IProps {
|
||||
children: Element | React.ReactChild;
|
||||
|
@ -33,11 +33,11 @@ export const Scroll = ({
|
|||
renderTrackVertical={data => <div className={styles.track_vertical} {...data} />}
|
||||
renderThumbHorizontal={data => <div className={styles.thumb_horizontal} {...data} />}
|
||||
renderThumbVertical={data => <div className={styles.thumb_vertical} {...data} />}
|
||||
renderView = {data => <div className={styles.view} {...data} />}
|
||||
renderView={data => <div className={styles.view} {...data} />}
|
||||
hideTracksWhenNotNeeded
|
||||
universal
|
||||
ref={setRef}
|
||||
{ ...props }
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Scrollbars>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, {FC, HTMLAttributes} from 'react';
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {}
|
||||
|
||||
const TagField: FC<IProps> = ({
|
||||
children,
|
||||
children,
|
||||
}) => (
|
||||
<div className={styles.wrap}>
|
||||
{children}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { FC, ChangeEventHandler } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { INode } from '~/redux/types';
|
||||
import { ImageUploadButton } from '~/components/editors/ImageUploadButton';
|
||||
import { EditorUploadButton } from '~/components/editors/EditorUploadButton';
|
||||
|
||||
interface IProps {
|
||||
data: INode;
|
||||
|
@ -11,7 +11,7 @@ interface IProps {
|
|||
|
||||
const EditorPanel: FC<IProps> = ({ onUpload }) => (
|
||||
<div className={styles.panel}>
|
||||
<ImageUploadButton onUpload={onUpload} />
|
||||
<EditorUploadButton onUpload={onUpload} />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
21
src/components/editors/EditorUploadButton/index.tsx
Normal file
21
src/components/editors/EditorUploadButton/index.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React, { FC, ChangeEventHandler } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
|
||||
interface IProps {
|
||||
onUpload?: ChangeEventHandler<HTMLInputElement>;
|
||||
}
|
||||
|
||||
const EditorUploadButton: FC<IProps> = ({
|
||||
onUpload,
|
||||
}) => (
|
||||
<div className={styles.wrap}>
|
||||
<input type="file" onChange={onUpload} accept="image/*" multiple />
|
||||
|
||||
<div className={styles.icon}>
|
||||
<Icon size={32} icon="plus" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export { EditorUploadButton };
|
|
@ -1,40 +1,55 @@
|
|||
import React, { FC, useCallback, useEffect, useState, ChangeEventHandler, DragEventHandler } from 'react';
|
||||
import React, {
|
||||
FC,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
ChangeEventHandler,
|
||||
DragEventHandler
|
||||
} from 'react';
|
||||
import uuid from 'uuid4';
|
||||
import { INode, IFileWithUUID, IFile } from '~/redux/types';
|
||||
import * as UPLOAD_ACTIONS from '~/redux/uploads/actions';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectUploads } from '~/redux/uploads/selectors';
|
||||
import assocPath from 'ramda/es/assocPath';
|
||||
import append from 'ramda/es/append';
|
||||
import { INode, IFileWithUUID, IFile } from '~/redux/types';
|
||||
import * as UPLOAD_ACTIONS from '~/redux/uploads/actions';
|
||||
import { selectUploads } from '~/redux/uploads/selectors';
|
||||
import { ImageGrid } from '~/components/editors/ImageGrid';
|
||||
import { moveArrItem } from '~/utils/fn';
|
||||
import { IUploadStatus } from '~/redux/uploads/reducer';
|
||||
|
||||
const mapStateToProps = selectUploads;
|
||||
const mapDispatchToProps = {
|
||||
uploadUploadFiles: UPLOAD_ACTIONS.uploadUploadFiles,
|
||||
uploadUploadFiles: UPLOAD_ACTIONS.uploadUploadFiles
|
||||
};
|
||||
|
||||
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {
|
||||
type IProps = ReturnType<typeof mapStateToProps> &
|
||||
typeof mapDispatchToProps & {
|
||||
data: INode;
|
||||
pending_files: IUploadStatus[];
|
||||
setData: (val: INode) => void;
|
||||
onFileMove: (o: number, n: number) => void;
|
||||
onInputChange: ChangeEventHandler<HTMLInputElement>;
|
||||
onDrop: DragEventHandler<HTMLFormElement>;
|
||||
}
|
||||
|
||||
const ImageEditorUnconnected: FC<IProps> = ({ data, onFileMove, onInputChange, onDrop, pending_files }) => {
|
||||
return (
|
||||
<ImageGrid
|
||||
onFileMove={onFileMove}
|
||||
items={data.files}
|
||||
locked={pending_files}
|
||||
onUpload={onInputChange}
|
||||
onDrop={onDrop}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ImageEditor = connect(mapStateToProps, mapDispatchToProps)(ImageEditorUnconnected)
|
||||
const ImageEditorUnconnected: FC<IProps> = ({
|
||||
data,
|
||||
onFileMove,
|
||||
onInputChange,
|
||||
onDrop,
|
||||
pending_files
|
||||
}) => (
|
||||
<ImageGrid
|
||||
onFileMove={onFileMove}
|
||||
items={data.files}
|
||||
locked={pending_files}
|
||||
onUpload={onInputChange}
|
||||
onDrop={onDrop}
|
||||
/>
|
||||
);
|
||||
|
||||
const ImageEditor = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ImageEditorUnconnected);
|
||||
export { ImageEditor };
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React, { FC, ReactChildren, useCallback, ChangeEventHandler, DragEventHandler } from 'react';
|
||||
import React, {
|
||||
FC, ReactChildren, useCallback, ChangeEventHandler, DragEventHandler
|
||||
} from 'react';
|
||||
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
|
||||
import * as styles from './styles.scss';
|
||||
import { ImageUpload } from '~/components/upload/ImageUpload';
|
||||
import { IFile } from '~/redux/types';
|
||||
import { IUploadStatus } from '~/redux/uploads/reducer';
|
||||
import { ImageUploadButton } from '~/components/editors/ImageUploadButton';
|
||||
|
||||
interface IProps {
|
||||
items: IFile[];
|
||||
|
@ -12,50 +13,52 @@ interface IProps {
|
|||
onFileMove: (o: number, n: number) => void;
|
||||
onUpload?: ChangeEventHandler<HTMLInputElement>;
|
||||
onDrop: DragEventHandler<HTMLFormElement>;
|
||||
};
|
||||
}
|
||||
|
||||
const SortableItem = SortableElement(({ children }) => <div className={styles.item}>{children}</div>);
|
||||
|
||||
const SortableList = SortableContainer(({ items, locked, onUpload, onDrop }: { items: IFile[]; locked: IUploadStatus[]; onUpload: ChangeEventHandler<HTMLInputElement>; onDrop: DragEventHandler<HTMLFormElement> }) => {
|
||||
return (
|
||||
const SortableList = SortableContainer(
|
||||
({
|
||||
items,
|
||||
locked,
|
||||
onDrop
|
||||
}: {
|
||||
items: IFile[];
|
||||
locked: IUploadStatus[];
|
||||
onUpload: ChangeEventHandler<HTMLInputElement>;
|
||||
onDrop: DragEventHandler<HTMLFormElement>;
|
||||
}) => (
|
||||
<form className={styles.grid} onDrop={onDrop}>
|
||||
{
|
||||
items.map((file, index) => (
|
||||
<SortableItem key={file.id} index={index} collection={0}>
|
||||
<ImageUpload
|
||||
id={file.id}
|
||||
thumb={file.url}
|
||||
/>
|
||||
</SortableItem>
|
||||
))
|
||||
}
|
||||
{
|
||||
locked.map((item, index) => (
|
||||
<SortableItem key={item.temp_id} index={index} collection={1} disabled>
|
||||
<ImageUpload
|
||||
thumb={item.preview}
|
||||
progress={item.progress}
|
||||
is_uploading
|
||||
/>
|
||||
</SortableItem>
|
||||
))
|
||||
}
|
||||
{items.map((file, index) => (
|
||||
<SortableItem key={file.id} index={index} collection={0}>
|
||||
<ImageUpload id={file.id} thumb={file.url} />
|
||||
</SortableItem>
|
||||
))}
|
||||
{locked.map((item, index) => (
|
||||
<SortableItem key={item.temp_id} index={index} collection={1} disabled>
|
||||
<ImageUpload thumb={item.preview} progress={item.progress} is_uploading />
|
||||
</SortableItem>
|
||||
))}
|
||||
</form>
|
||||
);
|
||||
});
|
||||
)
|
||||
);
|
||||
|
||||
const ImageGrid: FC<IProps> = ({
|
||||
items,
|
||||
locked,
|
||||
onFileMove,
|
||||
onUpload,
|
||||
onDrop,
|
||||
items, locked, onFileMove, onUpload, onDrop
|
||||
}) => {
|
||||
const onMove = useCallback(({ oldIndex, newIndex }) => onFileMove(oldIndex, newIndex), [onFileMove]);
|
||||
|
||||
return (
|
||||
<SortableList onSortEnd={onMove} axis="xy" items={items} locked={locked} onUpload={onUpload} onDrop={onDrop} pressDelay={100} />
|
||||
)
|
||||
}
|
||||
<SortableList
|
||||
onSortEnd={onMove}
|
||||
axis="xy"
|
||||
items={items}
|
||||
locked={locked}
|
||||
onUpload={onUpload}
|
||||
onDrop={onDrop}
|
||||
pressDelay={100}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { ImageGrid };
|
||||
export { ImageGrid };
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
import React, { FC, ChangeEventHandler } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
|
||||
interface IProps {
|
||||
onUpload?: ChangeEventHandler<HTMLInputElement>;
|
||||
};
|
||||
|
||||
const ImageUploadButton: FC<IProps> = ({
|
||||
onUpload,
|
||||
}) => (
|
||||
<div className={styles.wrap}>
|
||||
<input type="file" onChange={onUpload} accept="image/*" multiple />
|
||||
|
||||
<div className={styles.icon}>
|
||||
<Icon size={32} icon="plus" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export { ImageUploadButton };
|
|
@ -1,6 +1,7 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
interface IProps {
|
||||
height?: number;
|
||||
|
@ -16,15 +17,15 @@ const Cell: FC<IProps> = ({
|
|||
title,
|
||||
is_hero,
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.cell, { is_hero })}
|
||||
style={{
|
||||
gridRowEnd: `span ${height}`,
|
||||
gridColumnEnd: `span ${width}`,
|
||||
}}
|
||||
>
|
||||
{ title && <div className={styles.title}>{title}</div> }
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.cell, { is_hero })}
|
||||
style={{
|
||||
gridRowEnd: `span ${height}`,
|
||||
gridColumnEnd: `span ${width}`,
|
||||
}}
|
||||
>
|
||||
{ title && <div className={styles.title}>{title}</div> }
|
||||
</div>
|
||||
);
|
||||
|
||||
export { Cell };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
const style = require('./style.scss');
|
||||
|
||||
export const HeroPlaceholder = () => (
|
||||
<div className={style.container}>
|
||||
</div>
|
||||
<div className={style.container} />
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react';
|
||||
import { Cell } from '~/components/flow/Cell';
|
||||
import { range } from 'ramda';
|
||||
import { Cell } from '~/components/flow/Cell';
|
||||
|
||||
import * as styles from './styles.scss';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { describeArc } from '~/utils/dom';
|
|||
interface IProps {
|
||||
size: number;
|
||||
progress: number;
|
||||
};
|
||||
}
|
||||
|
||||
export const ArcProgress: FC<IProps> = ({ size, progress }) => (
|
||||
<svg className={styles.icon} width={size} height={size}>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import classnames from "classnames";
|
||||
import * as styles from "./styles.scss";
|
||||
import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from "react";
|
||||
import { Icon } from "~/components/input/Icon";
|
||||
import { IIcon } from "~/redux/types";
|
||||
import classnames from 'classnames';
|
||||
import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { IIcon } from '~/redux/types';
|
||||
|
||||
type IButtonProps = DetailedHTMLProps<
|
||||
ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
HTMLButtonElement
|
||||
ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
HTMLButtonElement
|
||||
> & {
|
||||
size?: "mini" | "normal" | "big" | "giant" | "micro";
|
||||
size?: 'mini' | 'normal' | 'big' | 'giant' | 'micro';
|
||||
iconLeft?: IIcon;
|
||||
iconRight?: IIcon;
|
||||
seamless?: boolean;
|
||||
|
@ -22,8 +22,8 @@ type IButtonProps = DetailedHTMLProps<
|
|||
};
|
||||
|
||||
export const Button: FC<IButtonProps> = ({
|
||||
className = "",
|
||||
size = "normal",
|
||||
className = '',
|
||||
size = 'normal',
|
||||
iconLeft,
|
||||
iconRight,
|
||||
children,
|
||||
|
@ -36,26 +36,25 @@ export const Button: FC<IButtonProps> = ({
|
|||
title,
|
||||
stretchy,
|
||||
...props
|
||||
}) =>
|
||||
React.createElement(seamless || non_submitting ? "div" : "button", {
|
||||
className: classnames(styles.button, className, styles[size], {
|
||||
red,
|
||||
grey,
|
||||
seamless,
|
||||
transparent,
|
||||
disabled: props.disabled,
|
||||
icon: (iconLeft || iconRight) && !title && !children,
|
||||
is_loading,
|
||||
stretchy
|
||||
}),
|
||||
children: [
|
||||
iconLeft && <Icon icon={iconLeft} size={20} key={0} />,
|
||||
title ? (
|
||||
<span key={1}>{title}</span>
|
||||
) : (
|
||||
(children && <span key={1}>{children}</span>) || null
|
||||
),
|
||||
iconRight && <Icon icon={iconRight} size={20} key={2} />
|
||||
],
|
||||
...props
|
||||
});
|
||||
}) => React.createElement(seamless || non_submitting ? 'div' : 'button', {
|
||||
className: classnames(styles.button, className, styles[size], {
|
||||
red,
|
||||
grey,
|
||||
seamless,
|
||||
transparent,
|
||||
disabled: props.disabled,
|
||||
icon: (iconLeft || iconRight) && !title && !children,
|
||||
is_loading,
|
||||
stretchy
|
||||
}),
|
||||
children: [
|
||||
iconLeft && <Icon icon={iconLeft} size={20} key={0} />,
|
||||
title ? (
|
||||
<span key={1}>{title}</span>
|
||||
) : (
|
||||
(children && <span key={1}>{children}</span>) || null
|
||||
),
|
||||
iconRight && <Icon icon={iconRight} size={20} key={2} />
|
||||
],
|
||||
...props
|
||||
});
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
import React, { FC } from "react";
|
||||
import { IIcon } from "~/redux/types";
|
||||
import React, { FC } from 'react';
|
||||
import { IIcon } from '~/redux/types';
|
||||
|
||||
type IProps = React.SVGAttributes<SVGElement> & {
|
||||
size?: number;
|
||||
icon: IIcon;
|
||||
};
|
||||
|
||||
export const Icon: FC<IProps> = ({ size = 20, icon, style, ...props }) => (
|
||||
export const Icon: FC<IProps> = ({
|
||||
size = 20, icon, style, ...props
|
||||
}) => (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox={`0 0 24 24`}
|
||||
viewBox="0 0 24 24"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
style={{ ...style, outline: "none" }}
|
||||
style={{ ...style, outline: 'none' }}
|
||||
{...props}
|
||||
>
|
||||
<use xlinkHref={`#${icon}`} />
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import * as React from 'react';
|
||||
import classNames = require("classnames");
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
const style = require('./style.scss');
|
||||
|
||||
interface IInfoProps {
|
||||
text?: string,
|
||||
children?: string,
|
||||
level?: string,
|
||||
text?: string;
|
||||
children?: string;
|
||||
level?: string;
|
||||
}
|
||||
export const Info: React.FunctionComponent<IInfoProps> = ({
|
||||
text,
|
||||
|
|
|
@ -4,8 +4,8 @@ import React, {
|
|||
useCallback,
|
||||
useState, useEffect,
|
||||
} from 'react';
|
||||
import * as styles from '~/styles/inputs.scss';
|
||||
import classNames from 'classnames';
|
||||
import * as styles from '~/styles/inputs.scss';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { IInputTextProps } from '~/redux/types';
|
||||
import { LoaderCircle } from '~/components/input/LoaderCircle';
|
||||
|
@ -31,8 +31,8 @@ const InputText: FC<IInputTextProps> = ({
|
|||
[handler],
|
||||
);
|
||||
|
||||
const onFocus = useCallback(() => setFocused(true), [focused]);
|
||||
const onBlur = useCallback(() => setFocused(false), [focused]);
|
||||
const onFocus = useCallback(() => setFocused(true), []);
|
||||
const onBlur = useCallback(() => setFocused(false), []);
|
||||
|
||||
useEffect(() => {
|
||||
if (onRef) onRef(inner_ref);
|
||||
|
@ -50,7 +50,8 @@ const InputText: FC<IInputTextProps> = ({
|
|||
[styles.has_error]: !!error,
|
||||
[styles.has_loader]: is_loading,
|
||||
},
|
||||
)}>
|
||||
)}
|
||||
>
|
||||
<div className={styles.input}>
|
||||
<input
|
||||
type="text"
|
||||
|
|
|
@ -2,12 +2,12 @@ import * as React from 'react';
|
|||
import * as styles from './styles.scss';
|
||||
|
||||
interface ITextInputProps {
|
||||
type?: 'text' | 'password',
|
||||
placeholder?: string,
|
||||
label?: string,
|
||||
value?: string,
|
||||
type?: 'text' | 'password';
|
||||
placeholder?: string;
|
||||
label?: string;
|
||||
value?: string;
|
||||
|
||||
onChange: React.ChangeEventHandler,
|
||||
onChange: React.ChangeEventHandler;
|
||||
}
|
||||
|
||||
export const TextInput: React.FunctionComponent<ITextInputProps> = ({
|
||||
|
@ -15,15 +15,15 @@ export const TextInput: React.FunctionComponent<ITextInputProps> = ({
|
|||
placeholder = '',
|
||||
label,
|
||||
onChange = () => {},
|
||||
value='',
|
||||
value = '',
|
||||
}) => (
|
||||
<div
|
||||
className={styles.wrapper}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
{
|
||||
label &&
|
||||
<div className={styles.label}>{label}</div>
|
||||
label
|
||||
&& <div className={styles.label}>{label}</div>
|
||||
}
|
||||
<input
|
||||
placeholder={placeholder}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
interface IGodRaysProps {
|
||||
raised?: boolean,
|
||||
raised?: boolean;
|
||||
}
|
||||
|
||||
export class GodRays extends React.Component<IGodRaysProps> {
|
||||
|
@ -30,22 +30,26 @@ export class GodRays extends React.Component<IGodRaysProps> {
|
|||
return setTimeout(() => window.requestAnimationFrame(this.draw), 1000);
|
||||
}
|
||||
|
||||
const { width, height, rays, particles } = this.state;
|
||||
const {
|
||||
width, height, rays, particles
|
||||
} = this.state;
|
||||
|
||||
const ctx = this.canvas.getContext('2d');
|
||||
|
||||
ctx.globalCompositeOperation = "luminosity";
|
||||
ctx.globalCompositeOperation = 'luminosity';
|
||||
ctx.clearRect(0, 0, width, height + 100); // clear canvas
|
||||
ctx.save();
|
||||
|
||||
rays.map(({ angle, iterator, weight, speed, pulsar, opacity }, index) => {
|
||||
rays.map(({
|
||||
angle, iterator, weight, speed, pulsar, opacity
|
||||
}, index) => {
|
||||
const gradient = ctx.createLinearGradient(0, 0, 0, height * 1.3);
|
||||
gradient.addColorStop(0.2, `rgba(255, 60, 40, ${opacity * 0.1})`);
|
||||
gradient.addColorStop(1, `rgba(255, 60, 40, 0)`);
|
||||
gradient.addColorStop(1, 'rgba(255, 60, 40, 0)');
|
||||
|
||||
const gradient2 = ctx.createLinearGradient(0, 0, 0, height * 1.3);
|
||||
gradient2.addColorStop(0.2, `rgba(255, 40, 100, ${opacity * 0.2})`);
|
||||
gradient2.addColorStop(1, "rgba(255, 40, 100, 0)");
|
||||
gradient2.addColorStop(1, 'rgba(255, 40, 100, 0)');
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(width / 2, -900);
|
||||
|
@ -106,7 +110,7 @@ export class GodRays extends React.Component<IGodRaysProps> {
|
|||
this.init();
|
||||
}
|
||||
|
||||
render(){
|
||||
render() {
|
||||
const { width, height } = this.state;
|
||||
|
||||
return (
|
||||
|
@ -119,7 +123,8 @@ export class GodRays extends React.Component<IGodRaysProps> {
|
|||
zIndex: -1,
|
||||
opacity: 1,
|
||||
pointerEvents: 'none',
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<canvas
|
||||
width={width}
|
||||
height={height + 100}
|
||||
|
@ -128,12 +133,13 @@ export class GodRays extends React.Component<IGodRaysProps> {
|
|||
position: 'relative',
|
||||
top: -100,
|
||||
}}
|
||||
ref={el => { this.canvas = el; }}
|
||||
ref={(el) => { this.canvas = el; }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
canvas: HTMLCanvasElement;
|
||||
|
||||
inc;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import * as React from "react";
|
||||
import { Logo } from "~/components/main/Logo";
|
||||
import { connect } from "react-redux";
|
||||
import { push as historyPush } from "connected-react-router";
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { push as historyPush } from 'connected-react-router';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Logo } from '~/components/main/Logo';
|
||||
|
||||
import * as style from "./style.scss";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { Link } from "react-router-dom";
|
||||
import {selectUser} from "~/redux/auth/selectors";
|
||||
import {Group} from "~/components/containers/Group";
|
||||
import * as style from './style.scss';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { selectUser } from '~/redux/auth/selectors';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
|
||||
const mapStateToProps = selectUser;
|
||||
|
||||
|
@ -20,31 +20,29 @@ type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {
|
|||
const HeaderUnconnected: React.FunctionComponent<IProps> = ({
|
||||
username,
|
||||
is_user
|
||||
}) => {
|
||||
return (
|
||||
<div className="default_container head_container">
|
||||
<div className={style.container}>
|
||||
<Logo />
|
||||
}) => (
|
||||
<div className="default_container head_container">
|
||||
<div className={style.container}>
|
||||
<Logo />
|
||||
|
||||
<Filler />
|
||||
<Filler />
|
||||
|
||||
<div className={style.plugs}>
|
||||
<Link to="/">flow</Link>
|
||||
<Link to="/examples/image">image</Link>
|
||||
<Link to="/examples/edit">editor</Link>
|
||||
<Link to="/examples/horizontal">horizontal</Link>
|
||||
</div>
|
||||
|
||||
<Filler />
|
||||
|
||||
<Group horizontal className={style.user_button}>
|
||||
<div>username</div>
|
||||
<div className={style.user_avatar}/>
|
||||
</Group>
|
||||
<div className={style.plugs}>
|
||||
<Link to="/">flow</Link>
|
||||
<Link to="/examples/image">image</Link>
|
||||
<Link to="/examples/edit">editor</Link>
|
||||
<Link to="/examples/horizontal">horizontal</Link>
|
||||
</div>
|
||||
|
||||
<Filler />
|
||||
|
||||
<Group horizontal className={style.user_button}>
|
||||
<div>username</div>
|
||||
<div className={style.user_avatar} />
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
||||
const Header = connect(
|
||||
mapStateToProps,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import React, { FC, LegacyRef, ReactChild, useCallback, useEffect, useState } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import React, {
|
||||
FC, LegacyRef, ReactChild, useCallback, useEffect, useState
|
||||
} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {Group} from "~/components/containers/Group";
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
|
||||
interface IProps {
|
||||
}
|
||||
|
@ -28,8 +30,8 @@ export const SidePane: FC<IProps> = ({
|
|||
return () => {
|
||||
window.removeEventListener('resize', moveThis);
|
||||
document.removeEventListener('DOMContentLoaded', moveThis);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
}, [moveThis]);
|
||||
|
||||
return (
|
||||
<div className={styles.pane} style={{ transform: `translate(${left}px, 0px)` }}>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, {FC, HTMLAttributes} from 'react';
|
||||
import { Card } from "~/components/containers/Card";
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||
is_empty?: boolean;
|
||||
|
@ -14,17 +15,17 @@ const Comment: FC<IProps> = ({
|
|||
className,
|
||||
...props
|
||||
}) => (
|
||||
<Card
|
||||
className={classNames(styles.wrap, className, { is_empty, is_loading })}
|
||||
seamless
|
||||
{...props}
|
||||
>
|
||||
<div className={styles.thumb}>
|
||||
<div className={styles.thumb_image} />
|
||||
</div>
|
||||
<Card
|
||||
className={classNames(styles.wrap, className, { is_empty, is_loading })}
|
||||
seamless
|
||||
{...props}
|
||||
>
|
||||
<div className={styles.thumb}>
|
||||
<div className={styles.thumb_image} />
|
||||
</div>
|
||||
|
||||
<div className={styles.text} />
|
||||
</Card>
|
||||
<div className={styles.text} />
|
||||
</Card>
|
||||
);
|
||||
|
||||
export { Comment };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {FC} from 'react';
|
||||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
|
||||
interface IProps {
|
||||
title: string;
|
||||
|
@ -19,7 +19,10 @@ const MenuButton: FC<IProps> = ({
|
|||
>
|
||||
<Group horizontal>
|
||||
<div className={styles.icon}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
|
||||
<path fill="none" d="M0 0h24v24H0V0z" />
|
||||
<path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<Filler>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React, { FC } from "react";
|
||||
import { Comment } from "~/components/node/Comment";
|
||||
import React, { FC } from 'react';
|
||||
import { Comment } from '~/components/node/Comment';
|
||||
import * as styles from './styles.scss';
|
||||
import {Group} from "~/components/containers/Group";
|
||||
import { Group } from '~/components/containers/Group';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
const NodeNoComments: FC<IProps> = () => (
|
||||
<Group className={styles.wrap}>
|
||||
<Comment is_empty={true} is_loading={false} style={{ height: 94 }} />
|
||||
<Comment is_empty={true} is_loading={false} style={{ height: 104 }} />
|
||||
<Comment is_empty={true} is_loading={false} style={{ height: 100 }} />
|
||||
<Comment is_empty is_loading={false} style={{ height: 94 }} />
|
||||
<Comment is_empty is_loading={false} style={{ height: 104 }} />
|
||||
<Comment is_empty is_loading={false} style={{ height: 100 }} />
|
||||
</Group>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
const NodePanel: FC<IProps> = () => (
|
||||
<div className={styles.wrap}>
|
||||
<Group horizontal className={styles.panel}>
|
||||
<Filler>
|
||||
<div className={styles.title}>Node title</div>
|
||||
<div className={styles.name}>~author</div>
|
||||
</Filler>
|
||||
</Group>
|
||||
<div className={styles.wrap}>
|
||||
<Group horizontal className={styles.panel}>
|
||||
<Filler>
|
||||
<div className={styles.title}>Node title</div>
|
||||
<div className={styles.name}>~author</div>
|
||||
</Filler>
|
||||
</Group>
|
||||
|
||||
<div className={styles.mark} />
|
||||
</div>
|
||||
<div className={styles.mark} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export { NodePanel };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {FC, HTMLAttributes} from 'react';
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import { range } from 'ramda';
|
||||
import * as styles from './styles.scss';
|
||||
import {Group} from "~/components/containers/Group";
|
||||
import { Group } from '~/components/containers/Group';
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {}
|
||||
|
||||
|
@ -16,7 +16,7 @@ const NodeRelated: FC<IProps> = ({
|
|||
</div>
|
||||
<div className={styles.grid}>
|
||||
{
|
||||
range(1,7).map(el => (<div className={styles.item} key={el} />))
|
||||
range(1, 7).map(el => (<div className={styles.item} key={el} />))
|
||||
}
|
||||
</div>
|
||||
</Group>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames = require("classnames");
|
||||
import {ITag} from "~/redux/types";
|
||||
import { ITag } from '~/redux/types';
|
||||
|
||||
import classNames = require('classnames');
|
||||
|
||||
interface IProps {
|
||||
title: ITag['title'];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {FC, HTMLAttributes} from 'react';
|
||||
import {TagField} from "~/components/containers/TagField";
|
||||
import {ITag} from "~/redux/types";
|
||||
import {Tag} from "~/components/node/Tag";
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import { TagField } from '~/components/containers/TagField';
|
||||
import { ITag } from '~/redux/types';
|
||||
import { Tag } from '~/components/node/Tag';
|
||||
|
||||
type IProps = HTMLAttributes<HTMLDivElement> & {
|
||||
tags: ITag[];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { FC } from 'react';
|
||||
import { Placeholder } from "~/components/placeholders/Placeholder";
|
||||
import { Placeholder } from '~/components/placeholders/Placeholder';
|
||||
import * as styles from './styles.scss';
|
||||
import {Group} from "~/components/containers/Group";
|
||||
import { Group } from '~/components/containers/Group';
|
||||
|
||||
const ParagraphPlaceholder = ({ }) => (
|
||||
<Group>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { FC } from 'react';
|
||||
import * as styles from './styles.scss';
|
||||
import classNames from 'classnames';
|
||||
import * as styles from './styles.scss';
|
||||
import { ArcProgress } from '~/components/input/ArcProgress';
|
||||
|
||||
interface IProps {
|
||||
|
@ -9,22 +9,20 @@ interface IProps {
|
|||
progress?: number;
|
||||
|
||||
is_uploading?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const ImageUpload: FC<IProps> = ({
|
||||
thumb,
|
||||
id,
|
||||
progress,
|
||||
is_uploading,
|
||||
}) => {
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<div className={classNames(styles.thumb_wrap, { is_uploading })}>
|
||||
{thumb && <div className={styles.thumb} style={{ background: `url("${thumb}")` }}>{id}</div>}
|
||||
{is_uploading && <div className={styles.progress}><ArcProgress size={72} progress={progress} /></div>}
|
||||
</div>
|
||||
}) => (
|
||||
<div className={styles.wrap}>
|
||||
<div className={classNames(styles.thumb_wrap, { is_uploading })}>
|
||||
{thumb && <div className={styles.thumb} style={{ background: `url("${thumb}")` }}>{id}</div>}
|
||||
{is_uploading && <div className={styles.progress}><ArcProgress size={72} progress={progress} /></div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
export { ImageUpload };
|
||||
export { ImageUpload };
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
import * as React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { bindActionCreators } from "redux";
|
||||
import { hot } from "react-hot-loader";
|
||||
import { ConnectedRouter } from "connected-react-router";
|
||||
import { history } from "~/redux/store";
|
||||
import { NavLink, Switch, Route, Redirect } from "react-router-dom";
|
||||
import { FlowLayout } from "~/containers/flow/FlowLayout";
|
||||
import { MainLayout } from "~/containers/main/MainLayout";
|
||||
import { ImageExample } from "~/containers/examples/ImageExample";
|
||||
import { EditorExample } from "~/containers/examples/EditorExample";
|
||||
import { HorizontalExample } from "~/containers/examples/HorizontalExample";
|
||||
import { Sprites } from "~/sprites/Sprites";
|
||||
import { URLS } from "~/constants/urls";
|
||||
import { Modal } from "~/containers/dialogs/Modal";
|
||||
import { selectModal } from "~/redux/modal/selectors";
|
||||
import { BlurWrapper } from "~/components/containers/BlurWrapper";
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { ConnectedRouter } from 'connected-react-router';
|
||||
import {
|
||||
NavLink, Switch, Route, Redirect
|
||||
} from 'react-router-dom';
|
||||
import { history } from '~/redux/store';
|
||||
import { FlowLayout } from '~/containers/flow/FlowLayout';
|
||||
import { MainLayout } from '~/containers/main/MainLayout';
|
||||
import { ImageExample } from '~/containers/examples/ImageExample';
|
||||
import { EditorExample } from '~/containers/examples/EditorExample';
|
||||
import { HorizontalExample } from '~/containers/examples/HorizontalExample';
|
||||
import { Sprites } from '~/sprites/Sprites';
|
||||
import { URLS } from '~/constants/urls';
|
||||
import { Modal } from '~/containers/dialogs/Modal';
|
||||
import { selectModal } from '~/redux/modal/selectors';
|
||||
import { BlurWrapper } from '~/components/containers/BlurWrapper';
|
||||
|
||||
const mapStateToProps = selectModal;
|
||||
const mapDispatchToProps = {};
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import React, { FC, useState, useCallback, useEffect } from 'react';
|
||||
import React, {
|
||||
FC, useState, useCallback, useEffect
|
||||
} from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import assocPath from 'ramda/es/assocPath';
|
||||
import append from 'ramda/es/append';
|
||||
import uuid from 'uuid4';
|
||||
import { ScrollDialog } from '../ScrollDialog';
|
||||
import { IDialogProps } from '~/redux/modal/constants';
|
||||
import { useCloseOnEscape } from '~/utils/hooks';
|
||||
|
@ -7,19 +13,15 @@ import { InputText } from '~/components/input/InputText';
|
|||
import { Button } from '~/components/input/Button';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import * as styles from './styles.scss';
|
||||
import { connect } from 'react-redux';
|
||||
import { selectNode } from '~/redux/node/selectors';
|
||||
import { ImageEditor } from '~/components/editors/ImageEditor';
|
||||
import { EditorPanel } from '~/components/editors/EditorPanel';
|
||||
import assocPath from 'ramda/es/assocPath';
|
||||
import append from 'ramda/es/append';
|
||||
import { moveArrItem } from '~/utils/fn';
|
||||
import { IFile, IFileWithUUID } from '~/redux/types';
|
||||
import uuid from 'uuid4';
|
||||
import * as UPLOAD_ACTIONS from '~/redux/uploads/actions';
|
||||
import { selectUploads } from '~/redux/uploads/selectors';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state) => {
|
||||
const { editor } = selectNode(state);
|
||||
const { statuses, files } = selectUploads(state);
|
||||
|
||||
|
@ -32,7 +34,9 @@ const mapDispatchToProps = {
|
|||
|
||||
type IProps = IDialogProps & ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {};
|
||||
|
||||
const EditorDialogUnconnected: FC<IProps> = ({ onRequestClose, editor, uploadUploadFiles, files, statuses }) => {
|
||||
const EditorDialogUnconnected: FC<IProps> = ({
|
||||
onRequestClose, editor, uploadUploadFiles, files, statuses
|
||||
}) => {
|
||||
const [data, setData] = useState(editor);
|
||||
const eventPreventer = useCallback(event => event.preventDefault(), []);
|
||||
const [temp, setTemp] = useState([]);
|
||||
|
@ -68,7 +72,7 @@ const EditorDialogUnconnected: FC<IProps> = ({ onRequestClose, editor, uploadUpl
|
|||
);
|
||||
|
||||
const onInputChange = useCallback(
|
||||
event => {
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
if (!event.target.files || !event.target.files.length) return;
|
||||
|
@ -109,10 +113,10 @@ const EditorDialogUnconnected: FC<IProps> = ({ onRequestClose, editor, uploadUpl
|
|||
setTemp(temp.filter(el => el !== id));
|
||||
}
|
||||
});
|
||||
}, [statuses, files]);
|
||||
}, [statuses, files, temp, onFileAdd]);
|
||||
|
||||
const setTitle = useCallback(
|
||||
title => {
|
||||
(title) => {
|
||||
setData({ ...data, title });
|
||||
},
|
||||
[setData, data]
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import React, { FC, FormEvent, useCallback, useEffect, useState } from 'react';
|
||||
import React, {
|
||||
FC, FormEvent, useCallback, useEffect, useState
|
||||
} from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { ScrollDialog } from '../ScrollDialog';
|
||||
import { IDialogProps } from '~/redux/modal/constants';
|
||||
import { useCloseOnEscape } from '~/utils/hooks';
|
||||
|
@ -7,9 +10,8 @@ import { InputText } from '~/components/input/InputText';
|
|||
import { Button } from '~/components/input/Button';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import * as styles from './styles.scss';
|
||||
import { selectAuthLogin } from "~/redux/auth/selectors";
|
||||
import { selectAuthLogin } from '~/redux/auth/selectors';
|
||||
import * as ACTIONS from '~/redux/auth/actions';
|
||||
import { connect } from "react-redux";
|
||||
|
||||
const mapStateToProps = selectAuthLogin;
|
||||
|
||||
|
@ -20,7 +22,9 @@ const mapDispatchToProps = {
|
|||
|
||||
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & IDialogProps & {};
|
||||
|
||||
const LoginDialogUnconnected: FC<IProps> = ({ onRequestClose, error, userSendLoginRequest, userSetLoginError }) => {
|
||||
const LoginDialogUnconnected: FC<IProps> = ({
|
||||
onRequestClose, error, userSendLoginRequest, userSetLoginError
|
||||
}) => {
|
||||
const [username, setUserName] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
|
||||
|
@ -31,7 +35,7 @@ const LoginDialogUnconnected: FC<IProps> = ({ onRequestClose, error, userSendLog
|
|||
|
||||
useEffect(() => {
|
||||
if (error) userSetLoginError(null);
|
||||
}, [username, password]);
|
||||
}, [username, password, error, userSetLoginError]);
|
||||
|
||||
const buttons = (
|
||||
<Padder>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { Attributes, FC, useCallback } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as styles from './styles.scss';
|
||||
import { IState } from '~/redux/store';
|
||||
import * as ACTIONS from '~/redux/modal/actions';
|
||||
import { connect } from 'react-redux';
|
||||
import { DIALOG_CONTENT, IDialogProps } from '~/redux/modal/constants';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
const mapStateToProps = ({ modal }: IState) => ({ ...modal });
|
||||
const mapDispatchToProps = {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import React, { FC, MouseEventHandler, ReactChild, useCallback, useEffect, useState } from 'react';
|
||||
import React, {
|
||||
FC, MouseEventHandler, ReactChild, useCallback, useEffect, useState
|
||||
} from 'react';
|
||||
// import { DialogPanel } from '~/components/panels/DialogPanel';
|
||||
import classNames from 'classnames';
|
||||
import { Scroll } from '~/components/containers/Scroll';
|
||||
|
@ -41,7 +43,7 @@ const ScrollDialog: FC<IProps> = ({
|
|||
useEffect(() => {
|
||||
window.addEventListener('resize', onResize);
|
||||
return () => window.removeEventListener('resize', onResize);
|
||||
}, []);
|
||||
}, [onResize]);
|
||||
|
||||
const onScroll = useCallback(
|
||||
({ target: { scrollTop = 0 } = {} } = {}) => {
|
||||
|
@ -54,7 +56,7 @@ const ScrollDialog: FC<IProps> = ({
|
|||
[top_sticky, top_sticky_offset, show_top_sticky, setShowTopSticky]
|
||||
);
|
||||
|
||||
useEffect(() => onScroll(), []);
|
||||
useEffect(() => onScroll(), [onScroll]);
|
||||
useEffect(() => {
|
||||
if (ref && onRefCapture) onRefCapture(ref);
|
||||
}, [ref, onRefCapture]);
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import React, { FC } from "react";
|
||||
import { Card } from "~/components/containers/Card";
|
||||
import * as styles from "./styles.scss";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { CellGrid } from "~/components/containers/CellGrid";
|
||||
import { Panel } from "~/components/containers/Panel";
|
||||
import classNames from "classnames";
|
||||
import { Scroll } from "~/components/containers/Scroll";
|
||||
import { Tags } from "~/components/node/Tags";
|
||||
import { Button } from "~/components/input/Button";
|
||||
import { Filler } from "~/components/containers/Filler";
|
||||
import { InputText } from "~/components/input/InputText";
|
||||
import { Icon } from "~/components/input/Icon";
|
||||
import { Grid } from "~/components/containers/Grid";
|
||||
import React, { FC } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { CellGrid } from '~/components/containers/CellGrid';
|
||||
import { Panel } from '~/components/containers/Panel';
|
||||
import { Scroll } from '~/components/containers/Scroll';
|
||||
import { Tags } from '~/components/node/Tags';
|
||||
import { Button } from '~/components/input/Button';
|
||||
import { Filler } from '~/components/containers/Filler';
|
||||
import { InputText } from '~/components/input/InputText';
|
||||
import { Icon } from '~/components/input/Icon';
|
||||
import { Grid } from '~/components/containers/Grid';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
|
@ -48,11 +48,11 @@ const EditorExample: FC<IProps> = () => (
|
|||
|
||||
<Tags
|
||||
tags={[
|
||||
{ title: "Избранный", feature: "red" },
|
||||
{ title: "Плейлист", feature: "green" },
|
||||
{ title: "Просто" },
|
||||
{ title: "+ фото", feature: "black" },
|
||||
{ title: "+ с музыкой", feature: "black" }
|
||||
{ title: 'Избранный', feature: 'red' },
|
||||
{ title: 'Плейлист', feature: 'green' },
|
||||
{ title: 'Просто' },
|
||||
{ title: '+ фото', feature: 'black' },
|
||||
{ title: '+ с музыкой', feature: 'black' }
|
||||
]}
|
||||
/>
|
||||
</Group>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { FC } from "react";
|
||||
import { Card } from "~/components/containers/Card";
|
||||
import * as styles from "./styles.scss";
|
||||
import { Group } from "~/components/containers/Group";
|
||||
import { Padder } from "~/components/containers/Padder";
|
||||
import range from "ramda/es/range";
|
||||
import { Comment } from "~/components/node/Comment";
|
||||
import { NodePanel } from "~/components/node/NodePanel";
|
||||
import { NodeRelated } from "~/components/node/NodeRelated";
|
||||
import { Tags } from "~/components/node/Tags";
|
||||
import { MenuButton } from "~/components/node/MenuButton";
|
||||
import { NodeNoComments } from "~/components/node/NodeNoComments";
|
||||
import { InputText } from "~/components/input/InputText";
|
||||
import React, { FC } from 'react';
|
||||
import range from 'ramda/es/range';
|
||||
import { Card } from '~/components/containers/Card';
|
||||
import * as styles from './styles.scss';
|
||||
import { Group } from '~/components/containers/Group';
|
||||
import { Padder } from '~/components/containers/Padder';
|
||||
import { Comment } from '~/components/node/Comment';
|
||||
import { NodePanel } from '~/components/node/NodePanel';
|
||||
import { NodeRelated } from '~/components/node/NodeRelated';
|
||||
import { Tags } from '~/components/node/Tags';
|
||||
import { MenuButton } from '~/components/node/MenuButton';
|
||||
import { NodeNoComments } from '~/components/node/NodeNoComments';
|
||||
import { InputText } from '~/components/input/InputText';
|
||||
|
||||
interface IProps {}
|
||||
|
||||
|
@ -55,11 +55,11 @@ const ImageExample: FC<IProps> = () => (
|
|||
|
||||
<Tags
|
||||
tags={[
|
||||
{ title: "Избранный", feature: "red" },
|
||||
{ title: "Плейлист", feature: "green" },
|
||||
{ title: "Просто" },
|
||||
{ title: "+ фото", feature: "black" },
|
||||
{ title: "+ с музыкой", feature: "black" }
|
||||
{ title: 'Избранный', feature: 'red' },
|
||||
{ title: 'Плейлист', feature: 'green' },
|
||||
{ title: 'Просто' },
|
||||
{ title: '+ фото', feature: 'black' },
|
||||
{ title: '+ с музыкой', feature: 'black' }
|
||||
]}
|
||||
/>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { TestGrid } from "~/components/flow/TestGrid";
|
||||
import { TestGrid } from '~/components/flow/TestGrid';
|
||||
|
||||
export const FlowLayout = () => (
|
||||
<div className="default_container content_container">
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import { SidePane } from "~/components/main/SidePane";
|
||||
import { SidePane } from '~/components/main/SidePane';
|
||||
import * as styles from './styles.scss';
|
||||
import { Header } from "~/components/main/Header";
|
||||
import { Header } from '~/components/main/Header';
|
||||
|
||||
export const MainLayout = ({ children }) => {
|
||||
export const MainLayout = ({ children }) => (
|
||||
<div className={styles.wrapper}>
|
||||
<Header />
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<Header />
|
||||
|
||||
<div className={styles.content}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as styles from './styles.scss';
|
|||
interface IProps {}
|
||||
|
||||
const NodeLayout: FC<IProps> = () => (
|
||||
<div></div>
|
||||
<div />
|
||||
);
|
||||
|
||||
export { NodeLayout };
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { AUTH_USER_ACTIONS } from "~/redux/auth/constants";
|
||||
import {IAuthState, IUser} from "~/redux/auth/types";
|
||||
import { AUTH_USER_ACTIONS } from '~/redux/auth/constants';
|
||||
import { IAuthState, IUser } from '~/redux/auth/types';
|
||||
|
||||
export const userSendLoginRequest = ({
|
||||
username, password
|
||||
}: {
|
||||
username: string, password: string
|
||||
username: string; password: string;
|
||||
}) => ({ type: AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, username, password });
|
||||
|
||||
export const userSetLoginError = (error: IAuthState['login']['error']) => ({
|
||||
|
|
|
@ -15,9 +15,8 @@ export const apiUserLogin = ({
|
|||
}: {
|
||||
username: string;
|
||||
password: string;
|
||||
}): Promise<IResultWithStatus<{ token: string; status?: number }>> =>
|
||||
api
|
||||
.post(API.USER.LOGIN, { username, password })
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware)
|
||||
.then(userLoginTransform);
|
||||
}): Promise<IResultWithStatus<{ token: string; status?: number }>> => api
|
||||
.post(API.USER.LOGIN, { username, password })
|
||||
.then(resultMiddleware)
|
||||
.catch(errorMiddleware)
|
||||
.then(userLoginTransform);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {IToken, IUser} from "~/redux/auth/types";
|
||||
import { IToken, IUser } from '~/redux/auth/types';
|
||||
|
||||
export const AUTH_USER_ACTIONS = {
|
||||
SEND_LOGIN_REQUEST: 'SEND_LOGIN_REQUEST',
|
||||
|
@ -39,11 +39,11 @@ export const EMPTY_USER: IUser = {
|
|||
};
|
||||
|
||||
export interface IApiUser {
|
||||
id: number,
|
||||
username: string,
|
||||
email: string,
|
||||
role: string,
|
||||
activated: boolean,
|
||||
createdAt: string,
|
||||
updatedAt: string,
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
role: string;
|
||||
activated: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {AUTH_USER_ACTIONS} from "~/redux/auth/constants";
|
||||
import * as ActionCreators from "~/redux/auth/actions";
|
||||
import {IAuthState} from "~/redux/auth/types";
|
||||
import { AUTH_USER_ACTIONS } from '~/redux/auth/constants';
|
||||
import * as ActionCreators from '~/redux/auth/actions';
|
||||
import { IAuthState } from '~/redux/auth/types';
|
||||
|
||||
interface ActionHandler<T> {
|
||||
(state: IAuthState, payload: T extends (...args: any[]) => infer R ? R : any): IAuthState;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { EMPTY_USER } from "~/redux/auth/constants";
|
||||
import { createReducer } from "~/utils/reducer";
|
||||
import { IAuthState } from "~/redux/auth/types";
|
||||
import { AUTH_USER_HANDLERS } from "~/redux/auth/handlers";
|
||||
import { EMPTY_USER } from '~/redux/auth/constants';
|
||||
import { createReducer } from '~/utils/reducer';
|
||||
import { IAuthState } from '~/redux/auth/types';
|
||||
import { AUTH_USER_HANDLERS } from '~/redux/auth/handlers';
|
||||
|
||||
const HANDLERS = {
|
||||
...AUTH_USER_HANDLERS,
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { call, put, takeLatest, select } from 'redux-saga/effects';
|
||||
import {
|
||||
call, put, takeLatest, select
|
||||
} from 'redux-saga/effects';
|
||||
import { SagaIterator } from 'redux-saga';
|
||||
import { AUTH_USER_ACTIONS } from "~/redux/auth/constants";
|
||||
import * as ActionCreators from '~/redux/auth/actions';
|
||||
import { authSetToken, userSetLoginError, authSetUser } from "~/redux/auth/actions";
|
||||
import { apiUserLogin } from "~/redux/auth/api";
|
||||
import { modalSetShown, modalShowDialog } from "~/redux/modal/actions";
|
||||
import { selectToken } from './selectors';
|
||||
import { push } from 'connected-react-router';
|
||||
import { AUTH_USER_ACTIONS } from '~/redux/auth/constants';
|
||||
import * as ActionCreators from '~/redux/auth/actions';
|
||||
import { authSetToken, userSetLoginError, authSetUser } from '~/redux/auth/actions';
|
||||
import { apiUserLogin } from '~/redux/auth/api';
|
||||
import { modalSetShown, modalShowDialog } from '~/redux/modal/actions';
|
||||
import { selectToken } from './selectors';
|
||||
import { URLS } from '~/constants/urls';
|
||||
import { DIALOGS } from '../modal/constants';
|
||||
import { IResultWithStatus } from '../types';
|
||||
|
@ -30,7 +32,7 @@ export function* reqWrapper(requestAction, props = {}): ReturnType<typeof reques
|
|||
function* sendLoginRequestSaga({ username, password }: ReturnType<typeof ActionCreators.userSendLoginRequest>): SagaIterator {
|
||||
if (!username || !password) return;
|
||||
|
||||
const { error, data: { token, user } }: IResultWithStatus<{ token: string, user: IUser }> = yield call(apiUserLogin, { username, password });
|
||||
const { error, data: { token, user } }: IResultWithStatus<{ token: string; user: IUser }> = yield call(apiUserLogin, { username, password });
|
||||
|
||||
console.log({ token, error });
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IState } from "~/redux/store";
|
||||
import { IState } from '~/redux/store';
|
||||
|
||||
export const selectUser = (state: IState): IState['auth']['user'] => state.auth.user;
|
||||
export const selectToken = (state: IState): IState['auth']['token'] => state.auth.token;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IResultWithStatus } from "~/redux/types";
|
||||
import { HTTP_RESPONSES } from "~/utils/api";
|
||||
import { IResultWithStatus } from '~/redux/types';
|
||||
import { HTTP_RESPONSES } from '~/utils/api';
|
||||
|
||||
export const userLoginTransform = ({ status, data, error }: IResultWithStatus<any>): IResultWithStatus<any> => {
|
||||
switch (true) {
|
||||
|
@ -12,4 +12,4 @@ export const userLoginTransform = ({ status, data, error }: IResultWithStatus<an
|
|||
default:
|
||||
return { status, data, error: error || 'Неизвестная ошибка' };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { IState } from "~/redux/store";
|
||||
import { IState } from '~/redux/store';
|
||||
|
||||
export const selectModal = (state: IState) => state.modal;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {IBlock, INode} from "../types";
|
||||
import { IBlock, INode } from '../types';
|
||||
|
||||
export const EMPTY_BLOCK: IBlock = {
|
||||
type: null,
|
||||
|
@ -25,4 +25,4 @@ export const EMPTY_NODE: INode = {
|
|||
show_description: false,
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export const NODE_HANDLERS = {
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { createReducer } from "~/utils/reducer";
|
||||
import { INode } from "../types";
|
||||
import { EMPTY_BLOCK, EMPTY_NODE } from "./constants";
|
||||
import { NODE_HANDLERS } from "./handlers";
|
||||
import { EMPTY_FILE } from "../uploads/constants";
|
||||
import uuid from 'uuid4';
|
||||
import { createReducer } from '~/utils/reducer';
|
||||
import { INode } from '../types';
|
||||
import { EMPTY_BLOCK, EMPTY_NODE } from './constants';
|
||||
import { NODE_HANDLERS } from './handlers';
|
||||
import { EMPTY_FILE } from '../uploads/constants';
|
||||
|
||||
export type INodeState = Readonly<{
|
||||
is_loading: boolean;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export default function* nodeSaga() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IState } from "../store";
|
||||
import { INodeState } from "./reducer";
|
||||
import { IState } from '../store';
|
||||
import { INodeState } from './reducer';
|
||||
|
||||
export const selectNode = (state: IState): INodeState => state.node;
|
||||
export const selectNode = (state: IState): INodeState => state.node;
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
import { createStore, applyMiddleware, combineReducers, compose, Store } from "redux";
|
||||
import {
|
||||
createStore, applyMiddleware, combineReducers, compose, Store
|
||||
} from 'redux';
|
||||
|
||||
import { persistStore, persistReducer } from "redux-persist";
|
||||
import storage from "redux-persist/lib/storage";
|
||||
import createSagaMiddleware from "redux-saga";
|
||||
import { connectRouter, RouterState, routerMiddleware } from "connected-react-router";
|
||||
import { createBrowserHistory } from "history";
|
||||
import { PersistConfig, Persistor } from "redux-persist/es/types";
|
||||
import { persistStore, persistReducer } from 'redux-persist';
|
||||
import storage from 'redux-persist/lib/storage';
|
||||
import createSagaMiddleware from 'redux-saga';
|
||||
import { connectRouter, RouterState, routerMiddleware } from 'connected-react-router';
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { PersistConfig, Persistor } from 'redux-persist/es/types';
|
||||
|
||||
import authReducer from "~/redux/auth/reducer";
|
||||
import authSaga from "~/redux/auth/sagas";
|
||||
import authReducer from '~/redux/auth/reducer';
|
||||
import authSaga from '~/redux/auth/sagas';
|
||||
|
||||
import nodeReducer, { INodeState } from "~/redux/node/reducer";
|
||||
import nodeSaga from "~/redux/node/sagas";
|
||||
import nodeReducer, { INodeState } from '~/redux/node/reducer';
|
||||
import nodeSaga from '~/redux/node/sagas';
|
||||
|
||||
import uploadReducer, { IUploadState } from "~/redux/uploads/reducer";
|
||||
import uploadSaga from "~/redux/uploads/sagas";
|
||||
import uploadReducer, { IUploadState } from '~/redux/uploads/reducer';
|
||||
import uploadSaga from '~/redux/uploads/sagas';
|
||||
|
||||
import { IAuthState } from "~/redux/auth/types";
|
||||
import { IAuthState } from '~/redux/auth/types';
|
||||
|
||||
import modalReducer, { IModalState } from "~/redux/modal/reducer";
|
||||
import modalReducer, { IModalState } from '~/redux/modal/reducer';
|
||||
|
||||
const authPersistConfig: PersistConfig = {
|
||||
key: "auth",
|
||||
whitelist: ["token", "user"],
|
||||
key: 'auth',
|
||||
whitelist: ['token', 'user'],
|
||||
storage
|
||||
};
|
||||
|
||||
|
@ -37,10 +39,9 @@ export interface IState {
|
|||
export const sagaMiddleware = createSagaMiddleware();
|
||||
export const history = createBrowserHistory();
|
||||
|
||||
const composeEnhancers =
|
||||
typeof window === "object" && (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
? (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
|
||||
: compose;
|
||||
const composeEnhancers = typeof window === 'object' && (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
||||
? (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
|
||||
: compose;
|
||||
|
||||
export const store = createStore(
|
||||
combineReducers<IState>({
|
||||
|
|
|
@ -7,8 +7,8 @@ export interface ITag {
|
|||
}
|
||||
|
||||
export type IInputTextProps = DetailedHTMLProps<
|
||||
InputHTMLAttributes<HTMLInputElement>,
|
||||
HTMLInputElement
|
||||
InputHTMLAttributes<HTMLInputElement>,
|
||||
HTMLInputElement
|
||||
> & {
|
||||
wrapperClassName?: string;
|
||||
handler?: (value: string) => void;
|
||||
|
@ -72,7 +72,7 @@ export interface IFileWithUUID {
|
|||
}
|
||||
|
||||
export interface IBlock {
|
||||
type: 'image' | 'text' | 'media' | 'youtube' | 'video',
|
||||
type: 'image' | 'text' | 'media' | 'youtube' | 'video';
|
||||
temp_ids: UUID[];
|
||||
attaches: UUID[];
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ export interface INode {
|
|||
flow: {
|
||||
display: 'single' | 'double' | 'quadro';
|
||||
show_description: boolean;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
createdAt?: string;
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import { UPLOAD_ACTIONS } from "~/redux/uploads/constants";
|
||||
import { IFileWithUUID, UUID, IFile } from "../types";
|
||||
import { IUploadStatus } from "./reducer";
|
||||
import { UPLOAD_ACTIONS } from '~/redux/uploads/constants';
|
||||
import { IFileWithUUID, UUID, IFile } from '../types';
|
||||
import { IUploadStatus } from './reducer';
|
||||
|
||||
export const uploadUploadFiles = (files: IFileWithUUID[]) => ({
|
||||
files,
|
||||
type: UPLOAD_ACTIONS.UPLOAD_FILES,
|
||||
type: UPLOAD_ACTIONS.UPLOAD_FILES
|
||||
});
|
||||
|
||||
export const uploadAddStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({
|
||||
temp_id,
|
||||
status,
|
||||
type: UPLOAD_ACTIONS.ADD_STATUS,
|
||||
type: UPLOAD_ACTIONS.ADD_STATUS
|
||||
});
|
||||
|
||||
export const uploadAddFile = (file: IFile) => ({
|
||||
file,
|
||||
type: UPLOAD_ACTIONS.ADD_FILE,
|
||||
type: UPLOAD_ACTIONS.ADD_FILE
|
||||
});
|
||||
|
||||
export const uploadSetStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({
|
||||
temp_id,
|
||||
status,
|
||||
type: UPLOAD_ACTIONS.SET_STATUS,
|
||||
type: UPLOAD_ACTIONS.SET_STATUS
|
||||
});
|
||||
|
||||
export const uploadDropStatus = (temp_id: UUID) => ({
|
||||
temp_id,
|
||||
type: UPLOAD_ACTIONS.DROP_STATUS,
|
||||
type: UPLOAD_ACTIONS.DROP_STATUS
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IFile } from "~/redux/types";
|
||||
import { IUploadState, IUploadStatus } from "./reducer";
|
||||
import { IFile } from '~/redux/types';
|
||||
import { IUploadState, IUploadStatus } from './reducer';
|
||||
|
||||
const prefix = 'UPLOAD.';
|
||||
|
||||
|
@ -38,4 +38,4 @@ export const EMPTY_UPLOAD_STATUS: IUploadStatus = {
|
|||
thumbnail_url: null,
|
||||
type: null,
|
||||
temp_id: null,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,9 @@ import assocPath from 'ramda/es/assocPath';
|
|||
import omit from 'ramda/es/omit';
|
||||
|
||||
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 = (
|
||||
|
@ -17,33 +19,25 @@ const addStatus = (
|
|||
const dropStatus = (
|
||||
state: IUploadState,
|
||||
{ temp_id }: ReturnType<typeof uploadDropStatus>
|
||||
): IUploadState => assocPath(
|
||||
['statuses'],
|
||||
omit([temp_id], state.statuses),
|
||||
state,
|
||||
);
|
||||
): 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.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 => assocPath(['files'], { ...state.files, [file.id]: file }, state);
|
||||
|
||||
export const UPLOAD_HANDLERS = {
|
||||
[UPLOAD_ACTIONS.ADD_STATUS]: addStatus,
|
||||
[UPLOAD_ACTIONS.DROP_STATUS]: dropStatus,
|
||||
[UPLOAD_ACTIONS.SET_STATUS]: setStatus,
|
||||
[UPLOAD_ACTIONS.ADD_FILE]: addFile,
|
||||
[UPLOAD_ACTIONS.ADD_FILE]: addFile
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { IResultWithStatus, IFile, UUID } from "../types";
|
||||
import { HTTP_RESPONSES } from "~/utils/api";
|
||||
import { EMPTY_FILE } from "./constants";
|
||||
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>> => (
|
||||
export const uploadMock = ({ temp_id, file }: { temp_id: UUID; file: File }): Promise<IResultWithStatus<IFile>> => (
|
||||
Promise.resolve({
|
||||
status: HTTP_RESPONSES.CREATED,
|
||||
data: {
|
||||
|
@ -12,4 +12,4 @@ export const uploadMock = ({ temp_id, file }: { temp_id: UUID, file: File }): Pr
|
|||
temp_id,
|
||||
},
|
||||
error: null,
|
||||
}));
|
||||
}));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createReducer } from "~/utils/reducer";
|
||||
import { IFile, UUID } from "~/redux/types";
|
||||
import { UPLOAD_HANDLERS } from "./handlers";
|
||||
import { createReducer } from '~/utils/reducer';
|
||||
import { IFile, UUID } from '~/redux/types';
|
||||
import { UPLOAD_HANDLERS } from './handlers';
|
||||
|
||||
export interface IUploadStatus {
|
||||
is_uploading: boolean;
|
||||
|
@ -24,4 +24,4 @@ const INITIAL_STATE = {
|
|||
statuses: {},
|
||||
};
|
||||
|
||||
export default createReducer(INITIAL_STATE, UPLOAD_HANDLERS);
|
||||
export default createReducer(INITIAL_STATE, UPLOAD_HANDLERS);
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
import { takeEvery, all, spawn, call, put, take, fork, race } from 'redux-saga/effects';
|
||||
import {
|
||||
takeEvery, all, spawn, call, put, take, fork, race
|
||||
} from 'redux-saga/effects';
|
||||
import { UPLOAD_ACTIONS } from '~/redux/uploads/constants';
|
||||
import { uploadUploadFiles, uploadSetStatus, uploadAddStatus, uploadDropStatus, uploadAddFile } from './actions';
|
||||
import {
|
||||
uploadUploadFiles, uploadSetStatus, uploadAddStatus, uploadDropStatus, uploadAddFile
|
||||
} from './actions';
|
||||
import { reqWrapper } from '../auth/sagas';
|
||||
import { createUploader, uploadGetThumb, fakeUploader } from '~/utils/uploader';
|
||||
import { HTTP_RESPONSES } from '~/utils/api';
|
||||
import { VALIDATORS } from '~/utils/validators';
|
||||
import { UUID, IFileWithUUID, IResultWithStatus, IFile } from '../types';
|
||||
import { UUID, IFileWithUUID, IFile } from '../types';
|
||||
|
||||
function* uploadCall({ temp_id, onProgress, file }) {
|
||||
return yield call(reqWrapper, fakeUploader, { file: { url: 'some', error: 'cant do this boss' }, onProgress, mustSucceed: true });
|
||||
|
|
|
@ -2,4 +2,4 @@ import { IState } from '~/redux/store';
|
|||
import { IUploadState } from '~/redux/uploads/reducer';
|
||||
|
||||
export const selectUploads = ({ uploads }: IState): IUploadState => uploads;
|
||||
export const selectUploadStatuses = ({ uploads: { statuses } }: IState): IUploadState['statuses'] => statuses;
|
||||
export const selectUploadStatuses = ({ uploads: { statuses } }: IState): IUploadState['statuses'] => statuses;
|
||||
|
|
|
@ -1,42 +1,43 @@
|
|||
import React, {FC} from 'react';
|
||||
import React, { FC } from 'react';
|
||||
|
||||
const Sprites: FC<{}> = () => (
|
||||
<svg width={0} height={0} viewBox="0 0 24 24">
|
||||
<g id="cell-single" stroke="none" transform="translate(2 2)">
|
||||
<path d="M0,0 L9,0 L9,9 L0,9 L0,0 Z"></path>
|
||||
<path d="M11,0 L20,0 L20,9 L11,9 L11,0 Z M12,1 L12,8 L19,8 L19,1 L12,1 Z"></path>
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z"></path>
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z"></path>
|
||||
<path d="M0,0 L9,0 L9,9 L0,9 L0,0 Z" />
|
||||
<path d="M11,0 L20,0 L20,9 L11,9 L11,0 Z M12,1 L12,8 L19,8 L19,1 L12,1 Z" />
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z" />
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
|
||||
</g>
|
||||
|
||||
<g id="cell-double-h" stroke="none">
|
||||
<path d="M0,0 L20,0 L20,9 L0,9 L0,0 Z M1,1 L1,8 L19,8 L19,1 L1,1 Z"></path>
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z"/>
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z"></path>
|
||||
<path d="M0,0 L20,0 L20,9 L0,9 L0,0 Z M1,1 L1,8 L19,8 L19,1 L1,1 Z" />
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z" />
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
|
||||
</g>
|
||||
|
||||
<g id="cell-double-v" stroke="none">
|
||||
<path d="M0,0 L20,0 L20,9 L0,9 L0,0 Z M1,1 L1,8 L19,8 L19,1 L1,1 Z"></path>
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z"></path>
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z"></path>
|
||||
<path d="M0,0 L20,0 L20,9 L0,9 L0,0 Z M1,1 L1,8 L19,8 L19,1 L1,1 Z" />
|
||||
<path d="M11,11 L20,11 L20,20 L11,20 L11,11 Z M12,12 L12,19 L19,19 L19,12 L12,12 Z" />
|
||||
<path d="M0,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
|
||||
</g>
|
||||
|
||||
<g id="play">
|
||||
<path d="M8 6.82v10.36c0 .79.87 1.27 1.54.84l8.14-5.18c.62-.39.62-1.29 0-1.69L9.54 5.98C8.87 5.55 8 6.03 8 6.82z"/>
|
||||
<path d="M8 6.82v10.36c0 .79.87 1.27 1.54.84l8.14-5.18c.62-.39.62-1.29 0-1.69L9.54 5.98C8.87 5.55 8 6.03 8 6.82z" />
|
||||
</g>
|
||||
|
||||
<g id="plus" stroke="none">
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/>
|
||||
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
<path fill="none" d="M0 0h24v24H0V0z" />
|
||||
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||
</g>
|
||||
|
||||
<g id="close" stroke="none">
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/>
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
|
||||
<path fill="none" d="M0 0h24v24H0V0z" />
|
||||
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||
</g>
|
||||
|
||||
<g id="check" stroke="none">
|
||||
<path fill="none" d="M0 0h24v24H0V0z"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
|
||||
<path fill="none" d="M0 0h24v24H0V0z" />
|
||||
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import { push } from 'connected-react-router';
|
||||
import { API } from '~/constants/api';
|
||||
import { store } from '~/redux/store';
|
||||
import { push } from 'connected-react-router';
|
||||
import { IResultWithStatus } from '~/redux/types';
|
||||
|
||||
export const authMiddleware = r => {
|
||||
export const authMiddleware = (r) => {
|
||||
store.dispatch(push('/login'));
|
||||
return r;
|
||||
};
|
||||
|
@ -23,18 +23,15 @@ export const HTTP_RESPONSES = {
|
|||
TOO_MANY_REQUESTS: 429,
|
||||
};
|
||||
|
||||
export const resultMiddleware = <T extends {}>({
|
||||
export const resultMiddleware = (<)T extends {}>({
|
||||
status,
|
||||
data,
|
||||
}: {
|
||||
status: number;
|
||||
data: T;
|
||||
}): { status: number; data: T } => {
|
||||
return data && { status, data };
|
||||
};
|
||||
}): { status: number; data: T } => data && { status, data };
|
||||
|
||||
export const errorMiddleware = <T extends any>(debug): IResultWithStatus<T> =>
|
||||
debug && debug.response
|
||||
export const errorMiddleware = <T extends any>(debug): IResultWithStatus<T> => debug && debug.response
|
||||
? debug.response
|
||||
: {
|
||||
status: HTTP_RESPONSES.CONNECTION_REFUSED,
|
||||
|
|
|
@ -26,7 +26,6 @@ export const describeArc = (
|
|||
startAngle: number = 0,
|
||||
endAngle: number = 360,
|
||||
): string => {
|
||||
|
||||
const start = polarToCartesian(x, y, radius, endAngle);
|
||||
const end = polarToCartesian(x, y, radius, startAngle);
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@ import insert from 'ramda/es/insert';
|
|||
import nth from 'ramda/es/nth';
|
||||
import remove from 'ramda/es/remove';
|
||||
|
||||
export const moveArrItem = curry((at, to, list) => insert(to, nth(at, list), remove(at, 1, list)))
|
||||
export const moveArrItem = curry((at, to, list) => insert(to, nth(at, list), remove(at, 1, list)));
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
useCallback, useEffect, useRef, useState
|
||||
} from 'react';
|
||||
|
||||
export const useCloseOnEscape = (onRequestClose: () => void, ignore_inputs = false) => {
|
||||
const onEscape = useCallback(
|
||||
event => {
|
||||
(event) => {
|
||||
if (event.key !== 'Escape') return;
|
||||
if (
|
||||
ignore_inputs &&
|
||||
(event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')
|
||||
)
|
||||
return;
|
||||
ignore_inputs
|
||||
&& (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')
|
||||
) return;
|
||||
|
||||
onRequestClose();
|
||||
},
|
||||
[onRequestClose],
|
||||
[ignore_inputs, onRequestClose],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -30,5 +32,5 @@ export const useDelayedReady = (setReady: (val: boolean) => void, delay: number
|
|||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
}, []);
|
||||
}, [delay, setReady]);
|
||||
};
|
||||
|
|
|
@ -14,6 +14,6 @@ type Handlers<State, Types extends string, Actions extends Action<Types>> = {
|
|||
export const createReducer = (
|
||||
initialState,
|
||||
handlers,
|
||||
) => (state = initialState, action) => handlers.hasOwnProperty(action.type)
|
||||
) => (state = initialState, action) => (handlers.hasOwnProperty(action.type)
|
||||
? handlers[action.type](state, action)
|
||||
: state;
|
||||
: state);
|
||||
|
|
|
@ -13,7 +13,7 @@ export function createUploader<T extends {}, R extends {}>(
|
|||
): [(args: T) => (args: T & { onProgress: (current: number, total: number) => void }) => any, EventChannel<any>] {
|
||||
let emit;
|
||||
|
||||
const chan = eventChannel(emitter => {
|
||||
const chan = eventChannel((emitter) => {
|
||||
emit = emitter;
|
||||
return () => null;
|
||||
});
|
||||
|
@ -27,7 +27,7 @@ export function createUploader<T extends {}, R extends {}>(
|
|||
return [wrappedCallback, chan];
|
||||
}
|
||||
|
||||
export const uploadGetThumb = async file => {
|
||||
export const uploadGetThumb = async (file) => {
|
||||
if (!file.type || !VALIDATORS.IS_IMAGE_MIME(file.type)) return '';
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue