This commit is contained in:
@ -84,8 +84,9 @@
|
|||||||
"require-await": "warn",
|
"require-await": "warn",
|
||||||
"wrap-iife": ["warn", "inside"],
|
"wrap-iife": ["warn", "inside"],
|
||||||
"yoda": "warn",
|
"yoda": "warn",
|
||||||
"no-shadow": "warn",
|
"no-shadow": "off",
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
"@typescript-eslint/no-use-before-define": "off",
|
||||||
|
"@typescript-eslint/no-shadow": "warn",
|
||||||
"@typescript-eslint/no-namespace": "off",
|
"@typescript-eslint/no-namespace": "off",
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["error"],
|
"@typescript-eslint/no-unused-vars": ["error"],
|
||||||
|
|||||||
80
src/app/components/both-menu/BothMenu.tsx
Normal file
80
src/app/components/both-menu/BothMenu.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import {AppBar, createStyles, Fab, IconButton, makeStyles, Theme, Toolbar} from '@material-ui/core';
|
||||||
|
import React, {memo} from 'react';
|
||||||
|
import MoreIcon from '@material-ui/icons/MoreVert';
|
||||||
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
|
import MoveToInboxIcon from '@material-ui/icons/MoveToInbox';
|
||||||
|
import CalendarTodayIcon from '@material-ui/icons/CalendarToday';
|
||||||
|
import ListAltIcon from '@material-ui/icons/ListAlt';
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
|
createStyles({
|
||||||
|
iconRight: {
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
},
|
||||||
|
appBar: {
|
||||||
|
top: 'auto',
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
grow: {
|
||||||
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
fabButton: {
|
||||||
|
position: 'absolute',
|
||||||
|
zIndex: 1,
|
||||||
|
top: -30,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
margin: '0 auto',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
const BothMenu: React.FC = () => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppBar
|
||||||
|
position="fixed"
|
||||||
|
color="primary"
|
||||||
|
className={classes.appBar}
|
||||||
|
>
|
||||||
|
<Toolbar>
|
||||||
|
<IconButton
|
||||||
|
className={classes.iconRight}
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<MoveToInboxIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<ListAltIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Fab
|
||||||
|
color="secondary"
|
||||||
|
className={classes.fabButton}
|
||||||
|
>
|
||||||
|
<AddIcon />
|
||||||
|
</Fab>
|
||||||
|
<div className={classes.grow} />
|
||||||
|
<IconButton
|
||||||
|
className={classes.iconRight}
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<CalendarTodayIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<MoreIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(BothMenu);
|
||||||
1
src/app/components/both-menu/index.ts
Normal file
1
src/app/components/both-menu/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {default} from './BothMenu';
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import React, {memo} from 'react';
|
import React, {Fragment, memo} from 'react';
|
||||||
import {HashRouter, Route, Switch} from 'react-router-dom';
|
import {Route, Switch} from 'react-router-dom';
|
||||||
import mainPageRouter from '_pages/main/routing';
|
import mainPageRouter from '_pages/main/routing';
|
||||||
import chaosBoxPageRouter from '_pages/chaos-box/routing';
|
import chaosBoxPageRouter from '_pages/chaos-box/routing';
|
||||||
import calendarPageRouter from '_pages/calendar/routing';
|
import calendarPageRouter from '_pages/calendar/routing';
|
||||||
@ -8,14 +8,16 @@ import projectsPageRouter from '_pages/projects/routing';
|
|||||||
import settingsPageRouter from '_pages/settings/routing';
|
import settingsPageRouter from '_pages/settings/routing';
|
||||||
import signInPageRouter from '_pages/sign-in/routing';
|
import signInPageRouter from '_pages/sign-in/routing';
|
||||||
import tagsPageRouter from '_pages/tags/routing';
|
import tagsPageRouter from '_pages/tags/routing';
|
||||||
import NotFoundPage from '_pages/not-found/components/page/Page';
|
import NotFoundPage from '_pages/not-found/components/page';
|
||||||
import TopMenu from '../top-menu/TopMenu';
|
import TopMenu from '../top-menu';
|
||||||
import './Page.scss';
|
import './Page.scss';
|
||||||
|
import BothMenu from '../both-menu';
|
||||||
|
|
||||||
const Page: React.FC = () => {
|
const Page: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<HashRouter>
|
<Fragment>
|
||||||
<TopMenu />
|
<TopMenu />
|
||||||
|
<div>
|
||||||
<Switch>
|
<Switch>
|
||||||
{mainPageRouter}
|
{mainPageRouter}
|
||||||
{chaosBoxPageRouter}
|
{chaosBoxPageRouter}
|
||||||
@ -29,7 +31,9 @@ const Page: React.FC = () => {
|
|||||||
<NotFoundPage />
|
<NotFoundPage />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</HashRouter>
|
</div>
|
||||||
|
<BothMenu />
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1
src/app/components/page/index.ts
Normal file
1
src/app/components/page/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {default} from './Page';
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import {List, ListItem as MaterialListItem, ListItemIcon, ListItemText} from '@material-ui/core';
|
|
||||||
import React, {memo} from 'react';
|
|
||||||
import {Link} from 'react-router-dom';
|
|
||||||
import InboxIcon from '@material-ui/icons/MoveToInbox';
|
|
||||||
import {ListItem} from '_types/common';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
list: ListItem[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const MenuList: React.FC<Props> = ({list}) => {
|
|
||||||
return (
|
|
||||||
<List>
|
|
||||||
{list.map(({title, url}) => (
|
|
||||||
<Link to={url} key={url}>
|
|
||||||
<MaterialListItem button key={url}>
|
|
||||||
<ListItemIcon>
|
|
||||||
<InboxIcon />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary={title} />
|
|
||||||
</MaterialListItem>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(MenuList);
|
|
||||||
@ -1,32 +1,72 @@
|
|||||||
import React, {memo} from 'react';
|
import React, {memo} from 'react';
|
||||||
import {createStyles, makeStyles, Theme} from '@material-ui/core/styles';
|
import {useHistory} from 'react-router-dom';
|
||||||
|
import {createStyles, makeStyles} from '@material-ui/core/styles';
|
||||||
import AppBar from '@material-ui/core/AppBar';
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
import Toolbar from '@material-ui/core/Toolbar';
|
import Toolbar from '@material-ui/core/Toolbar';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import {Avatar} from '@material-ui/core';
|
||||||
|
import {useParams} from '_hooks/useParams';
|
||||||
|
import {PageType} from '_enums/common';
|
||||||
|
import {PAGE_TITLE, ROUTES} from '_consts/common';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const NO_NAME_AVATAR = 'https://d.newsweek.com/en/full/425257/02-10-putin-economy.jpg';
|
||||||
|
|
||||||
|
const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
menuButton: {
|
|
||||||
marginRight: theme.spacing(2),
|
|
||||||
},
|
|
||||||
title: {
|
title: {
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const TopMenu: React.FC = () => {
|
const TopMenu: React.FC = () => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const {pageType} = useParams();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const handleGoRoot = () => {
|
||||||
|
history.push(ROUTES.MAIN);
|
||||||
|
};
|
||||||
|
|
||||||
|
const title = PAGE_TITLE[pageType];
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<AppBar position="static">
|
<AppBar position="static">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography variant="h6" className={classes.title}>
|
{pageType === PageType.Main && (
|
||||||
Free your brain
|
<IconButton
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<SearchIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
{pageType !== PageType.Main && (
|
||||||
|
<IconButton
|
||||||
|
onClick={handleGoRoot}
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<ArrowBackIosIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
className={classes.title}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
<Avatar src={NO_NAME_AVATAR} />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
1
src/app/components/top-menu/index.ts
Normal file
1
src/app/components/top-menu/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {default} from './TopMenu';
|
||||||
@ -1,10 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import App from './components/page/Page';
|
import {HashRouter} from 'react-router-dom';
|
||||||
|
import App from './components/page';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
<HashRouter >
|
||||||
<App />
|
<App />
|
||||||
|
</HashRouter>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import {PageType} from '../enums/common';
|
||||||
|
|
||||||
export const ROUTES = {
|
export const ROUTES = {
|
||||||
MAIN: '/',
|
MAIN: '/',
|
||||||
CHAOS_BOX: '/chaos-box',
|
CHAOS_BOX: '/chaos-box',
|
||||||
@ -8,3 +10,14 @@ export const ROUTES = {
|
|||||||
SETTINGS: '/settings',
|
SETTINGS: '/settings',
|
||||||
SIGN_IN: '/sign-in',
|
SIGN_IN: '/sign-in',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const PAGE_TITLE = {
|
||||||
|
[PageType.Main]: 'Free your brain',
|
||||||
|
[PageType.ChaosBox]: 'Chaos box',
|
||||||
|
[PageType.Calendar]: 'Calendar',
|
||||||
|
[PageType.Information]: 'Information',
|
||||||
|
[PageType.Tags]: 'Tags',
|
||||||
|
[PageType.Projects]: 'Projects',
|
||||||
|
[PageType.Settings]: 'Settings',
|
||||||
|
[PageType.SigIn]: 'SigIn',
|
||||||
|
};
|
||||||
|
|||||||
21
src/core/enums/common.ts
Normal file
21
src/core/enums/common.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export const enum TaskStatus {
|
||||||
|
Progress = 'progress',
|
||||||
|
Removed = 'removed',
|
||||||
|
Done = 'done',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum FolderType {
|
||||||
|
Project = 'project',
|
||||||
|
Information = 'information',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PageType {
|
||||||
|
Main = '',
|
||||||
|
ChaosBox = 'chaos-box',
|
||||||
|
Projects = 'projects',
|
||||||
|
Information = 'information',
|
||||||
|
Tags = 'tags',
|
||||||
|
Calendar = 'calendar',
|
||||||
|
Settings = 'settings',
|
||||||
|
SigIn = 'sign-in',
|
||||||
|
}
|
||||||
25
src/core/hooks/useParams.ts
Normal file
25
src/core/hooks/useParams.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import {useMemo} from 'react';
|
||||||
|
import {useLocation, useParams as useReactParams} from 'react-router-dom';
|
||||||
|
import {PageType} from '../enums/common';
|
||||||
|
import {getPageType} from '../utils/common';
|
||||||
|
|
||||||
|
type ParamsParser<T> = (value?: string) => T;
|
||||||
|
export type ParamsParsers<T> = Partial<{[K in keyof T]: ParamsParser<T[K]>}>;
|
||||||
|
|
||||||
|
export function useParams<T extends {[name: string]: unknown}>(paramParsers: ParamsParsers<T> = {}) {
|
||||||
|
const params = useReactParams<Record<keyof T, string>>();
|
||||||
|
const {pathname} = useLocation();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return Object.keys(paramParsers).reduce<T & {pageType: PageType}>((memo, key) => {
|
||||||
|
const parser = paramParsers[key];
|
||||||
|
|
||||||
|
return {
|
||||||
|
...memo,
|
||||||
|
[key]: parser?.(params[key]),
|
||||||
|
};
|
||||||
|
}, {
|
||||||
|
pageType: getPageType(pathname),
|
||||||
|
} as T & {pageType: PageType});
|
||||||
|
}, [params, paramParsers, pathname]);
|
||||||
|
}
|
||||||
@ -49,16 +49,14 @@ export function booleanParser(defaultValue?: boolean) {
|
|||||||
|
|
||||||
// Array parser (должен уметь с enum)
|
// Array parser (должен уметь с enum)
|
||||||
|
|
||||||
export function useQuery(): ParsedUrlQuery;
|
|
||||||
export function useQuery<T extends {[name: string]: unknown}>(queryParsers: QueryParsers<T>): Partial<T>;
|
|
||||||
export function useQuery<T extends {[name: string]: unknown}>(
|
export function useQuery<T extends {[name: string]: unknown}>(
|
||||||
queryParsers?: QueryParsers<T>
|
queryParsers: QueryParsers<T>
|
||||||
): ParsedUrlQuery | Partial<T> {
|
): ParsedUrlQuery | Partial<T> {
|
||||||
const {search} = useLocation();
|
const {search} = useLocation();
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const query = parse(search.slice(1));
|
const query = parse(search.slice(1));
|
||||||
return queryParsers ? Object.keys(query).reduce<Partial<T>>((memo, key) => {
|
return queryParsers ? Object.keys(queryParsers).reduce<T>((memo, key) => {
|
||||||
if (key in queryParsers) {
|
if (key in queryParsers) {
|
||||||
const parser = queryParsers[key];
|
const parser = queryParsers[key];
|
||||||
return {
|
return {
|
||||||
@ -67,6 +65,6 @@ export function useQuery<T extends {[name: string]: unknown}>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
return memo;
|
return memo;
|
||||||
}, {}) : query;
|
}, {} as T) : query;
|
||||||
}, [search, queryParsers]);
|
}, [search, queryParsers]);
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/core/referers/common.ts
Normal file
5
src/core/referers/common.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import {PageType} from '../enums/common';
|
||||||
|
|
||||||
|
export const isPageType = (value?: string): value is PageType => (
|
||||||
|
Object.values(PageType).some(pageType => pageType === value)
|
||||||
|
);
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import {createAdapter} from '@most/adapter';
|
|
||||||
import {state} from 'fp-ts/lib/State';
|
|
||||||
|
|
||||||
export namespace AuthService {
|
|
||||||
type State = {
|
|
||||||
isAuth: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const initState: State = {
|
|
||||||
isAuth: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const [changeState, stream$] = createAdapter<State>();
|
|
||||||
|
|
||||||
export const handleChangeAuth = (isAuth: boolean): void => changeState({
|
|
||||||
...state,
|
|
||||||
isAuth,
|
|
||||||
});
|
|
||||||
export const state$ = stream$;
|
|
||||||
}
|
|
||||||
21
src/core/services/LocalStorageService.ts
Normal file
21
src/core/services/LocalStorageService.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export const makeLocalStorageService = <T>(init: T, stateName: string) => {
|
||||||
|
if (!localStorage.getItem(stateName)) {
|
||||||
|
localStorage.setItem(stateName, JSON.stringify(init));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
set: (updatedState: T) => {
|
||||||
|
localStorage.setItem(stateName, JSON.stringify(updatedState));
|
||||||
|
return updatedState;
|
||||||
|
},
|
||||||
|
get: (): T => {
|
||||||
|
const stringValue = localStorage.getItem(stateName) || '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(stringValue);
|
||||||
|
} catch (e) {
|
||||||
|
return init;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
36
src/core/services/TasksService.ts
Normal file
36
src/core/services/TasksService.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import {v4} from 'uuid';
|
||||||
|
import {TaskStatus} from '../enums/common';
|
||||||
|
import {Task} from '../types/common';
|
||||||
|
import {createService} from '../utils/createService';
|
||||||
|
import {makeLocalStorageService} from './LocalStorageService';
|
||||||
|
|
||||||
|
const TASK_STORAGE_NAME = 'FYB_TASK_STORAGE';
|
||||||
|
|
||||||
|
const INIT_TASKS: Task[] = [
|
||||||
|
{
|
||||||
|
id: v4(),
|
||||||
|
status: TaskStatus.Progress,
|
||||||
|
created_at: '2021-03-01T13:00+03:00',
|
||||||
|
title: 'Первая таска',
|
||||||
|
body: 'Описание таски',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: v4(),
|
||||||
|
status: TaskStatus.Progress,
|
||||||
|
created_at: '2021-03-01T13:00+03:00',
|
||||||
|
title: 'Вторая таска',
|
||||||
|
body: 'Описание таски',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: v4(),
|
||||||
|
status: TaskStatus.Progress,
|
||||||
|
created_at: '2021-03-01T13:00+03:00',
|
||||||
|
title: 'Третья таска',
|
||||||
|
body: 'Описание таски',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const taskListService = makeLocalStorageService(INIT_TASKS, TASK_STORAGE_NAME);
|
||||||
|
|
||||||
|
export const tasksService = createService(taskListService.get(), {
|
||||||
|
});
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import {createAdapter} from '@most/adapter';
|
|
||||||
|
|
||||||
const arr: Array<number> = [];
|
|
||||||
let inc = 0;
|
|
||||||
|
|
||||||
const [handler, stream$] = createAdapter<Array<number>>();
|
|
||||||
|
|
||||||
export const list$ = stream$;
|
|
||||||
setInterval(() => {
|
|
||||||
arr.push(inc += 1);
|
|
||||||
handler(arr);
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
@ -1,4 +1,49 @@
|
|||||||
export type ListItem = {
|
import {FolderType, TaskStatus} from '../enums/common';
|
||||||
title: string;
|
|
||||||
url: string;
|
export type Task = {
|
||||||
|
/**
|
||||||
|
* Идентификатор
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
title?: string;
|
||||||
|
body?: string;
|
||||||
|
created_at: string;
|
||||||
|
start_at?: string;
|
||||||
|
end_at?: string;
|
||||||
|
/**
|
||||||
|
* Контекст выполнения, теги
|
||||||
|
*/
|
||||||
|
tags?: string[];
|
||||||
|
/**
|
||||||
|
* Папка, проект, список
|
||||||
|
*/
|
||||||
|
folder?: string;
|
||||||
|
status: TaskStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Folder = {
|
||||||
|
/**
|
||||||
|
* Идентификатор
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
type: FolderType;
|
||||||
|
/**
|
||||||
|
* Папка, проект
|
||||||
|
*/
|
||||||
|
folder?: string;
|
||||||
|
removed?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Tag = {
|
||||||
|
/**
|
||||||
|
* Идентификатор
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* Цвет тега в формате #FFFFFF
|
||||||
|
*/
|
||||||
|
color?: string;
|
||||||
|
removed?: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1 +1,9 @@
|
|||||||
|
import {PageType} from '../enums/common';
|
||||||
|
import {isPageType} from '../referers/common';
|
||||||
|
|
||||||
export const numberToString = (num: number): string => num.toString();
|
export const numberToString = (num: number): string => num.toString();
|
||||||
|
|
||||||
|
export const getPageType = (pathname?: string): PageType => {
|
||||||
|
const path = pathname?.startsWith('/') ? pathname.slice(1) : pathname ?? '';
|
||||||
|
return isPageType(path) ? path : PageType.Main;
|
||||||
|
};
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.CHAOS_BOX} exact />
|
<Route component={Page} path={ROUTES.CHAOS_BOX} exact />
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.INFORMATION} exact />
|
<Route component={Page} path={ROUTES.INFORMATION} exact />
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
import React, {FC, memo} from 'react';
|
|
||||||
import {chain, fromPromise, map} from '@most/core';
|
|
||||||
import {pipe} from 'fp-ts/lib/pipeable';
|
|
||||||
import {useStream} from '_utils/useStream';
|
|
||||||
import {list$} from '_services/service1';
|
|
||||||
|
|
||||||
const promise1: (id: number) => Promise<string> = (id: number) => new Promise(res => {
|
|
||||||
setTimeout(() => res(`${id} 123123`), 6000);
|
|
||||||
});
|
|
||||||
|
|
||||||
const getStreamFromPromise = (id: number) => fromPromise(promise1(id));
|
|
||||||
|
|
||||||
const ComponentStream: FC = () => {
|
|
||||||
const data = useStream(
|
|
||||||
pipe(
|
|
||||||
list$,
|
|
||||||
map(arr => {
|
|
||||||
return arr.length;
|
|
||||||
}),
|
|
||||||
chain(id => getStreamFromPromise(id))
|
|
||||||
),
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div>{data}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(ComponentStream);
|
|
||||||
@ -1,41 +1,26 @@
|
|||||||
import React, {memo} from 'react';
|
import React, {memo} from 'react';
|
||||||
import {AuthService} from '_services/AuthService';
|
|
||||||
import {useStream} from '_utils/useStream';
|
import {useStream} from '_utils/useStream';
|
||||||
import {createService} from '_utils/createService';
|
import {tasksService} from '_services/TasksService';
|
||||||
import ComponentStream from '../component-stream/ComponentStream';
|
import {List, ListItem, ListItemIcon, ListItemText} from '@material-ui/core';
|
||||||
|
import InboxIcon from '@material-ui/icons/Inbox';
|
||||||
const service = createService(1, {
|
|
||||||
changeWithStr: (state: number, val: string) => {
|
|
||||||
const parsedNumber = Number(val);
|
|
||||||
if (Number.isNaN(val)) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedNumber;
|
|
||||||
},
|
|
||||||
add: (state: number) => {
|
|
||||||
return state + 1;
|
|
||||||
},
|
|
||||||
sub: (state: number) => {
|
|
||||||
return state - 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const MainPage: React.FC = () => {
|
const MainPage: React.FC = () => {
|
||||||
const {isAuth} = useStream(AuthService.state$, AuthService.initState);
|
const taskList = useStream(tasksService.stream$, []);
|
||||||
const toggle = () => AuthService.handleChangeAuth(!isAuth);
|
|
||||||
const data = useStream(service.stream$, 0);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<List component="nav" aria-label="main mailbox folders">
|
||||||
Main Page
|
{taskList.map(task => (
|
||||||
Auth: {isAuth ? 'yes' : 'no'}
|
<ListItem button key={task.id}>
|
||||||
<button onClick={toggle}>click</button>
|
<ListItemIcon>
|
||||||
<ComponentStream />
|
<InboxIcon />
|
||||||
<div>{data}</div>
|
</ListItemIcon>
|
||||||
<button onClick={service.actions.add}>Add</button>
|
<ListItemText
|
||||||
<button onClick={service.actions.sub}>Sub</button>
|
primary={task.title ?? 'Нет темы'}
|
||||||
</div>
|
secondary={task.body ?? 'Нет Описания'}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
1
src/pages/not-found/components/page/index.ts
Normal file
1
src/pages/not-found/components/page/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {default} from './Page';
|
||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.PROJECTS} exact />
|
<Route component={Page} path={ROUTES.PROJECTS} exact />
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.SETTINGS} exact />
|
<Route component={Page} path={ROUTES.SETTINGS} exact />
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.SIGN_IN} exact />
|
<Route component={Page} path={ROUTES.SIGN_IN} exact />
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export {default as Page} from './Page';
|
export {default} from './Page';
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom';
|
import {Route} from 'react-router-dom';
|
||||||
import {ROUTES} from '_consts/common';
|
import {ROUTES} from '_consts/common';
|
||||||
import Page from './components/page/Page';
|
import Page from './components/page';
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Route component={Page} path={ROUTES.TAGS} exact />
|
<Route component={Page} path={ROUTES.TAGS} exact />
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
"_utils/*": ["./src/core/utils/*"],
|
"_utils/*": ["./src/core/utils/*"],
|
||||||
"_enums/*": ["./src/core/enums/*"],
|
"_enums/*": ["./src/core/enums/*"],
|
||||||
"_pages/*": ["./src/pages/*"],
|
"_pages/*": ["./src/pages/*"],
|
||||||
|
"_referers/*": ["./src/referers/*"],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
mode: 'development',
|
||||||
entry: {
|
entry: {
|
||||||
app: {
|
app: {
|
||||||
import: './src/app/index.tsx',
|
import: './src/app/index.tsx',
|
||||||
@ -38,6 +39,7 @@ module.exports = {
|
|||||||
_utils: path.resolve(__dirname, 'src/core/utils/'),
|
_utils: path.resolve(__dirname, 'src/core/utils/'),
|
||||||
_enums: path.resolve(__dirname, 'src/core/enums/'),
|
_enums: path.resolve(__dirname, 'src/core/enums/'),
|
||||||
_pages: path.resolve(__dirname, 'src/pages/'),
|
_pages: path.resolve(__dirname, 'src/pages/'),
|
||||||
|
_referers: path.resolve(__dirname, 'src/referers/'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
|
|||||||
Reference in New Issue
Block a user