1
0
Fork 0
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:
muerwre 2019-08-09 12:23:07 +07:00
parent dfaac877fb
commit fa4d51360b
81 changed files with 741 additions and 972 deletions

View file

@ -1,26 +1,27 @@
module.exports = { 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": "babel-eslint",
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
ecmaFeatures: { 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: { settings: {
'import/resolver': { 'import/resolver': {
// node: { // node: {
// extensions: ['.js', '.jsx', '.ts', '.tsx'], // extensions: ['.js', '.jsx', '.ts', '.tsx'],
// }, // },
typescript: {} typescript: {},
} },
}, },
rules: { rules: {
indent: ['error', 2], indent: ['error', 2],
'@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/indent': ['error', 2], '@typescript-eslint/indent': ['warn', 2],
"indent": "off",
'comma-dangle': 0, 'comma-dangle': 0,
'no-restricted-syntax': 1, 'no-restricted-syntax': 1,
'react/prop-types': 0, 'react/prop-types': 0,
@ -44,16 +45,16 @@ module.exports = {
'react-hooks/rules-of-hooks': 'error', 'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn', 'react-hooks/exhaustive-deps': 'warn',
'no-nested-ternary': 1, 'no-nested-ternary': 1,
'arrow-parens': 0,
'import/prefer-default-export': 0, 'import/prefer-default-export': 0,
'no-return-await': 0, 'max-line-length': [true, 100],
'prefer-promise-reject-errors': 0, // 'max-len': 100,
'import/order': 0 // 'max-len': { "code": 100 },
'max-len': ["warn", { "code": 100 }]
}, },
globals: { globals: {
document: false, document: false,
window: false, window: false,
HTMLInputElement: false, HTMLInputElement: false,
HTMLDivElement: false HTMLDivElement: false,
} },
}; };

View file

@ -1,4 +1,4 @@
{ {
"printWidth": 120, "printWidth": 100,
"singleQuote": true "singleQuote": true
} }

20
.vscode/settings.json vendored Normal file
View 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

File diff suppressed because it is too large Load diff

View file

@ -27,18 +27,6 @@
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1", "babel-preset-stage-2": "^6.24.1",
"css-loader": "^0.28.11", "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", "file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
@ -51,7 +39,6 @@
"style-loader": "^0.21.0", "style-loader": "^0.21.0",
"ts-node": "^8.0.1", "ts-node": "^8.0.1",
"typescript": "^3.2.4", "typescript": "^3.2.4",
"typescript-eslint-parser": "^22.0.0",
"uglifyjs-webpack-plugin": "^1.3.0", "uglifyjs-webpack-plugin": "^1.3.0",
"webpack": "^4.6.0", "webpack": "^4.6.0",
"webpack-cli": "^3.2.3", "webpack-cli": "^3.2.3",
@ -74,7 +61,19 @@
"date-fns": "^2.0.0-alpha.27", "date-fns": "^2.0.0-alpha.27",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"dotenv-webpack": "^1.7.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", "history": "^4.7.2",
"http-errors": "~1.6.2", "http-errors": "~1.6.2",
"less": "^3.8.1", "less": "^3.8.1",

View file

@ -1,5 +1,5 @@
import React, { AllHTMLAttributes, FC } from "react"; import React, { AllHTMLAttributes, FC } from 'react';
import * as styles from "./styles.scss"; import * as styles from './styles.scss';
type IProps = AllHTMLAttributes<HTMLDivElement> & { is_blurred: boolean }; type IProps = AllHTMLAttributes<HTMLDivElement> & { is_blurred: boolean };

View file

@ -1,7 +1,8 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import classNames = require("classnames");
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import classNames = require('classnames');
type IProps = React.HTMLAttributes<HTMLDivElement> & { type IProps = React.HTMLAttributes<HTMLDivElement> & {
seamless?: boolean; seamless?: boolean;
} }

View file

@ -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 * as styles from './styles.scss';
import classNames = require("classnames");
import classNames = require('classnames');
type IProps = HTMLAttributes<HTMLDivElement> & { type IProps = HTMLAttributes<HTMLDivElement> & {
children: any; children: any;

View file

@ -1,6 +1,6 @@
import React, { FC } from "react"; import React, { FC } from 'react';
import classNames from "classnames"; import classNames from 'classnames';
import * as styles from "./styles.scss"; import * as styles from './styles.scss';
type IProps = React.HTMLAttributes<HTMLDivElement> & { type IProps = React.HTMLAttributes<HTMLDivElement> & {
horizontal?: boolean; horizontal?: boolean;
@ -15,14 +15,14 @@ type IProps = React.HTMLAttributes<HTMLDivElement> & {
const Grid: FC<IProps> = ({ const Grid: FC<IProps> = ({
children, children,
className = "", className = '',
horizontal = false, horizontal = false,
vertical = false, vertical = false,
square = false, square = false,
size = "auto", size = 'auto',
style = {}, style = {},
columns = "auto", columns = 'auto',
rows = "auto", rows = 'auto',
gap = 10, gap = 10,
stretchy, stretchy,
...props ...props
@ -37,10 +37,10 @@ const Grid: FC<IProps> = ({
style={{ style={{
...style, ...style,
gridTemplateColumns: square gridTemplateColumns: square
? `repeat(auto-fill, ${(columns !== "auto" && columns) || size})` ? `repeat(auto-fill, ${(columns !== 'auto' && columns) || size})`
: columns, : columns,
gridTemplateRows: square gridTemplateRows: square
? `repeat(auto-fill, ${(rows !== "auto" && rows) || size})` ? `repeat(auto-fill, ${(rows !== 'auto' && rows) || size})`
: rows, : rows,
gridAutoRows: rows, gridAutoRows: rows,
gridAutoColumns: columns, gridAutoColumns: columns,

View file

@ -1,6 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import classNames = require("classnames");
import classNames = require('classnames');
type IProps = React.HTMLAttributes<HTMLDivElement> & { type IProps = React.HTMLAttributes<HTMLDivElement> & {
padding?: number; padding?: number;

View file

@ -1,10 +1,11 @@
import React, { FC, HTMLAttributes } from 'react'; import React, { FC, HTMLAttributes } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import classNames = require("classnames");
import classNames = require('classnames');
type IProps = HTMLAttributes<HTMLDivElement> & { type IProps = HTMLAttributes<HTMLDivElement> & {
seamless?: boolean; seamless?: boolean;
stretchy?: boolean stretchy?: boolean;
} }
const Panel: FC<IProps> = ({ const Panel: FC<IProps> = ({

View file

@ -1,7 +1,7 @@
import React, { MouseEventHandler, useEffect, useState } from 'react'; import React, { MouseEventHandler, useEffect, useState } from 'react';
import * as styles from './styles.scss';
import { Scrollbars } from 'tt-react-custom-scrollbars'; import { Scrollbars } from 'tt-react-custom-scrollbars';
import classNames from 'classnames'; import classNames from 'classnames';
import * as styles from './styles.scss';
interface IProps { interface IProps {
children: Element | React.ReactChild; children: Element | React.ReactChild;
@ -33,11 +33,11 @@ export const Scroll = ({
renderTrackVertical={data => <div className={styles.track_vertical} {...data} />} renderTrackVertical={data => <div className={styles.track_vertical} {...data} />}
renderThumbHorizontal={data => <div className={styles.thumb_horizontal} {...data} />} renderThumbHorizontal={data => <div className={styles.thumb_horizontal} {...data} />}
renderThumbVertical={data => <div className={styles.thumb_vertical} {...data} />} renderThumbVertical={data => <div className={styles.thumb_vertical} {...data} />}
renderView = {data => <div className={styles.view} {...data} />} renderView={data => <div className={styles.view} {...data} />}
hideTracksWhenNotNeeded hideTracksWhenNotNeeded
universal universal
ref={setRef} ref={setRef}
{ ...props } {...props}
> >
{children} {children}
</Scrollbars> </Scrollbars>

View file

@ -1,4 +1,4 @@
import React, {FC, HTMLAttributes} from 'react'; import React, { FC, HTMLAttributes } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
type IProps = HTMLAttributes<HTMLDivElement> & {} type IProps = HTMLAttributes<HTMLDivElement> & {}

View file

@ -1,7 +1,7 @@
import React, { FC, ChangeEventHandler } from 'react'; import React, { FC, ChangeEventHandler } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { ImageUploadButton } from '~/components/editors/ImageUploadButton'; import { EditorUploadButton } from '~/components/editors/EditorUploadButton';
interface IProps { interface IProps {
data: INode; data: INode;
@ -11,7 +11,7 @@ interface IProps {
const EditorPanel: FC<IProps> = ({ onUpload }) => ( const EditorPanel: FC<IProps> = ({ onUpload }) => (
<div className={styles.panel}> <div className={styles.panel}>
<ImageUploadButton onUpload={onUpload} /> <EditorUploadButton onUpload={onUpload} />
</div> </div>
); );

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

View file

@ -1,31 +1,44 @@
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 uuid from 'uuid4';
import { INode, IFileWithUUID, IFile } from '~/redux/types';
import * as UPLOAD_ACTIONS from '~/redux/uploads/actions';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectUploads } from '~/redux/uploads/selectors';
import assocPath from 'ramda/es/assocPath'; import assocPath from 'ramda/es/assocPath';
import append from 'ramda/es/append'; 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 { ImageGrid } from '~/components/editors/ImageGrid';
import { moveArrItem } from '~/utils/fn'; import { moveArrItem } from '~/utils/fn';
import { IUploadStatus } from '~/redux/uploads/reducer'; import { IUploadStatus } from '~/redux/uploads/reducer';
const mapStateToProps = selectUploads; const mapStateToProps = selectUploads;
const mapDispatchToProps = { 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; data: INode;
pending_files: IUploadStatus[]; pending_files: IUploadStatus[];
setData: (val: INode) => void; setData: (val: INode) => void;
onFileMove: (o: number, n: number) => void; onFileMove: (o: number, n: number) => void;
onInputChange: ChangeEventHandler<HTMLInputElement>; onInputChange: ChangeEventHandler<HTMLInputElement>;
onDrop: DragEventHandler<HTMLFormElement>; onDrop: DragEventHandler<HTMLFormElement>;
} };
const ImageEditorUnconnected: FC<IProps> = ({ data, onFileMove, onInputChange, onDrop, pending_files }) => { const ImageEditorUnconnected: FC<IProps> = ({
return ( data,
onFileMove,
onInputChange,
onDrop,
pending_files
}) => (
<ImageGrid <ImageGrid
onFileMove={onFileMove} onFileMove={onFileMove}
items={data.files} items={data.files}
@ -33,8 +46,10 @@ const ImageEditorUnconnected: FC<IProps> = ({ data, onFileMove, onInputChange, o
onUpload={onInputChange} onUpload={onInputChange}
onDrop={onDrop} onDrop={onDrop}
/> />
); );
};
const ImageEditor = connect(mapStateToProps, mapDispatchToProps)(ImageEditorUnconnected) const ImageEditor = connect(
mapStateToProps,
mapDispatchToProps
)(ImageEditorUnconnected);
export { ImageEditor }; export { ImageEditor };

View file

@ -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 { SortableContainer, SortableElement } from 'react-sortable-hoc';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { ImageUpload } from '~/components/upload/ImageUpload'; import { ImageUpload } from '~/components/upload/ImageUpload';
import { IFile } from '~/redux/types'; import { IFile } from '~/redux/types';
import { IUploadStatus } from '~/redux/uploads/reducer'; import { IUploadStatus } from '~/redux/uploads/reducer';
import { ImageUploadButton } from '~/components/editors/ImageUploadButton';
interface IProps { interface IProps {
items: IFile[]; items: IFile[];
@ -12,50 +13,52 @@ interface IProps {
onFileMove: (o: number, n: number) => void; onFileMove: (o: number, n: number) => void;
onUpload?: ChangeEventHandler<HTMLInputElement>; onUpload?: ChangeEventHandler<HTMLInputElement>;
onDrop: DragEventHandler<HTMLFormElement>; onDrop: DragEventHandler<HTMLFormElement>;
}; }
const SortableItem = SortableElement(({ children }) => <div className={styles.item}>{children}</div>); 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> }) => { const SortableList = SortableContainer(
return ( ({
<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>
))
}
</form>
);
});
const ImageGrid: FC<IProps> = ({
items, items,
locked, locked,
onFileMove, onDrop
onUpload, }: {
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>
))}
</form>
)
);
const ImageGrid: FC<IProps> = ({
items, locked, onFileMove, onUpload, onDrop
}) => { }) => {
const onMove = useCallback(({ oldIndex, newIndex }) => onFileMove(oldIndex, newIndex), [onFileMove]); const onMove = useCallback(({ oldIndex, newIndex }) => onFileMove(oldIndex, newIndex), [onFileMove]);
return ( 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 };

View file

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

View file

@ -1,6 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import classNames = require("classnames");
import classNames = require('classnames');
interface IProps { interface IProps {
height?: number; height?: number;

View file

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
const style = require('./style.scss'); const style = require('./style.scss');
export const HeroPlaceholder = () => ( export const HeroPlaceholder = () => (
<div className={style.container}> <div className={style.container} />
</div>
); );

View file

@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { Cell } from '~/components/flow/Cell';
import { range } from 'ramda'; import { range } from 'ramda';
import { Cell } from '~/components/flow/Cell';
import * as styles from './styles.scss'; import * as styles from './styles.scss';

View file

@ -5,7 +5,7 @@ import { describeArc } from '~/utils/dom';
interface IProps { interface IProps {
size: number; size: number;
progress: number; progress: number;
}; }
export const ArcProgress: FC<IProps> = ({ size, progress }) => ( export const ArcProgress: FC<IProps> = ({ size, progress }) => (
<svg className={styles.icon} width={size} height={size}> <svg className={styles.icon} width={size} height={size}>

View file

@ -1,14 +1,14 @@
import classnames from "classnames"; import classnames from 'classnames';
import * as styles from "./styles.scss"; import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react';
import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from "react"; import * as styles from './styles.scss';
import { Icon } from "~/components/input/Icon"; import { Icon } from '~/components/input/Icon';
import { IIcon } from "~/redux/types"; import { IIcon } from '~/redux/types';
type IButtonProps = DetailedHTMLProps< type IButtonProps = DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>, ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement HTMLButtonElement
> & { > & {
size?: "mini" | "normal" | "big" | "giant" | "micro"; size?: 'mini' | 'normal' | 'big' | 'giant' | 'micro';
iconLeft?: IIcon; iconLeft?: IIcon;
iconRight?: IIcon; iconRight?: IIcon;
seamless?: boolean; seamless?: boolean;
@ -22,8 +22,8 @@ type IButtonProps = DetailedHTMLProps<
}; };
export const Button: FC<IButtonProps> = ({ export const Button: FC<IButtonProps> = ({
className = "", className = '',
size = "normal", size = 'normal',
iconLeft, iconLeft,
iconRight, iconRight,
children, children,
@ -36,8 +36,7 @@ export const Button: FC<IButtonProps> = ({
title, title,
stretchy, stretchy,
...props ...props
}) => }) => React.createElement(seamless || non_submitting ? 'div' : 'button', {
React.createElement(seamless || non_submitting ? "div" : "button", {
className: classnames(styles.button, className, styles[size], { className: classnames(styles.button, className, styles[size], {
red, red,
grey, grey,
@ -58,4 +57,4 @@ export const Button: FC<IButtonProps> = ({
iconRight && <Icon icon={iconRight} size={20} key={2} /> iconRight && <Icon icon={iconRight} size={20} key={2} />
], ],
...props ...props
}); });

View file

@ -1,18 +1,20 @@
import React, { FC } from "react"; import React, { FC } from 'react';
import { IIcon } from "~/redux/types"; import { IIcon } from '~/redux/types';
type IProps = React.SVGAttributes<SVGElement> & { type IProps = React.SVGAttributes<SVGElement> & {
size?: number; size?: number;
icon: IIcon; icon: IIcon;
}; };
export const Icon: FC<IProps> = ({ size = 20, icon, style, ...props }) => ( export const Icon: FC<IProps> = ({
size = 20, icon, style, ...props
}) => (
<svg <svg
width={size} width={size}
height={size} height={size}
viewBox={`0 0 24 24`} viewBox="0 0 24 24"
preserveAspectRatio="xMidYMid slice" preserveAspectRatio="xMidYMid slice"
style={{ ...style, outline: "none" }} style={{ ...style, outline: 'none' }}
{...props} {...props}
> >
<use xlinkHref={`#${icon}`} /> <use xlinkHref={`#${icon}`} />

View file

@ -1,12 +1,13 @@
import * as React from 'react'; import * as React from 'react';
import classNames = require("classnames");
import classNames = require('classnames');
const style = require('./style.scss'); const style = require('./style.scss');
interface IInfoProps { interface IInfoProps {
text?: string, text?: string;
children?: string, children?: string;
level?: string, level?: string;
} }
export const Info: React.FunctionComponent<IInfoProps> = ({ export const Info: React.FunctionComponent<IInfoProps> = ({
text, text,

View file

@ -4,8 +4,8 @@ import React, {
useCallback, useCallback,
useState, useEffect, useState, useEffect,
} from 'react'; } from 'react';
import * as styles from '~/styles/inputs.scss';
import classNames from 'classnames'; import classNames from 'classnames';
import * as styles from '~/styles/inputs.scss';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { IInputTextProps } from '~/redux/types'; import { IInputTextProps } from '~/redux/types';
import { LoaderCircle } from '~/components/input/LoaderCircle'; import { LoaderCircle } from '~/components/input/LoaderCircle';
@ -31,8 +31,8 @@ const InputText: FC<IInputTextProps> = ({
[handler], [handler],
); );
const onFocus = useCallback(() => setFocused(true), [focused]); const onFocus = useCallback(() => setFocused(true), []);
const onBlur = useCallback(() => setFocused(false), [focused]); const onBlur = useCallback(() => setFocused(false), []);
useEffect(() => { useEffect(() => {
if (onRef) onRef(inner_ref); if (onRef) onRef(inner_ref);
@ -50,7 +50,8 @@ const InputText: FC<IInputTextProps> = ({
[styles.has_error]: !!error, [styles.has_error]: !!error,
[styles.has_loader]: is_loading, [styles.has_loader]: is_loading,
}, },
)}> )}
>
<div className={styles.input}> <div className={styles.input}>
<input <input
type="text" type="text"

View file

@ -2,12 +2,12 @@ import * as React from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
interface ITextInputProps { interface ITextInputProps {
type?: 'text' | 'password', type?: 'text' | 'password';
placeholder?: string, placeholder?: string;
label?: string, label?: string;
value?: string, value?: string;
onChange: React.ChangeEventHandler, onChange: React.ChangeEventHandler;
} }
export const TextInput: React.FunctionComponent<ITextInputProps> = ({ export const TextInput: React.FunctionComponent<ITextInputProps> = ({
@ -15,15 +15,15 @@ export const TextInput: React.FunctionComponent<ITextInputProps> = ({
placeholder = '', placeholder = '',
label, label,
onChange = () => {}, onChange = () => {},
value='', value = '',
}) => ( }) => (
<div <div
className={styles.wrapper} className={styles.wrapper}
> >
<div className={styles.container}> <div className={styles.container}>
{ {
label && label
<div className={styles.label}>{label}</div> && <div className={styles.label}>{label}</div>
} }
<input <input
placeholder={placeholder} placeholder={placeholder}

View file

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
interface IGodRaysProps { interface IGodRaysProps {
raised?: boolean, raised?: boolean;
} }
export class GodRays extends React.Component<IGodRaysProps> { 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); 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'); const ctx = this.canvas.getContext('2d');
ctx.globalCompositeOperation = "luminosity"; ctx.globalCompositeOperation = 'luminosity';
ctx.clearRect(0, 0, width, height + 100); // clear canvas ctx.clearRect(0, 0, width, height + 100); // clear canvas
ctx.save(); 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); const gradient = ctx.createLinearGradient(0, 0, 0, height * 1.3);
gradient.addColorStop(0.2, `rgba(255, 60, 40, ${opacity * 0.1})`); 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); const gradient2 = ctx.createLinearGradient(0, 0, 0, height * 1.3);
gradient2.addColorStop(0.2, `rgba(255, 40, 100, ${opacity * 0.2})`); 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.save();
ctx.translate(width / 2, -900); ctx.translate(width / 2, -900);
@ -106,7 +110,7 @@ export class GodRays extends React.Component<IGodRaysProps> {
this.init(); this.init();
} }
render(){ render() {
const { width, height } = this.state; const { width, height } = this.state;
return ( return (
@ -119,7 +123,8 @@ export class GodRays extends React.Component<IGodRaysProps> {
zIndex: -1, zIndex: -1,
opacity: 1, opacity: 1,
pointerEvents: 'none', pointerEvents: 'none',
}}> }}
>
<canvas <canvas
width={width} width={width}
height={height + 100} height={height + 100}
@ -128,12 +133,13 @@ export class GodRays extends React.Component<IGodRaysProps> {
position: 'relative', position: 'relative',
top: -100, top: -100,
}} }}
ref={el => { this.canvas = el; }} ref={(el) => { this.canvas = el; }}
/> />
</div> </div>
); );
} }
canvas: HTMLCanvasElement; canvas: HTMLCanvasElement;
inc; inc;
}; }

View file

@ -1,13 +1,13 @@
import * as React from "react"; import * as React from 'react';
import { Logo } from "~/components/main/Logo"; import { connect } from 'react-redux';
import { connect } from "react-redux"; import { push as historyPush } from 'connected-react-router';
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 * as style from './style.scss';
import { Filler } from "~/components/containers/Filler"; import { Filler } from '~/components/containers/Filler';
import { Link } from "react-router-dom"; import { selectUser } from '~/redux/auth/selectors';
import {selectUser} from "~/redux/auth/selectors"; import { Group } from '~/components/containers/Group';
import {Group} from "~/components/containers/Group";
const mapStateToProps = selectUser; const mapStateToProps = selectUser;
@ -20,8 +20,7 @@ type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {
const HeaderUnconnected: React.FunctionComponent<IProps> = ({ const HeaderUnconnected: React.FunctionComponent<IProps> = ({
username, username,
is_user is_user
}) => { }) => (
return (
<div className="default_container head_container"> <div className="default_container head_container">
<div className={style.container}> <div className={style.container}>
<Logo /> <Logo />
@ -39,12 +38,11 @@ const HeaderUnconnected: React.FunctionComponent<IProps> = ({
<Group horizontal className={style.user_button}> <Group horizontal className={style.user_button}>
<div>username</div> <div>username</div>
<div className={style.user_avatar}/> <div className={style.user_avatar} />
</Group> </Group>
</div> </div>
</div> </div>
); );
};
const Header = connect( const Header = connect(
mapStateToProps, mapStateToProps,

View file

@ -1,7 +1,9 @@
import React, { FC, LegacyRef, ReactChild, useCallback, useEffect, useState } from 'react'; import React, {
import * as styles from './styles.scss'; FC, LegacyRef, ReactChild, useCallback, useEffect, useState
} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import {Group} from "~/components/containers/Group"; import * as styles from './styles.scss';
import { Group } from '~/components/containers/Group';
interface IProps { interface IProps {
} }
@ -28,8 +30,8 @@ export const SidePane: FC<IProps> = ({
return () => { return () => {
window.removeEventListener('resize', moveThis); window.removeEventListener('resize', moveThis);
document.removeEventListener('DOMContentLoaded', moveThis); document.removeEventListener('DOMContentLoaded', moveThis);
} };
}, []); }, [moveThis]);
return ( return (
<div className={styles.pane} style={{ transform: `translate(${left}px, 0px)` }}> <div className={styles.pane} style={{ transform: `translate(${left}px, 0px)` }}>

View file

@ -1,7 +1,8 @@
import React, {FC, HTMLAttributes} from 'react'; import React, { FC, HTMLAttributes } from 'react';
import { Card } from "~/components/containers/Card"; import { Card } from '~/components/containers/Card';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import classNames = require("classnames");
import classNames = require('classnames');
type IProps = HTMLAttributes<HTMLDivElement> & { type IProps = HTMLAttributes<HTMLDivElement> & {
is_empty?: boolean; is_empty?: boolean;

View file

@ -1,7 +1,7 @@
import React, {FC} from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { Group } from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
import { Filler } from "~/components/containers/Filler"; import { Filler } from '~/components/containers/Filler';
interface IProps { interface IProps {
title: string; title: string;
@ -19,7 +19,10 @@ const MenuButton: FC<IProps> = ({
> >
<Group horizontal> <Group horizontal>
<div className={styles.icon}> <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> </div>
<Filler> <Filler>

View file

@ -1,15 +1,15 @@
import React, { FC } from "react"; import React, { FC } from 'react';
import { Comment } from "~/components/node/Comment"; import { Comment } from '~/components/node/Comment';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import {Group} from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
interface IProps {} interface IProps {}
const NodeNoComments: FC<IProps> = () => ( const NodeNoComments: FC<IProps> = () => (
<Group className={styles.wrap}> <Group className={styles.wrap}>
<Comment is_empty={true} is_loading={false} style={{ height: 94 }} /> <Comment is_empty is_loading={false} style={{ height: 94 }} />
<Comment is_empty={true} is_loading={false} style={{ height: 104 }} /> <Comment is_empty is_loading={false} style={{ height: 104 }} />
<Comment is_empty={true} is_loading={false} style={{ height: 100 }} /> <Comment is_empty is_loading={false} style={{ height: 100 }} />
</Group> </Group>
); );

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { Group } from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
import { Filler } from "~/components/containers/Filler"; import { Filler } from '~/components/containers/Filler';
interface IProps {} interface IProps {}

View file

@ -1,7 +1,7 @@
import React, {FC, HTMLAttributes} from 'react'; import React, { FC, HTMLAttributes } from 'react';
import { range } from 'ramda'; import { range } from 'ramda';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import {Group} from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
type IProps = HTMLAttributes<HTMLDivElement> & {} type IProps = HTMLAttributes<HTMLDivElement> & {}
@ -16,7 +16,7 @@ const NodeRelated: FC<IProps> = ({
</div> </div>
<div className={styles.grid}> <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> </div>
</Group> </Group>

View file

@ -1,7 +1,8 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss'; 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 { interface IProps {
title: ITag['title']; title: ITag['title'];

View file

@ -1,7 +1,7 @@
import React, {FC, HTMLAttributes} from 'react'; import React, { FC, HTMLAttributes } from 'react';
import {TagField} from "~/components/containers/TagField"; import { TagField } from '~/components/containers/TagField';
import {ITag} from "~/redux/types"; import { ITag } from '~/redux/types';
import {Tag} from "~/components/node/Tag"; import { Tag } from '~/components/node/Tag';
type IProps = HTMLAttributes<HTMLDivElement> & { type IProps = HTMLAttributes<HTMLDivElement> & {
tags: ITag[]; tags: ITag[];

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { Placeholder } from "~/components/placeholders/Placeholder"; import { Placeholder } from '~/components/placeholders/Placeholder';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import {Group} from "~/components/containers/Group"; import { Group } from '~/components/containers/Group';
const ParagraphPlaceholder = ({ }) => ( const ParagraphPlaceholder = ({ }) => (
<Group> <Group>

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import * as styles from './styles.scss';
import classNames from 'classnames'; import classNames from 'classnames';
import * as styles from './styles.scss';
import { ArcProgress } from '~/components/input/ArcProgress'; import { ArcProgress } from '~/components/input/ArcProgress';
interface IProps { interface IProps {
@ -9,22 +9,20 @@ interface IProps {
progress?: number; progress?: number;
is_uploading?: boolean; is_uploading?: boolean;
}; }
const ImageUpload: FC<IProps> = ({ const ImageUpload: FC<IProps> = ({
thumb, thumb,
id, id,
progress, progress,
is_uploading, is_uploading,
}) => { }) => (
return (
<div className={styles.wrap}> <div className={styles.wrap}>
<div className={classNames(styles.thumb_wrap, { is_uploading })}> <div className={classNames(styles.thumb_wrap, { is_uploading })}>
{thumb && <div className={styles.thumb} style={{ background: `url("${thumb}")` }}>{id}</div>} {thumb && <div className={styles.thumb} style={{ background: `url("${thumb}")` }}>{id}</div>}
{is_uploading && <div className={styles.progress}><ArcProgress size={72} progress={progress} /></div>} {is_uploading && <div className={styles.progress}><ArcProgress size={72} progress={progress} /></div>}
</div> </div>
</div> </div>
); );
}
export { ImageUpload }; export { ImageUpload };

View file

@ -1,20 +1,22 @@
import * as React from "react"; import * as React from 'react';
import { connect } from "react-redux"; import { connect } from 'react-redux';
import { bindActionCreators } from "redux"; import { bindActionCreators } from 'redux';
import { hot } from "react-hot-loader"; import { hot } from 'react-hot-loader';
import { ConnectedRouter } from "connected-react-router"; import { ConnectedRouter } from 'connected-react-router';
import { history } from "~/redux/store"; import {
import { NavLink, Switch, Route, Redirect } from "react-router-dom"; NavLink, Switch, Route, Redirect
import { FlowLayout } from "~/containers/flow/FlowLayout"; } from 'react-router-dom';
import { MainLayout } from "~/containers/main/MainLayout"; import { history } from '~/redux/store';
import { ImageExample } from "~/containers/examples/ImageExample"; import { FlowLayout } from '~/containers/flow/FlowLayout';
import { EditorExample } from "~/containers/examples/EditorExample"; import { MainLayout } from '~/containers/main/MainLayout';
import { HorizontalExample } from "~/containers/examples/HorizontalExample"; import { ImageExample } from '~/containers/examples/ImageExample';
import { Sprites } from "~/sprites/Sprites"; import { EditorExample } from '~/containers/examples/EditorExample';
import { URLS } from "~/constants/urls"; import { HorizontalExample } from '~/containers/examples/HorizontalExample';
import { Modal } from "~/containers/dialogs/Modal"; import { Sprites } from '~/sprites/Sprites';
import { selectModal } from "~/redux/modal/selectors"; import { URLS } from '~/constants/urls';
import { BlurWrapper } from "~/components/containers/BlurWrapper"; import { Modal } from '~/containers/dialogs/Modal';
import { selectModal } from '~/redux/modal/selectors';
import { BlurWrapper } from '~/components/containers/BlurWrapper';
const mapStateToProps = selectModal; const mapStateToProps = selectModal;
const mapDispatchToProps = {}; const mapDispatchToProps = {};

View file

@ -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 { ScrollDialog } from '../ScrollDialog';
import { IDialogProps } from '~/redux/modal/constants'; import { IDialogProps } from '~/redux/modal/constants';
import { useCloseOnEscape } from '~/utils/hooks'; import { useCloseOnEscape } from '~/utils/hooks';
@ -7,19 +13,15 @@ import { InputText } from '~/components/input/InputText';
import { Button } from '~/components/input/Button'; import { Button } from '~/components/input/Button';
import { Padder } from '~/components/containers/Padder'; import { Padder } from '~/components/containers/Padder';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { connect } from 'react-redux';
import { selectNode } from '~/redux/node/selectors'; import { selectNode } from '~/redux/node/selectors';
import { ImageEditor } from '~/components/editors/ImageEditor'; import { ImageEditor } from '~/components/editors/ImageEditor';
import { EditorPanel } from '~/components/editors/EditorPanel'; import { EditorPanel } from '~/components/editors/EditorPanel';
import assocPath from 'ramda/es/assocPath';
import append from 'ramda/es/append';
import { moveArrItem } from '~/utils/fn'; import { moveArrItem } from '~/utils/fn';
import { IFile, IFileWithUUID } from '~/redux/types'; import { IFile, IFileWithUUID } from '~/redux/types';
import uuid from 'uuid4';
import * as UPLOAD_ACTIONS from '~/redux/uploads/actions'; import * as UPLOAD_ACTIONS from '~/redux/uploads/actions';
import { selectUploads } from '~/redux/uploads/selectors'; import { selectUploads } from '~/redux/uploads/selectors';
const mapStateToProps = state => { const mapStateToProps = (state) => {
const { editor } = selectNode(state); const { editor } = selectNode(state);
const { statuses, files } = selectUploads(state); const { statuses, files } = selectUploads(state);
@ -32,7 +34,9 @@ const mapDispatchToProps = {
type IProps = IDialogProps & ReturnType<typeof mapStateToProps> & typeof 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 [data, setData] = useState(editor);
const eventPreventer = useCallback(event => event.preventDefault(), []); const eventPreventer = useCallback(event => event.preventDefault(), []);
const [temp, setTemp] = useState([]); const [temp, setTemp] = useState([]);
@ -68,7 +72,7 @@ const EditorDialogUnconnected: FC<IProps> = ({ onRequestClose, editor, uploadUpl
); );
const onInputChange = useCallback( const onInputChange = useCallback(
event => { (event) => {
event.preventDefault(); event.preventDefault();
if (!event.target.files || !event.target.files.length) return; 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)); setTemp(temp.filter(el => el !== id));
} }
}); });
}, [statuses, files]); }, [statuses, files, temp, onFileAdd]);
const setTitle = useCallback( const setTitle = useCallback(
title => { (title) => {
setData({ ...data, title }); setData({ ...data, title });
}, },
[setData, data] [setData, data]

View file

@ -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 { ScrollDialog } from '../ScrollDialog';
import { IDialogProps } from '~/redux/modal/constants'; import { IDialogProps } from '~/redux/modal/constants';
import { useCloseOnEscape } from '~/utils/hooks'; import { useCloseOnEscape } from '~/utils/hooks';
@ -7,9 +10,8 @@ import { InputText } from '~/components/input/InputText';
import { Button } from '~/components/input/Button'; import { Button } from '~/components/input/Button';
import { Padder } from '~/components/containers/Padder'; import { Padder } from '~/components/containers/Padder';
import * as styles from './styles.scss'; 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 * as ACTIONS from '~/redux/auth/actions';
import { connect } from "react-redux";
const mapStateToProps = selectAuthLogin; const mapStateToProps = selectAuthLogin;
@ -20,7 +22,9 @@ const mapDispatchToProps = {
type IProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & IDialogProps & {}; 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 [username, setUserName] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
@ -31,7 +35,7 @@ const LoginDialogUnconnected: FC<IProps> = ({ onRequestClose, error, userSendLog
useEffect(() => { useEffect(() => {
if (error) userSetLoginError(null); if (error) userSetLoginError(null);
}, [username, password]); }, [username, password, error, userSetLoginError]);
const buttons = ( const buttons = (
<Padder> <Padder>

View file

@ -1,10 +1,10 @@
import React, { Attributes, FC, useCallback } from 'react'; import React, { Attributes, FC, useCallback } from 'react';
import { connect } from 'react-redux';
import ReactDOM from 'react-dom';
import * as styles from './styles.scss'; import * as styles from './styles.scss';
import { IState } from '~/redux/store'; import { IState } from '~/redux/store';
import * as ACTIONS from '~/redux/modal/actions'; import * as ACTIONS from '~/redux/modal/actions';
import { connect } from 'react-redux';
import { DIALOG_CONTENT, IDialogProps } from '~/redux/modal/constants'; import { DIALOG_CONTENT, IDialogProps } from '~/redux/modal/constants';
import ReactDOM from 'react-dom';
const mapStateToProps = ({ modal }: IState) => ({ ...modal }); const mapStateToProps = ({ modal }: IState) => ({ ...modal });
const mapDispatchToProps = { const mapDispatchToProps = {

View file

@ -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 { DialogPanel } from '~/components/panels/DialogPanel';
import classNames from 'classnames'; import classNames from 'classnames';
import { Scroll } from '~/components/containers/Scroll'; import { Scroll } from '~/components/containers/Scroll';
@ -41,7 +43,7 @@ const ScrollDialog: FC<IProps> = ({
useEffect(() => { useEffect(() => {
window.addEventListener('resize', onResize); window.addEventListener('resize', onResize);
return () => window.removeEventListener('resize', onResize); return () => window.removeEventListener('resize', onResize);
}, []); }, [onResize]);
const onScroll = useCallback( const onScroll = useCallback(
({ target: { scrollTop = 0 } = {} } = {}) => { ({ target: { scrollTop = 0 } = {} } = {}) => {
@ -54,7 +56,7 @@ const ScrollDialog: FC<IProps> = ({
[top_sticky, top_sticky_offset, show_top_sticky, setShowTopSticky] [top_sticky, top_sticky_offset, show_top_sticky, setShowTopSticky]
); );
useEffect(() => onScroll(), []); useEffect(() => onScroll(), [onScroll]);
useEffect(() => { useEffect(() => {
if (ref && onRefCapture) onRefCapture(ref); if (ref && onRefCapture) onRefCapture(ref);
}, [ref, onRefCapture]); }, [ref, onRefCapture]);

View file

@ -1,17 +1,17 @@
import React, { FC } from "react"; import React, { FC } from 'react';
import { Card } from "~/components/containers/Card"; import classNames from 'classnames';
import * as styles from "./styles.scss"; import { Card } from '~/components/containers/Card';
import { Group } from "~/components/containers/Group"; import * as styles from './styles.scss';
import { CellGrid } from "~/components/containers/CellGrid"; import { Group } from '~/components/containers/Group';
import { Panel } from "~/components/containers/Panel"; import { CellGrid } from '~/components/containers/CellGrid';
import classNames from "classnames"; import { Panel } from '~/components/containers/Panel';
import { Scroll } from "~/components/containers/Scroll"; import { Scroll } from '~/components/containers/Scroll';
import { Tags } from "~/components/node/Tags"; import { Tags } from '~/components/node/Tags';
import { Button } from "~/components/input/Button"; import { Button } from '~/components/input/Button';
import { Filler } from "~/components/containers/Filler"; import { Filler } from '~/components/containers/Filler';
import { InputText } from "~/components/input/InputText"; import { InputText } from '~/components/input/InputText';
import { Icon } from "~/components/input/Icon"; import { Icon } from '~/components/input/Icon';
import { Grid } from "~/components/containers/Grid"; import { Grid } from '~/components/containers/Grid';
interface IProps {} interface IProps {}
@ -48,11 +48,11 @@ const EditorExample: FC<IProps> = () => (
<Tags <Tags
tags={[ tags={[
{ title: "Избранный", feature: "red" }, { title: 'Избранный', feature: 'red' },
{ title: "Плейлист", feature: "green" }, { title: 'Плейлист', feature: 'green' },
{ title: "Просто" }, { title: 'Просто' },
{ title: "+ фото", feature: "black" }, { title: '+ фото', feature: 'black' },
{ title: "+ с музыкой", feature: "black" } { title: '+ с музыкой', feature: 'black' }
]} ]}
/> />
</Group> </Group>

View file

@ -1,16 +1,16 @@
import React, { FC } from "react"; import React, { FC } from 'react';
import { Card } from "~/components/containers/Card"; import range from 'ramda/es/range';
import * as styles from "./styles.scss"; import { Card } from '~/components/containers/Card';
import { Group } from "~/components/containers/Group"; import * as styles from './styles.scss';
import { Padder } from "~/components/containers/Padder"; import { Group } from '~/components/containers/Group';
import range from "ramda/es/range"; import { Padder } from '~/components/containers/Padder';
import { Comment } from "~/components/node/Comment"; import { Comment } from '~/components/node/Comment';
import { NodePanel } from "~/components/node/NodePanel"; import { NodePanel } from '~/components/node/NodePanel';
import { NodeRelated } from "~/components/node/NodeRelated"; import { NodeRelated } from '~/components/node/NodeRelated';
import { Tags } from "~/components/node/Tags"; import { Tags } from '~/components/node/Tags';
import { MenuButton } from "~/components/node/MenuButton"; import { MenuButton } from '~/components/node/MenuButton';
import { NodeNoComments } from "~/components/node/NodeNoComments"; import { NodeNoComments } from '~/components/node/NodeNoComments';
import { InputText } from "~/components/input/InputText"; import { InputText } from '~/components/input/InputText';
interface IProps {} interface IProps {}
@ -55,11 +55,11 @@ const ImageExample: FC<IProps> = () => (
<Tags <Tags
tags={[ tags={[
{ title: "Избранный", feature: "red" }, { title: 'Избранный', feature: 'red' },
{ title: "Плейлист", feature: "green" }, { title: 'Плейлист', feature: 'green' },
{ title: "Просто" }, { title: 'Просто' },
{ title: "+ фото", feature: "black" }, { title: '+ фото', feature: 'black' },
{ title: "+ с музыкой", feature: "black" } { title: '+ с музыкой', feature: 'black' }
]} ]}
/> />

View file

@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { TestGrid } from "~/components/flow/TestGrid"; import { TestGrid } from '~/components/flow/TestGrid';
export const FlowLayout = () => ( export const FlowLayout = () => (
<div className="default_container content_container"> <div className="default_container content_container">

View file

@ -1,11 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import { SidePane } from "~/components/main/SidePane"; import { SidePane } from '~/components/main/SidePane';
import * as styles from './styles.scss'; 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 }) => (
return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<Header /> <Header />
@ -13,5 +11,4 @@ export const MainLayout = ({ children }) => {
{children} {children}
</div> </div>
</div> </div>
); );
};

View file

@ -4,7 +4,7 @@ import * as styles from './styles.scss';
interface IProps {} interface IProps {}
const NodeLayout: FC<IProps> = () => ( const NodeLayout: FC<IProps> = () => (
<div></div> <div />
); );
export { NodeLayout }; export { NodeLayout };

View file

@ -1,10 +1,10 @@
import { AUTH_USER_ACTIONS } from "~/redux/auth/constants"; import { AUTH_USER_ACTIONS } from '~/redux/auth/constants';
import {IAuthState, IUser} from "~/redux/auth/types"; import { IAuthState, IUser } from '~/redux/auth/types';
export const userSendLoginRequest = ({ export const userSendLoginRequest = ({
username, password username, password
}: { }: {
username: string, password: string username: string; password: string;
}) => ({ type: AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, username, password }); }) => ({ type: AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, username, password });
export const userSetLoginError = (error: IAuthState['login']['error']) => ({ export const userSetLoginError = (error: IAuthState['login']['error']) => ({

View file

@ -15,8 +15,7 @@ export const apiUserLogin = ({
}: { }: {
username: string; username: string;
password: string; password: string;
}): Promise<IResultWithStatus<{ token: string; status?: number }>> => }): Promise<IResultWithStatus<{ token: string; status?: number }>> => api
api
.post(API.USER.LOGIN, { username, password }) .post(API.USER.LOGIN, { username, password })
.then(resultMiddleware) .then(resultMiddleware)
.catch(errorMiddleware) .catch(errorMiddleware)

View file

@ -1,4 +1,4 @@
import {IToken, IUser} from "~/redux/auth/types"; import { IToken, IUser } from '~/redux/auth/types';
export const AUTH_USER_ACTIONS = { export const AUTH_USER_ACTIONS = {
SEND_LOGIN_REQUEST: 'SEND_LOGIN_REQUEST', SEND_LOGIN_REQUEST: 'SEND_LOGIN_REQUEST',
@ -39,11 +39,11 @@ export const EMPTY_USER: IUser = {
}; };
export interface IApiUser { export interface IApiUser {
id: number, id: number;
username: string, username: string;
email: string, email: string;
role: string, role: string;
activated: boolean, activated: boolean;
createdAt: string, createdAt: string;
updatedAt: string, updatedAt: string;
} }

View file

@ -1,6 +1,6 @@
import {AUTH_USER_ACTIONS} from "~/redux/auth/constants"; import { AUTH_USER_ACTIONS } from '~/redux/auth/constants';
import * as ActionCreators from "~/redux/auth/actions"; import * as ActionCreators from '~/redux/auth/actions';
import {IAuthState} from "~/redux/auth/types"; import { IAuthState } from '~/redux/auth/types';
interface ActionHandler<T> { interface ActionHandler<T> {
(state: IAuthState, payload: T extends (...args: any[]) => infer R ? R : any): IAuthState; (state: IAuthState, payload: T extends (...args: any[]) => infer R ? R : any): IAuthState;

View file

@ -1,7 +1,7 @@
import { EMPTY_USER } from "~/redux/auth/constants"; import { EMPTY_USER } from '~/redux/auth/constants';
import { createReducer } from "~/utils/reducer"; import { createReducer } from '~/utils/reducer';
import { IAuthState } from "~/redux/auth/types"; import { IAuthState } from '~/redux/auth/types';
import { AUTH_USER_HANDLERS } from "~/redux/auth/handlers"; import { AUTH_USER_HANDLERS } from '~/redux/auth/handlers';
const HANDLERS = { const HANDLERS = {
...AUTH_USER_HANDLERS, ...AUTH_USER_HANDLERS,

View file

@ -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 { 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 { 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 { URLS } from '~/constants/urls';
import { DIALOGS } from '../modal/constants'; import { DIALOGS } from '../modal/constants';
import { IResultWithStatus } from '../types'; 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 { function* sendLoginRequestSaga({ username, password }: ReturnType<typeof ActionCreators.userSendLoginRequest>): SagaIterator {
if (!username || !password) return; 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 }); console.log({ token, error });

View file

@ -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 selectUser = (state: IState): IState['auth']['user'] => state.auth.user;
export const selectToken = (state: IState): IState['auth']['token'] => state.auth.token; export const selectToken = (state: IState): IState['auth']['token'] => state.auth.token;

View file

@ -1,5 +1,5 @@
import { IResultWithStatus } from "~/redux/types"; import { IResultWithStatus } from '~/redux/types';
import { HTTP_RESPONSES } from "~/utils/api"; import { HTTP_RESPONSES } from '~/utils/api';
export const userLoginTransform = ({ status, data, error }: IResultWithStatus<any>): IResultWithStatus<any> => { export const userLoginTransform = ({ status, data, error }: IResultWithStatus<any>): IResultWithStatus<any> => {
switch (true) { switch (true) {

View file

@ -1,3 +1,3 @@
import { IState } from "~/redux/store"; import { IState } from '~/redux/store';
export const selectModal = (state: IState) => state.modal; export const selectModal = (state: IState) => state.modal;

View file

@ -1,4 +1,4 @@
import {IBlock, INode} from "../types"; import { IBlock, INode } from '../types';
export const EMPTY_BLOCK: IBlock = { export const EMPTY_BLOCK: IBlock = {
type: null, type: null,
@ -25,4 +25,4 @@ export const EMPTY_NODE: INode = {
show_description: false, show_description: false,
} }
}, },
} };

View file

@ -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 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<{ export type INodeState = Readonly<{
is_loading: boolean; is_loading: boolean;

View file

@ -1,4 +1,4 @@
import { IState } from "../store"; import { IState } from '../store';
import { INodeState } from "./reducer"; import { INodeState } from './reducer';
export const selectNode = (state: IState): INodeState => state.node; export const selectNode = (state: IState): INodeState => state.node;

View file

@ -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 { persistStore, persistReducer } from 'redux-persist';
import storage from "redux-persist/lib/storage"; import storage from 'redux-persist/lib/storage';
import createSagaMiddleware from "redux-saga"; import createSagaMiddleware from 'redux-saga';
import { connectRouter, RouterState, routerMiddleware } from "connected-react-router"; import { connectRouter, RouterState, routerMiddleware } from 'connected-react-router';
import { createBrowserHistory } from "history"; import { createBrowserHistory } from 'history';
import { PersistConfig, Persistor } from "redux-persist/es/types"; import { PersistConfig, Persistor } from 'redux-persist/es/types';
import authReducer from "~/redux/auth/reducer"; import authReducer from '~/redux/auth/reducer';
import authSaga from "~/redux/auth/sagas"; import authSaga from '~/redux/auth/sagas';
import nodeReducer, { INodeState } from "~/redux/node/reducer"; import nodeReducer, { INodeState } from '~/redux/node/reducer';
import nodeSaga from "~/redux/node/sagas"; import nodeSaga from '~/redux/node/sagas';
import uploadReducer, { IUploadState } from "~/redux/uploads/reducer"; import uploadReducer, { IUploadState } from '~/redux/uploads/reducer';
import uploadSaga from "~/redux/uploads/sagas"; 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 = { const authPersistConfig: PersistConfig = {
key: "auth", key: 'auth',
whitelist: ["token", "user"], whitelist: ['token', 'user'],
storage storage
}; };
@ -37,8 +39,7 @@ export interface IState {
export const sagaMiddleware = createSagaMiddleware(); export const sagaMiddleware = createSagaMiddleware();
export const history = createBrowserHistory(); export const history = createBrowserHistory();
const composeEnhancers = const composeEnhancers = typeof window === 'object' && (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
typeof window === "object" && (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) ? (<any>window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose; : compose;

View file

@ -7,8 +7,8 @@ export interface ITag {
} }
export type IInputTextProps = DetailedHTMLProps< export type IInputTextProps = DetailedHTMLProps<
InputHTMLAttributes<HTMLInputElement>, InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement HTMLInputElement
> & { > & {
wrapperClassName?: string; wrapperClassName?: string;
handler?: (value: string) => void; handler?: (value: string) => void;
@ -72,7 +72,7 @@ export interface IFileWithUUID {
} }
export interface IBlock { export interface IBlock {
type: 'image' | 'text' | 'media' | 'youtube' | 'video', type: 'image' | 'text' | 'media' | 'youtube' | 'video';
temp_ids: UUID[]; temp_ids: UUID[];
attaches: UUID[]; attaches: UUID[];
} }
@ -100,7 +100,7 @@ export interface INode {
flow: { flow: {
display: 'single' | 'double' | 'quadro'; display: 'single' | 'double' | 'quadro';
show_description: boolean; show_description: boolean;
} };
}; };
createdAt?: string; createdAt?: string;

View file

@ -1,30 +1,30 @@
import { UPLOAD_ACTIONS } from "~/redux/uploads/constants"; import { UPLOAD_ACTIONS } from '~/redux/uploads/constants';
import { IFileWithUUID, UUID, IFile } from "../types"; import { IFileWithUUID, UUID, IFile } from '../types';
import { IUploadStatus } from "./reducer"; import { IUploadStatus } from './reducer';
export const uploadUploadFiles = (files: IFileWithUUID[]) => ({ export const uploadUploadFiles = (files: IFileWithUUID[]) => ({
files, files,
type: UPLOAD_ACTIONS.UPLOAD_FILES, type: UPLOAD_ACTIONS.UPLOAD_FILES
}); });
export const uploadAddStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({ export const uploadAddStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({
temp_id, temp_id,
status, status,
type: UPLOAD_ACTIONS.ADD_STATUS, type: UPLOAD_ACTIONS.ADD_STATUS
}); });
export const uploadAddFile = (file: IFile) => ({ export const uploadAddFile = (file: IFile) => ({
file, file,
type: UPLOAD_ACTIONS.ADD_FILE, type: UPLOAD_ACTIONS.ADD_FILE
}); });
export const uploadSetStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({ export const uploadSetStatus = (temp_id: UUID, status?: Partial<IUploadStatus>) => ({
temp_id, temp_id,
status, status,
type: UPLOAD_ACTIONS.SET_STATUS, type: UPLOAD_ACTIONS.SET_STATUS
}); });
export const uploadDropStatus = (temp_id: UUID) => ({ export const uploadDropStatus = (temp_id: UUID) => ({
temp_id, temp_id,
type: UPLOAD_ACTIONS.DROP_STATUS, type: UPLOAD_ACTIONS.DROP_STATUS
}); });

View file

@ -1,5 +1,5 @@
import { IFile } from "~/redux/types"; import { IFile } from '~/redux/types';
import { IUploadState, IUploadStatus } from "./reducer"; import { IUploadState, IUploadStatus } from './reducer';
const prefix = 'UPLOAD.'; const prefix = 'UPLOAD.';
@ -38,4 +38,4 @@ export const EMPTY_UPLOAD_STATUS: IUploadStatus = {
thumbnail_url: null, thumbnail_url: null,
type: null, type: null,
temp_id: null, temp_id: null,
} };

View file

@ -2,7 +2,9 @@ import assocPath from 'ramda/es/assocPath';
import omit from 'ramda/es/omit'; import omit from 'ramda/es/omit';
import { UPLOAD_ACTIONS, EMPTY_UPLOAD_STATUS } from './constants'; 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'; import { IUploadState } from './reducer';
const addStatus = ( const addStatus = (
@ -17,33 +19,25 @@ const addStatus = (
const dropStatus = ( const dropStatus = (
state: IUploadState, state: IUploadState,
{ temp_id }: ReturnType<typeof uploadDropStatus> { temp_id }: ReturnType<typeof uploadDropStatus>
): IUploadState => assocPath( ): IUploadState => assocPath(['statuses'], omit([temp_id], state.statuses), state);
['statuses'],
omit([temp_id], state.statuses),
state,
);
const setStatus = ( const setStatus = (
state: IUploadState, state: IUploadState,
{ temp_id, status }: ReturnType<typeof uploadSetStatus> { temp_id, status }: ReturnType<typeof uploadSetStatus>
): IUploadState => assocPath( ): IUploadState => assocPath(
['statuses'], ['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 state
); );
const addFile = ( const addFile = (state: IUploadState, { file }: ReturnType<typeof uploadAddFile>): IUploadState => assocPath(['files'], { ...state.files, [file.id]: file }, state);
state: IUploadState,
{ file }: ReturnType<typeof uploadAddFile>
): IUploadState => assocPath(
['files'],
{ ...state.files, [file.id]: file },
state
);
export const UPLOAD_HANDLERS = { export const UPLOAD_HANDLERS = {
[UPLOAD_ACTIONS.ADD_STATUS]: addStatus, [UPLOAD_ACTIONS.ADD_STATUS]: addStatus,
[UPLOAD_ACTIONS.DROP_STATUS]: dropStatus, [UPLOAD_ACTIONS.DROP_STATUS]: dropStatus,
[UPLOAD_ACTIONS.SET_STATUS]: setStatus, [UPLOAD_ACTIONS.SET_STATUS]: setStatus,
[UPLOAD_ACTIONS.ADD_FILE]: addFile, [UPLOAD_ACTIONS.ADD_FILE]: addFile
}; };

View file

@ -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 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({ Promise.resolve({
status: HTTP_RESPONSES.CREATED, status: HTTP_RESPONSES.CREATED,
data: { data: {

View file

@ -1,6 +1,6 @@
import { createReducer } from "~/utils/reducer"; import { createReducer } from '~/utils/reducer';
import { IFile, UUID } from "~/redux/types"; import { IFile, UUID } from '~/redux/types';
import { UPLOAD_HANDLERS } from "./handlers"; import { UPLOAD_HANDLERS } from './handlers';
export interface IUploadStatus { export interface IUploadStatus {
is_uploading: boolean; is_uploading: boolean;

View file

@ -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 { 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 { reqWrapper } from '../auth/sagas';
import { createUploader, uploadGetThumb, fakeUploader } from '~/utils/uploader'; import { createUploader, uploadGetThumb, fakeUploader } from '~/utils/uploader';
import { HTTP_RESPONSES } from '~/utils/api'; import { HTTP_RESPONSES } from '~/utils/api';
import { VALIDATORS } from '~/utils/validators'; import { VALIDATORS } from '~/utils/validators';
import { UUID, IFileWithUUID, IResultWithStatus, IFile } from '../types'; import { UUID, IFileWithUUID, IFile } from '../types';
function* uploadCall({ temp_id, onProgress, file }) { function* uploadCall({ temp_id, onProgress, file }) {
return yield call(reqWrapper, fakeUploader, { file: { url: 'some', error: 'cant do this boss' }, onProgress, mustSucceed: true }); return yield call(reqWrapper, fakeUploader, { file: { url: 'some', error: 'cant do this boss' }, onProgress, mustSucceed: true });

View file

@ -1,42 +1,43 @@
import React, {FC} from 'react'; import React, { FC } from 'react';
const Sprites: FC<{}> = () => ( const Sprites: FC<{}> = () => (
<svg width={0} height={0} viewBox="0 0 24 24"> <svg width={0} height={0} viewBox="0 0 24 24">
<g id="cell-single" stroke="none" transform="translate(2 2)"> <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="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> <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> <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,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
</g> </g>
<g id="cell-double-h" stroke="none"> <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="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="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,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
</g> </g>
<g id="cell-double-v" stroke="none"> <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="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> <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,11 L9,11 L9,20 L0,20 L0,11 Z M1,12 L1,19 L8,19 L8,12 L1,12 Z" />
</g> </g>
<g id="play"> <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>
<g id="plus" stroke="none"> <g id="plus" stroke="none">
<path fill="none" d="M0 0h24v24H0V0z"/> <path fill="none" d="M0 0h24v24H0V0z" />
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/> <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</g> </g>
<g id="close" stroke="none"> <g id="close" stroke="none">
<path fill="none" d="M0 0h24v24H0V0z"/> <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 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>
<g id="check" stroke="none"> <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> </g>
</svg> </svg>
); );

View file

@ -1,10 +1,10 @@
import axios, { AxiosRequestConfig } from 'axios'; import axios, { AxiosRequestConfig } from 'axios';
import { push } from 'connected-react-router';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { store } from '~/redux/store'; import { store } from '~/redux/store';
import { push } from 'connected-react-router';
import { IResultWithStatus } from '~/redux/types'; import { IResultWithStatus } from '~/redux/types';
export const authMiddleware = r => { export const authMiddleware = (r) => {
store.dispatch(push('/login')); store.dispatch(push('/login'));
return r; return r;
}; };
@ -23,18 +23,15 @@ export const HTTP_RESPONSES = {
TOO_MANY_REQUESTS: 429, TOO_MANY_REQUESTS: 429,
}; };
export const resultMiddleware = <T extends {}>({ export const resultMiddleware = (<)T extends {}>({
status, status,
data, data,
}: { }: {
status: number; status: number;
data: T; data: T;
}): { status: number; data: T } => { }): { status: number; data: T } => data && { status, data };
return data && { status, data };
};
export const errorMiddleware = <T extends any>(debug): IResultWithStatus<T> => export const errorMiddleware = <T extends any>(debug): IResultWithStatus<T> => debug && debug.response
debug && debug.response
? debug.response ? debug.response
: { : {
status: HTTP_RESPONSES.CONNECTION_REFUSED, status: HTTP_RESPONSES.CONNECTION_REFUSED,

View file

@ -26,7 +26,6 @@ export const describeArc = (
startAngle: number = 0, startAngle: number = 0,
endAngle: number = 360, endAngle: number = 360,
): string => { ): string => {
const start = polarToCartesian(x, y, radius, endAngle); const start = polarToCartesian(x, y, radius, endAngle);
const end = polarToCartesian(x, y, radius, startAngle); const end = polarToCartesian(x, y, radius, startAngle);

View file

@ -3,4 +3,4 @@ import insert from 'ramda/es/insert';
import nth from 'ramda/es/nth'; import nth from 'ramda/es/nth';
import remove from 'ramda/es/remove'; 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)));

View file

@ -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) => { export const useCloseOnEscape = (onRequestClose: () => void, ignore_inputs = false) => {
const onEscape = useCallback( const onEscape = useCallback(
event => { (event) => {
if (event.key !== 'Escape') return; if (event.key !== 'Escape') return;
if ( if (
ignore_inputs && ignore_inputs
(event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') && (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA')
) ) return;
return;
onRequestClose(); onRequestClose();
}, },
[onRequestClose], [ignore_inputs, onRequestClose],
); );
useEffect(() => { useEffect(() => {
@ -30,5 +32,5 @@ export const useDelayedReady = (setReady: (val: boolean) => void, delay: number
return () => { return () => {
if (timer) clearTimeout(timer); if (timer) clearTimeout(timer);
}; };
}, []); }, [delay, setReady]);
}; };

View file

@ -14,6 +14,6 @@ type Handlers<State, Types extends string, Actions extends Action<Types>> = {
export const createReducer = ( export const createReducer = (
initialState, initialState,
handlers, handlers,
) => (state = initialState, action) => handlers.hasOwnProperty(action.type) ) => (state = initialState, action) => (handlers.hasOwnProperty(action.type)
? handlers[action.type](state, action) ? handlers[action.type](state, action)
: state; : state);

View file

@ -13,7 +13,7 @@ export function createUploader<T extends {}, R extends {}>(
): [(args: T) => (args: T & { onProgress: (current: number, total: number) => void }) => any, EventChannel<any>] { ): [(args: T) => (args: T & { onProgress: (current: number, total: number) => void }) => any, EventChannel<any>] {
let emit; let emit;
const chan = eventChannel(emitter => { const chan = eventChannel((emitter) => {
emit = emitter; emit = emitter;
return () => null; return () => null;
}); });
@ -27,7 +27,7 @@ export function createUploader<T extends {}, R extends {}>(
return [wrappedCallback, chan]; return [wrappedCallback, chan];
} }
export const uploadGetThumb = async file => { export const uploadGetThumb = async (file) => {
if (!file.type || !VALIDATORS.IS_IMAGE_MIME(file.type)) return ''; if (!file.type || !VALIDATORS.IS_IMAGE_MIME(file.type)) return '';
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {