This commit is contained in:
bakhirev 2024-08-14 00:56:49 +03:00
parent 5d890b4848
commit 72d3c59f30
18 changed files with 250 additions and 145 deletions

View file

@ -5,23 +5,24 @@ import Banner from 'ts/components/Banner';
import style from '../index.module.scss'; import style from '../index.module.scss';
interface ICardWithBannerProps { interface ICardWithBannerProps {
long?: boolean; size?: 's' | 'm' | 'l';
} }
function CardWithBanner({ function CardWithBanner({ size }: ICardWithBannerProps): React.ReactElement | null {
long = false, const className = [
}: ICardWithBannerProps): React.ReactElement | null { style.card_with_icon,
const className = long style.card_with_icon_banner,
? style.card_with_icon_long ];
: 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 ( return (
<Banner className={`${className} ${style.card_with_icon_banner}`} /> <Banner className={className.join(' ')} />
); );
} }
CardWithBanner.defaultProps = { CardWithBanner.defaultProps = {
long: false, size: 'm',
}; };
export default CardWithBanner; export default CardWithBanner;

View file

@ -15,6 +15,7 @@ function Scoring({
total, total,
}: IScoringProps): React.ReactElement | null { }: IScoringProps): React.ReactElement | null {
const { t } = useTranslation(); const { t } = useTranslation();
if (!value) return null; if (!value) return null;
return ( return (

View file

@ -1,14 +1,13 @@
@import 'src/styles/variables'; @import 'src/styles/variables';
.card_with_icon, .card_with_icon {
.card_with_icon_long {
position: relative; position: relative;
display: inline-block; display: inline-block;
width: calc(50% - 12px); width: calc(50% - 12px);
min-height: 270px; min-height: 270px;
margin: 0 24px 24px 0; margin: 0 var(--space-xxl) var(--space-xxl) 0;
padding: 16px; padding: var(--space-l);
vertical-align: top; vertical-align: top;
text-decoration: none; text-decoration: none;
@ -35,10 +34,13 @@
&_value { &_value {
font-weight: bold; font-weight: bold;
font-size: 28px; font-size: 28px;
display: block; display: block;
margin: 0 0 4px 0; margin: 0 0 var(--space-xxs) 0;
padding: 0; padding: 0;
text-align: center; text-align: center;
color: var(--color-11); color: var(--color-11);
} }
@ -46,19 +48,22 @@
&_description, &_description,
&_scoring { &_scoring {
font-weight: 100; font-weight: 100;
display: block; display: block;
margin: 0 auto; margin: 0 auto;
padding: 0; padding: 0;
line-height: 1.3; line-height: 1.3;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
color: var(--color-black); color: var(--color-black);
} }
&_title { &_title {
font-size: var(--font-m); font-size: var(--font-m);
line-height: 14px; line-height: 14px;
margin: 0 0 4px 0; margin: 0 0 var(--space-xxs) 0;
} }
&_description, &_description,
@ -68,12 +73,6 @@
color: var(--color-grey); color: var(--color-grey);
} }
&_banner {
font-size: 32px;
padding: 0;
line-height: 270px;
}
&_scoring { &_scoring {
position: absolute; position: absolute;
bottom: -11px; bottom: -11px;
@ -82,6 +81,7 @@
display: inline-block; display: inline-block;
padding: var(--space-xxxs) var(--space-xs); padding: var(--space-xxxs) var(--space-xs);
white-space: nowrap; white-space: nowrap;
text-align: center; text-align: center;
@ -89,11 +89,31 @@
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
background-color: var(--color-white); 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 { .card_with_icon_small {
width: 100%; .card_with_icon_value {
margin: 0 0 24px 0; 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) { .card_with_icon:nth-child(2n+2) {
@ -101,10 +121,9 @@
} }
@media (max-width: 900px) { @media (max-width: 900px) {
.card_with_icon, .card_with_icon {
.card_with_icon_long {
min-height: 220px; min-height: 220px;
padding: 16px 0; padding: var(--space-l) 0;
&_title { &_title {
margin: 0; margin: 0;
@ -117,8 +136,7 @@
} }
@media (max-width: 650px) { @media (max-width: 650px) {
.card_with_icon, .card_with_icon {
.card_with_icon_long {
min-height: 190px; min-height: 190px;
padding: 32px 0; padding: 32px 0;
@ -139,10 +157,9 @@
} }
@media print { @media print {
.card_with_icon, .card_with_icon {
.card_with_icon_long {
min-height: 220px; min-height: 220px;
padding: 16px 0; padding: var(--space-l) 0;
&_icon { &_icon {
height: 60px; height: 60px;
@ -155,7 +172,7 @@
&_title { &_title {
font-size: var(--font-s); font-size: var(--font-s);
margin: 0 0 8px 0; margin: 0 0 var(--space-s) 0;
} }
&_description { &_description {

View file

@ -10,9 +10,8 @@ interface ICardWithIconProps {
description?: string; description?: string;
value: number | string | null; value: number | string | null;
suffix?: string; suffix?: string;
color?: string;
icon?: string; icon?: string;
long?: boolean; size?: 's' | 'm' | 'l';
scoring?: IScoringProps; scoring?: IScoringProps;
} }
@ -21,43 +20,47 @@ function CardWithIcon({
description, description,
value, value,
suffix, suffix,
color,
icon, icon,
long = false, size,
scoring, scoring,
}: ICardWithIconProps): React.ReactElement | null { }: ICardWithIconProps): React.ReactElement | null {
const { t } = useTranslation(); const { t } = useTranslation();
if (!value && value !== 0) return null; 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 ( return (
<figure className={long <figure className={className.join(' ')}>
? style.card_with_icon_long
: style.card_with_icon}>
{icon && ( {icon && (
<img <img
className={style.card_with_icon_icon} className={style.card_with_icon_icon}
src={icon} src={icon}
/> />
)} )}
<p
className={style.card_with_icon_value} <p className={style.card_with_icon_value}>
style={{ color: color || '' }}
>
{value} {value}
{suffix || ''} {suffix || ''}
</p> </p>
<h4 className={style.card_with_icon_title}> <h4 className={style.card_with_icon_title}>
{t(title || '')} {t(title || '')}
</h4> </h4>
<figcaption className={style.card_with_icon_description}> <figcaption className={style.card_with_icon_description}>
{t(description || '')} {t(description || '')}
</figcaption> </figcaption>
<Scoring
title={scoring?.title} {scoring ? (
value={scoring?.value} <Scoring
total={scoring?.total} title={scoring?.title}
/> value={scoring?.value}
total={scoring?.total}
/>
) : null}
</figure> </figure>
); );
} }
@ -65,9 +68,8 @@ function CardWithIcon({
CardWithIcon.defaultProps = { CardWithIcon.defaultProps = {
description: '', description: '',
suffix: '', suffix: '',
color: undefined,
icon: undefined, icon: undefined,
long: false, size: 'm',
scoring: undefined, scoring: undefined,
}; };

View file

@ -1,16 +1,21 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { observer } from 'mobx-react-lite';
import Logo from 'ts/pages/PageWrapper/components/sidebar/Logo'; 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 style from './index.module.scss';
import progress from './progress.module.scss'; import progress from './progress.module.scss';
function SplashScreen(): React.ReactElement | null { const SplashScreen = observer((): React.ReactElement | null => {
useEffect(() => { useEffect(() => {
globalScroll.off(5400); if (!splashScreenStore.isOpen) return;
}, []); setTimeout(() => {
splashScreenStore.hide();
}, 5400);
}, [splashScreenStore.isOpen]);
if (!splashScreenStore.isOpen) return null;
return ( return (
<div className={style.splash_screen}> <div className={style.splash_screen}>
@ -20,6 +25,6 @@ function SplashScreen(): React.ReactElement | null {
</div> </div>
</div> </div>
); );
} });
export default SplashScreen; export default SplashScreen;

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

View file

@ -26,16 +26,20 @@ export default class FileBuilderLineStat {
file.removedLines += fileChange.removedLines; file.removedLines += fileChange.removedLines;
file.changedLines += fileChange.changedLines; file.changedLines += fileChange.changedLines;
file.addedLinesByAuthor[commit.author] = file.addedLinesByAuthor[commit.author] // TODO: performance
? (file.addedLinesByAuthor[commit.author] + fileChange.addedLines) const addedLinesByAuthor = file.addedLinesByAuthor[commit.author];
file.addedLinesByAuthor[commit.author] = addedLinesByAuthor
? (addedLinesByAuthor + fileChange.addedLines)
: fileChange.addedLines; : fileChange.addedLines;
file.removedLinesByAuthor[commit.author] = file.removedLinesByAuthor[commit.author] const removedLinesByAuthor = file.removedLinesByAuthor[commit.author];
? (file.removedLinesByAuthor[commit.author] + fileChange.removedLines) file.removedLinesByAuthor[commit.author] = removedLinesByAuthor
? (removedLinesByAuthor + fileChange.removedLines)
: fileChange.removedLines; : fileChange.removedLines;
file.changedLinesByAuthor[commit.author] = file.changedLinesByAuthor[commit.author] const changedLinesByAuthor = file.changedLinesByAuthor[commit.author];
? (file.changedLinesByAuthor[commit.author] + fileChange.changedLines) file.changedLinesByAuthor[commit.author] = changedLinesByAuthor
? (changedLinesByAuthor + fileChange.changedLines)
: fileChange.changedLines; : fileChange.changedLines;
} }

View file

@ -11,6 +11,8 @@ const MASTER_BRANCH = {
let prevDate = new Date(); let prevDate = new Date();
let refTimestampTime = {};
export default function getCommitInfo( export default function getCommitInfo(
logString: string, logString: string,
refEmailAuthor: IHashMap<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" // "2021-02-09T12:59:17+03:00>Frolov Ivan>frolov@mail.ru>profile"
const parts = logString.split('>'); const parts = logString.split('>');
const sourceDate = parts.shift() || ''; const sourceDate = parts[0] || '';
let date = new Date(sourceDate); let date = new Date(sourceDate);
if (isNaN(date.getDay())) { if (isNaN(date.getDay())) {
console.log(`PARSE ERROR: Date parse error for: "${logString}"`); console.log(`PARSE ERROR: Date parse error for: "${logString}"`);
@ -26,11 +28,14 @@ export default function getCommitInfo(
} }
prevDate = date; prevDate = date;
const day = date.getDay() - 1; 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 author = parts[1]?.replace(/[._]/gm, ' ') || '';
let email = parts.shift() || ''; let email = parts[2] || '';
if (!(/@/gim).test(email)) email = ''; if (email.indexOf('@') === -1) email = '';
const authorID = author.replace(/\s|\t/gm, ''); const authorID = author.replace(/\s|\t/gm, '');
if (authorID && refEmailAuthor[authorID] && refEmailAuthor[authorID] !== author) { if (authorID && refEmailAuthor[authorID] && refEmailAuthor[authorID] !== author) {
@ -52,7 +57,8 @@ export default function getCommitInfo(
refEmailAuthor[author] = email; refEmailAuthor[author] = email;
refEmailAuthor[authorID] = author; 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 = { const commonInfo: any = {
date: sourceDate, date: sourceDate,
@ -64,7 +70,7 @@ export default function getCommitInfo(
year: date.getUTCFullYear(), year: date.getUTCFullYear(),
week: 0, week: 0,
timestamp, timestamp,
milliseconds: (new Date(timestamp)).getTime(), milliseconds: refTimestampTime[timestamp],
author, author,
email, email,
@ -99,7 +105,7 @@ export default function getCommitInfo(
task = getTask(branch); task = getTask(branch);
} else if (isBitbucketPR) { } else if (isBitbucketPR) {
commitType = COMMIT_TYPE.PR_BITBUCKET; commitType = COMMIT_TYPE.PR_BITBUCKET;
const messageParts = message.substring(14, Infinity).split(':'); const messageParts = message.substring(14).split(':');
prId = messageParts.shift(); prId = messageParts.shift();
task = getTask(messageParts.join(':')); task = getTask(messageParts.join(':'));
} else if (isAutoMerge) { } else if (isAutoMerge) {

View file

@ -19,7 +19,7 @@ function getFilePath(path: string): string[] {
return [oldPath, newPath]; 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) { export function getNumStatInfo(message: string) {
let [addedRaw, removedRaw, path] = message.split('\t'); 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'] // ":000000 100644 000000000 fc44b0a37 A public/logo192.png" -> ['A', 'public/logo192.png']
export function getRawInfo(message: string) { export function getRawInfo(message: string) {
const action = message[35]; return {
const path = message.split('\t')[1]; action:message[35],
return { path, action }; path: message.substring(37),
};
} }
// "src/AppGit.css" -> { id: 'src/appgit.css', path: 'src/AppGit.css' } // "src/AppGit.css" -> { id: 'src/appgit.css', path: 'src/AppGit.css' }
export function getInfoFromPath(path: string): IFileChange { export function getInfoFromPath(path: string): IFileChange {
const [oldPath, newPath] = getFilePath(path); const [oldPath, newPath] = getFilePath(path);
const id = oldPath.toLowerCase(); const id = oldPath.toLowerCase(); // TODO: performance
const newId = newPath?.toLowerCase(); const newId = newPath?.toLowerCase();
return { return {

View file

@ -47,7 +47,7 @@ function getMenu(navigate: Function): any[] {
confirm.open({ confirm.open({
title: 'Вы уверены что хотите выйти?', title: 'Вы уверены что хотите выйти?',
}).then(() => { }).then(() => {
dataGripStore.setCommits([]); dataGripStore.asyncSetCommits([]);
navigate('/'); navigate('/');
}); });
}, },

View file

@ -82,7 +82,7 @@ const Money = observer(({ user }: IPersonCommonProps): React.ReactElement => {
) : ( ) : (
<div> <div>
<CardWithIcon <CardWithIcon
long size="l"
value={taskNumber value={taskNumber
? getShortMoney(statistic.moneyWorked / taskNumber, 0) ? getShortMoney(statistic.moneyWorked / taskNumber, 0)
: null} : null}
@ -91,7 +91,7 @@ const Money = observer(({ user }: IPersonCommonProps): React.ReactElement => {
description="page.person.money.tasks.description" description="page.person.money.tasks.description"
/> />
<CardWithIcon <CardWithIcon
long size="l"
value={taskNumber value={taskNumber
? getShortMoney(statistic.moneyWorked / statistic.commits, 0) ? getShortMoney(statistic.moneyWorked / statistic.commits, 0)
: null} : null}

View file

@ -65,14 +65,14 @@ const Speed = observer(({ user }: IPersonCommonProps): React.ReactElement => {
<Title title="page.person.speed.max"/> <Title title="page.person.speed.max"/>
<div> <div>
<CardWithIcon <CardWithIcon
long size="l"
value={byTimestamp.tasksByTimestampCounter.max} value={byTimestamp.tasksByTimestampCounter.max}
icon="./assets/cards/tasks.png" icon="./assets/cards/tasks.png"
title="page.person.speed.tasks.title" title="page.person.speed.tasks.title"
description="page.person.speed.tasks.description" description="page.person.speed.tasks.description"
/> />
<CardWithIcon <CardWithIcon
long size="l"
value={byTimestamp.commitsByTimestampCounter.max} value={byTimestamp.commitsByTimestampCounter.max}
icon="./assets/cards/commits.png" icon="./assets/cards/commits.png"
title="page.person.speed.maxCommits.title" title="page.person.speed.maxCommits.title"

View file

@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import achievementByAuthor from 'ts/helpers/achievement/byCompetition'; import achievementByAuthor from 'ts/helpers/achievement/byCompetition';
import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type'; import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
import { getDate } from 'ts/helpers/formatter';
import CardWithIcon from 'ts/components/CardWithIcon'; import CardWithIcon from 'ts/components/CardWithIcon';
import CardWithBanner from 'ts/components/CardWithIcon/components/Banner'; import CardWithBanner from 'ts/components/CardWithIcon/components/Banner';
@ -48,6 +49,20 @@ const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
<PageColumn> <PageColumn>
<Title title="page.person.total.title"/> <Title title="page.person.total.title"/>
<div> <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 <CardWithIcon
value={statistic.daysWorked} value={statistic.daysWorked}
icon="./assets/cards/work_days.png" icon="./assets/cards/work_days.png"
@ -88,7 +103,7 @@ const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
total: scoringTotal.commits, total: scoringTotal.commits,
}} }}
/> />
<CardWithBanner long /> <CardWithBanner size="l" />
</div> </div>
{false && <Title title="page.person.character.title"/>} {false && <Title title="page.person.character.title"/>}
{false && <Character user={statistic} />} {false && <Character user={statistic} />}

View file

@ -54,7 +54,7 @@ const Total = observer((): React.ReactElement => {
description="page.team.total.employment.description" description="page.team.total.employment.description"
/> />
<CardWithIcon <CardWithIcon
long size="l"
value={workSpeed} value={workSpeed}
icon="./assets/cards/tasks_month.png" icon="./assets/cards/tasks_month.png"
title="page.team.total.workSpeed.title" title="page.team.total.workSpeed.title"
@ -99,7 +99,7 @@ const Total = observer((): React.ReactElement => {
description="page.team.total.weekendPayment.description" description="page.team.total.weekendPayment.description"
/> />
<CardWithIcon <CardWithIcon
long size="l"
value={getShortMoney(moneySpeed)} value={getShortMoney(moneySpeed)}
icon="./assets/cards/money_month.png" icon="./assets/cards/money_month.png"
title="page.team.total.moneySpeed.title" title="page.team.total.moneySpeed.title"

View file

@ -2,6 +2,7 @@ import React from 'react';
import Console from 'ts/components/Console'; import Console from 'ts/components/Console';
import Description from 'ts/components/Description'; import Description from 'ts/components/Description';
import splashScreenStore from 'ts/components/SplashScreen/store';
import { import {
getStringFromFileList, getStringFromFileList,
getStringsForParser, getStringsForParser,
@ -60,7 +61,8 @@ function Welcome() {
const files = Array.from(event.target.files); const files = Array.from(event.target.files);
const text = await getStringFromFileList(files); const text = await getStringFromFileList(files);
const report = getStringsForParser(text); const report = getStringsForParser(text);
dataGripStore.setCommits(report); splashScreenStore.show();
dataGripStore.asyncSetCommits(report);
}} }}
/> />
</label> </label>

View file

@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect } from 'react';
import { Route, Routes } from 'react-router-dom'; import { Route, Routes } from 'react-router-dom';
import { observer } from 'mobx-react-lite'; 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 DropZone from 'ts/components/DropZone';
import Sponsor from 'ts/components/Sponsor'; import Sponsor from 'ts/components/Sponsor';
import SplashScreen from 'ts/components/SplashScreen'; import SplashScreen from 'ts/components/SplashScreen';
@ -16,11 +17,7 @@ import Welcome from './Welcome/index';
import Settings from './Settings/index'; import Settings from './Settings/index';
import DebugPage from './Debug/index'; import DebugPage from './Debug/index';
interface IViewWithChartsProps { function ViewWithCharts() {
showSplashScreen: boolean;
}
function ViewWithCharts({ showSplashScreen }: IViewWithChartsProps) {
return ( return (
<> <>
<Sponsor /> <Sponsor />
@ -75,7 +72,6 @@ function ViewWithCharts({ showSplashScreen }: IViewWithChartsProps) {
)} )}
/> />
</Routes> </Routes>
{showSplashScreen && <SplashScreen />}
</> </>
); );
} }
@ -94,36 +90,38 @@ function ViewWithWelcome() {
} }
const Main = observer(() => { const Main = observer(() => {
const [showSplashScreen, setShowSplashScreen] = useState<boolean>(true); const view = viewNameStore.view;
const status = dataGripStore.status;
useEffect(() => { useEffect(() => {
// @ts-ignore // @ts-ignore
dataGripStore.setCommits(window?.report || []); const list = window?.report || [];
if (list?.length) {
dataGripStore.asyncSetCommits(list);
} else {
viewNameStore.toggle(ViewNameEnum.WELCOME);
}
}, []); }, []);
useEffect(() => { useEffect(() => {
if (status !== DataParseStatusEnum.DONE || window.location.hash) return; if (view !== ViewNameEnum.INFO || window.location.hash) return;
window.location.hash = '#/team/total'; window.location.hash = '#/team/total';
}, [status]); }, [view]);
if (status === DataParseStatusEnum.PROCESSING) return null; if (view === ViewNameEnum.EMPTY) return null;
return ( return (
<> <>
{status === DataParseStatusEnum.DONE && ( {view === ViewNameEnum.WELCOME && (
<ViewWithCharts showSplashScreen={showSplashScreen} />
)}
{status === DataParseStatusEnum.WAITING && (
<ViewWithWelcome /> <ViewWithWelcome />
)} )}
{view === ViewNameEnum.INFO && (
<ViewWithCharts />
)}
<SplashScreen />
<DropZone <DropZone
onChange={(type: string, data: any[]) => { onChange={(type: string, data: any[]) => {
setShowSplashScreen(false); if (type !== 'dump') return;
if (type === 'dump') dataGripStore.setCommits(data); dataGripStore.asyncSetCommits(data);
setTimeout(() => {
setShowSplashScreen(true);
});
}} }}
/> />
</> </>

View file

@ -1,4 +1,4 @@
import { makeObservable, observable, action } from 'mobx'; import { action, makeObservable, observable } from 'mobx';
import ICommit, { ISystemCommit } from 'ts/interfaces/Commit'; import ICommit, { ISystemCommit } from 'ts/interfaces/Commit';
@ -9,27 +9,16 @@ import Parser from 'ts/helpers/Parser';
import getTitle from 'ts/helpers/Title'; import getTitle from 'ts/helpers/Title';
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings'; import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
import splashScreenStore from 'ts/components/SplashScreen/store';
import { applicationHasCustom } from 'ts/helpers/RPC'; import { applicationHasCustom } from 'ts/helpers/RPC';
import Depersonalized from 'ts/helpers/Depersonalized'; import Depersonalized from 'ts/helpers/Depersonalized';
import filtersInHeaderStore from './FiltersInHeader'; import filtersInHeaderStore from './FiltersInHeader';
import viewNameStore, { ViewNameEnum } from './ViewName';
export enum DataParseStatusEnum { const PROCESSING_DELAY = 300;
WAITING = 'waiting',
PROCESSING = 'processing',
DONE = 'done',
}
interface IDataGripStore { class DataGripStore {
commits: ICommit[];
dataGrip: any;
fileGrip: any;
status: DataParseStatusEnum;
isDepersonalized: boolean;
setCommits: (log?: string[]) => void;
}
class DataGripStore implements IDataGripStore {
commits: any[] = []; commits: any[] = [];
dataGrip: any = null; dataGrip: any = null;
@ -40,55 +29,66 @@ class DataGripStore implements IDataGripStore {
isDepersonalized: boolean = false; isDepersonalized: boolean = false;
status: DataParseStatusEnum = DataParseStatusEnum.PROCESSING;
constructor() { constructor() {
makeObservable(this, { makeObservable(this, {
commits: observable,
dataGrip: observable, dataGrip: observable,
fileGrip: observable,
hash: observable, hash: observable,
isDepersonalized: observable, isDepersonalized: observable,
status: observable, asyncSetCommits: action,
setCommits: action, processingStep01: action,
processingStep03: action,
depersonalized: action, depersonalized: action,
updateStatistic: 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(); dataGrip.clear();
fileGrip.clear(); fileGrip.clear();
const commits = Parser(dump || []); 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.sort((a, b) => a.milliseconds - b.milliseconds);
commits.forEach((commit: ICommit | ISystemCommit) => { commits.forEach((commit: ICommit | ISystemCommit) => {
dataGrip.addCommit(commit); dataGrip.addCommit(commit);
fileGrip.addCommit(commit); fileGrip.addCommit(commit);
}); });
fileGrip.updateTotalInfo();
setTimeout(() => this.processingStep03(commits), PROCESSING_DELAY);
}
processingStep03(commits: (ICommit | ISystemCommit)[]) {
fileGrip.updateTotalInfo();
this.commits = commits; this.commits = commits;
this.status = this.commits.length filtersInHeaderStore.updateByCommits(
? DataParseStatusEnum.DONE dataGrip.firstLastCommit.minData,
: DataParseStatusEnum.WAITING; dataGrip.firstLastCommit.maxData,
);
setDefaultValues(dataGrip.firstLastCommit.minData, dataGrip.firstLastCommit.maxData);
if (this.status === DataParseStatusEnum.DONE) { dataGrip.updateTotalInfo();
filtersInHeaderStore.updateByCommits( achievements.updateByGrip(dataGrip, fileGrip);
dataGrip.firstLastCommit.minData,
dataGrip.firstLastCommit.maxData,
);
setDefaultValues(dataGrip.firstLastCommit.minData, dataGrip.firstLastCommit.maxData);
dataGrip.updateTotalInfo();
achievements.updateByGrip(dataGrip, fileGrip);
}
viewNameStore.toggle(ViewNameEnum.INFO);
this.#updateRender(); this.#updateRender();
console.dir(this.dataGrip); console.dir(this.dataGrip);
console.dir(this.fileGrip);
if (!applicationHasCustom.title) { if (!applicationHasCustom.title) {
document.title = getTitle(this.dataGrip, this.fileGrip, this.commits); document.title = getTitle(this.dataGrip, this.fileGrip, this.commits);
} }

26
src/ts/store/ViewName.tsx Normal file
View 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;