1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

removed boris reducer

This commit is contained in:
Fedor Katurov 2022-01-02 21:28:31 +07:00
parent 77af1ab05a
commit 120bf8954c
72 changed files with 225 additions and 298 deletions

16
src/api/boris/index.ts Normal file
View file

@ -0,0 +1,16 @@
import { API } from '~/constants/api';
import { api, cleanResult } from '~/utils/api';
import { IGetGithubIssuesResult, StatBackend } from '~/types/boris';
import axios from 'axios';
export const getBorisBackendStats = () =>
api.get<StatBackend>(API.BORIS.GET_BACKEND_STATS).then(cleanResult);
export const getGithubIssues = () => {
return axios
.get<IGetGithubIssuesResult>(API.BORIS.GITHUB_ISSUES, {
params: { state: 'all', sort: 'created' },
})
.then(result => result.data)
.catch(() => []);
};

View file

@ -1,7 +1,7 @@
import { api, cleanResult } from '~/utils/api'; import { api, cleanResult } from '~/utils/api';
import { IComment, INode } from '../types'; import { IComment, INode } from '~/redux/types';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { COMMENTS_DISPLAY } from './constants'; import { COMMENTS_DISPLAY } from '~/constants/node';
import { import {
ApiDeleteNodeTagsRequest, ApiDeleteNodeTagsRequest,
ApiDeleteNodeTagsResult, ApiDeleteNodeTagsResult,
@ -23,7 +23,7 @@ import {
ApiPostNodeTagsResult, ApiPostNodeTagsResult,
GetNodeDiffRequest, GetNodeDiffRequest,
GetNodeDiffResult, GetNodeDiffResult,
} from '~/redux/node/types'; } from '~/types/node';
import axios, { AxiosRequestConfig } from 'axios'; import axios, { AxiosRequestConfig } from 'axios';
export type ApiPostNodeRequest = { node: INode }; export type ApiPostNodeRequest = { node: INode };

View file

@ -5,16 +5,17 @@ import { BorisContacts } from '~/components/boris/BorisContacts';
import { BorisStats } from '~/components/boris/BorisStats'; import { BorisStats } from '~/components/boris/BorisStats';
import { Group } from '~/components/containers/Group'; import { Group } from '~/components/containers/Group';
import { IUser } from '~/redux/auth/types'; import { IUser } from '~/redux/auth/types';
import { BorisUsageStats } from '~/redux/boris/reducer'; import { BorisUsageStats } from '~/types/boris';
interface Props { interface Props {
user: IUser; user: IUser;
isTester: boolean; isTester: boolean;
stats: BorisUsageStats; stats: BorisUsageStats;
setBetaTester: (val: boolean) => void; setBetaTester: (val: boolean) => void;
isLoading: boolean;
} }
const BorisSidebar: FC<Props> = ({ user, stats, isTester, setBetaTester }) => ( const BorisSidebar: FC<Props> = ({ user, stats, isLoading, isTester, setBetaTester }) => (
<Group className={styles.stats__container}> <Group className={styles.stats__container}>
<div className={styles.super_powers}> <div className={styles.super_powers}>
{user.is_user && <BorisSuperpowers active={isTester} onChange={setBetaTester} />} {user.is_user && <BorisSuperpowers active={isTester} onChange={setBetaTester} />}
@ -23,7 +24,7 @@ const BorisSidebar: FC<Props> = ({ user, stats, isTester, setBetaTester }) => (
<BorisContacts /> <BorisContacts />
<div className={styles.stats__wrap}> <div className={styles.stats__wrap}>
<BorisStats stats={stats} /> <BorisStats stats={stats} isLoading={isLoading} />
</div> </div>
</Group> </Group>
); );

View file

@ -1,17 +1,18 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { BorisUsageStats } from '~/redux/boris/reducer'; import { BorisUsageStats } from '~/types/boris';
import { BorisStatsGit } from '../BorisStatsGit'; import { BorisStatsGit } from '../BorisStatsGit';
import { BorisStatsBackend } from '../BorisStatsBackend'; import { BorisStatsBackend } from '../BorisStatsBackend';
interface IProps { interface IProps {
stats: BorisUsageStats; stats: BorisUsageStats;
isLoading: boolean;
} }
const BorisStats: FC<IProps> = ({ stats }) => { const BorisStats: FC<IProps> = ({ stats, isLoading }) => {
return ( return (
<> <>
<BorisStatsBackend stats={stats} /> <BorisStatsBackend stats={stats.backend} isLoading={isLoading} />
<BorisStatsGit stats={stats} /> <BorisStatsGit issues={stats.issues} isLoading={isLoading} />
</> </>
); );
}; };

View file

@ -1,72 +1,73 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { IBorisState } from '~/redux/boris/reducer'; import { StatBackend } from '~/types/boris';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { sizeOf } from '~/utils/dom'; import { sizeOf } from '~/utils/dom';
import { StatsRow } from '~/components/common/StatsRow'; import { StatsRow } from '~/components/common/StatsRow';
import { SubTitle } from '~/components/common/SubTitle'; import { SubTitle } from '~/components/common/SubTitle';
interface IProps { interface IProps {
stats: IBorisState['stats']; stats: StatBackend;
isLoading: boolean;
} }
const BorisStatsBackend: FC<IProps> = ({ stats: { is_loading, backend } }) => { const BorisStatsBackend: FC<IProps> = ({ isLoading, stats }) => {
if (!backend && !is_loading) { if (!stats && !isLoading) {
return null; return null;
} }
return ( return (
<div className={styles.wrap}> <div className={styles.wrap}>
<SubTitle isLoading={is_loading} className={styles.title}> <SubTitle isLoading={isLoading} className={styles.title}>
Юнитс Юнитс
</SubTitle> </SubTitle>
<ul> <ul>
<StatsRow isLoading={is_loading} label="В сознании"> <StatsRow isLoading={isLoading} label="В сознании">
{backend.users.alive} {stats.users.alive}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="Криокамера"> <StatsRow isLoading={isLoading} label="Криокамера">
{backend.users.total - backend.users.alive} {stats.users.total - stats.users.alive}
</StatsRow> </StatsRow>
</ul> </ul>
<SubTitle isLoading={is_loading} className={styles.title}> <SubTitle isLoading={isLoading} className={styles.title}>
Контент Контент
</SubTitle> </SubTitle>
<ul> <ul>
<StatsRow isLoading={is_loading} label="Фотографии"> <StatsRow isLoading={isLoading} label="Фотографии">
{backend.nodes.images} {stats.nodes.images}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="Письма"> <StatsRow isLoading={isLoading} label="Письма">
{backend.nodes.texts} {stats.nodes.texts}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="Видеозаписи"> <StatsRow isLoading={isLoading} label="Видеозаписи">
{backend.nodes.videos} {stats.nodes.videos}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="Аудиозаписи"> <StatsRow isLoading={isLoading} label="Аудиозаписи">
{backend.nodes.audios} {stats.nodes.audios}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="Комментарии"> <StatsRow isLoading={isLoading} label="Комментарии">
{backend.comments.total} {stats.comments.total}
</StatsRow> </StatsRow>
</ul> </ul>
<SubTitle isLoading={is_loading} className={styles.title}> <SubTitle isLoading={isLoading} className={styles.title}>
Сторедж Сторедж
</SubTitle> </SubTitle>
<ul> <ul>
<StatsRow isLoading={is_loading} label="Файлы"> <StatsRow isLoading={isLoading} label="Файлы">
{backend.files.count} {stats.files.count}
</StatsRow> </StatsRow>
<StatsRow isLoading={is_loading} label="На диске"> <StatsRow isLoading={isLoading} label="На диске">
{sizeOf(backend.files.size)} {sizeOf(stats.files.size)}
</StatsRow> </StatsRow>
</ul> </ul>
</div> </div>

View file

@ -1,27 +1,28 @@
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
import { IBorisState } from '~/redux/boris/reducer'; import { GithubIssue } from '~/types/boris';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { Placeholder } from '~/components/placeholders/Placeholder'; import { Placeholder } from '~/components/placeholders/Placeholder';
import { BorisStatsGitCard } from '../BorisStatsGitCard'; import { BorisStatsGitCard } from '../BorisStatsGitCard';
interface IProps { interface IProps {
stats: IBorisState['stats']; issues: GithubIssue[];
isLoading: boolean;
} }
const BorisStatsGit: FC<IProps> = ({ stats }) => { const BorisStatsGit: FC<IProps> = ({ issues, isLoading }) => {
const open = useMemo( const open = useMemo(
() => stats.issues.filter(el => !el.pull_request && el.state === 'open').slice(0, 5), () => issues.filter(el => !el.pull_request && el.state === 'open').slice(0, 5),
[stats.issues] [issues]
); );
const closed = useMemo( const closed = useMemo(
() => stats.issues.filter(el => !el.pull_request && el.state === 'closed').slice(0, 5), () => issues.filter(el => !el.pull_request && el.state === 'closed').slice(0, 5),
[stats.issues] [issues]
); );
if (!stats.issues.length) return null; if (!issues.length) return null;
if (stats.is_loading) { if (isLoading) {
return ( return (
<> <>
<div className={styles.stats__title}> <div className={styles.stats__title}>

View file

@ -1,14 +1,14 @@
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { getPrettyDate } from '~/utils/dom'; import { getPrettyDate } from '~/utils/dom';
import { IGithubIssue } from '~/redux/boris/types'; import { GithubIssue } from '~/types/boris';
import classNames from 'classnames'; import classNames from 'classnames';
interface IProps { interface IProps {
data: IGithubIssue; data: GithubIssue;
} }
const stateLabels: Record<IGithubIssue['state'], string> = { const stateLabels: Record<GithubIssue['state'], string> = {
open: 'Ожидает', open: 'Ожидает',
closed: 'Сделано', closed: 'Сделано',
}; };

View file

@ -10,7 +10,7 @@ import { CommentFormFormatButtons } from '~/components/comment/CommentFormFormat
import { CommentFormAttaches } from '~/components/comment/CommentFormAttaches'; import { CommentFormAttaches } from '~/components/comment/CommentFormAttaches';
import { LoaderCircle } from '~/components/input/LoaderCircle'; import { LoaderCircle } from '~/components/input/LoaderCircle';
import { IComment, INode } from '~/redux/types'; import { IComment, INode } from '~/redux/types';
import { EMPTY_COMMENT } from '~/redux/node/constants'; import { EMPTY_COMMENT } from '~/constants/node';
import { UploadDropzone } from '~/components/upload/UploadDropzone'; import { UploadDropzone } from '~/components/upload/UploadDropzone';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { ERROR_LITERAL } from '~/constants/errors'; import { ERROR_LITERAL } from '~/constants/errors';

View file

@ -3,7 +3,7 @@ import { UPLOAD_TYPES } from '~/redux/uploads/constants';
import { ImageGrid } from '../ImageGrid'; import { ImageGrid } from '../ImageGrid';
import { AudioGrid } from '../AudioGrid'; import { AudioGrid } from '../AudioGrid';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NodeEditorProps } from '~/redux/node/types'; import { NodeEditorProps } from '~/types/node';
import { useNodeImages } from '~/hooks/node/useNodeImages'; import { useNodeImages } from '~/hooks/node/useNodeImages';
import { useNodeAudios } from '~/hooks/node/useNodeAudios'; import { useNodeAudios } from '~/hooks/node/useNodeAudios';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';

View file

@ -1,6 +1,6 @@
import React, { createElement, FC } from 'react'; import React, { createElement, FC } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NODE_PANEL_COMPONENTS } from '~/redux/node/constants'; import { NODE_PANEL_COMPONENTS } from '~/constants/node';
import { has } from 'ramda'; import { has } from 'ramda';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { EditorUploadButton } from '~/components/editors/EditorUploadButton'; import { EditorUploadButton } from '~/components/editors/EditorUploadButton';
import { UPLOAD_TYPES } from '~/redux/uploads/constants'; import { UPLOAD_TYPES } from '~/redux/uploads/constants';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
type IProps = IEditorComponentProps & {}; type IProps = IEditorComponentProps & {};

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { Filler } from '~/components/containers/Filler'; import { Filler } from '~/components/containers/Filler';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
type IProps = IEditorComponentProps & {}; type IProps = IEditorComponentProps & {};

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { EditorUploadButton } from '~/components/editors/EditorUploadButton'; import { EditorUploadButton } from '~/components/editors/EditorUploadButton';
import { UPLOAD_TYPES } from '~/redux/uploads/constants'; import { UPLOAD_TYPES } from '~/redux/uploads/constants';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
type IProps = IEditorComponentProps & {}; type IProps = IEditorComponentProps & {};

View file

@ -1,5 +1,5 @@
import React, { FC, useCallback } from 'react'; import React, { FC, useCallback } from 'react';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
import { Button } from '~/components/input/Button'; import { Button } from '~/components/input/Button';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import styles from './styles.module.scss'; import styles from './styles.module.scss';

View file

@ -2,7 +2,7 @@ import React, { ChangeEvent, FC, useCallback } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { UPLOAD_TYPES } from '~/redux/uploads/constants'; import { UPLOAD_TYPES } from '~/redux/uploads/constants';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
import { useFileUploaderContext } from '~/hooks/data/useFileUploader'; import { useFileUploaderContext } from '~/hooks/data/useFileUploader';
import { getFileType } from '~/utils/uploader'; import { getFileType } from '~/utils/uploader';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';

View file

@ -5,7 +5,7 @@ import { path } from 'ramda';
import { getURL } from '~/utils/dom'; import { getURL } from '~/utils/dom';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { PRESETS } from '~/constants/urls'; import { PRESETS } from '~/constants/urls';
import { IEditorComponentProps } from '~/redux/node/types'; import { IEditorComponentProps } from '~/types/node';
import { useFileUploader } from '~/hooks/data/useFileUploader'; import { useFileUploader } from '~/hooks/data/useFileUploader';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';
import { getFileType } from '~/utils/uploader'; import { getFileType } from '~/utils/uploader';

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { ImageGrid } from '~/components/editors/ImageGrid'; import { ImageGrid } from '~/components/editors/ImageGrid';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NodeEditorProps } from '~/redux/node/types'; import { NodeEditorProps } from '~/types/node';
import { useFileUploaderContext } from '~/hooks/data/useFileUploader'; import { useFileUploaderContext } from '~/hooks/data/useFileUploader';
import { UploadDropzone } from '~/components/upload/UploadDropzone'; import { UploadDropzone } from '~/components/upload/UploadDropzone';

View file

@ -2,7 +2,7 @@ import React, { FC, useCallback } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { Textarea } from '~/components/input/Textarea'; import { Textarea } from '~/components/input/Textarea';
import { path } from 'ramda'; import { path } from 'ramda';
import { NodeEditorProps } from '~/redux/node/types'; import { NodeEditorProps } from '~/types/node';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';
type IProps = NodeEditorProps & {}; type IProps = NodeEditorProps & {};

View file

@ -4,7 +4,7 @@ import { path } from 'ramda';
import { InputText } from '~/components/input/InputText'; import { InputText } from '~/components/input/InputText';
import classnames from 'classnames'; import classnames from 'classnames';
import { getYoutubeThumb } from '~/utils/dom'; import { getYoutubeThumb } from '~/utils/dom';
import { NodeEditorProps } from '~/redux/node/types'; import { NodeEditorProps } from '~/types/node';
import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik'; import { useNodeFormContext } from '~/hooks/node/useNodeFormFormik';
type IProps = NodeEditorProps & {}; type IProps = NodeEditorProps & {};

View file

@ -7,7 +7,7 @@ import styles from './styles.module.scss';
import markdown from '~/styles/common/markdown.module.scss'; import markdown from '~/styles/common/markdown.module.scss';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import { PRESETS } from '~/constants/urls'; import { PRESETS } from '~/constants/urls';
import { NODE_TYPES } from '~/redux/node/constants'; import { NODE_TYPES } from '~/constants/node';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { CellShade } from '~/components/flow/CellShade'; import { CellShade } from '~/components/flow/CellShade';

View file

@ -1,5 +1,5 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { Placeholder } from '~/components/placeholders/Placeholder'; import { Placeholder } from '~/components/placeholders/Placeholder';
import { NodeAudioBlock } from '~/components/node/NodeAudioBlock'; import { NodeAudioBlock } from '~/components/node/NodeAudioBlock';

View file

@ -1,5 +1,5 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { Markdown } from '~/components/containers/Markdown'; import { Markdown } from '~/components/containers/Markdown';
import { formatText } from '~/utils/dom'; import { formatText } from '~/utils/dom';

View file

@ -1,5 +1,5 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import SwiperCore, { A11y, Navigation, Pagination, SwiperOptions } from 'swiper'; import SwiperCore, { A11y, Navigation, Pagination, SwiperOptions } from 'swiper';
import 'swiper/swiper.scss'; import 'swiper/swiper.scss';

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { useColorGradientFromString } from '~/hooks/color/useColorGradientFromString'; import { useColorGradientFromString } from '~/hooks/color/useColorGradientFromString';
interface Props extends INodeComponentProps {} interface Props extends INodeComponentProps {}

View file

@ -4,7 +4,7 @@ import { Group } from '~/components/containers/Group';
import { Icon } from '~/components/input/Icon'; import { Icon } from '~/components/input/Icon';
import Tippy from '@tippy.js/react'; import Tippy from '@tippy.js/react';
import { useGotoNode } from '~/hooks/node/useGotoNode'; import { useGotoNode } from '~/hooks/node/useGotoNode';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { Placeholder } from '~/components/placeholders/Placeholder'; import { Placeholder } from '~/components/placeholders/Placeholder';
const LabNodeTitle: FC<INodeComponentProps> = ({ node, isLoading }) => { const LabNodeTitle: FC<INodeComponentProps> = ({ node, isLoading }) => {

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { useGotoNode } from '~/hooks/node/useGotoNode'; import { useGotoNode } from '~/hooks/node/useGotoNode';
const LabPad: FC<INodeComponentProps> = ({ node }) => { const LabPad: FC<INodeComponentProps> = ({ node }) => {

View file

@ -1,6 +1,6 @@
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
import { Markdown } from '~/components/containers/Markdown'; import { Markdown } from '~/components/containers/Markdown';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { formatTextParagraphs } from '~/utils/dom'; import { formatTextParagraphs } from '~/utils/dom';
import { path } from 'ramda'; import { path } from 'ramda';
import styles from './styles.module.scss'; import styles from './styles.module.scss';

View file

@ -1,5 +1,5 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { NodeVideoBlock } from '~/components/node/NodeVideoBlock'; import { NodeVideoBlock } from '~/components/node/NodeVideoBlock';
import { Placeholder } from '~/components/placeholders/Placeholder'; import { Placeholder } from '~/components/placeholders/Placeholder';

View file

@ -1,7 +1,7 @@
import React, { FC } from 'react'; import React, { FC } from 'react';
import { AudioPlayer } from '~/components/media/AudioPlayer'; import { AudioPlayer } from '~/components/media/AudioPlayer';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { useNodeAudios } from '~/hooks/node/useNodeAudios'; import { useNodeAudios } from '~/hooks/node/useNodeAudios';
interface IProps extends INodeComponentProps {} interface IProps extends INodeComponentProps {}

View file

@ -3,7 +3,7 @@ import styles from './styles.module.scss';
import { path } from 'ramda'; import { path } from 'ramda';
import { getURL } from '~/utils/dom'; import { getURL } from '~/utils/dom';
import { PRESETS } from '~/constants/urls'; import { PRESETS } from '~/constants/urls';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { useNodeImages } from '~/hooks/node/useNodeImages'; import { useNodeImages } from '~/hooks/node/useNodeImages';
interface IProps extends INodeComponentProps {} interface IProps extends INodeComponentProps {}

View file

@ -1,5 +1,5 @@
import React, { FC, useCallback, useState } from 'react'; import React, { FC, useCallback, useState } from 'react';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import { Swiper, SwiperSlide } from 'swiper/react'; import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/swiper.scss'; import 'swiper/swiper.scss';

View file

@ -3,7 +3,7 @@ import { NodeRelatedPlaceholder } from '~/components/node/NodeRelated/placeholde
import { NodeRelated } from '~/components/node/NodeRelated'; import { NodeRelated } from '~/components/node/NodeRelated';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { INodeRelated } from '~/redux/node/types'; import { INodeRelated } from '~/types/node';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
interface IProps { interface IProps {

View file

@ -1,7 +1,7 @@
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
import { path } from 'ramda'; import { path } from 'ramda';
import { formatTextParagraphs } from '~/utils/dom'; import { formatTextParagraphs } from '~/utils/dom';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
import classNames from 'classnames'; import classNames from 'classnames';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import markdown from '~/styles/common/markdown.module.scss'; import markdown from '~/styles/common/markdown.module.scss';

View file

@ -1,7 +1,7 @@
import React, { FC, useMemo } from 'react'; import React, { FC, useMemo } from 'react';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { path } from 'ramda'; import { path } from 'ramda';
import { INodeComponentProps } from '~/redux/node/constants'; import { INodeComponentProps } from '~/constants/node';
interface IProps extends INodeComponentProps {} interface IProps extends INodeComponentProps {}

View file

@ -46,6 +46,7 @@ export const API = {
}, },
BORIS: { BORIS: {
GET_BACKEND_STATS: '/stats/', GET_BACKEND_STATS: '/stats/',
GITHUB_ISSUES: 'https://api.github.com/repos/muerwre/vault-frontend/issues',
}, },
TAG: { TAG: {
NODES: `/tag/nodes`, NODES: `/tag/nodes`,

View file

@ -0,0 +1,22 @@
import { StatBackend } from '~/types/boris';
export const initialBackendStats: StatBackend = {
users: {
total: 0,
alive: 0,
},
nodes: {
images: 0,
audios: 0,
videos: 0,
texts: 0,
total: 0,
},
comments: {
total: 0,
},
files: {
count: 0,
size: 0,
},
};

View file

@ -1,4 +1,4 @@
import { NODE_TYPES } from '~/redux/node/constants'; import { NODE_TYPES } from '~/constants/node';
import { LoginDialog } from '~/containers/dialogs/LoginDialog'; import { LoginDialog } from '~/containers/dialogs/LoginDialog';
import { LoadingDialog } from '~/containers/dialogs/LoadingDialog'; import { LoadingDialog } from '~/containers/dialogs/LoadingDialog';
import { TestDialog } from '~/containers/dialogs/TestDialog'; import { TestDialog } from '~/containers/dialogs/TestDialog';

View file

@ -1 +0,0 @@
export const DEFAULT_DOMINANT_COLOR = '#000000';

View file

@ -1,5 +1,5 @@
import { FC } from 'react'; import { FC } from 'react';
import { IComment, INode, ValueOf } from '../types'; import { IComment, INode, ValueOf } from 'src/redux/types';
import { NodeTextBlock } from '~/components/node/NodeTextBlock'; import { NodeTextBlock } from '~/components/node/NodeTextBlock';
import { NodeAudioBlock } from '~/components/node/NodeAudioBlock'; import { NodeAudioBlock } from '~/components/node/NodeAudioBlock';
import { NodeVideoBlock } from '~/components/node/NodeVideoBlock'; import { NodeVideoBlock } from '~/components/node/NodeVideoBlock';
@ -11,7 +11,7 @@ import { AudioEditor } from '~/components/editors/AudioEditor';
import { EditorImageUploadButton } from '~/components/editors/EditorImageUploadButton'; import { EditorImageUploadButton } from '~/components/editors/EditorImageUploadButton';
import { EditorAudioUploadButton } from '~/components/editors/EditorAudioUploadButton'; import { EditorAudioUploadButton } from '~/components/editors/EditorAudioUploadButton';
import { EditorUploadCoverButton } from '~/components/editors/EditorUploadCoverButton'; import { EditorUploadCoverButton } from '~/components/editors/EditorUploadCoverButton';
import { IEditorComponentProps, NodeEditorProps } from '~/redux/node/types'; import { IEditorComponentProps, NodeEditorProps } from '~/types/node';
import { EditorFiller } from '~/components/editors/EditorFiller'; import { EditorFiller } from '~/components/editors/EditorFiller';
import { EditorPublicSwitch } from '~/components/editors/EditorPublicSwitch'; import { EditorPublicSwitch } from '~/components/editors/EditorPublicSwitch';
import { NodeImageSwiperBlock } from '~/components/node/NodeImageSwiperBlock'; import { NodeImageSwiperBlock } from '~/components/node/NodeImageSwiperBlock';
@ -127,4 +127,6 @@ export const NODE_SETTINGS = {
MAX_IMAGE_ASPECT: 1.2, MAX_IMAGE_ASPECT: 1.2,
}; };
export const DEFAULT_DOMINANT_COLOR = '#000000';
export const COMMENTS_DISPLAY = 25; export const COMMENTS_DISPLAY = 25;

View file

@ -1,5 +1,5 @@
import React, { FC, useCallback, useMemo, useRef } from 'react'; import React, { FC, useCallback, useMemo, useRef } from 'react';
import { EMPTY_NODE, NODE_TYPES } from '~/redux/node/constants'; import { EMPTY_NODE, NODE_TYPES } from '~/constants/node';
import { EditorDialog } from '~/containers/dialogs/EditorDialog'; import { EditorDialog } from '~/containers/dialogs/EditorDialog';
import { useHistory, useRouteMatch } from 'react-router'; import { useHistory, useRouteMatch } from 'react-router';
import { values } from 'ramda'; import { values } from 'ramda';

View file

@ -1,7 +1,7 @@
import React, { createElement, FC, useCallback, useMemo, useState } from 'react'; import React, { createElement, FC, useCallback, useMemo, useState } from 'react';
import { IDialogProps } from '~/redux/modal/constants'; import { IDialogProps } from '~/redux/modal/constants';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { NODE_EDITORS } from '~/redux/node/constants'; import { NODE_EDITORS } from '~/constants/node';
import { BetterScrollDialog } from '../BetterScrollDialog'; import { BetterScrollDialog } from '../BetterScrollDialog';
import { CoverBackdrop } from '~/components/containers/CoverBackdrop'; import { CoverBackdrop } from '~/components/containers/CoverBackdrop';
import { prop } from 'ramda'; import { prop } from 'ramda';

View file

@ -2,7 +2,7 @@ import React, { FC, useMemo } from 'react';
import Masonry from 'react-masonry-css'; import Masonry from 'react-masonry-css';
import styles from './styles.module.scss'; import styles from './styles.module.scss';
import { LabNode } from '~/components/lab/LabNode'; import { LabNode } from '~/components/lab/LabNode';
import { EMPTY_NODE, NODE_TYPES } from '~/redux/node/constants'; import { EMPTY_NODE, NODE_TYPES } from '~/constants/node';
import { values } from 'ramda'; import { values } from 'ramda';
import { useLabPagination } from '~/hooks/lab/useLabPagination'; import { useLabPagination } from '~/hooks/lab/useLabPagination';
import { useLabContext } from '~/utils/context/LabContextProvider'; import { useLabContext } from '~/utils/context/LabContextProvider';

View file

@ -2,13 +2,12 @@ import { useDispatch } from 'react-redux';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import isBefore from 'date-fns/isBefore'; import isBefore from 'date-fns/isBefore';
import { authSetState, authSetUser } from '~/redux/auth/actions'; import { authSetState, authSetUser } from '~/redux/auth/actions';
import { borisLoadStats } from '~/redux/boris/actions';
import { useUser } from '~/hooks/user/userUser'; import { useUser } from '~/hooks/user/userUser';
import { IComment } from '~/redux/types'; import { IComment } from '~/redux/types';
import { useShallowSelect } from '~/hooks/data/useShallowSelect'; import { useShallowSelect } from '~/hooks/data/useShallowSelect';
import { selectAuthIsTester } from '~/redux/auth/selectors'; import { selectAuthIsTester } from '~/redux/auth/selectors';
import { selectBorisStats } from '~/redux/boris/selectors';
import { useRandomPhrase } from '~/constants/phrases'; import { useRandomPhrase } from '~/constants/phrases';
import { useBorisStats } from '~/hooks/boris/useBorisStats';
export const useBoris = (comments: IComment[]) => { export const useBoris = (comments: IComment[]) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -29,9 +28,7 @@ export const useBoris = (comments: IComment[]) => {
dispatch(authSetUser({ last_seen_boris: last_comment.created_at })); dispatch(authSetUser({ last_seen_boris: last_comment.created_at }));
}, [user.last_seen_boris, dispatch, comments]); }, [user.last_seen_boris, dispatch, comments]);
useEffect(() => { const { stats, isLoading: isLoadingStats } = useBorisStats();
dispatch(borisLoadStats());
}, [dispatch]);
const setIsBetaTester = useCallback( const setIsBetaTester = useCallback(
(is_tester: boolean) => { (is_tester: boolean) => {
@ -41,8 +38,7 @@ export const useBoris = (comments: IComment[]) => {
); );
const isTester = useShallowSelect(selectAuthIsTester); const isTester = useShallowSelect(selectAuthIsTester);
const stats = useShallowSelect(selectBorisStats);
const title = useRandomPhrase('BORIS_TITLE'); const title = useRandomPhrase('BORIS_TITLE');
return { setIsBetaTester, isTester, stats, title }; return { setIsBetaTester, isTester, stats, title, isLoadingStats };
}; };

View file

@ -0,0 +1,25 @@
import useSWR from 'swr';
import { API } from '~/constants/api';
import { getBorisBackendStats, getGithubIssues } from '~/api/boris';
import { BorisUsageStats } from '~/types/boris';
import { initialBackendStats } from '~/constants/boris/constants';
export const useBorisStats = () => {
const { data: backend = initialBackendStats, isValidating: isValidatingBackend } = useSWR(
API.BORIS.GET_BACKEND_STATS,
() => getBorisBackendStats()
);
const { data: issues = [], isValidating: isValidatingGit } = useSWR(API.BORIS.GITHUB_ISSUES, () =>
getGithubIssues()
);
const stats: BorisUsageStats = {
backend,
issues,
};
const isLoading = !backend && isValidatingBackend;
return { stats, isLoading };
};

View file

@ -3,8 +3,8 @@ import { IComment } from '~/redux/types';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { flatten, isNil } from 'ramda'; import { flatten, isNil } from 'ramda';
import useSWRInfinite from 'swr/infinite'; import useSWRInfinite from 'swr/infinite';
import { apiGetNodeComments } from '~/redux/node/api'; import { apiGetNodeComments } from '~/api/node';
import { COMMENTS_DISPLAY } from '~/redux/node/constants'; import { COMMENTS_DISPLAY } from '~/constants/node';
import { useCallback } from 'react'; import { useCallback } from 'react';
const getKey: (nodeId: number) => KeyLoader<IComment[]> = (nodeId: number) => ( const getKey: (nodeId: number) => KeyLoader<IComment[]> = (nodeId: number) => (

View file

@ -1,7 +1,7 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { IComment } from '~/redux/types'; import { IComment } from '~/redux/types';
import { useGetComments } from '~/hooks/comments/useGetComments'; import { useGetComments } from '~/hooks/comments/useGetComments';
import { apiLockComment, apiPostComment } from '~/redux/node/api'; import { apiLockComment, apiPostComment } from '~/api/node';
import { showErrorToast } from '~/utils/errors/showToast'; import { showErrorToast } from '~/utils/errors/showToast';
export const useNodeComments = (nodeId: number) => { export const useNodeComments = (nodeId: number) => {

View file

@ -1,6 +1,6 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { apiPostNode } from '~/redux/node/api'; import { apiPostNode } from '~/api/node';
import { selectFlowNodes } from '~/redux/flow/selectors'; import { selectFlowNodes } from '~/redux/flow/selectors';
import { flowSetNodes } from '~/redux/flow/actions'; import { flowSetNodes } from '~/redux/flow/actions';
import { selectLabListNodes } from '~/redux/lab/selectors'; import { selectLabListNodes } from '~/redux/lab/selectors';

View file

@ -1,9 +1,9 @@
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import useSWR from 'swr'; import useSWR from 'swr';
import { ApiGetNodeRelatedResult } from '~/redux/node/types'; import { ApiGetNodeRelatedResult } from '~/types/node';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { apiGetNodeRelated } from '~/redux/node/api'; import { apiGetNodeRelated } from '~/api/node';
export const useGetNodeRelated = (id?: INode['id']) => { export const useGetNodeRelated = (id?: INode['id']) => {
const { data, isValidating, mutate } = useSWR<ApiGetNodeRelatedResult>(API.NODE.RELATED(id), () => const { data, isValidating, mutate } = useSWR<ApiGetNodeRelatedResult>(API.NODE.RELATED(id), () =>

View file

@ -1,11 +1,11 @@
import useSWR from 'swr'; import useSWR from 'swr';
import { ApiGetNodeResponse } from '~/redux/node/types'; import { ApiGetNodeResponse } from '~/types/node';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { useOnNodeSeen } from '~/hooks/node/useOnNodeSeen'; import { useOnNodeSeen } from '~/hooks/node/useOnNodeSeen';
import { apiGetNode } from '~/redux/node/api'; import { apiGetNode } from '~/api/node';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { EMPTY_NODE } from '~/redux/node/constants'; import { EMPTY_NODE } from '~/constants/node';
export const useLoadNode = (id: number) => { export const useLoadNode = (id: number) => {
const { data, isValidating, mutate } = useSWR<ApiGetNodeResponse>(API.NODE.GET_NODE(id), () => const { data, isValidating, mutate } = useSWR<ApiGetNodeResponse>(API.NODE.GET_NODE(id), () =>

View file

@ -3,7 +3,7 @@ import { useCallback } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { modalShowDialog } from '~/redux/modal/actions'; import { modalShowDialog } from '~/redux/modal/actions';
import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs'; import { NODE_EDITOR_DIALOGS } from '~/constants/dialogs';
import { apiLockNode, apiPostNodeHeroic, apiPostNodeLike } from '~/redux/node/api'; import { apiLockNode, apiPostNodeHeroic, apiPostNodeLike } from '~/api/node';
import { showErrorToast } from '~/utils/errors/showToast'; import { showErrorToast } from '~/utils/errors/showToast';
export const useNodeActions = (node: INode, update: (node: Partial<INode>) => Promise<unknown>) => { export const useNodeActions = (node: INode, update: (node: Partial<INode>) => Promise<unknown>) => {

View file

@ -1,13 +1,7 @@
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { createElement, FC, useCallback, useMemo } from 'react'; import { createElement, FC, useCallback, useMemo } from 'react';
import { isNil, prop } from 'ramda'; import { isNil, prop } from 'ramda';
import { import { INodeComponentProps, LAB_PREVIEW_LAYOUT, NODE_COMPONENTS, NODE_HEADS, NODE_INLINES, } from '~/constants/node';
INodeComponentProps,
LAB_PREVIEW_LAYOUT,
NODE_COMPONENTS,
NODE_HEADS,
NODE_INLINES,
} from '~/redux/node/constants';
// useNodeBlocks returns head, block and inline blocks of node // useNodeBlocks returns head, block and inline blocks of node
export const useNodeBlocks = (node: INode, isLoading: boolean) => { export const useNodeBlocks = (node: INode, isLoading: boolean) => {

View file

@ -3,7 +3,7 @@ import { useCallback } from 'react';
import { ITag } from '~/redux/types'; import { ITag } from '~/redux/types';
import { URLS } from '~/constants/urls'; import { URLS } from '~/constants/urls';
import { useLoadNode } from '~/hooks/node/useLoadNode'; import { useLoadNode } from '~/hooks/node/useLoadNode';
import { apiDeleteNodeTag, apiPostNodeTags } from '~/redux/node/api'; import { apiDeleteNodeTag, apiPostNodeTags } from '~/api/node';
export const useNodeTags = (id: number) => { export const useNodeTags = (id: number) => {
const { update } = useLoadNode(id); const { update } = useLoadNode(id);

View file

@ -1,7 +1,7 @@
import { useLoadNode } from '~/hooks/node/useLoadNode'; import { useLoadNode } from '~/hooks/node/useLoadNode';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { apiPostNode } from '~/redux/node/api'; import { apiPostNode } from '~/api/node';
import { selectFlowNodes } from '~/redux/flow/selectors'; import { selectFlowNodes } from '~/redux/flow/selectors';
import { flowSetNodes } from '~/redux/flow/actions'; import { flowSetNodes } from '~/redux/flow/actions';
import { selectLabListNodes } from '~/redux/lab/selectors'; import { selectLabListNodes } from '~/redux/lab/selectors';

View file

@ -9,7 +9,7 @@ import { Card } from '~/components/containers/Card';
import { SidebarRouter } from '~/containers/main/SidebarRouter'; import { SidebarRouter } from '~/containers/main/SidebarRouter';
import { BorisSidebar } from '~/components/boris/BorisSidebar'; import { BorisSidebar } from '~/components/boris/BorisSidebar';
import { useUserContext } from '~/utils/context/UserContextProvider'; import { useUserContext } from '~/utils/context/UserContextProvider';
import { BorisUsageStats } from '~/redux/boris/reducer'; import { BorisUsageStats } from '~/types/boris';
import { Tabs } from '~/components/dialogs/Tabs'; import { Tabs } from '~/components/dialogs/Tabs';
import { Superpower } from '~/components/boris/Superpower'; import { Superpower } from '~/components/boris/Superpower';
import { BorisUIDemo } from '~/components/boris/BorisUIDemo'; import { BorisUIDemo } from '~/components/boris/BorisUIDemo';
@ -19,9 +19,10 @@ type IProps = {
setIsBetaTester: (val: boolean) => void; setIsBetaTester: (val: boolean) => void;
isTester: boolean; isTester: boolean;
stats: BorisUsageStats; stats: BorisUsageStats;
isLoadingStats: boolean;
}; };
const BorisLayout: FC<IProps> = ({ title, setIsBetaTester, isTester, stats }) => { const BorisLayout: FC<IProps> = ({ title, setIsBetaTester, isTester, stats, isLoadingStats }) => {
const user = useUserContext(); const user = useUserContext();
return ( return (
@ -60,6 +61,7 @@ const BorisLayout: FC<IProps> = ({ title, setIsBetaTester, isTester, stats }) =>
stats={stats} stats={stats}
setBetaTester={setIsBetaTester} setBetaTester={setIsBetaTester}
user={user} user={user}
isLoading={isLoadingStats}
/> />
</StickyBox> </StickyBox>
</Group> </Group>

View file

@ -19,7 +19,7 @@ const BorisPage: VFC = () => {
hasMore, hasMore,
isLoading: isLoadingComments, isLoading: isLoadingComments,
} = useNodeComments(696); } = useNodeComments(696);
const { title, setIsBetaTester, isTester, stats } = useBoris(comments); const { title, setIsBetaTester, isTester, stats, isLoadingStats } = useBoris(comments);
return ( return (
<NodeContextProvider node={node} isLoading={isLoading} update={update}> <NodeContextProvider node={node} isLoading={isLoading} update={update}>
@ -37,6 +37,7 @@ const BorisPage: VFC = () => {
setIsBetaTester={setIsBetaTester} setIsBetaTester={setIsBetaTester}
isTester={isTester} isTester={isTester}
stats={stats} stats={stats}
isLoadingStats={isLoadingStats}
/> />
</CommentContextProvider> </CommentContextProvider>
</NodeContextProvider> </NodeContextProvider>

View file

@ -1,16 +0,0 @@
import { IBorisState } from './reducer';
import { BORIS_ACTIONS } from './constants';
export const borisSet = (state: Partial<IBorisState>) => ({
type: BORIS_ACTIONS.SET_BORIS,
state,
});
export const borisSetStats = (stats: Partial<IBorisState['stats']>) => ({
type: BORIS_ACTIONS.SET_STATS,
stats,
});
export const borisLoadStats = () => ({
type: BORIS_ACTIONS.LOAD_STATS,
});

View file

@ -1,20 +0,0 @@
import git from '~/stats/git.json';
import { API } from '~/constants/api';
import { api, cleanResult } from '~/utils/api';
import { IBorisState, IStatBackend } from './reducer';
import axios from 'axios';
import { IGetGithubIssuesResult } from '~/redux/boris/types';
export const getBorisGitStats = () => Promise.resolve<IBorisState['stats']['git']>(git);
export const getBorisBackendStats = () =>
api.get<IStatBackend>(API.BORIS.GET_BACKEND_STATS).then(cleanResult);
export const getGithubIssues = () => {
return axios
.get<IGetGithubIssuesResult>('https://api.github.com/repos/muerwre/vault-frontend/issues', {
params: { state: 'all', sort: 'created' },
})
.then(result => result.data)
.catch(() => []);
};

View file

@ -1,8 +0,0 @@
const prefix = `BORIS.`;
export const BORIS_ACTIONS = {
SET_BORIS: `${prefix}SET_BORIS`,
SET_STATS: `${prefix}SET_STATS`,
LOAD_STATS: `${prefix}LOAD_STATS`,
};

View file

@ -1,20 +0,0 @@
import { IBorisState } from './reducer';
import { BORIS_ACTIONS } from './constants';
const borisSet = (current: IBorisState, { state }: ReturnType<typeof borisSet>) => ({
...current,
...state,
});
const borisSetStats = (state: IBorisState, { stats }: ReturnType<typeof borisSetStats>) => ({
...state,
stats: {
...state.stats,
...stats,
},
});
export const BORIS_HANDLERS = {
[BORIS_ACTIONS.SET_BORIS]: borisSet,
[BORIS_ACTIONS.SET_STATS]: borisSetStats,
};

View file

@ -1,72 +0,0 @@
import { createReducer } from '~/utils/reducer';
import { BORIS_HANDLERS } from './handlers';
import { IGithubIssue } from '~/redux/boris/types';
export type IStatGitRow = {
commit: string;
subject: string;
timestamp: string;
};
export type IStatBackend = {
users: {
total: number;
alive: number;
};
nodes: {
images: number;
audios: number;
videos: number;
texts: number;
total: number;
};
comments: {
total: number;
};
files: {
count: number;
size: number;
};
};
export interface BorisUsageStats {
git: Partial<IStatGitRow>[];
issues: IGithubIssue[];
backend: IStatBackend;
is_loading: boolean;
}
export type IBorisState = Readonly<{
stats: BorisUsageStats;
}>;
const initialBackendStats: IStatBackend = {
users: {
total: 0,
alive: 0,
},
nodes: {
images: 0,
audios: 0,
videos: 0,
texts: 0,
total: 0,
},
comments: {
total: 0,
},
files: {
count: 0,
size: 0,
},
};
const BORIS_INITIAL_STATE: IBorisState = {
stats: {
git: [],
issues: [],
backend: initialBackendStats,
is_loading: false,
},
};
export default createReducer(BORIS_INITIAL_STATE, BORIS_HANDLERS);

View file

@ -1,24 +0,0 @@
import { call, put, takeLatest } from 'redux-saga/effects';
import { BORIS_ACTIONS } from './constants';
import { borisSetStats } from './actions';
import { getBorisBackendStats, getGithubIssues } from './api';
import { Unwrap } from '../types';
function* loadStats() {
try {
yield put(borisSetStats({ is_loading: true }));
const backend: Unwrap<typeof getBorisBackendStats> = yield call(getBorisBackendStats);
const issues: Unwrap<typeof getGithubIssues> = yield call(getGithubIssues);
yield put(borisSetStats({ issues, backend }));
} catch (e) {
yield put(borisSetStats({ git: [], backend: undefined }));
} finally {
yield put(borisSetStats({ is_loading: false }));
}
}
export default function* borisSaga() {
yield takeLatest(BORIS_ACTIONS.LOAD_STATS, loadStats);
}

View file

@ -1,4 +0,0 @@
import { IState } from '../store';
export const selectBoris = (state: IState) => state.boris;
export const selectBorisStats = (state: IState) => state.boris.stats;

View file

@ -1,12 +0,0 @@
export interface IGithubIssue {
id: string;
url: string;
html_url: string;
body: string;
title: string;
state: 'open' | 'closed';
created_at: string;
pull_request?: unknown;
}
export type IGetGithubIssuesResult = IGithubIssue[];

View file

@ -1,7 +1,7 @@
import { api, cleanResult, configWithToken } from '~/utils/api'; import { api, cleanResult, configWithToken } from '~/utils/api';
import { INode, IResultWithStatus } from '../types'; import { INode, IResultWithStatus } from '../types';
import { API } from '~/constants/api'; import { API } from '~/constants/api';
import { PostCellViewRequest, PostCellViewResult } from '~/redux/node/types'; import { PostCellViewRequest, PostCellViewResult } from '~/types/node';
import { GetSearchResultsRequest, GetSearchResultsResult } from '~/redux/flow/types'; import { GetSearchResultsRequest, GetSearchResultsResult } from '~/redux/flow/types';
export const postNode = ({ export const postNode = ({

View file

@ -1,7 +1,7 @@
import { call, delay, put, race, select, take, takeLatest, takeLeading } from 'redux-saga/effects'; import { call, delay, put, race, select, take, takeLatest, takeLeading } from 'redux-saga/effects';
import { REHYDRATE } from 'redux-persist'; import { REHYDRATE } from 'redux-persist';
import { FLOW_ACTIONS } from './constants'; import { FLOW_ACTIONS } from './constants';
import { getNodeDiff } from '../node/api'; import { getNodeDiff } from '~/api/node';
import { import {
flowChangeSearch, flowChangeSearch,
flowSetCellView, flowSetCellView,

View file

@ -29,9 +29,6 @@ import { modalSaga } from './modal/sagas';
import { authLogout, authOpenProfile, gotAuthPostMessage } from './auth/actions'; import { authLogout, authOpenProfile, gotAuthPostMessage } from './auth/actions';
import boris, { IBorisState } from './boris/reducer';
import borisSaga from './boris/sagas';
import messages, { IMessagesState } from './messages'; import messages, { IMessagesState } from './messages';
import messagesSaga from './messages/sagas'; import messagesSaga from './messages/sagas';
@ -66,7 +63,6 @@ export interface IState {
uploads: IUploadState; uploads: IUploadState;
flow: IFlowState; flow: IFlowState;
player: IPlayerState; player: IPlayerState;
boris: IBorisState;
messages: IMessagesState; messages: IMessagesState;
tag: ITagState; tag: ITagState;
lab: ILabState; lab: ILabState;
@ -86,7 +82,6 @@ export const store = createStore(
combineReducers<IState>({ combineReducers<IState>({
auth: persistReducer(authPersistConfig, auth), auth: persistReducer(authPersistConfig, auth),
modal, modal,
boris,
router: connectRouter(history), router: connectRouter(history),
uploads, uploads,
flow: persistReducer(flowPersistConfig, flow), flow: persistReducer(flowPersistConfig, flow),
@ -107,7 +102,6 @@ export function configureStore(): {
sagaMiddleware.run(flowSaga); sagaMiddleware.run(flowSaga);
sagaMiddleware.run(playerSaga); sagaMiddleware.run(playerSaga);
sagaMiddleware.run(modalSaga); sagaMiddleware.run(modalSaga);
sagaMiddleware.run(borisSaga);
sagaMiddleware.run(messagesSaga); sagaMiddleware.run(messagesSaga);
sagaMiddleware.run(tagSaga); sagaMiddleware.run(tagSaga);
sagaMiddleware.run(labSaga); sagaMiddleware.run(labSaga);

47
src/types/boris/index.ts Normal file
View file

@ -0,0 +1,47 @@
export interface GithubIssue {
id: string;
url: string;
html_url: string;
body: string;
title: string;
state: 'open' | 'closed';
created_at: string;
pull_request?: unknown;
}
export type IGetGithubIssuesResult = GithubIssue[];
export type IStatGitRow = {
commit: string;
subject: string;
timestamp: string;
};
export type StatBackend = {
users: {
total: number;
alive: number;
};
nodes: {
images: number;
audios: number;
videos: number;
texts: number;
total: number;
};
comments: {
total: number;
};
files: {
count: number;
size: number;
};
};
export interface BorisUsageStats {
issues: GithubIssue[];
backend: StatBackend;
}
export type IBorisState = Readonly<{
stats: BorisUsageStats;
}>;

View file

@ -1,5 +1,5 @@
import { INode } from '~/redux/types'; import { INode } from '~/redux/types';
import { EMPTY_NODE } from '~/redux/node/constants'; import { EMPTY_NODE } from '~/constants/node';
import React, { createContext, FC, useContext } from 'react'; import React, { createContext, FC, useContext } from 'react';
export interface NodeContextProps { export interface NodeContextProps {

View file

@ -1,4 +1,4 @@
import { INodeRelated } from '~/redux/node/types'; import { INodeRelated } from '~/types/node';
import React, { createContext, FC, useContext } from 'react'; import React, { createContext, FC, useContext } from 'react';
interface NodeRelatedProviderProps { interface NodeRelatedProviderProps {

View file

@ -2,7 +2,7 @@ import { USER_ROLES } from '~/redux/auth/constants';
import { ICommentGroup, INode } from '~/redux/types'; import { ICommentGroup, INode } from '~/redux/types';
import { IUser } from '~/redux/auth/types'; import { IUser } from '~/redux/auth/types';
import { path } from 'ramda'; import { path } from 'ramda';
import { NODE_TYPES } from '~/redux/node/constants'; import { NODE_TYPES } from '~/constants/node';
export const canEditNode = (node?: Partial<INode>, user?: Partial<IUser>): boolean => export const canEditNode = (node?: Partial<INode>, user?: Partial<IUser>): boolean =>
path(['role'], user) === USER_ROLES.ADMIN || path(['role'], user) === USER_ROLES.ADMIN ||

View file

@ -1,7 +1,7 @@
import React, { FC, useEffect } from 'react'; import React, { FC, useEffect } from 'react';
import { INode, ITag } from '~/redux/types'; import { INode, ITag } from '~/redux/types';
import { NodeRelatedContextProvider } from '~/utils/context/NodeRelatedContextProvider'; import { NodeRelatedContextProvider } from '~/utils/context/NodeRelatedContextProvider';
import { INodeRelated } from '~/redux/node/types'; import { INodeRelated } from '~/types/node';
import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated'; import { useGetNodeRelated } from '~/hooks/node/useGetNodeRelated';
interface NodeRelatedProviderProps { interface NodeRelatedProviderProps {