JIRA-1234 feat(lang): test test test

This commit is contained in:
bakhirev 2023-10-13 14:19:38 +03:00
parent 781812520f
commit 3d4cb821ac
85 changed files with 3567 additions and 178596 deletions

View file

@ -1,17 +1,17 @@
{
"files": {
"main.css": "./static/css/main.48701252.css",
"main.js": "./static/js/main.7da5e350.js",
"main.css": "./static/css/main.f032b99c.css",
"main.js": "./static/js/main.9af297c4.js",
"static/media/car.png": "./static/media/car.b8dd8738e37fe866285f.png",
"index.html": "./index.html",
"static/media/warning.svg": "./static/media/warning.e39a87773603f3ab157f.svg",
"static/media/info.svg": "./static/media/info.954631f6b19e3fe9c495.svg",
"static/media/alert.svg": "./static/media/alert.41e2b99c481139c13074.svg",
"main.48701252.css.map": "./static/css/main.48701252.css.map",
"main.7da5e350.js.map": "./static/js/main.7da5e350.js.map"
"main.f032b99c.css.map": "./static/css/main.f032b99c.css.map",
"main.9af297c4.js.map": "./static/js/main.9af297c4.js.map"
},
"entrypoints": [
"static/css/main.48701252.css",
"static/js/main.7da5e350.js"
"static/css/main.f032b99c.css",
"static/js/main.9af297c4.js"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

2
build/assets/close.svg Normal file
View file

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#84858D"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
</svg>

After

Width:  |  Height:  |  Size: 201 B

File diff suppressed because it is too large Load diff

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#84858D"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 521 B

File diff suppressed because it is too large Load diff

View file

@ -1 +1 @@
<!doctype html><html lang="ru"><head><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no,maximum-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="cleartype" content="on"><meta name="HandheldFriendly" content="True"><meta name="format-detection" content="telephone=no"><meta name="format-detection" content="address=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script type="text/javascript">var report=[]</script><script src="/log.txt"></script><script src="./log.txt"></script><script src="../log.txt"></script><script src="./log-0.txt"></script><script src="./log-1.txt"></script><script src="./log-2.txt"></script><script src="./log-3.txt"></script><script src="./log-4.txt"></script><script src="./log-5.txt"></script><script src="./log-6.txt"></script><script src="./report/log-0.txt"></script><script src="./report/log-1.txt"></script><script src="./report/log-2.txt"></script><script src="./report/log-3.txt"></script><script src="./report/log-4.txt"></script><script src="./report/log-5.txt"></script><script src="./report/log-6.txt"></script><link rel="icon" href="./favicon.svg"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>Git статистика</title><meta name="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="keywords" content="git, статистика, аудит, история, log, мониторинг, контроль сотрудников"><meta name="author" content="Bakhirev Aleksei"><meta name="copyright" content="(c) Bakhirev Aleksei"><meta http-equiv="Reply-to" content="alexey-bakhirev@yandex.ru"><meta name="application-name" content="GIT Статистика"><meta name="msapplication-tooltip" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:title" content="GIT Статистика"><meta property="og:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="http://assayo.jp/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="GIT Статистика"><meta name="twitter:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="twitter:creator" content="Bakhirev Aleksei"><meta name="twitter:image:src" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.jp"><meta name="twitter:site" content="assayo.jp"><meta itemprop="name" content="GIT Статистика"><meta itemprop="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.7da5e350.js"></script><link href="./static/css/main.48701252.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script type="text/javascript">!function(e,t,c,n,r,a,s){e[r]=e[r]||function(){(e[r].a=e[r].a||[]).push(arguments)},e[r].l=1*new Date;for(var i=0;i<document.scripts.length;i++)if(document.scripts[i].src===n)return;a=t.createElement(c),s=t.getElementsByTagName(c)[0],a.async=1,a.src=n,s.parentNode.insertBefore(a,s)}(window,document,"script","https://mc.yandex.ru/metrika/tag.js","ym"),ym(94903985,"init",{clickmap:!0,trackLinks:!0,accurateTrackBounce:!0,webvisor:!0})</script><noscript><div><img src="https://mc.yandex.ru/watch/94903985" style="position:absolute;left:-9999px" alt=""/></div></noscript></body></html>
<!doctype html><html lang="ru"><head><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no,maximum-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="cleartype" content="on"><meta name="HandheldFriendly" content="True"><meta name="format-detection" content="telephone=no"><meta name="format-detection" content="address=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script type="text/javascript">var report=[]</script><script src="/log.txt"></script><script src="./log.txt"></script><script src="../log.txt"></script><script src="./log-0.txt"></script><script src="./log-1.txt"></script><script src="./log-2.txt"></script><script src="./log-3.txt"></script><script src="./log-4.txt"></script><script src="./log-5.txt"></script><script src="./log-6.txt"></script><script src="./report/log-0.txt"></script><script src="./report/log-1.txt"></script><script src="./report/log-2.txt"></script><script src="./report/log-3.txt"></script><script src="./report/log-4.txt"></script><script src="./report/log-5.txt"></script><script src="./report/log-6.txt"></script><link rel="icon" href="./favicon.svg"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>Git статистика</title><meta name="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="keywords" content="git, статистика, аудит, история, log, мониторинг, контроль сотрудников"><meta name="author" content="Bakhirev Aleksei"><meta name="copyright" content="(c) Bakhirev Aleksei"><meta http-equiv="Reply-to" content="alexey-bakhirev@yandex.ru"><meta name="application-name" content="GIT Статистика"><meta name="msapplication-tooltip" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:title" content="GIT Статистика"><meta property="og:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="http://assayo.jp/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="GIT Статистика"><meta name="twitter:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="twitter:creator" content="Bakhirev Aleksei"><meta name="twitter:image:src" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.jp"><meta name="twitter:site" content="assayo.jp"><meta itemprop="name" content="GIT Статистика"><meta itemprop="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.9af297c4.js"></script><link href="./static/css/main.f032b99c.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 KiB

2
public/assets/close.svg Normal file
View file

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#84858D"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
</svg>

After

Width:  |  Height:  |  Size: 201 B

File diff suppressed because it is too large Load diff

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#84858D"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 521 B

File diff suppressed because it is too large Load diff

View file

@ -64,7 +64,7 @@
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- Yandex.Metrika counter -->
<!-- Yandex.Metrika counter
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
@ -80,6 +80,6 @@
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/94903985" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
/Yandex.Metrika counter -->
</body>
</html>

BIN
src/assets/cards/print.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

2
src/assets/close.svg Normal file
View file

@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#84858D"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
</svg>

After

Width:  |  Height:  |  Size: 201 B

View file

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#84858D"><path d="M658-648v-132H302v132h-60v-192h476v192h-60Zm-518 60h680-680Zm599 95q12 0 21-9t9-21q0-12-9-21t-21-9q-12 0-21 9t-9 21q0 12 9 21t21 9Zm-81 313v-192H302v192h356Zm60 60H242v-176H80v-246q0-45.05 30.5-75.525Q141-648 186-648h588q45.05 0 75.525 30.475Q880-587.05 880-542v246H718v176Zm102-236v-186.215Q820-562 806.775-575 793.55-588 774-588H186q-19.55 0-32.775 13.225Q140-561.55 140-542v186h102v-76h476v76h102Z"/></svg>

Before

Width:  |  Height:  |  Size: 506 B

After

Width:  |  Height:  |  Size: 521 B

View file

@ -26,8 +26,9 @@
--color-black: #12131B;
--color-grey: #CBCBCD;
--color-border: #E2E9F0;
--color-button: #0D69F2;
--color-button-2: #0B59CC;
--color-button: #1A73E8;
--color-button-2: #3081EA;
--color-button-3: #0B59CC;
--color-11: #7F9BE0;
--color-12: #E9A5A1;

View file

@ -0,0 +1,27 @@
import React from 'react';
import IHashMap from 'ts/interfaces/HashMap';
import style from '../styles/index.module.scss';
interface IWeaponProps {
tasksTypes?: IHashMap<number>;
}
function Weapon({ tasksTypes }: IWeaponProps) {
if (!tasksTypes) return null;
console.log(tasksTypes);
// if (tasksNumber > 750) level = 1;
// if (tasksNumber > 1000) level = 1;
// if (tasksNumber > 1500) level = 1;
return (
<div
className={style.character_halo}
style={{ backgroundImage: 'url("./assets/character/halo/1.png")' }}
/>
);
}
export default Weapon;

View file

@ -0,0 +1,26 @@
import React from 'react';
import style from '../styles/index.module.scss';
interface ILayersProps {
type: string;
level?: number;
}
function Layers({ type, level }: ILayersProps) {
const content = [];
for (let layer = level || 0; layer > 0; layer--) {
content.push((
<img
key={`${type}_${layer}`}
className={style.character_layer}
src={`./assets/character/${type}/${layer}.png`}
/>
));
}
return (<>{content}</>);
}
export default Layers;

View file

@ -0,0 +1,19 @@
export function getWingsLevel(workedDays: number) {
const month = Math.floor(workedDays / 30);
return month < 36
? [
0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, // 1 year
4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, // 2 year
8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, // 3 year
][month] : 9;
}
export function getWeaponLevel(tasksNumber: number) {
if (tasksNumber > 500) return 6;
if (tasksNumber > 300) return 5;
if (tasksNumber > 200) return 4;
if (tasksNumber > 100) return 3;
if (tasksNumber > 50) return 2;
if (tasksNumber > 25) return 1;
return 0;
}

View file

@ -0,0 +1,33 @@
import React from 'react';
import Halo from './components/Halo';
import {
getWeaponLevel,
getWingsLevel,
} from './helpers';
import Layers from './components/Layers';
import style from './styles/index.module.scss';
interface ICharacterProps {
user: any;
}
function Character({ user }: ICharacterProps) {
if (!user) return null;
return (
<div className={style.character}>
<Halo tasksTypes={user?.types} />
<Layers
type="weapon"
level={getWingsLevel(user?.allDaysInProject)}
/>
<Layers
type="weapon"
level={getWeaponLevel(user?.tasks?.length)}
/>
</div>
);
}
export default Character;

View file

@ -0,0 +1,46 @@
@import '../../../../styles/variables';
.character {
position: relative;
display: inline-block;
width: 100%;
height: 500px;
pointer-events: none;
&_layer {
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
}
&_halo {
--temp-halo: 70px;
position: absolute;
top: 7%;
left: 45%;
display: block;
width: var(--temp-halo);
height: var(--temp-halo);
box-shadow: -5px 0 15px red;
border-radius: var(--temp-halo);
background-size: 100% 100%;
background-repeat: no-repeat;
animation: 9s linear 1s infinite both running slidein;
animation-name: character_halo;
}
}
@keyframes character_halo {
from {
transform: rotateZ(0);
}
to {
transform: rotateZ(360deg);
}
}

View file

@ -1,5 +1,7 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
interface ILineProps {
value?: number;
width?: number;
@ -23,12 +25,15 @@ function Line({
}: ILineProps): React.ReactElement | null {
if (!width || width <= 0) return null;
const formattedTitle = title || '';
const formattedTitle = localization.get(title || '');
const localizationDescription = localization.get(description || '');
const fullDescription = localizationDescription || formattedTitle;
const formattedValue = formatter?.(value);
const formattedSuffix = suffix ? ` ${suffix}` : '';
const formattedSuffix = suffix ? ` ${localization.get(suffix || '')}` : '';
const formattedDescription = value
? `${width}% (${formattedValue}${formattedSuffix}) ${description || formattedTitle}`
: `${width}% ${description || formattedTitle}`;
? `${width}% (${formattedValue}${formattedSuffix}) ${fullDescription}`
: `${width}% ${fullDescription}`;
return (
<div

View file

@ -24,6 +24,7 @@ const Header = observer(({
{onClose ? (
<img
id={`${id}-close`}
src="./assets/close.svg"
className={`${style.modal_window_close} ${className || ''}`}
onClick={(event: any) => {
event.stopPropagation();

View file

@ -1,5 +1,7 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import style from './index.module.scss';
interface ITitleProps {
@ -15,7 +17,7 @@ function Title({
}: ITitleProps) {
return (
<h3 className={`${style.title} ${addPadding ? style.title_padding : ''} ${className || ''}`}>
{title || ''}
{localization.get(title || '')}
</h3>
);
}

View file

@ -70,6 +70,7 @@
--button-color-text: #FFFFFF;
--button-color-border: var(--color-button);
--button-color-hover: var(--color-button-2);
--button-color-active: var(--color-button-3);
&_slim,
&_second {
@ -77,6 +78,7 @@
--button-color-text: var(--color-black);
--button-color-border: var(--color-border);
--button-color-hover: var(--color-border);
--button-color-active: var(--color-border);
}
}
@ -105,6 +107,10 @@
background-color: var(--button-color-hover);
}
&:active {
background-color: var(--button-color-hover);
}
&.disabled {
pointer-events: none;
opacity: 0.5;

View file

@ -103,6 +103,19 @@ localization.parse('ru', `
§ page.team.week.files: Изменения файлов
§ page.team.week.days: Дни с коммитами и без
§ page.team.week.lossesDetails: Кто не коммитил
§ page.person.total.title: Основные характеристики
§ page.person.total.daysWorked.title: дней работы
§ page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
§ page.person.total.tasks.title: задач
§ page.person.total.tasks.description: Если коммиты правильно подписаны
§ page.person.character.title: Персонаж
§ page.person.achievement.title: Достижения
§ page.person.achievement.positive: Позитивные
§ page.person.achievement.normal: Нейтральные
§ page.person.achievement.negative: Негативные
§ page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
§ page.person.gets.title: Взятые геты:
§ page.person.gets.description: &laquo;Взять гет&raquo; в данном случае означает первым оставить коммит к&nbsp;задаче с&nbsp;&laquo;красивым&raquo; номером.
§ page.person.business.days.title: дней работы
§ page.person.business.days.description: Учтены только дни, в которые делались коммиты
§ page.person.business.tasks.title: задач
@ -124,18 +137,20 @@ git может показать малое количество изменени
будет отмечен, как скачок «удаленных» и «добавленных» строк.
§ page.person.changes.description: Список коммитов и количество изменений в них за этот день:
§ page.person.commits.title: Список коммитов:
§ page.person.money.title.total: За всё время
§ page.person.money.title.middle: Средняя стоимость
§ page.person.money.moneyAll.title: получил
§ page.person.money.moneyAll.description: Предполагаемая сумма зп с проекта (см. настройки)
§ page.person.money.moneyWorked.title: отработал
§ page.person.money.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
§ page.person.money.moneyLosses.title: не делал коммиты
§ page.person.money.moneyLosses.description: Дни когда мог работать, но не работал умноженные на среднюю зп
§ page.person.money.moneyLosses.title: возможная переплата
§ page.person.money.moneyLosses.description: Дни без коммитов умноженные на среднюю зп
§ page.person.money.tasks.title: задача
§ page.person.money.tasks.description: Количество закрытых задач к стоимости дня
§ page.person.money.commits.title: коммит
§ page.person.money.commits.description: Количество коммитов к стоимости рабочего дня
§ page.person.money.total: За всё время
§ page.person.money.middle: Средняя стоимость
§ page.person.speed.task: Одна задача в среднем это
§ page.person.speed.max: Максимальная скорость в день
§ page.person.speed.days.title: дней
§ page.person.speed.days.description: Имеются ввиду рабочие дни, если коммиты правильно подписаны
§ page.person.speed.commits.title: коммитов
@ -146,13 +161,11 @@ git может показать малое количество изменени
§ page.person.speed.tasks.description: Задача может быть не доделана, но работа по ней должна быть
§ page.person.speed.maxCommits.title: коммитов
§ page.person.speed.maxCommits.description: Задача может быть не доделана, но работа по ней должна быть
§ page.person.speed.task: Одна задача в среднем это
§ page.person.speed.max: Максимальная скорость в день
§ page.person.hours.title: Распределение коммитов в течении каждого дня недели
§ page.person.week.date: Дата
§ page.person.week.tasks: Количество задач
§ page.person.week.workDays: Рабочие дни
§ page.person.week.workDays: Дни с коммитами
§ page.person.week.taskInDay: Задач в день
§ page.person.week.commits: коммитов
§ page.person.week.days: дней
§ page.person.week.workDay: будни
§ page.person.week.weekends: выходные
@ -453,6 +466,19 @@ Bus factor = 1
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
- повышается мотивация и вовлеченность сотрудников;
§ recommendations.author.club.title
Ходите в бар
§ recommendations.author.club.description
один раз в месяц или два.
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
# Почему это важно:
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
- повышается вовлеченность сотрудников;
§ recommendations.hour.onlyWork.title
Выходных тут нет
@ -569,6 +595,39 @@ Bus factor = 1
# Возможно, это не так
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
§ recommendations.type.diff.title
Разбейте лидирующий тип на подтипы
§ recommendations.type.diff.description
для детализации ошибок.
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
Рассмотрим несколько вариантов подтипов:
- fix_dev (ошибка выявленная в процессе разработки);
- fix_test (ошибка выявленная в процессе тестирования);
- fix (ошибка выявленная в проде);
§ recommendations.type.buddy.title
Копите мелкие задачи
§ recommendations.type.buddy.description
для новых сотрудников.
# Если задача:
- не важная;
- не большая;
- не требует сильного погружения в контекст;
- больше про рефакторинг, чем про новый код;
# Положите её в backlog с меткой «для новичков».
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
`);
export default {};

View file

@ -97,6 +97,11 @@ export default class RecommendationsTeamByAuthor {
localization.get('recommendations.author.oneToOne.description'),
'info',
],
[
localization.get('recommendations.author.club.title'),
localization.get('recommendations.author.club.description'),
'info',
],
].filter(item => item);
}

View file

@ -13,6 +13,16 @@ export default class RecommendationsTeamByType {
localization.get('recommendations.type.fewTypes.description'),
'fact',
] : null),
[
localization.get('recommendations.type.diff.title'),
localization.get('recommendations.type.diff.description'),
'info',
],
[
localization.get('recommendations.type.buddy.title'),
localization.get('recommendations.type.buddy.description'),
'info',
],
].filter(item => item);
}

View file

@ -21,7 +21,7 @@ const Print = observer(() => {
</Header>
<Body>
<img
src="./assets/cards/commits.png"
src="./assets/cards/print.png"
className={style.page_wrapper_print_icon}
/>
<UiKitButton

View file

@ -6,7 +6,6 @@ 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';
const Hours = observer((): React.ReactElement => {
@ -15,7 +14,7 @@ const Hours = observer((): React.ReactElement => {
return (
<>
<Title title="Распределение коммитов в течении каждого дня недели"/>
<Title title="page.person.hours.title"/>
<PageWrapper template="table">
<HoursChart statistic={statistic} />
</PageWrapper>

View file

@ -3,7 +3,6 @@ import { useParams } from 'react-router-dom';
import { observer } from 'mobx-react-lite';
import { getShortMoney } from 'ts/helpers/formatter';
import localization from 'ts/helpers/Localization';
import CardWithIcon from 'ts/components/CardWithIcon';
import NothingFound from 'ts/components/NothingFound';
@ -31,36 +30,36 @@ const Money = observer((): React.ReactElement => {
return (
<PageWrapper>
<PageColumn>
<Title title={localization.get('За всё время')}/>
<Title title="page.person.money.title.total"/>
<div>
<CardWithIcon
value={getShortMoney(statistic.moneyAll)}
icon="./assets/cards/money_total.png"
title="получил"
description="Предполагаемая сумма зп с проекта (см. настройки)"
title="page.person.money.moneyAll.title"
description="page.person.money.moneyAll.description"
/>
<CardWithIcon
value={getShortMoney(statistic.moneyWorked)}
icon="./assets/cards/money_work.png"
title="отработал"
description="Фактически отработанные дни умноженные на среднюю зп"
title="page.person.money.moneyWorked.title"
description="page.person.money.moneyWorked.description"
/>
<CardWithIcon
value={getShortMoney(statistic.moneyLosses)}
icon="./assets/cards/money_lazy.png"
title="возможная переплата"
description="Дни без коммитов умноженные на среднюю зп"
title="page.person.money.moneyLosses.title"
description="page.person.money.moneyLosses.description"
/>
<CardWithIcon
value={getShortMoney(byTimestamp.weekendPayment)}
icon="./assets/cards/money_holidays.png"
title={localization.get('page.team.total.weekendPayment.title')}
description={localization.get('page.team.total.weekendPayment.description')}
title="page.team.total.weekendPayment.title"
description="page.team.total.weekendPayment.description"
/>
</div>
</PageColumn>
<PageColumn>
<Title title={localization.get('Средняя стоимость')}/>
<Title title="page.person.money.title.middle"/>
{taskNumber === 0 ? (
<NothingFound />
) : (
@ -71,8 +70,8 @@ const Money = observer((): React.ReactElement => {
? getShortMoney(statistic.moneyWorked / taskNumber, 0)
: null}
icon="./assets/cards/money_task.png"
title="задача"
description="Количество закрытых задач к стоимости дня"
title="page.person.money.tasks.title"
description="page.person.money.tasks.description"
/>
<CardWithIcon
long
@ -80,8 +79,8 @@ const Money = observer((): React.ReactElement => {
? getShortMoney(statistic.moneyWorked / statistic.commits, 0)
: null}
icon="./assets/cards/money_work.png"
title="коммит"
description="Количество коммитов к стоимости рабочего дня"
title="page.person.money.commits.title"
description="page.person.money.commits.description"
/>
</div>
)}

View file

@ -3,7 +3,6 @@ import { useParams } from 'react-router-dom';
import { observer } from 'mobx-react-lite';
import { getShortNumber } from 'ts/helpers/formatter';
import localization from 'ts/helpers/Localization';
import CardWithIcon from 'ts/components/CardWithIcon';
import NothingFound from 'ts/components/NothingFound';
@ -31,7 +30,7 @@ const Speed = observer((): React.ReactElement => {
return (
<PageWrapper>
<PageColumn>
<Title title={localization.get('Одна задача в среднем это')}/>
<Title title="page.person.speed.task"/>
{taskNumber === 0 ? (
<NothingFound />
) : (
@ -41,42 +40,42 @@ const Speed = observer((): React.ReactElement => {
? getShortNumber(statistic.daysForTask)
: null}
icon="./assets/cards/month.png"
title="дней"
description="Имеются ввиду рабочие дни,<br>если коммиты правильно подписаны"
title="page.person.speed.days.title"
description="page.person.speed.days.description"
/>
<CardWithIcon
value={taskNumber
? (statistic.commits / taskNumber).toFixed(1)
: null}
icon="./assets/cards/commits.png"
title="коммитов"
description="Отрезаны 10% максимальных и минимальных значений"
title="page.person.speed.commits.title"
description="page.person.speed.commits.description"
/>
<CardWithIcon
value={taskNumber ? statistic.changesForTask : null}
icon="./assets/cards/lines.png"
title="строк кода"
description="Отрезаны 10% максимальных и минимальных значений"
title="page.person.speed.line.title"
description="page.person.speed.line.description"
/>
</div>
)}
</PageColumn>
<PageColumn>
<Title title={localization.get('Максимальная скорость в день')}/>
<Title title="page.person.speed.max"/>
<div>
<CardWithIcon
long
value={byTimestamp.tasksByTimestampCounter.max}
icon="./assets/cards/tasks.png"
title="задач"
description="Задача может быть не доделана, но работа по ней должна быть"
title="page.person.speed.tasks.title"
description="page.person.speed.tasks.description"
/>
<CardWithIcon
long
value={byTimestamp.commitsByTimestampCounter.max}
icon="./assets/cards/commits.png"
title="коммитов"
description="Задача может быть не доделана, но работа по ней должна быть"
title="page.person.speed.maxCommits.title"
description="page.person.speed.maxCommits.description"
/>
</div>
</PageColumn>

View file

@ -5,7 +5,6 @@ import { observer } from 'mobx-react-lite';
import { IPagination } from 'ts/interfaces/Pagination';
import dataGripStore from 'ts/store/DataGrip';
import { getShortDateRange } from 'ts/helpers/formatter';
import localization from 'ts/helpers/Localization';
import UiKitButton from 'ts/components/UiKit/components/Button';
import PageWrapper from 'ts/components/Page/wrapper';
@ -60,7 +59,7 @@ const Tempo = observer((): React.ReactElement => {
if (!partOfData?.length) return (<NothingFound />);
return (
<>
<Title title={localization.get('common.filters')} />
<Title title="common.filters" />
<PageWrapper>
<div className={style.tempo_page_filters}>
<UiKitButton
@ -95,9 +94,7 @@ const Tempo = observer((): React.ReactElement => {
loader={() => getFakeLoader({ content: partOfData })}
watch={week}
>
<TempoView
user={author.author}
/>
<TempoView user={author.author}/>
<Pagination />
</DataLoader>
</PageWrapper>

View file

@ -11,6 +11,7 @@ import Achievements from 'ts/components/Achievement';
import Description from 'ts/components/Description';
import PageWrapper from 'ts/components/Page/wrapper';
import PageColumn from 'ts/components/Page/column';
import Character from 'ts/components/Character';
import Title from 'ts/components/Title';
import GetList from 'ts/components/GetList';
@ -25,7 +26,7 @@ function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
if (!achievements.length) return null;
return (
<>
<Description text={`# ${title}`}/>
<Description text={`# ${localization.get(title)}`}/>
<Achievements list={achievements} />
</>
);
@ -41,19 +42,19 @@ const Total = observer((): React.ReactElement => {
return (
<PageWrapper>
<PageColumn>
<Title title={localization.get('Основные характеристики')}/>
<Title title="page.person.total.title"/>
<div>
<CardWithIcon
value={statistic.daysWorked}
icon="./assets/cards/work_days.png"
title="дней работы"
description="page.team.total.daysWorked.description"
title="page.person.total.daysWorked.title"
description="page.person.total.daysWorked.description"
/>
<CardWithIcon
value={taskNumber ? taskNumber : null}
icon="./assets/cards/tasks.png"
title="задач"
description="Если коммиты правильно подписаны"
title="page.person.total.tasks.title"
description="page.person.total.tasks.description"
/>
<CardWithIcon
value={statistic.daysLosses}
@ -68,29 +69,35 @@ const Total = observer((): React.ReactElement => {
description="page.team.total.commits.description"
/>
</div>
<Title title="page.person.character.title"/>
<Character user={statistic} />
</PageColumn>
<PageColumn>
<Title title={localization.get('Достижения')}/>
<Title title="page.person.achievement.title"/>
<AchievementBlock
title="Позитивные"
title="page.person.achievement.positive"
achievements={achievements[ACHIEVEMENT_TYPE.GOOD]}
/>
<AchievementBlock
title="Нейтральные"
title="page.person.achievement.normal"
achievements={achievements[ACHIEVEMENT_TYPE.NORMAL]}
/>
<AchievementBlock
title="Негативные"
title="page.person.achievement.negative"
achievements={achievements[ACHIEVEMENT_TYPE.BAD]}
/>
<Description text="Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе."/>
<Description
text={localization.get('page.person.achievement.description')}
/>
<br />
<br />
{commitsWithGet?.length ? (
<>
<Title title={localization.get('Взятые геты:')}/>
<Title title="page.person.gets.title"/>
<GetList list={commitsWithGet} />
<Description text="&laquo;Взять гет&raquo; в данном случае означает первым оставить коммит к&nbsp;задаче с&nbsp;&laquo;красивым&raquo; номером."/>
<Description
text={localization.get('page.person.gets.description')}
/>
</>
) : null}
</PageColumn>

View file

@ -32,7 +32,10 @@ function WeekView({ response, name }: IWeekViewProps) {
if (!response) return null;
const typeChart = getOptions({ max: getMax(response, 'authors', name), order: dataGripStore.dataGrip.type.list });
const workDaysChart = getOptions({ max: 7, order: ['будни', 'выходные'], suffix: 'дней' });
const workDaysChart = getOptions({ max: 7, order: [
'page.person.week.workDay',
'page.person.week.weekends',
], suffix: 'page.person.week.days' });
const taskInDayChart = getOptions({ max: getMax(response, 'taskInDay', name) });
return (
@ -40,7 +43,7 @@ function WeekView({ response, name }: IWeekViewProps) {
<Column
isFixed
template={ColumnTypesEnum.STRING}
title="Дата"
title="page.person.week.date"
properties="timestamp"
formatter={getShortDateRange}
width={200}
@ -51,7 +54,7 @@ function WeekView({ response, name }: IWeekViewProps) {
formatter={(authors: IHashMap<number>) => authors[name] || 0}
/>
<Column
title="Количество задач"
title="page.person.week.tasks"
template={(row: any) => (
<LineChart
options={typeChart}
@ -67,12 +70,15 @@ function WeekView({ response, name }: IWeekViewProps) {
formatter={(workDays: IHashMap<number>) => workDays[name] || 0}
/>
<Column
title="Дни с коммитами"
title="page.person.week.workDays"
template={([work, week]: any) => (
<LineChart
options={workDaysChart}
value={work + week}
details={{ 'будни': work, 'выходные': week }}
details={{
'page.person.week.workDay': work,
'page.person.week.weekends': week,
}}
/>
)}
formatter={(row: any) => ( // TODO: не верно, тут сумма, а сб или вс не факт. Он мог прогулять пн, но работать в вс
@ -88,7 +94,7 @@ function WeekView({ response, name }: IWeekViewProps) {
formatter={(taskInDay: IHashMap<number>) => getShortNumber(taskInDay[name] || 0)}
/>
<Column
title="Задач в день"
title="page.person.week.taskInDay"
properties="taskInDay"
template={(taskInDay: any) => (
<LineChart

View file

@ -39,32 +39,34 @@ const Total = observer((): React.ReactElement => {
return (
<PageWrapper>
<PageColumn>
<Title title={localization.get('Достижения')}/>
<Title title="page.person.achievement.title"/>
<AchievementBlock
title="Позитивные"
title="page.person.achievement.positive"
achievements={achievements[ACHIEVEMENT_TYPE.GOOD]}
/>
</PageColumn>
<PageColumn>
<Title title={localization.get('_')}/>
<AchievementBlock
title="Нейтральные"
title="page.person.achievement.normal"
achievements={achievements[ACHIEVEMENT_TYPE.NORMAL]}
/>
<AchievementBlock
title="Негативные"
title="page.person.achievement.negative"
achievements={achievements[ACHIEVEMENT_TYPE.BAD]}
/>
<br />
<br />
{commitsWithGet?.length ? (
<>
<Title title={localization.get('Взятые геты:')}/>
<Title title="page.person.gets.title"/>
<GetList
mode="print"
list={commitsWithGet}
/>
<Description text="&laquo;Взять гет&raquo; в данном случае означает первым оставить коммит к&nbsp;задаче с&nbsp;&laquo;красивым&raquo; номером."/>
<Description
text={localization.get('page.person.gets.description')}
/>
</>
) : null}
</PageColumn>

View file

@ -21,7 +21,7 @@ const Total = observer((): React.ReactElement => {
<CardWithIcon
value=""
icon="./assets/cards/work_days.png"
title="Фотограция"
title="Фотография"
/>
<div className={style.place_for_photo}>
место для фотографии
@ -33,14 +33,14 @@ const Total = observer((): React.ReactElement => {
<CardWithIcon
value={statistic.daysWorked}
icon="./assets/cards/work_days.png"
title="дней работы"
description="page.team.total.daysWorked.description"
title="page.person.total.daysWorked.title"
description="page.person.total.daysWorked.description"
/>
<CardWithIcon
value={taskNumber ? taskNumber : null}
icon="./assets/cards/tasks.png"
title="задач"
description="Если коммиты правильно подписаны"
title="page.person.total.tasks.title"
description="page.person.total.tasks.description"
/>
<CardWithIcon
value={statistic.daysLosses}