update
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 9.9 KiB |
|
@ -16,9 +16,12 @@ function Block({
|
|||
const src = {
|
||||
home: `./assets/games/home${getRandom(2)}.png`,
|
||||
road: './assets/games/road.png',
|
||||
green: './assets/games/green.png',
|
||||
}[type || ''] || defaultSprite;
|
||||
|
||||
if (type === 'green') {
|
||||
return (<div className={className.join(' ')} />);
|
||||
}
|
||||
|
||||
return (
|
||||
<img
|
||||
className={className.join(' ')}
|
||||
|
|
|
@ -42,7 +42,6 @@ function CityMap({
|
|||
style={{
|
||||
padding: `${paddingTop * cellSize}px ${paddingLeft * cellSize}px`,
|
||||
maxWidth: 24 * cellSize,
|
||||
backgroundImage: 'url(./assets/games/green.png)',
|
||||
}}
|
||||
>
|
||||
<div className={style.city_builder}>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import IHashMap from 'ts/interfaces/HashMap';
|
||||
import UiKitButton from 'ts/components/UiKit/components/Button';
|
||||
import Description from 'ts/components/Description';
|
||||
import ShowSymbol from 'ts/components/ShowSymbol';
|
||||
import { shuffle } from 'ts/helpers/random';
|
||||
|
@ -54,19 +53,22 @@ function CityBuilder({
|
|||
length={20}
|
||||
/>
|
||||
<Description
|
||||
className={style.city_builder_description}
|
||||
text={`Сейчас в проекте есть ${selected.value || 0} файлов созданных этим пользователем. Это примерно ${percent}% от всех файлов в проекте.`}
|
||||
/>
|
||||
<div className={style.city_builder_control}>
|
||||
<UiKitButton
|
||||
<button
|
||||
disabled={!selectedIndex}
|
||||
className={style.city_builder_control_prev}
|
||||
style={{ backgroundImage: 'url(./assets/menu/arrow_left.svg)' }}
|
||||
onClick={() => {
|
||||
setSelectedIndex(selectedIndex - 1);
|
||||
}}
|
||||
/>
|
||||
<UiKitButton
|
||||
<button
|
||||
disabled={selectedIndex === lastIndex}
|
||||
className={style.city_builder_control_next}
|
||||
style={{ backgroundImage: 'url(./assets/menu/arrow_right.svg)' }}
|
||||
onClick={() => {
|
||||
setSelectedIndex(selectedIndex + 1);
|
||||
}}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
margin: 0 auto;
|
||||
|
||||
box-sizing: border-box;
|
||||
background-color: #6CCB70;
|
||||
}
|
||||
|
||||
&_block {
|
||||
|
@ -29,7 +28,6 @@
|
|||
box-sizing: border-box;
|
||||
|
||||
border: none;
|
||||
background-color: var(--color-13);
|
||||
|
||||
background-repeat: repeat;
|
||||
background-size: auto 100%;
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.city_builder_description {
|
||||
margin: var(--space-m) auto;
|
||||
}
|
||||
|
||||
.city_builder_control {
|
||||
position: relative;
|
||||
margin: 0 0 var(--space-xxl);
|
||||
margin: var(--space-xxl) auto;
|
||||
user-select: none;
|
||||
background-color: var(--color-13);
|
||||
|
||||
background-size: auto;
|
||||
background-repeat: repeat;
|
||||
background-position: top left;
|
||||
|
||||
&_prev,
|
||||
&_next {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 30%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
@ -20,7 +31,15 @@
|
|||
border-radius: 0;
|
||||
border: none;
|
||||
color: transparent;
|
||||
|
||||
background-color: transparent;
|
||||
background-size: auto 30%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
&_prev {
|
||||
|
|
|
@ -2,48 +2,48 @@ import IHashMap from 'ts/interfaces/HashMap';
|
|||
import { IDirtyFile } from 'ts/interfaces/FileInfo';
|
||||
|
||||
export default class FileGripByAuthor {
|
||||
addedFilesByAuthor: IHashMap<number> = {};
|
||||
|
||||
addedWithoutRemoveFilesByAuthor: IHashMap<number> = {};
|
||||
|
||||
removedFilesByAuthor: IHashMap<number> = {};
|
||||
statisticByName: IHashMap<any> = {};
|
||||
|
||||
totalAddedFiles: number = 0;
|
||||
|
||||
clear() {
|
||||
this.addedFilesByAuthor = {};
|
||||
this.addedWithoutRemoveFilesByAuthor = {};
|
||||
this.removedFilesByAuthor = {};
|
||||
this.totalAddedFiles = 0;
|
||||
this.statisticByName = {};
|
||||
}
|
||||
|
||||
addFile(file: IDirtyFile) {
|
||||
const create = file?.firstCommit?.author || '';
|
||||
const remove = file?.lastCommit?.author || '';
|
||||
const firstAuthor = file?.firstCommit?.author || '';
|
||||
const lastAuthor = file?.lastCommit?.author || '';
|
||||
|
||||
if (!(create || remove) || file?.name?.[0] === '.') return;
|
||||
if (!(firstAuthor || lastAuthor) || file?.name?.[0] === '.') return;
|
||||
|
||||
this.#addNewAuthor(create);
|
||||
this.#addNewAuthor(remove);
|
||||
this.#addCommitByAuthor(firstAuthor);
|
||||
this.#addCommitByAuthor(lastAuthor);
|
||||
this.#updateCommitByAuthor(file, firstAuthor, lastAuthor);
|
||||
}
|
||||
|
||||
this.addedWithoutRemoveFilesByAuthor[create] += 1;
|
||||
if (file.action !== 'D') {
|
||||
this.addedFilesByAuthor[create] += 1;
|
||||
#addCommitByAuthor(author: string) {
|
||||
if (this.statisticByName[author]) return;
|
||||
this.statisticByName[author] = {
|
||||
addedFiles: 0,
|
||||
removedFiles: 0,
|
||||
addedWithoutRemoveFiles: 0,
|
||||
};
|
||||
}
|
||||
|
||||
#updateCommitByAuthor(file: IDirtyFile, firstAuthor: string, lastAuthor: string) {
|
||||
const createStatistic = this.statisticByName[firstAuthor];
|
||||
const removeStatistic = this.statisticByName[lastAuthor];
|
||||
|
||||
createStatistic.addedWithoutRemoveFiles += 1;
|
||||
if (file.action === 'D') {
|
||||
removeStatistic.removedFiles += 1;
|
||||
} else {
|
||||
this.removedFilesByAuthor[remove] += 1;
|
||||
createStatistic.addedFiles += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#addNewAuthor(author: string) {
|
||||
const value = this.addedFilesByAuthor[author];
|
||||
if (value || value === 0) return;
|
||||
this.addedFilesByAuthor[author] = 0;
|
||||
this.addedWithoutRemoveFilesByAuthor[author] = 0;
|
||||
this.removedFilesByAuthor[author] = 0;
|
||||
}
|
||||
|
||||
updateTotalInfo() {
|
||||
this.totalAddedFiles = Object.values(this.addedFilesByAuthor)
|
||||
.reduce((sum: number, value: number) => sum + value, 0);
|
||||
this.totalAddedFiles = Object.values(this.statisticByName)
|
||||
.reduce((sum: number, stat: any) => sum + stat.addedFiles, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,36 +51,36 @@ const SettingForm = observer((response: any): React.ReactElement | null => {
|
|||
<PageWrapper>
|
||||
<PageColumn>
|
||||
<Common />
|
||||
<Prefixes />
|
||||
<Salary />
|
||||
</PageColumn>
|
||||
<PageColumn>
|
||||
<Title title="page.settings.user.title"/>
|
||||
{employees.length > 0 ? (
|
||||
users
|
||||
) : (
|
||||
<NothingFound message="page.settings.user.notFound" />
|
||||
)}
|
||||
{authors.length && (
|
||||
<div className={style.buttons_footer}>
|
||||
<UiKitButtonMenu
|
||||
options={authors}
|
||||
onClick={(user: any) => {
|
||||
formStore.updateState('employees', [
|
||||
...employees,
|
||||
getNewEmployeesSettings(user?.title, formStore.state, selectedNames?.length),
|
||||
]);
|
||||
}}
|
||||
>
|
||||
{localization.get('page.settings.form.addEmployee')}
|
||||
</UiKitButtonMenu>
|
||||
</div>
|
||||
)}
|
||||
<Prefixes />
|
||||
<Title title="page.settings.mailmap"/>
|
||||
<MailMap />
|
||||
</PageColumn>
|
||||
</PageWrapper>
|
||||
<PageWrapper>
|
||||
<Title title="page.settings.mailmap"/>
|
||||
<MailMap />
|
||||
<Title title="page.settings.user.title"/>
|
||||
{employees.length > 0 ? (
|
||||
users
|
||||
) : (
|
||||
<NothingFound message="page.settings.user.notFound" />
|
||||
)}
|
||||
{authors.length && (
|
||||
<div className={style.buttons_footer}>
|
||||
<UiKitButtonMenu
|
||||
options={authors}
|
||||
onClick={(user: any) => {
|
||||
formStore.updateState('employees', [
|
||||
...employees,
|
||||
getNewEmployeesSettings(user?.title, formStore.state, selectedNames?.length),
|
||||
]);
|
||||
}}
|
||||
>
|
||||
{localization.get('page.settings.form.addEmployee')}
|
||||
</UiKitButtonMenu>
|
||||
</div>
|
||||
)}
|
||||
</PageWrapper>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -3,36 +3,8 @@ import { observer } from 'mobx-react-lite';
|
|||
|
||||
import DataLoader from 'ts/components/DataLoader';
|
||||
import SettingForm from './components/Form';
|
||||
// import settingsStore from 'ts/store/Settings';
|
||||
import settingsApi from 'ts/api/settings';
|
||||
import formStore from './store/Form';
|
||||
//
|
||||
// function getDeepCopy(state: any) {
|
||||
// const {
|
||||
// from,
|
||||
// to,
|
||||
// minCommits,
|
||||
// isFullTime,
|
||||
// defaultSalary,
|
||||
// defaultWorkDays,
|
||||
// holidaysInYear,
|
||||
// currency,
|
||||
// salary,
|
||||
// workDays,
|
||||
// } = state;
|
||||
// return {
|
||||
// from,
|
||||
// to,
|
||||
// minCommits,
|
||||
// isFullTime,
|
||||
// defaultSalary,
|
||||
// defaultWorkDays,
|
||||
// holidaysInYear,
|
||||
// currency,
|
||||
// salary: { ...salary },
|
||||
// workDays: { ...workDays },
|
||||
// };
|
||||
// }
|
||||
|
||||
const SettingPage = observer((): React.ReactElement | null => {
|
||||
return (
|
||||
|
|
|
@ -15,7 +15,12 @@ import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
|
||||
const TeamBuilding = observer((): React.ReactElement => {
|
||||
const filesByAuthor = dataGripStore.fileGrip.author?.addedFilesByAuthor;
|
||||
const filesByAuthor = dataGripStore.fileGrip.author?.statisticByName || {};
|
||||
const addedFilesByAuthor = Object.entries(filesByAuthor)
|
||||
.reduce((acc: any, item: any) => {
|
||||
acc[item[0]] = item[1].addedFiles;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const tracksAuth = dataGripStore.dataGrip.author.statistic
|
||||
.filter((item: any) => !item.isStaff);
|
||||
|
@ -69,7 +74,7 @@ const TeamBuilding = observer((): React.ReactElement => {
|
|||
</DataView>
|
||||
|
||||
<Title title="Количество созданных файлов, если бы это был город"/>
|
||||
<CityBuilder valuesByTitle={filesByAuthor} />
|
||||
<CityBuilder valuesByTitle={addedFilesByAuthor} />
|
||||
|
||||
<Title title="Количество созданных папок"/>
|
||||
<DataView rows={maxMessageLength}>
|
||||
|
|