mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
SOME-123 test(test): test
This commit is contained in:
parent
196d6ff75e
commit
81f81a86dd
|
@ -34,9 +34,7 @@ function DataView({
|
|||
}: IDataViewProps): React.ReactElement | null {
|
||||
const urlParams = useParams<any>();
|
||||
const defaultType = viewSettings.getItem(urlParams, 'table');
|
||||
console.log(defaultType);
|
||||
const [localType, setType] = useState<string>(type || defaultType);
|
||||
console.log(localType);
|
||||
|
||||
if (!rows || !rows.length) return null;
|
||||
|
||||
|
|
|
@ -46,6 +46,15 @@
|
|||
max-height: 60vh;
|
||||
padding: 0 24px;
|
||||
overflow: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #AAAAAA;
|
||||
}
|
||||
}
|
||||
|
||||
&_footer {
|
||||
|
@ -63,5 +72,10 @@
|
|||
height: 24px;
|
||||
|
||||
cursor: pointer;
|
||||
transition: transform 1s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import React from 'react';
|
||||
|
||||
import Description from 'ts/components/Description';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import RECOMMENDATION_TYPES from 'ts/helpers/Recommendations/contstants';
|
||||
|
||||
import { getFormattedTitle, getDescriptionText } from '../helpers';
|
||||
import style from '../styles/card.module.scss';
|
||||
|
||||
function getClassName(recommendation?: any) {
|
||||
const type = recommendation?.type;
|
||||
return {
|
||||
[RECOMMENDATION_TYPES.INFO]: style.recommendations_card_info,
|
||||
[RECOMMENDATION_TYPES.FACT]: style.recommendations_card_fact,
|
||||
[RECOMMENDATION_TYPES.WARNING]: style.recommendations_card_warning,
|
||||
[RECOMMENDATION_TYPES.ALERT]: style.recommendations_card_error,
|
||||
}[type || RECOMMENDATION_TYPES.INFO] ?? style.recommendations_card_fact;
|
||||
}
|
||||
|
||||
interface IRecommendationsProps {
|
||||
recommendation: any;
|
||||
}
|
||||
|
||||
function CardForPrint({
|
||||
recommendation,
|
||||
}: IRecommendationsProps) {
|
||||
if (!recommendation) return null;
|
||||
|
||||
const className = getClassName(recommendation);
|
||||
const title = getFormattedTitle(recommendation);
|
||||
const titleArgs = recommendation?.arguments?.title;
|
||||
const description = getDescriptionText(recommendation);
|
||||
|
||||
return (
|
||||
<div className={`${style.recommendations_card} ${style.recommendations_card_for_print} ${className}`}>
|
||||
<h5 className={style.recommendations_card_title}>
|
||||
<span className={style.recommendations_card_icon}></span>
|
||||
{localization.get(title, titleArgs)}
|
||||
</h5>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={description}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default CardForPrint;
|
|
@ -4,20 +4,27 @@ import Title from 'ts/components/Title';
|
|||
import localization from 'ts/helpers/Localization';
|
||||
|
||||
import Card from './components/Card';
|
||||
import CardForPrint from './components/CardForPrint';
|
||||
import recommendationStore from './store/index';
|
||||
import style from './styles/index.module.scss';
|
||||
|
||||
interface IRecommendationsProps {
|
||||
recommendations: any[];
|
||||
mode?: string;
|
||||
}
|
||||
|
||||
function Recommendations({
|
||||
recommendations,
|
||||
mode,
|
||||
}: IRecommendationsProps) {
|
||||
|
||||
const cards = (recommendations || [])
|
||||
.filter(item => item)
|
||||
.map((recommendation) => (
|
||||
.map((recommendation) => (mode === 'print' ? (
|
||||
<CardForPrint
|
||||
key={recommendation[1]}
|
||||
recommendation={recommendation}
|
||||
/>
|
||||
) : (
|
||||
<Card
|
||||
key={recommendation[1]}
|
||||
recommendation={recommendation}
|
||||
|
@ -25,21 +32,27 @@ function Recommendations({
|
|||
recommendationStore.open(recommendation);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
)));
|
||||
|
||||
if (!cards.length) return null;
|
||||
|
||||
const title = localization.get('recommendations.title');
|
||||
const className = mode === 'print'
|
||||
? `${style.recommendations_container} ${style.recommendations_container_for_print}`
|
||||
: style.recommendations_container;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title title={title}/>
|
||||
<div className={style.recommendations_container}>
|
||||
<div className={className}>
|
||||
{cards}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Recommendations.defaultProps = {
|
||||
mode: undefined,
|
||||
};
|
||||
|
||||
export default Recommendations;
|
||||
|
|
|
@ -6,18 +6,27 @@
|
|||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
width: 220px;
|
||||
margin: 0 24px var(--space-l) 0;
|
||||
margin: 0 var(--space-xxl) var(--space-l) 0;
|
||||
padding: var(--space-m) var(--space-l);
|
||||
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
border-left-width: var(--space-s);
|
||||
border-radius: var(--border-radius-m);
|
||||
|
||||
&_for_print {
|
||||
display: block;
|
||||
max-height: none;
|
||||
width: 100%;
|
||||
margin: 0 0 var(--space-l) 0;
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-xs);
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
|
||||
&_for_print {
|
||||
column-count: 2;
|
||||
white-space: normal;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
background-color: transparent;
|
||||
|
@ -20,3 +26,10 @@
|
|||
background: #AAAAAA;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.recommendations_container {
|
||||
white-space: normal;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--button-color-hover);
|
||||
background-color: var(--button-color-active);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
|
@ -197,4 +197,4 @@
|
|||
&:hover {
|
||||
background-color: var(--button-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import Confirm from 'ts/components/ModalWindow/Confirm';
|
|||
import PageWrapper from '../../PageWrapper';
|
||||
import Team from '../../Team/index';
|
||||
import Person from '../../Person/index';
|
||||
import PrintAll from '../../PrintAll/index';
|
||||
import Welcome from '../../Welcome/index';
|
||||
import Settings from '../../Settings/index';
|
||||
import DebugPage from '../../Debug/index';
|
||||
|
@ -55,6 +56,14 @@ const Success = observer((): React.ReactElement => {
|
|||
</PageWrapper>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="/print"
|
||||
element={(
|
||||
<PageWrapper>
|
||||
<PrintAll />
|
||||
</PageWrapper>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="/:type/:page"
|
||||
element={(
|
||||
|
|
|
@ -36,9 +36,10 @@ function PopularWords({ statistic, mode }: IPopularWordsProps) {
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.common.words.title"/>
|
||||
<PageWrapper template="table">
|
||||
<CandyChart
|
||||
|
|
|
@ -22,7 +22,10 @@ function TableOfContents({ titles }: ITableOfContents) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Title title="page.print.tableOfContents" />
|
||||
<Title
|
||||
className={style.table_of_contents_title}
|
||||
title="page.print.tableOfContents"
|
||||
/>
|
||||
<nav className={style.table_of_contents}>
|
||||
{items}
|
||||
</nav>
|
||||
|
|
|
@ -4,14 +4,28 @@
|
|||
display: block;
|
||||
margin-bottom: var(--space-xxl);
|
||||
|
||||
&_title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&_item {
|
||||
font-size: var(--font-s);
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 0 0 0 22px;
|
||||
margin: var(--space-m) 0;
|
||||
list-style-type: none;
|
||||
text-decoration: none;
|
||||
color: var(--color-black);
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
color: var(--color-button);
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: var(--color-button);
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
|
|
|
@ -41,16 +41,14 @@ const Print = observer(() => {
|
|||
>
|
||||
{localization.get('page.print.modal.type')}
|
||||
</UiKitButton>
|
||||
{false && (
|
||||
<UiKitButton
|
||||
className={style.page_wrapper_print_button}
|
||||
onClick={() => {
|
||||
printStore.printAllPages();
|
||||
}}
|
||||
>
|
||||
{localization.get('page.print.modal.all')}
|
||||
</UiKitButton>
|
||||
)}
|
||||
<UiKitButton
|
||||
className={style.page_wrapper_print_button}
|
||||
onClick={() => {
|
||||
printStore.printAllPages();
|
||||
}}
|
||||
>
|
||||
{localization.get('page.print.modal.all')}
|
||||
</UiKitButton>
|
||||
<UiKitButton
|
||||
type="second"
|
||||
className={style.page_wrapper_print_button}
|
||||
|
|
|
@ -12,9 +12,12 @@ class PrintStore implements IPrintStore {
|
|||
|
||||
prevUrl: string = '';
|
||||
|
||||
processing: boolean = false;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
isOpen: observable,
|
||||
processing: observable,
|
||||
|
||||
open: action,
|
||||
close: action,
|
||||
|
@ -52,17 +55,20 @@ class PrintStore implements IPrintStore {
|
|||
}
|
||||
|
||||
printAllPages() {
|
||||
this.navigate('/print');
|
||||
this.triggerPrint();
|
||||
}
|
||||
|
||||
triggerPrint() {
|
||||
this.isOpen = false;
|
||||
this.processing = true;
|
||||
setTimeout(() => {
|
||||
window.print();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
endPrint() {
|
||||
this.processing = false;
|
||||
if (this.prevUrl) this.navigate(this.prevUrl);
|
||||
this.navigate = null;
|
||||
this.prevUrl = '';
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import CommonChanges from 'ts/pages/Common/components/Changes';
|
||||
|
||||
const Changes = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[statistic.author];
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Changes = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[user.author];
|
||||
return (
|
||||
<CommonChanges statistic={byTimestamp} />
|
||||
);
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import CommonCommits from 'ts/pages/Common/components/Commits';
|
||||
|
||||
const Commits = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[statistic.author];
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Commits = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[user.author];
|
||||
return (
|
||||
<CommonCommits statistic={byTimestamp} />
|
||||
);
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
import HoursChart from 'ts/components/HoursChart';
|
||||
import Title from 'ts/components/Title';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Hours = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
|
||||
const Hours = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
return (
|
||||
<>
|
||||
<Title title="page.person.hours.title"/>
|
||||
<PageWrapper template="table">
|
||||
<HoursChart statistic={statistic} />
|
||||
<HoursChart statistic={user} />
|
||||
</PageWrapper>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { getShortMoney } from 'ts/helpers/formatter';
|
||||
|
@ -10,12 +9,12 @@ import IsStaff from 'ts/components/NothingFound/components/IsStaff';
|
|||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import PageColumn from 'ts/components/Page/column';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
const Money = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Money = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[statistic.author];
|
||||
const taskNumber = statistic.tasks.length;
|
||||
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
import YearChart from 'ts/components/YearChart';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
|
||||
const Month = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const author = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Month = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const author = user;
|
||||
const statistic = dataGripStore.dataGrip.timestamp.statisticByAuthor[author.author];
|
||||
const max = statistic.commitsByTimestampCounter.max;
|
||||
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import CommonPopularWords from 'ts/pages/Common/components/PopularWords';
|
||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||
|
||||
interface IPopularWordsProps extends ICommonPageProps {
|
||||
user: any;
|
||||
}
|
||||
const PopularWords = observer(({
|
||||
user,
|
||||
mode,
|
||||
}: ICommonPageProps): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0].wordStatistics;
|
||||
}: IPopularWordsProps): React.ReactElement => {
|
||||
const statistic = user.wordStatistics;
|
||||
return (
|
||||
<CommonPopularWords
|
||||
mode={mode}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import Title from 'ts/components/Title';
|
||||
import Description from 'ts/components/Description';
|
||||
import PageBreak from 'ts/pages/Common/components/PageBreak';
|
||||
import TableOfContents from 'ts/pages/Common/components/TableOfContents';
|
||||
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import style from 'ts/pages/Team/styles/cover.module.scss';
|
||||
|
||||
import Hours from './Hours';
|
||||
import Money from './Money';
|
||||
|
@ -17,33 +17,49 @@ import Achievements from './print/Achievements';
|
|||
import Week from './Week';
|
||||
import Month from './Month';
|
||||
|
||||
const Print = observer((): React.ReactElement => {
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Print = observer(({
|
||||
user,
|
||||
}: IPersonCommonProps): React.ReactElement => {
|
||||
return (
|
||||
<>
|
||||
<Title title={localization.get('page.print.title', document.title)} />
|
||||
<Description text={localization.get('page.print.description')} />
|
||||
<br />
|
||||
<TableOfContents titles={[
|
||||
'page.team.total.titleA',
|
||||
'page.person.speed.task',
|
||||
'page.person.speed.max',
|
||||
'page.team.total.titleB',
|
||||
'page.person.achievement.title',
|
||||
'page.person.hours.title',
|
||||
'page.common.words.title',
|
||||
]}/>
|
||||
<div className={style.cover}>
|
||||
<h1 className={style.cover_title}>
|
||||
{localization.get('page.print.title')}
|
||||
</h1>
|
||||
<h2 className={style.cover_sub_title}>
|
||||
{user.author}
|
||||
</h2>
|
||||
<TableOfContents titles={[
|
||||
'page.team.total.titleA',
|
||||
'page.person.speed.task',
|
||||
'page.person.speed.max',
|
||||
'page.team.total.titleB',
|
||||
'page.person.achievement.title',
|
||||
'page.person.hours.title',
|
||||
'page.common.words.title',
|
||||
]}/>
|
||||
<Description text={localization.get('page.print.description')}/>
|
||||
</div>
|
||||
<PageBreak/>
|
||||
<Total/>
|
||||
<Speed/>
|
||||
<Money/>
|
||||
<Total user={user}/>
|
||||
<Speed user={user}/>
|
||||
<Money user={user}/>
|
||||
<PageBreak/>
|
||||
<Achievements/>
|
||||
<Achievements user={user}/>
|
||||
<PageBreak/>
|
||||
<Hours/>
|
||||
<Week mode="print"/>
|
||||
<Hours user={user}/>
|
||||
<Week
|
||||
user={user}
|
||||
mode="print"
|
||||
/>
|
||||
<PageBreak/>
|
||||
<Month/>
|
||||
<PopularWords mode="print"/>
|
||||
<Month user={user}/>
|
||||
<PopularWords
|
||||
user={user}
|
||||
mode="print"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { getShortNumber } from 'ts/helpers/formatter';
|
||||
|
@ -10,12 +9,12 @@ import IsStaff from 'ts/components/NothingFound/components/IsStaff';
|
|||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import PageColumn from 'ts/components/Page/column';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
const Speed = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
const Speed = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const byTimestamp = dataGripStore.dataGrip.timestamp.statisticByAuthor[statistic.author];
|
||||
const taskNumber = statistic.tasks.length;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { IPagination } from 'ts/interfaces/Pagination';
|
||||
|
@ -17,6 +16,8 @@ import TempoChart from 'ts/components/Tempo';
|
|||
import uiKitStyle from 'ts/components/UiKit/styles/index.module.scss';
|
||||
import style from 'ts/pages/Team/styles/filters.module.scss';
|
||||
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
interface ITempoViewProps {
|
||||
user?: string;
|
||||
response?: IPagination<any>;
|
||||
|
@ -40,9 +41,8 @@ function getPartOfData(filters: any, rows: any[]) {
|
|||
return rows.filter((row: any) => (row.week === filters.week)).slice(0, 7);
|
||||
}
|
||||
|
||||
const Tempo = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const author = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const Tempo = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const author = user;
|
||||
|
||||
const rows = dataGripStore.dataGrip.timestamp.statisticByAuthor[author.author]?.allCommitsByTimestamp || [];
|
||||
const firstIndex = rows.length - 1;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
||||
|
@ -16,6 +15,7 @@ import Title from 'ts/components/Title';
|
|||
import GetList from 'ts/components/GetList';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import IPersonCommonProps from '../interfaces/CommonProps';
|
||||
|
||||
interface IAchievementBlockProps {
|
||||
title: string;
|
||||
|
@ -32,10 +32,9 @@ function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
|||
);
|
||||
}
|
||||
|
||||
const Total = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const commitsWithGet = dataGripStore.dataGrip.get.getsByAuthor[statistic.author];
|
||||
const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const commitsWithGet = dataGripStore.dataGrip.get.getsByAuthor[user.author];
|
||||
const taskNumber = statistic.tasks.length;
|
||||
const achievements = getAchievementByAuthor(statistic.author);
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import IHashMap from 'ts/interfaces/HashMap';
|
||||
|
@ -119,20 +118,24 @@ WeekView.defaultProps = {
|
|||
response: undefined,
|
||||
};
|
||||
|
||||
interface IWeekProps extends ICommonPageProps {
|
||||
user: any;
|
||||
}
|
||||
const Week = observer(({
|
||||
user,
|
||||
mode,
|
||||
}: ICommonPageProps): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
}: IWeekProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const rows = dataGripStore.dataGrip.week.statistic.filter((item: any) => item.authors[statistic.author]);
|
||||
if (!rows?.length) return (<NothingFound />);
|
||||
const recommendations = dataGripStore.dataGrip.recommendations.person?.byWeek[statistic.author];
|
||||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations}/>
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
||||
|
@ -14,6 +13,7 @@ import Title from 'ts/components/Title';
|
|||
import GetList from 'ts/components/GetList';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import IPersonCommonProps from '../../interfaces/CommonProps';
|
||||
|
||||
interface IAchievementBlockProps {
|
||||
title: string;
|
||||
|
@ -30,9 +30,10 @@ function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
|||
);
|
||||
}
|
||||
|
||||
const Total = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const Total = observer(({
|
||||
user,
|
||||
}: IPersonCommonProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const commitsWithGet = dataGripStore.dataGrip.get.getsByAuthor[statistic.author];
|
||||
const achievements = getAchievementByAuthor(statistic.author);
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import CardWithIcon from 'ts/components/CardWithIcon';
|
||||
|
@ -7,14 +6,15 @@ import PageWrapper from 'ts/components/Page/wrapper';
|
|||
import PageColumn from 'ts/components/Page/column';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
|
||||
import IPersonCommonProps from '../../interfaces/CommonProps';
|
||||
import style from '../../styles/print.module.scss';
|
||||
|
||||
const Total = observer((): React.ReactElement => {
|
||||
const { userId } = useParams<any>();
|
||||
const statistic = dataGripStore.dataGrip.author.statistic[userId || 0];
|
||||
const Total = observer(({
|
||||
user,
|
||||
}: IPersonCommonProps): React.ReactElement => {
|
||||
const statistic = user;
|
||||
const taskNumber = statistic.tasks.length;
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import Title from 'ts/components/Title';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
import UserSelect from './components/UserSelect';
|
||||
import Changes from './components/Changes';
|
||||
|
@ -17,9 +19,17 @@ import Month from './components/Month';
|
|||
import Tempo from './components/Tempo';
|
||||
import Print from './components/Print';
|
||||
|
||||
function Person() {
|
||||
const { type, page } = useParams<any>();
|
||||
if (type !== 'person') return null;
|
||||
interface IPersonProps {
|
||||
userId?: string | number;
|
||||
}
|
||||
|
||||
const Person = observer(({
|
||||
userId,
|
||||
}: IPersonProps) => {
|
||||
const { type, page, userId: userIdFromUrl } = useParams<any>();
|
||||
const user = dataGripStore.dataGrip.author.statistic[userId || userIdFromUrl || 0];
|
||||
if (type !== 'person' || !user) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{!['print'].includes(page || '') && (
|
||||
|
@ -28,19 +38,19 @@ function Person() {
|
|||
<UserSelect />
|
||||
</>
|
||||
)}
|
||||
{page === 'total' && <Total/>}
|
||||
{page === 'hours' && <Hours/>}
|
||||
{page === 'money' && <Money/>}
|
||||
{page === 'week' && <Week/>}
|
||||
{page === 'month' && <Month/>}
|
||||
{page === 'commits' && <Commits/>}
|
||||
{page === 'changes' && <Changes/>}
|
||||
{page === 'words' && <PopularWords/>}
|
||||
{page === 'speed' && <Speed/>}
|
||||
{page === 'day' && <Tempo/>}
|
||||
{page === 'print' && <Print/>}
|
||||
{page === 'total' && <Total user={user}/>}
|
||||
{page === 'hours' && <Hours user={user}/>}
|
||||
{page === 'money' && <Money user={user}/>}
|
||||
{page === 'week' && <Week user={user}/>}
|
||||
{page === 'month' && <Month user={user}/>}
|
||||
{page === 'commits' && <Commits user={user}/>}
|
||||
{page === 'changes' && <Changes user={user}/>}
|
||||
{page === 'words' && <PopularWords user={user}/>}
|
||||
{page === 'speed' && <Speed user={user}/>}
|
||||
{page === 'day' && <Tempo user={user}/>}
|
||||
{page === 'print' && <Print user={user}/>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Person;
|
||||
|
|
3
src/ts/pages/Person/interfaces/CommonProps.ts
Normal file
3
src/ts/pages/Person/interfaces/CommonProps.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default interface IPersonCommonProps {
|
||||
user: any;
|
||||
}
|
27
src/ts/pages/PrintAll/index.tsx
Normal file
27
src/ts/pages/PrintAll/index.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import Person from 'ts/pages/Person/components/Print';
|
||||
import Team from 'ts/pages/Team/components/Print';
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
const PrintAll = observer((): React.ReactElement | null => {
|
||||
const statistic = dataGripStore.dataGrip.author.statistic;
|
||||
const users = Object.entries(statistic)
|
||||
.filter(([, user]: [string, any]) => !user.isStaff)
|
||||
.map(([id, user]: [string, any]) => (
|
||||
<Person
|
||||
key={id}
|
||||
user={user}
|
||||
/>
|
||||
));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Team />
|
||||
{users}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export default PrintAll;
|
|
@ -162,15 +162,17 @@ const Author = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.team.author.title"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||
content: rows, pagination, sort, mode,
|
||||
})}
|
||||
watch={mode}
|
||||
>
|
||||
<AuthorView mode={mode} />
|
||||
<Pagination />
|
||||
|
|
|
@ -7,15 +7,21 @@ import Recommendations from 'ts/components/Recommendations';
|
|||
import HoursChart from 'ts/components/HoursChart';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
|
||||
const Hours = observer((): React.ReactElement => {
|
||||
const Hours = observer(({
|
||||
mode,
|
||||
}: ICommonPageProps): React.ReactElement => {
|
||||
const statistic = dataGripStore.dataGrip.team.statistic;
|
||||
const recommendations = dataGripStore.dataGrip.recommendations.team?.byHour;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Recommendations recommendations={recommendations} />
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.team.hours.title"/>
|
||||
<PageWrapper template="table">
|
||||
<HoursChart statistic={statistic} />
|
||||
|
|
|
@ -20,9 +20,10 @@ const Month = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations}/>
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.team.month.title"/>
|
||||
<PageWrapper template="table">
|
||||
<YearChart
|
||||
|
|
|
@ -3,11 +3,17 @@ import { observer } from 'mobx-react-lite';
|
|||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import CommonPopularWords from 'ts/pages/Common/components/PopularWords';
|
||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||
|
||||
const PopularWords = observer((): React.ReactElement => {
|
||||
const PopularWords = observer(({
|
||||
mode,
|
||||
}: ICommonPageProps): React.ReactElement => {
|
||||
const statistic = dataGripStore.dataGrip.team.statistic.wordStatistics;
|
||||
return (
|
||||
<CommonPopularWords statistic={statistic} />
|
||||
<CommonPopularWords
|
||||
mode={mode}
|
||||
statistic={statistic}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import Title from 'ts/components/Title';
|
||||
import Description from 'ts/components/Description';
|
||||
import TableOfContents from 'ts/pages/Common/components/TableOfContents';
|
||||
import PageBreak from 'ts/pages/Common/components/PageBreak';
|
||||
|
@ -18,24 +17,32 @@ import Week from './Week';
|
|||
import Month from './Month';
|
||||
import Pr from './PR';
|
||||
|
||||
import style from '../styles/cover.module.scss';
|
||||
|
||||
const Print = observer((): React.ReactElement => {
|
||||
return (
|
||||
<>
|
||||
<Title title={localization.get('page.print.title', document.title)} />
|
||||
<Description text={localization.get('page.print.description')} />
|
||||
<br />
|
||||
<TableOfContents titles={[
|
||||
'page.team.total.titleA',
|
||||
'page.team.total.titleB',
|
||||
'page.team.scope.title',
|
||||
'page.team.author.title',
|
||||
'page.team.type.title',
|
||||
'page.team.pr.oneTaskDays',
|
||||
'page.team.pr.statByAuthors',
|
||||
'page.team.pr.longDelay',
|
||||
'page.team.hours.title',
|
||||
'page.common.words.title',
|
||||
]}/>
|
||||
<div className={style.cover}>
|
||||
<h1 className={style.cover_title}>
|
||||
{localization.get('page.print.title')}
|
||||
</h1>
|
||||
<h2 className={style.cover_sub_title}>
|
||||
{document.title}
|
||||
</h2>
|
||||
<TableOfContents titles={[
|
||||
'page.team.total.titleA',
|
||||
'page.team.total.titleB',
|
||||
'page.team.scope.title',
|
||||
'page.team.author.title',
|
||||
'page.team.type.title',
|
||||
'page.team.pr.oneTaskDays',
|
||||
'page.team.pr.statByAuthors',
|
||||
'page.team.pr.longDelay',
|
||||
'page.team.hours.title',
|
||||
'page.common.words.title',
|
||||
]}/>
|
||||
<Description text={localization.get('page.print.description')}/>
|
||||
</div>
|
||||
<Total/>
|
||||
<PageBreak/>
|
||||
<Scope mode="print"/>
|
||||
|
@ -49,8 +56,8 @@ const Print = observer((): React.ReactElement => {
|
|||
<Week mode="print"/>
|
||||
<PageBreak/>
|
||||
<Month mode="print"/>
|
||||
<Hours/>
|
||||
<PopularWords/>
|
||||
<Hours mode="print"/>
|
||||
<PopularWords mode="print"/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -122,15 +122,17 @@ const Scope = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.team.scope.title"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||
content: rows, pagination, mode,
|
||||
})}
|
||||
watch={mode}
|
||||
>
|
||||
<ScopeView mode={mode} />
|
||||
<Pagination />
|
||||
|
|
|
@ -122,15 +122,17 @@ const Type = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
<Title title="page.team.type.title"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||
content: rows, pagination, sort, mode,
|
||||
})}
|
||||
watch={mode}
|
||||
>
|
||||
<TypeView mode={mode} />
|
||||
<Pagination />
|
||||
|
|
|
@ -161,9 +161,10 @@ const Week = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Recommendations
|
||||
mode={mode}
|
||||
recommendations={recommendations}
|
||||
/>
|
||||
{mode === 'print' ? (
|
||||
<Title title="page.team.week.title"/>
|
||||
) : (
|
||||
|
@ -178,6 +179,7 @@ const Week = observer(({
|
|||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||
content: rows, pagination, sort,
|
||||
})}
|
||||
watch={mode}
|
||||
>
|
||||
<WeekView mode={mode} />
|
||||
{mode !== 'print' && <Pagination />}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import printStore from 'ts/pages/PageWrapper/store/Print';
|
||||
|
||||
import Author from './components/Author';
|
||||
import Commits from './components/Commits';
|
||||
import Changes from './components/Changes';
|
||||
|
@ -17,31 +20,33 @@ import Top from './components/Top';
|
|||
import Pr from './components/PR';
|
||||
import Print from './components/Print';
|
||||
|
||||
function Team() {
|
||||
const Team = observer((): React.ReactElement | null => {
|
||||
const { type, page } = useParams<any>();
|
||||
|
||||
if (type && type !== 'team') return null;
|
||||
if (!type) return (<Total/>);
|
||||
|
||||
const mode = printStore.processing ? 'print' : undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
{page === 'total' && <Total/>}
|
||||
{page === 'scope' && <Scope/>}
|
||||
{page === 'author' && <Author/>}
|
||||
{page === 'type' && <Type/>}
|
||||
{page === 'pr' && <Pr/>}
|
||||
{page === 'scope' && <Scope mode={mode}/>}
|
||||
{page === 'author' && <Author mode={mode}/>}
|
||||
{page === 'type' && <Type mode={mode}/>}
|
||||
{page === 'pr' && <Pr mode={mode}/>}
|
||||
{page === 'day' && <Tempo/>}
|
||||
{page === 'week' && <Week/>}
|
||||
{page === 'month' && <Month/>}
|
||||
{page === 'hours' && <Hours/>}
|
||||
{page === 'week' && <Week mode={mode}/>}
|
||||
{page === 'month' && <Month mode={mode}/>}
|
||||
{page === 'hours' && <Hours mode={mode}/>}
|
||||
{page === 'tree' && <Tree/>}
|
||||
{page === 'commits' && <Commits/>}
|
||||
{page === 'changes' && <Changes/>}
|
||||
{page === 'words' && <PopularWords/>}
|
||||
{page === 'words' && <PopularWords mode={mode}/>}
|
||||
{page === 'top' && <Top/>}
|
||||
{page === 'print' && <Print/>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export default Team;
|
||||
|
|
25
src/ts/pages/Team/styles/cover.module.scss
Normal file
25
src/ts/pages/Team/styles/cover.module.scss
Normal file
|
@ -0,0 +1,25 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.cover {
|
||||
display: block;
|
||||
|
||||
&_title,
|
||||
&_sub_title {
|
||||
display: block;
|
||||
font-size: 42px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-weight: 100;
|
||||
margin: 350px 0 32px;
|
||||
}
|
||||
|
||||
&_sub_title {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 230px;
|
||||
}
|
||||
}
|
|
@ -71,7 +71,6 @@ class DataGripStore implements IDataGripStore {
|
|||
this.dataGrip = dataGrip;
|
||||
|
||||
console.dir(this.dataGrip);
|
||||
console.dir(getTitle(this.dataGrip, this.commits));
|
||||
if (!applicationHasCustom.title) {
|
||||
document.title = getTitle(this.dataGrip, this.commits);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ export default `
|
|||
§ page.print.modal.all: All statistics
|
||||
§ page.print.modal.cancel: Cancel
|
||||
§ page.print.tableOfContents: Table of contents
|
||||
§ page.print.title: Git repository report «$1»
|
||||
§ page.print.title: Git repository report
|
||||
§ page.print.sub_title: «$1»
|
||||
§ page.print.description: The data for the report was obtained from the commit history.
|
||||
§ page.team.author.title: Employee statistics
|
||||
§ page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work.
|
||||
|
@ -198,4 +199,4 @@ will be marked as a jump in "deleted" and "added" lines.
|
|||
§ page.person.week.days: days
|
||||
§ page.person.week.workDay: weekdays
|
||||
§ page.person.week.weekends: weekends
|
||||
`;
|
||||
`;
|
||||
|
|
|
@ -17,7 +17,8 @@ export default `
|
|||
§ page.print.modal.all: Всю статистику
|
||||
§ page.print.modal.cancel: Отмена
|
||||
§ page.print.tableOfContents: Оглавление
|
||||
§ page.print.title: Отчёт по git-репозиторию «$1»
|
||||
§ page.print.title: Отчёт по git-репозиторию
|
||||
§ page.print.sub_title: «$1»
|
||||
§ page.print.description: Данные для отчёта были получены из истории коммитов.
|
||||
§ page.team.author.title: Статистика по сотрудникам
|
||||
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||
|
@ -198,4 +199,4 @@ git может показать малое количество изменени
|
|||
§ page.person.week.days: дней
|
||||
§ page.person.week.workDay: будни
|
||||
§ page.person.week.weekends: выходные
|
||||
`;
|
||||
`;
|
||||
|
|
|
@ -17,7 +17,8 @@ export default `
|
|||
§ page.print.modal.all: Всю статистику
|
||||
§ page.print.modal.cancel: Отмена
|
||||
§ page.print.tableOfContents: Оглавление
|
||||
§ page.print.title: Отчёт по git-репозиторию «$1»
|
||||
§ page.print.title: Отчёт по git-репозиторию
|
||||
§ page.print.sub_title: «$1»
|
||||
§ page.print.description: Данные для отчёта были получены из истории коммитов.
|
||||
§ page.team.author.title: Статистика по сотрудникам
|
||||
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||
|
@ -198,4 +199,4 @@ git может показать малое количество изменени
|
|||
§ page.person.week.days: дней
|
||||
§ page.person.week.workDay: будни
|
||||
§ page.person.week.weekends: выходные
|
||||
`;
|
||||
`;
|
||||
|
|
Loading…
Reference in a new issue