mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
update
This commit is contained in:
parent
5d890b4848
commit
72d3c59f30
|
@ -5,23 +5,24 @@ import Banner from 'ts/components/Banner';
|
|||
import style from '../index.module.scss';
|
||||
|
||||
interface ICardWithBannerProps {
|
||||
long?: boolean;
|
||||
size?: 's' | 'm' | 'l';
|
||||
}
|
||||
|
||||
function CardWithBanner({
|
||||
long = false,
|
||||
}: ICardWithBannerProps): React.ReactElement | null {
|
||||
const className = long
|
||||
? style.card_with_icon_long
|
||||
: style.card_with_icon;
|
||||
function CardWithBanner({ size }: ICardWithBannerProps): React.ReactElement | null {
|
||||
const className = [
|
||||
style.card_with_icon,
|
||||
style.card_with_icon_banner,
|
||||
];
|
||||
if (size === 's') className.push(style.card_with_icon_small);
|
||||
if (size === 'l') className.push(style.card_with_icon_long);
|
||||
|
||||
return (
|
||||
<Banner className={`${className} ${style.card_with_icon_banner}`} />
|
||||
<Banner className={className.join(' ')} />
|
||||
);
|
||||
}
|
||||
|
||||
CardWithBanner.defaultProps = {
|
||||
long: false,
|
||||
size: 'm',
|
||||
};
|
||||
|
||||
export default CardWithBanner;
|
||||
|
|
|
@ -15,6 +15,7 @@ function Scoring({
|
|||
total,
|
||||
}: IScoringProps): React.ReactElement | null {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!value) return null;
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.card_with_icon,
|
||||
.card_with_icon_long {
|
||||
.card_with_icon {
|
||||
position: relative;
|
||||
|
||||
display: inline-block;
|
||||
width: calc(50% - 12px);
|
||||
min-height: 270px;
|
||||
margin: 0 24px 24px 0;
|
||||
padding: 16px;
|
||||
margin: 0 var(--space-xxl) var(--space-xxl) 0;
|
||||
padding: var(--space-l);
|
||||
|
||||
vertical-align: top;
|
||||
text-decoration: none;
|
||||
|
@ -35,10 +34,13 @@
|
|||
&_value {
|
||||
font-weight: bold;
|
||||
font-size: 28px;
|
||||
|
||||
display: block;
|
||||
margin: 0 0 4px 0;
|
||||
margin: 0 0 var(--space-xxs) 0;
|
||||
padding: 0;
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: var(--color-11);
|
||||
}
|
||||
|
||||
|
@ -46,19 +48,22 @@
|
|||
&_description,
|
||||
&_scoring {
|
||||
font-weight: 100;
|
||||
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-size: var(--font-m);
|
||||
line-height: 14px;
|
||||
margin: 0 0 4px 0;
|
||||
margin: 0 0 var(--space-xxs) 0;
|
||||
}
|
||||
|
||||
&_description,
|
||||
|
@ -68,12 +73,6 @@
|
|||
color: var(--color-grey);
|
||||
}
|
||||
|
||||
&_banner {
|
||||
font-size: 32px;
|
||||
padding: 0;
|
||||
line-height: 270px;
|
||||
}
|
||||
|
||||
&_scoring {
|
||||
position: absolute;
|
||||
bottom: -11px;
|
||||
|
@ -82,6 +81,7 @@
|
|||
|
||||
display: inline-block;
|
||||
padding: var(--space-xxxs) var(--space-xs);
|
||||
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
|
||||
|
@ -89,11 +89,31 @@
|
|||
border: 1px solid var(--color-border);
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_small {
|
||||
min-height: auto;
|
||||
padding: var(--space-l) 0;
|
||||
}
|
||||
|
||||
&_long {
|
||||
width: 100%;
|
||||
margin: 0 0 var(--space-xxl) 0;
|
||||
}
|
||||
|
||||
&_banner {
|
||||
font-size: 32px;
|
||||
padding: 0;
|
||||
line-height: 270px;
|
||||
}
|
||||
}
|
||||
|
||||
.card_with_icon_long {
|
||||
width: 100%;
|
||||
margin: 0 0 24px 0;
|
||||
.card_with_icon_small {
|
||||
.card_with_icon_value {
|
||||
font-size: var(--font-m);
|
||||
font-weight: 100;
|
||||
margin-bottom: var(--space-m);
|
||||
color: var(--color-button-2);
|
||||
}
|
||||
}
|
||||
|
||||
.card_with_icon:nth-child(2n+2) {
|
||||
|
@ -101,10 +121,9 @@
|
|||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.card_with_icon,
|
||||
.card_with_icon_long {
|
||||
.card_with_icon {
|
||||
min-height: 220px;
|
||||
padding: 16px 0;
|
||||
padding: var(--space-l) 0;
|
||||
|
||||
&_title {
|
||||
margin: 0;
|
||||
|
@ -117,8 +136,7 @@
|
|||
}
|
||||
|
||||
@media (max-width: 650px) {
|
||||
.card_with_icon,
|
||||
.card_with_icon_long {
|
||||
.card_with_icon {
|
||||
min-height: 190px;
|
||||
padding: 32px 0;
|
||||
|
||||
|
@ -139,10 +157,9 @@
|
|||
}
|
||||
|
||||
@media print {
|
||||
.card_with_icon,
|
||||
.card_with_icon_long {
|
||||
.card_with_icon {
|
||||
min-height: 220px;
|
||||
padding: 16px 0;
|
||||
padding: var(--space-l) 0;
|
||||
|
||||
&_icon {
|
||||
height: 60px;
|
||||
|
@ -155,7 +172,7 @@
|
|||
|
||||
&_title {
|
||||
font-size: var(--font-s);
|
||||
margin: 0 0 8px 0;
|
||||
margin: 0 0 var(--space-s) 0;
|
||||
}
|
||||
|
||||
&_description {
|
||||
|
|
|
@ -10,9 +10,8 @@ interface ICardWithIconProps {
|
|||
description?: string;
|
||||
value: number | string | null;
|
||||
suffix?: string;
|
||||
color?: string;
|
||||
icon?: string;
|
||||
long?: boolean;
|
||||
size?: 's' | 'm' | 'l';
|
||||
scoring?: IScoringProps;
|
||||
}
|
||||
|
||||
|
@ -21,43 +20,47 @@ function CardWithIcon({
|
|||
description,
|
||||
value,
|
||||
suffix,
|
||||
color,
|
||||
icon,
|
||||
long = false,
|
||||
size,
|
||||
scoring,
|
||||
}: ICardWithIconProps): React.ReactElement | null {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!value && value !== 0) return null;
|
||||
|
||||
const className = [style.card_with_icon];
|
||||
if (size === 's') className.push(style.card_with_icon_small);
|
||||
if (size === 'l') className.push(style.card_with_icon_long);
|
||||
|
||||
return (
|
||||
<figure className={long
|
||||
? style.card_with_icon_long
|
||||
: style.card_with_icon}>
|
||||
<figure className={className.join(' ')}>
|
||||
{icon && (
|
||||
<img
|
||||
className={style.card_with_icon_icon}
|
||||
src={icon}
|
||||
/>
|
||||
)}
|
||||
<p
|
||||
className={style.card_with_icon_value}
|
||||
style={{ color: color || '' }}
|
||||
>
|
||||
|
||||
<p className={style.card_with_icon_value}>
|
||||
{value}
|
||||
{suffix || ''}
|
||||
</p>
|
||||
|
||||
<h4 className={style.card_with_icon_title}>
|
||||
{t(title || '')}
|
||||
</h4>
|
||||
|
||||
<figcaption className={style.card_with_icon_description}>
|
||||
{t(description || '')}
|
||||
</figcaption>
|
||||
<Scoring
|
||||
title={scoring?.title}
|
||||
value={scoring?.value}
|
||||
total={scoring?.total}
|
||||
/>
|
||||
|
||||
{scoring ? (
|
||||
<Scoring
|
||||
title={scoring?.title}
|
||||
value={scoring?.value}
|
||||
total={scoring?.total}
|
||||
/>
|
||||
) : null}
|
||||
</figure>
|
||||
);
|
||||
}
|
||||
|
@ -65,9 +68,8 @@ function CardWithIcon({
|
|||
CardWithIcon.defaultProps = {
|
||||
description: '',
|
||||
suffix: '',
|
||||
color: undefined,
|
||||
icon: undefined,
|
||||
long: false,
|
||||
size: 'm',
|
||||
scoring: undefined,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import Logo from 'ts/pages/PageWrapper/components/sidebar/Logo';
|
||||
import globalScroll from 'ts/helpers/globalScroll';
|
||||
|
||||
import splashScreenStore from './store';
|
||||
import style from './index.module.scss';
|
||||
import progress from './progress.module.scss';
|
||||
|
||||
function SplashScreen(): React.ReactElement | null {
|
||||
|
||||
const SplashScreen = observer((): React.ReactElement | null => {
|
||||
useEffect(() => {
|
||||
globalScroll.off(5400);
|
||||
}, []);
|
||||
if (!splashScreenStore.isOpen) return;
|
||||
setTimeout(() => {
|
||||
splashScreenStore.hide();
|
||||
}, 5400);
|
||||
}, [splashScreenStore.isOpen]);
|
||||
|
||||
if (!splashScreenStore.isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className={style.splash_screen}>
|
||||
|
@ -20,6 +25,6 @@ function SplashScreen(): React.ReactElement | null {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default SplashScreen;
|
||||
|
|
27
src/ts/components/SplashScreen/store/index.ts
Normal file
27
src/ts/components/SplashScreen/store/index.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { observable, action, makeObservable } from 'mobx';
|
||||
import globalScroll from 'ts/helpers/globalScroll';
|
||||
|
||||
class SplashScreenStore {
|
||||
isOpen: boolean = false;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
isOpen: observable,
|
||||
show: action,
|
||||
hide: action,
|
||||
});
|
||||
}
|
||||
|
||||
show() {
|
||||
this.isOpen = true;
|
||||
globalScroll.off(5400);
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.isOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
const splashScreen = new SplashScreenStore();
|
||||
|
||||
export default splashScreen;
|
|
@ -26,16 +26,20 @@ export default class FileBuilderLineStat {
|
|||
file.removedLines += fileChange.removedLines;
|
||||
file.changedLines += fileChange.changedLines;
|
||||
|
||||
file.addedLinesByAuthor[commit.author] = file.addedLinesByAuthor[commit.author]
|
||||
? (file.addedLinesByAuthor[commit.author] + fileChange.addedLines)
|
||||
// TODO: performance
|
||||
const addedLinesByAuthor = file.addedLinesByAuthor[commit.author];
|
||||
file.addedLinesByAuthor[commit.author] = addedLinesByAuthor
|
||||
? (addedLinesByAuthor + fileChange.addedLines)
|
||||
: fileChange.addedLines;
|
||||
|
||||
file.removedLinesByAuthor[commit.author] = file.removedLinesByAuthor[commit.author]
|
||||
? (file.removedLinesByAuthor[commit.author] + fileChange.removedLines)
|
||||
const removedLinesByAuthor = file.removedLinesByAuthor[commit.author];
|
||||
file.removedLinesByAuthor[commit.author] = removedLinesByAuthor
|
||||
? (removedLinesByAuthor + fileChange.removedLines)
|
||||
: fileChange.removedLines;
|
||||
|
||||
file.changedLinesByAuthor[commit.author] = file.changedLinesByAuthor[commit.author]
|
||||
? (file.changedLinesByAuthor[commit.author] + fileChange.changedLines)
|
||||
const changedLinesByAuthor = file.changedLinesByAuthor[commit.author];
|
||||
file.changedLinesByAuthor[commit.author] = changedLinesByAuthor
|
||||
? (changedLinesByAuthor + fileChange.changedLines)
|
||||
: fileChange.changedLines;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ const MASTER_BRANCH = {
|
|||
|
||||
let prevDate = new Date();
|
||||
|
||||
let refTimestampTime = {};
|
||||
|
||||
export default function getCommitInfo(
|
||||
logString: string,
|
||||
refEmailAuthor: IHashMap<string>,
|
||||
|
@ -18,7 +20,7 @@ export default function getCommitInfo(
|
|||
// "2021-02-09T12:59:17+03:00>Frolov Ivan>frolov@mail.ru>profile"
|
||||
const parts = logString.split('>');
|
||||
|
||||
const sourceDate = parts.shift() || '';
|
||||
const sourceDate = parts[0] || '';
|
||||
let date = new Date(sourceDate);
|
||||
if (isNaN(date.getDay())) {
|
||||
console.log(`PARSE ERROR: Date parse error for: "${logString}"`);
|
||||
|
@ -26,11 +28,14 @@ export default function getCommitInfo(
|
|||
}
|
||||
prevDate = date;
|
||||
const day = date.getDay() - 1;
|
||||
const timestamp = sourceDate.split('T')[0];
|
||||
const timestamp = sourceDate.substring(0, 10); // split('T')[0];
|
||||
if (!refTimestampTime[timestamp]) {
|
||||
refTimestampTime[timestamp] = (new Date(timestamp)).getTime();
|
||||
}
|
||||
|
||||
let author = parts.shift()?.replace(/[._]/gm, ' ') || '';
|
||||
let email = parts.shift() || '';
|
||||
if (!(/@/gim).test(email)) email = '';
|
||||
let author = parts[1]?.replace(/[._]/gm, ' ') || '';
|
||||
let email = parts[2] || '';
|
||||
if (email.indexOf('@') === -1) email = '';
|
||||
|
||||
const authorID = author.replace(/\s|\t/gm, '');
|
||||
if (authorID && refEmailAuthor[authorID] && refEmailAuthor[authorID] !== author) {
|
||||
|
@ -52,7 +57,8 @@ export default function getCommitInfo(
|
|||
refEmailAuthor[author] = email;
|
||||
refEmailAuthor[authorID] = author;
|
||||
|
||||
const message = parts.join('>');
|
||||
// performance
|
||||
const message = logString.substring(parts[0]?.length + parts[1]?.length + parts[2]?.length + 3);
|
||||
|
||||
const commonInfo: any = {
|
||||
date: sourceDate,
|
||||
|
@ -64,7 +70,7 @@ export default function getCommitInfo(
|
|||
year: date.getUTCFullYear(),
|
||||
week: 0,
|
||||
timestamp,
|
||||
milliseconds: (new Date(timestamp)).getTime(),
|
||||
milliseconds: refTimestampTime[timestamp],
|
||||
|
||||
author,
|
||||
email,
|
||||
|
@ -99,7 +105,7 @@ export default function getCommitInfo(
|
|||
task = getTask(branch);
|
||||
} else if (isBitbucketPR) {
|
||||
commitType = COMMIT_TYPE.PR_BITBUCKET;
|
||||
const messageParts = message.substring(14, Infinity).split(':');
|
||||
const messageParts = message.substring(14).split(':');
|
||||
prId = messageParts.shift();
|
||||
task = getTask(messageParts.join(':'));
|
||||
} else if (isAutoMerge) {
|
||||
|
|
|
@ -19,7 +19,7 @@ function getFilePath(path: string): string[] {
|
|||
return [oldPath, newPath];
|
||||
}
|
||||
|
||||
// "38 9 src/app.css" -> [38, 9, 9, 'src/app.css']
|
||||
// "38 9 src/app.css" -> [38, 9, 'src/app.css']
|
||||
export function getNumStatInfo(message: string) {
|
||||
let [addedRaw, removedRaw, path] = message.split('\t');
|
||||
|
||||
|
@ -50,16 +50,17 @@ export function getNumStatInfo(message: string) {
|
|||
}
|
||||
// ":000000 100644 000000000 fc44b0a37 A public/logo192.png" -> ['A', 'public/logo192.png']
|
||||
export function getRawInfo(message: string) {
|
||||
const action = message[35];
|
||||
const path = message.split('\t')[1];
|
||||
return { path, action };
|
||||
return {
|
||||
action:message[35],
|
||||
path: message.substring(37),
|
||||
};
|
||||
}
|
||||
|
||||
// "src/AppGit.css" -> { id: 'src/appgit.css', path: 'src/AppGit.css' }
|
||||
export function getInfoFromPath(path: string): IFileChange {
|
||||
const [oldPath, newPath] = getFilePath(path);
|
||||
|
||||
const id = oldPath.toLowerCase();
|
||||
const id = oldPath.toLowerCase(); // TODO: performance
|
||||
const newId = newPath?.toLowerCase();
|
||||
|
||||
return {
|
||||
|
|
|
@ -47,7 +47,7 @@ function getMenu(navigate: Function): any[] {
|
|||
confirm.open({
|
||||
title: 'Вы уверены что хотите выйти?',
|
||||
}).then(() => {
|
||||
dataGripStore.setCommits([]);
|
||||
dataGripStore.asyncSetCommits([]);
|
||||
navigate('/');
|
||||
});
|
||||
},
|
||||
|
|
|
@ -82,7 +82,7 @@ const Money = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
) : (
|
||||
<div>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={taskNumber
|
||||
? getShortMoney(statistic.moneyWorked / taskNumber, 0)
|
||||
: null}
|
||||
|
@ -91,7 +91,7 @@ const Money = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
description="page.person.money.tasks.description"
|
||||
/>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={taskNumber
|
||||
? getShortMoney(statistic.moneyWorked / statistic.commits, 0)
|
||||
: null}
|
||||
|
|
|
@ -65,14 +65,14 @@ const Speed = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
<Title title="page.person.speed.max"/>
|
||||
<div>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={byTimestamp.tasksByTimestampCounter.max}
|
||||
icon="./assets/cards/tasks.png"
|
||||
title="page.person.speed.tasks.title"
|
||||
description="page.person.speed.tasks.description"
|
||||
/>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={byTimestamp.commitsByTimestampCounter.max}
|
||||
icon="./assets/cards/commits.png"
|
||||
title="page.person.speed.maxCommits.title"
|
||||
|
|
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||
|
||||
import achievementByAuthor from 'ts/helpers/achievement/byCompetition';
|
||||
import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
|
||||
import { getDate } from 'ts/helpers/formatter';
|
||||
|
||||
import CardWithIcon from 'ts/components/CardWithIcon';
|
||||
import CardWithBanner from 'ts/components/CardWithIcon/components/Banner';
|
||||
|
@ -48,6 +49,20 @@ const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
<PageColumn>
|
||||
<Title title="page.person.total.title"/>
|
||||
<div>
|
||||
{false && (
|
||||
<>
|
||||
<CardWithIcon
|
||||
size="s"
|
||||
value={getDate(statistic.firstCommit.timestamp)}
|
||||
title="page.team.tasks.from"
|
||||
/>
|
||||
<CardWithIcon
|
||||
size="s"
|
||||
value={getDate(statistic.lastCommit.timestamp)}
|
||||
title="page.team.tasks.to"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<CardWithIcon
|
||||
value={statistic.daysWorked}
|
||||
icon="./assets/cards/work_days.png"
|
||||
|
@ -88,7 +103,7 @@ const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
total: scoringTotal.commits,
|
||||
}}
|
||||
/>
|
||||
<CardWithBanner long />
|
||||
<CardWithBanner size="l" />
|
||||
</div>
|
||||
{false && <Title title="page.person.character.title"/>}
|
||||
{false && <Character user={statistic} />}
|
||||
|
|
|
@ -54,7 +54,7 @@ const Total = observer((): React.ReactElement => {
|
|||
description="page.team.total.employment.description"
|
||||
/>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={workSpeed}
|
||||
icon="./assets/cards/tasks_month.png"
|
||||
title="page.team.total.workSpeed.title"
|
||||
|
@ -99,7 +99,7 @@ const Total = observer((): React.ReactElement => {
|
|||
description="page.team.total.weekendPayment.description"
|
||||
/>
|
||||
<CardWithIcon
|
||||
long
|
||||
size="l"
|
||||
value={getShortMoney(moneySpeed)}
|
||||
icon="./assets/cards/money_month.png"
|
||||
title="page.team.total.moneySpeed.title"
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
|
||||
import Console from 'ts/components/Console';
|
||||
import Description from 'ts/components/Description';
|
||||
import splashScreenStore from 'ts/components/SplashScreen/store';
|
||||
import {
|
||||
getStringFromFileList,
|
||||
getStringsForParser,
|
||||
|
@ -60,7 +61,8 @@ function Welcome() {
|
|||
const files = Array.from(event.target.files);
|
||||
const text = await getStringFromFileList(files);
|
||||
const report = getStringsForParser(text);
|
||||
dataGripStore.setCommits(report);
|
||||
splashScreenStore.show();
|
||||
dataGripStore.asyncSetCommits(report);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore, { DataParseStatusEnum } from 'ts/store/DataGrip';
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import viewNameStore, { ViewNameEnum } from 'ts/store/ViewName';
|
||||
import DropZone from 'ts/components/DropZone';
|
||||
import Sponsor from 'ts/components/Sponsor';
|
||||
import SplashScreen from 'ts/components/SplashScreen';
|
||||
|
@ -16,11 +17,7 @@ import Welcome from './Welcome/index';
|
|||
import Settings from './Settings/index';
|
||||
import DebugPage from './Debug/index';
|
||||
|
||||
interface IViewWithChartsProps {
|
||||
showSplashScreen: boolean;
|
||||
}
|
||||
|
||||
function ViewWithCharts({ showSplashScreen }: IViewWithChartsProps) {
|
||||
function ViewWithCharts() {
|
||||
return (
|
||||
<>
|
||||
<Sponsor />
|
||||
|
@ -75,7 +72,6 @@ function ViewWithCharts({ showSplashScreen }: IViewWithChartsProps) {
|
|||
)}
|
||||
/>
|
||||
</Routes>
|
||||
{showSplashScreen && <SplashScreen />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -94,36 +90,38 @@ function ViewWithWelcome() {
|
|||
}
|
||||
|
||||
const Main = observer(() => {
|
||||
const [showSplashScreen, setShowSplashScreen] = useState<boolean>(true);
|
||||
const status = dataGripStore.status;
|
||||
const view = viewNameStore.view;
|
||||
|
||||
useEffect(() => {
|
||||
// @ts-ignore
|
||||
dataGripStore.setCommits(window?.report || []);
|
||||
const list = window?.report || [];
|
||||
if (list?.length) {
|
||||
dataGripStore.asyncSetCommits(list);
|
||||
} else {
|
||||
viewNameStore.toggle(ViewNameEnum.WELCOME);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (status !== DataParseStatusEnum.DONE || window.location.hash) return;
|
||||
if (view !== ViewNameEnum.INFO || window.location.hash) return;
|
||||
window.location.hash = '#/team/total';
|
||||
}, [status]);
|
||||
}, [view]);
|
||||
|
||||
if (status === DataParseStatusEnum.PROCESSING) return null;
|
||||
if (view === ViewNameEnum.EMPTY) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{status === DataParseStatusEnum.DONE && (
|
||||
<ViewWithCharts showSplashScreen={showSplashScreen} />
|
||||
)}
|
||||
{status === DataParseStatusEnum.WAITING && (
|
||||
{view === ViewNameEnum.WELCOME && (
|
||||
<ViewWithWelcome />
|
||||
)}
|
||||
{view === ViewNameEnum.INFO && (
|
||||
<ViewWithCharts />
|
||||
)}
|
||||
<SplashScreen />
|
||||
<DropZone
|
||||
onChange={(type: string, data: any[]) => {
|
||||
setShowSplashScreen(false);
|
||||
if (type === 'dump') dataGripStore.setCommits(data);
|
||||
setTimeout(() => {
|
||||
setShowSplashScreen(true);
|
||||
});
|
||||
if (type !== 'dump') return;
|
||||
dataGripStore.asyncSetCommits(data);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { makeObservable, observable, action } from 'mobx';
|
||||
import { action, makeObservable, observable } from 'mobx';
|
||||
|
||||
import ICommit, { ISystemCommit } from 'ts/interfaces/Commit';
|
||||
|
||||
|
@ -9,27 +9,16 @@ import Parser from 'ts/helpers/Parser';
|
|||
import getTitle from 'ts/helpers/Title';
|
||||
|
||||
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
|
||||
import splashScreenStore from 'ts/components/SplashScreen/store';
|
||||
import { applicationHasCustom } from 'ts/helpers/RPC';
|
||||
import Depersonalized from 'ts/helpers/Depersonalized';
|
||||
|
||||
import filtersInHeaderStore from './FiltersInHeader';
|
||||
import viewNameStore, { ViewNameEnum } from './ViewName';
|
||||
|
||||
export enum DataParseStatusEnum {
|
||||
WAITING = 'waiting',
|
||||
PROCESSING = 'processing',
|
||||
DONE = 'done',
|
||||
}
|
||||
const PROCESSING_DELAY = 300;
|
||||
|
||||
interface IDataGripStore {
|
||||
commits: ICommit[];
|
||||
dataGrip: any;
|
||||
fileGrip: any;
|
||||
status: DataParseStatusEnum;
|
||||
isDepersonalized: boolean;
|
||||
setCommits: (log?: string[]) => void;
|
||||
}
|
||||
|
||||
class DataGripStore implements IDataGripStore {
|
||||
class DataGripStore {
|
||||
commits: any[] = [];
|
||||
|
||||
dataGrip: any = null;
|
||||
|
@ -40,55 +29,66 @@ class DataGripStore implements IDataGripStore {
|
|||
|
||||
isDepersonalized: boolean = false;
|
||||
|
||||
status: DataParseStatusEnum = DataParseStatusEnum.PROCESSING;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
commits: observable,
|
||||
dataGrip: observable,
|
||||
fileGrip: observable,
|
||||
hash: observable,
|
||||
isDepersonalized: observable,
|
||||
status: observable,
|
||||
setCommits: action,
|
||||
asyncSetCommits: action,
|
||||
processingStep01: action,
|
||||
processingStep03: action,
|
||||
depersonalized: action,
|
||||
updateStatistic: action,
|
||||
});
|
||||
}
|
||||
|
||||
setCommits(dump?: string[]) {
|
||||
asyncSetCommits(dump?: string[]) {
|
||||
if (!dump?.length) return;
|
||||
splashScreenStore.show();
|
||||
setTimeout(() => this.processingStep01(dump), PROCESSING_DELAY);
|
||||
}
|
||||
|
||||
processingStep01(dump?: string[]) {
|
||||
dataGrip.clear();
|
||||
fileGrip.clear();
|
||||
|
||||
const commits = Parser(dump || []);
|
||||
if (!commits.length) {
|
||||
splashScreenStore.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => this.processingStep02(commits), PROCESSING_DELAY);
|
||||
}
|
||||
|
||||
processingStep02(commits: (ICommit | ISystemCommit)[]) {
|
||||
commits.sort((a, b) => a.milliseconds - b.milliseconds);
|
||||
commits.forEach((commit: ICommit | ISystemCommit) => {
|
||||
dataGrip.addCommit(commit);
|
||||
fileGrip.addCommit(commit);
|
||||
});
|
||||
fileGrip.updateTotalInfo();
|
||||
|
||||
setTimeout(() => this.processingStep03(commits), PROCESSING_DELAY);
|
||||
}
|
||||
|
||||
processingStep03(commits: (ICommit | ISystemCommit)[]) {
|
||||
fileGrip.updateTotalInfo();
|
||||
this.commits = commits;
|
||||
|
||||
this.status = this.commits.length
|
||||
? DataParseStatusEnum.DONE
|
||||
: DataParseStatusEnum.WAITING;
|
||||
filtersInHeaderStore.updateByCommits(
|
||||
dataGrip.firstLastCommit.minData,
|
||||
dataGrip.firstLastCommit.maxData,
|
||||
);
|
||||
setDefaultValues(dataGrip.firstLastCommit.minData, dataGrip.firstLastCommit.maxData);
|
||||
|
||||
if (this.status === DataParseStatusEnum.DONE) {
|
||||
filtersInHeaderStore.updateByCommits(
|
||||
dataGrip.firstLastCommit.minData,
|
||||
dataGrip.firstLastCommit.maxData,
|
||||
);
|
||||
setDefaultValues(dataGrip.firstLastCommit.minData, dataGrip.firstLastCommit.maxData);
|
||||
|
||||
dataGrip.updateTotalInfo();
|
||||
achievements.updateByGrip(dataGrip, fileGrip);
|
||||
}
|
||||
dataGrip.updateTotalInfo();
|
||||
achievements.updateByGrip(dataGrip, fileGrip);
|
||||
|
||||
viewNameStore.toggle(ViewNameEnum.INFO);
|
||||
this.#updateRender();
|
||||
|
||||
console.dir(this.dataGrip);
|
||||
console.dir(this.fileGrip);
|
||||
if (!applicationHasCustom.title) {
|
||||
document.title = getTitle(this.dataGrip, this.fileGrip, this.commits);
|
||||
}
|
||||
|
|
26
src/ts/store/ViewName.tsx
Normal file
26
src/ts/store/ViewName.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { observable, action, makeObservable } from 'mobx';
|
||||
|
||||
export enum ViewNameEnum {
|
||||
EMPTY = 'empty',
|
||||
WELCOME = 'welcome',
|
||||
INFO = 'info',
|
||||
}
|
||||
|
||||
class ViewNameStore {
|
||||
view: ViewNameEnum = ViewNameEnum.EMPTY;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
view: observable,
|
||||
toggle: action,
|
||||
});
|
||||
}
|
||||
|
||||
toggle(view: ViewNameEnum) {
|
||||
this.view = view;
|
||||
}
|
||||
}
|
||||
|
||||
const viewNameStore = new ViewNameStore();
|
||||
|
||||
export default viewNameStore;
|
Loading…
Reference in a new issue