mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
update
This commit is contained in:
parent
599bb1079d
commit
36d57c2737
|
@ -23,6 +23,7 @@
|
||||||
--color-second: #ED675F;
|
--color-second: #ED675F;
|
||||||
|
|
||||||
--color-black: #12131B;
|
--color-black: #12131B;
|
||||||
|
--color-white: #FFFFFF;
|
||||||
--color-grey: #CBCBCD;
|
--color-grey: #CBCBCD;
|
||||||
--color-border: #E2E9F0;
|
--color-border: #E2E9F0;
|
||||||
--color-button: #1A73E8;
|
--color-button: #1A73E8;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.achievement:last-child {
|
.achievement:last-child {
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
border-radius: 40px;
|
border-radius: 40px;
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
|
|
||||||
color: white;
|
color: var(--color-white);
|
||||||
background-color: var(--color-border);
|
background-color: var(--color-border);
|
||||||
border-color: var(--color-border);
|
border-color: var(--color-border);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
margin: 4px auto;
|
margin: 4px auto;
|
||||||
fill: #FFFFFF;
|
fill: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.achievement_title,
|
.achievement_title,
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
|
|
||||||
color: #FFFFFF;
|
color: var(--color-white);
|
||||||
background-color: #A7B6FE;
|
background-color: #A7B6FE;
|
||||||
//background: linear-gradient(135deg, rgba(64,117,252,1) 0%, rgba(172,179,246,1) 100%);
|
//background: linear-gradient(135deg, rgba(64,117,252,1) 0%, rgba(172,179,246,1) 100%);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
background-size: auto 100%;
|
background-size: auto 100%;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&_wrapper {
|
&_wrapper {
|
||||||
width: calc(100% + 24px);
|
width: calc(100% + 24px);
|
||||||
|
|
|
@ -31,6 +31,6 @@
|
||||||
|
|
||||||
&_text {
|
&_text {
|
||||||
margin: var(--space-s) auto;
|
margin: var(--space-s) auto;
|
||||||
color: white;
|
color: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
.infinite_scroll_border_bottom {
|
.infinite_scroll_border_bottom {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.infinite_scroll_border_top {
|
.infinite_scroll_border_top {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
border-radius: var(--border-radius-l);
|
border-radius: var(--border-radius-l);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -28,6 +28,6 @@
|
||||||
|
|
||||||
&_text {
|
&_text {
|
||||||
margin: var(--space-s) auto;
|
margin: var(--space-s) auto;
|
||||||
color: white;
|
color: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_title {
|
&_title {
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
transform: rotateZ(45deg);
|
transform: rotateZ(45deg);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
border-right: 1px solid var(--color-border);
|
border-right: 1px solid var(--color-border);
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&_hour {
|
&_hour {
|
||||||
color: white;
|
color: var(--color-white);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid #FFFFFF;
|
border: 1px solid #FFFFFF;
|
||||||
background-color: var(--color-first);
|
background-color: var(--color-first);
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
&_count {
|
&_count {
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
border: 1px solid var(--color-grey);
|
border: 1px solid var(--color-grey);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_title {
|
&_title {
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: var(--line_chart-height);
|
line-height: var(--line_chart-height);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #FFFFFF;
|
color: var(--color-white);
|
||||||
background-color: #D0D1D2;
|
background-color: #D0D1D2;
|
||||||
-webkit-print-color-adjust: exact;
|
-webkit-print-color-adjust: exact;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&_center {
|
&_center {
|
||||||
fill: white;
|
fill: var(--color-white);
|
||||||
stroke: none;
|
stroke: none;
|
||||||
stroke-width: 0;
|
stroke-width: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 0 0 5px gray;
|
box-shadow: 0 0 5px gray;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,16 +111,16 @@
|
||||||
@keyframes modal_window_halo {
|
@keyframes modal_window_halo {
|
||||||
from {
|
from {
|
||||||
transform: rotateZ(0deg);
|
transform: rotateZ(0deg);
|
||||||
opacity: 0;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
11% {
|
11% {
|
||||||
opacity: 0.4;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
89% {
|
89% {
|
||||||
opacity: 0.4;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: rotateZ(360deg);
|
transform: rotateZ(360deg);
|
||||||
opacity: 0;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,19 @@ function Card({ message }: ICardProps) {
|
||||||
info: style.notifications_item_info,
|
info: style.notifications_item_info,
|
||||||
}[message.type || 'success'] || style.notifications_item_info;
|
}[message.type || 'success'] || style.notifications_item_info;
|
||||||
|
|
||||||
|
const icon = {
|
||||||
|
error: './assets/notifications/alert.svg',
|
||||||
|
warning: './assets/notifications/warning.svg',
|
||||||
|
success: './assets/notifications/info.svg',
|
||||||
|
info: './assets/notifications/info.svg',
|
||||||
|
}[message.type || 'info'] || './assets/notifications/info.svg';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${style.notifications_item} ${className}`}>
|
<div className={`${style.notifications_item} ${className}`}>
|
||||||
|
<img
|
||||||
|
className={style.notifications_item_icon}
|
||||||
|
src={icon}
|
||||||
|
/>
|
||||||
{message.title && (
|
{message.title && (
|
||||||
<h6 className={style.notifications_item_title}>
|
<h6 className={style.notifications_item_title}>
|
||||||
{message.title}
|
{message.title}
|
||||||
|
|
|
@ -8,30 +8,41 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
&_item {
|
&_item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
padding: 24px;
|
padding: var(--space-xxl) var(--space-xxl) var(--space-xxl) 56px;
|
||||||
margin: 0 12px 12px;
|
margin: 0 12px 12px;
|
||||||
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 2px 2px 3px var(--color-grey);
|
box-shadow: 2px 2px 3px var(--color-grey);
|
||||||
border: 1px solid var(--color-border);
|
border: none;
|
||||||
border-left: 8px solid var(--color-border);
|
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
animation: notification_item 3s linear 0.5s forwards;
|
animation: notification_item 3s linear 0.5s forwards;
|
||||||
|
|
||||||
|
&_icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
left: 12px;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
&_error {
|
&_error {
|
||||||
border-color: var(--color-12);
|
background-color: var(--color-12);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_warning {
|
&_warning {
|
||||||
border-color: var(--color-32);
|
background-color: var(--color-32);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_success {
|
&_success {
|
||||||
border-color: var(--color-13);
|
background-color: #35D081;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_info {
|
&_info {
|
||||||
|
@ -44,7 +55,7 @@
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: var(--color-black);
|
color: var(--color-white);
|
||||||
animation: notification_title 3s linear 0.5s forwards;
|
animation: notification_title 3s linear 0.5s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +73,12 @@
|
||||||
80% {
|
80% {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 24px;
|
padding: var(--space-xxl) var(--space-xxl) var(--space-xxl) 56px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
height: 0;
|
height: 0;
|
||||||
padding: 0 24px;
|
padding: 0 var(--space-xxl) 0 64px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
break-inside: auto;
|
break-inside: auto;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_icons {
|
&_icons {
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main_wrapper_item + .main_wrapper_item {
|
.main_wrapper_item + .main_wrapper_item {
|
||||||
|
|
46
src/ts/components/PieChart/components/Legend.tsx
Normal file
46
src/ts/components/PieChart/components/Legend.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { IOptions, ISubLine } from 'ts/components/LineChart/interfaces';
|
||||||
|
|
||||||
|
import style from '../index.module.scss';
|
||||||
|
|
||||||
|
interface ILegendProps {
|
||||||
|
parts: ISubLine[];
|
||||||
|
options: IOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Legend({
|
||||||
|
parts,
|
||||||
|
options,
|
||||||
|
}: ILegendProps): React.ReactElement | null {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const lines = parts.map((item: ISubLine) => {
|
||||||
|
return (
|
||||||
|
<p
|
||||||
|
key={item.title}
|
||||||
|
className={style.pie_chart_line}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={style.pie_chart_color}
|
||||||
|
style={{ backgroundColor: options.color.get(item.title).first }}
|
||||||
|
/>
|
||||||
|
<span className={style.pie_chart_percent}>
|
||||||
|
{`${item.width}%`}
|
||||||
|
</span>
|
||||||
|
<span className={style.pie_chart_text}>
|
||||||
|
{t(item.title)}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.pie_chart_legend}>
|
||||||
|
{lines}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Legend;
|
64
src/ts/components/PieChart/index.module.scss
Normal file
64
src/ts/components/PieChart/index.module.scss
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.pie_chart {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto var(--space-xxl);
|
||||||
|
padding: var(--space-xxl);
|
||||||
|
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--border-radius-m);
|
||||||
|
background-color: var(--color-white);
|
||||||
|
|
||||||
|
&_data {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_icon,
|
||||||
|
&_legend {
|
||||||
|
display: inline-block;
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_icon {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_legend {
|
||||||
|
min-width: 160px;
|
||||||
|
padding-left: var(--space-xxl);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_line {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
padding: 0 0 var(--space-xxs) 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_color {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
width: var(--space-m);
|
||||||
|
height: var(--space-m);
|
||||||
|
|
||||||
|
background-color: #D0D1D2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_percent,
|
||||||
|
&_text {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.3;
|
||||||
|
white-space: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-black);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_percent {
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
}
|
68
src/ts/components/PieChart/index.tsx
Normal file
68
src/ts/components/PieChart/index.tsx
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import IHashMap from 'ts/interfaces/HashMap';
|
||||||
|
import { IOptions } from 'ts/components/LineChart/interfaces';
|
||||||
|
import getSubLines from 'ts/components/LineChart/helpers/getSubLines';
|
||||||
|
import PieSVG from 'ts/components/PieSVG';
|
||||||
|
import Title from 'ts/components/Title';
|
||||||
|
|
||||||
|
import Legend from './components/Legend';
|
||||||
|
import style from './index.module.scss';
|
||||||
|
|
||||||
|
interface IPieChartProps {
|
||||||
|
title?: string;
|
||||||
|
options: IOptions;
|
||||||
|
value?: number;
|
||||||
|
details?: IHashMap<number>;
|
||||||
|
center?: number;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultDetails(value: number, max: number) {
|
||||||
|
return {
|
||||||
|
a: value,
|
||||||
|
b: max - value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function PieChart({
|
||||||
|
title,
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
details,
|
||||||
|
center,
|
||||||
|
className,
|
||||||
|
}: IPieChartProps): React.ReactElement | null {
|
||||||
|
if (value === 0) return null;
|
||||||
|
|
||||||
|
const formattedDetails = details || getDefaultDetails(value || 100, options.max || 100);
|
||||||
|
const parts = getSubLines(formattedDetails, options);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${style.pie_chart} ${className || ''}`}>
|
||||||
|
<Title title={title || ''} />
|
||||||
|
<div className={style.pie_chart_data}>
|
||||||
|
<div className={style.pie_chart_icon}>
|
||||||
|
<PieSVG
|
||||||
|
parts={parts}
|
||||||
|
options={options}
|
||||||
|
center={center}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Legend
|
||||||
|
parts={parts}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PieChart.defaultProps = {
|
||||||
|
value: undefined,
|
||||||
|
details: undefined,
|
||||||
|
className: '',
|
||||||
|
title: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PieChart;
|
29
src/ts/components/PieSVG/helpers/index.ts
Normal file
29
src/ts/components/PieSVG/helpers/index.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
function polarToCartesian(x: number, y: number, r: number, degrees: number) {
|
||||||
|
const radians = degrees * Math.PI / 180;
|
||||||
|
return [
|
||||||
|
x + (r * Math.cos(radians)),
|
||||||
|
y + (r * Math.sin(radians)),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSegmentPath(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
r0: number,
|
||||||
|
r1: number,
|
||||||
|
d0: number,
|
||||||
|
d1: number,
|
||||||
|
) {
|
||||||
|
const arc = Math.abs(d0 - d1) > 180 ? 1 : 0;
|
||||||
|
const point = (radius: number, degree: number) =>
|
||||||
|
polarToCartesian(x, y, radius, degree)
|
||||||
|
.map(n => n.toPrecision(5))
|
||||||
|
.join(',');
|
||||||
|
return [
|
||||||
|
`M${point(r0, d0)}`,
|
||||||
|
`A${r0},${r0},0,${arc},1,${point(r0, d1)}`,
|
||||||
|
`L${point(r1, d1)}`,
|
||||||
|
`A${r1},${r1},0,${arc},0,${point(r1, d0)}`,
|
||||||
|
'Z',
|
||||||
|
].join('');
|
||||||
|
}
|
12
src/ts/components/PieSVG/index.module.scss
Normal file
12
src/ts/components/PieSVG/index.module.scss
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.pie_svg {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&_sector {
|
||||||
|
fill: #D0D1D2;
|
||||||
|
stroke: none;
|
||||||
|
stroke-width: 0;
|
||||||
|
}
|
||||||
|
}
|
60
src/ts/components/PieSVG/index.tsx
Normal file
60
src/ts/components/PieSVG/index.tsx
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { IOptions, ISubLine } from 'ts/components/LineChart/interfaces';
|
||||||
|
import { getSegmentPath } from './helpers';
|
||||||
|
import style from './index.module.scss';
|
||||||
|
|
||||||
|
interface IPieSVGProps {
|
||||||
|
options: IOptions;
|
||||||
|
parts: ISubLine[];
|
||||||
|
center?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ROTATE = -90;
|
||||||
|
|
||||||
|
function PieSVG({
|
||||||
|
options,
|
||||||
|
parts,
|
||||||
|
center,
|
||||||
|
}: IPieSVGProps): React.ReactElement | null {
|
||||||
|
const centerRadius = 49 * ((center || 72) / 100);
|
||||||
|
|
||||||
|
let prev = 0;
|
||||||
|
const paths = parts.map((item: ISubLine) => {
|
||||||
|
const fill = options.color.get(item.title).first;
|
||||||
|
const angle = 360 * item.width / 100;
|
||||||
|
const next = Math.min(prev + angle, 360);
|
||||||
|
const d = getSegmentPath(50, 50, centerRadius, 50, prev + ROTATE, next + ROTATE);
|
||||||
|
prev += angle;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<path
|
||||||
|
key={item.title}
|
||||||
|
style={{ fill }}
|
||||||
|
d={d}
|
||||||
|
className={style.pie_svg_sector}
|
||||||
|
>
|
||||||
|
<title>
|
||||||
|
{`${item.title} ${item.description || ''}`}
|
||||||
|
</title>
|
||||||
|
</path>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
preserveAspectRatio="xMidYMid meet"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={style.pie_svg}
|
||||||
|
>
|
||||||
|
{paths}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PieSVG.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PieSVG;
|
|
@ -3,11 +3,6 @@ import React from 'react';
|
||||||
import IAnswer from '../interfaces/Answer';
|
import IAnswer from '../interfaces/Answer';
|
||||||
import style from '../styles/answer.module.scss';
|
import style from '../styles/answer.module.scss';
|
||||||
|
|
||||||
const IS_WRAPPER_MODE = {
|
|
||||||
error: true,
|
|
||||||
small: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
interface IAnswerProps {
|
interface IAnswerProps {
|
||||||
answer: IAnswer;
|
answer: IAnswer;
|
||||||
mode: string;
|
mode: string;
|
||||||
|
@ -19,28 +14,27 @@ function Answer({
|
||||||
mode,
|
mode,
|
||||||
onClick,
|
onClick,
|
||||||
}: IAnswerProps): React.ReactElement | null {
|
}: IAnswerProps): React.ReactElement | null {
|
||||||
const className = [style.quize_answer];
|
const className = [style.quize_answer_wrapper];
|
||||||
if (mode === 'selected') className.push(style.quize_answer_selected);
|
const textClasName = [style.quize_answer_text];
|
||||||
if (mode === 'correct') className.push(style.quize_answer_correct);
|
|
||||||
if (mode === 'error') className.push(style.quize_answer_error);
|
|
||||||
if (mode === 'small') className.push(style.quize_answer_small);
|
|
||||||
|
|
||||||
const wrapperClass = [style.quize_answer_wrapper];
|
if (mode === 'small' || mode === 'error') className.push(style.quize_answer_wrapper_small);
|
||||||
if (IS_WRAPPER_MODE[mode]) wrapperClass.push(style.quize_answer_wrapper_small);
|
if (mode === 'selected') textClasName.push(style.quize_answer_text_selected);
|
||||||
|
if (mode === 'correct') textClasName.push(style.quize_answer_text_correct);
|
||||||
|
if (mode === 'error') textClasName.push(style.quize_answer_text_error);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={wrapperClass.join(' ')}>
|
<div className={className.join(' ')}>
|
||||||
<figure
|
<figure
|
||||||
className={className.join(' ')}
|
className={style.quize_answer}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onClick();
|
onClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className={style.quize_answer_icon}
|
className={style.quize_answer_icon}
|
||||||
src={answer.icon}
|
src="./assets/games/quize/balloon.png"
|
||||||
/>
|
/>
|
||||||
<figcaption className={style.quize_answer_text}>
|
<figcaption className={textClasName.join(' ')}>
|
||||||
{answer.title}
|
{answer.title}
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import UiKitButton from 'ts/components/UiKit/components/Button';
|
||||||
|
|
||||||
import IQuestion from '../interfaces/Question';
|
import IQuestion from '../interfaces/Question';
|
||||||
import IAnswer from '../interfaces/Answer';
|
import IAnswer from '../interfaces/Answer';
|
||||||
import Progress from './Progress';
|
|
||||||
import Answer from './Answer';
|
import Answer from './Answer';
|
||||||
|
|
||||||
import stylePage from '../styles/question.module.scss';
|
import stylePage from '../styles/question.module.scss';
|
||||||
|
@ -20,13 +19,11 @@ function getModes(answers: IAnswer[], selected: IAnswer | null) {
|
||||||
|
|
||||||
interface IQuestionProps {
|
interface IQuestionProps {
|
||||||
question: IQuestion;
|
question: IQuestion;
|
||||||
progress: number;
|
|
||||||
onClick: Function;
|
onClick: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Question({
|
function Question({
|
||||||
question,
|
question,
|
||||||
progress,
|
|
||||||
onClick,
|
onClick,
|
||||||
}: IQuestionProps): React.ReactElement | null {
|
}: IQuestionProps): React.ReactElement | null {
|
||||||
const [selected, setSelected] = useState<IAnswer | null>(null);
|
const [selected, setSelected] = useState<IAnswer | null>(null);
|
||||||
|
@ -71,7 +68,6 @@ function Question({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={stylePage.quize_question}>
|
<div className={stylePage.quize_question}>
|
||||||
<Progress progress={progress}/>
|
|
||||||
<div className={stylePage.quize_question_body}>
|
<div className={stylePage.quize_question_body}>
|
||||||
<div className={style.quize_title}>
|
<div className={style.quize_title}>
|
||||||
{question.title}
|
{question.title}
|
||||||
|
|
|
@ -21,11 +21,6 @@ function Result({
|
||||||
<h4 className={style.quize_title}>
|
<h4 className={style.quize_title}>
|
||||||
{result.title}
|
{result.title}
|
||||||
</h4>
|
</h4>
|
||||||
<img
|
|
||||||
className={style.quize_icon}
|
|
||||||
style={{ backgroundImage: `url(${result.icon})` }}
|
|
||||||
src="./assets/games/4x3.png"
|
|
||||||
/>
|
|
||||||
<p className={style.quize_description}>
|
<p className={style.quize_description}>
|
||||||
{result.description}
|
{result.description}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -21,11 +21,6 @@ function Start({
|
||||||
<h4 className={style.quize_title}>
|
<h4 className={style.quize_title}>
|
||||||
{quize.title}
|
{quize.title}
|
||||||
</h4>
|
</h4>
|
||||||
<img
|
|
||||||
className={style.quize_icon}
|
|
||||||
style={{ backgroundImage: `url(${quize.icon})` }}
|
|
||||||
src="./assets/games/4x3.png"
|
|
||||||
/>
|
|
||||||
<p className={style.quize_description}>
|
<p className={style.quize_description}>
|
||||||
{quize.description}
|
{quize.description}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -44,7 +44,6 @@ function QuizePage({
|
||||||
const questions = getQuestionByGroups(quize.questions);
|
const questions = getQuestionByGroups(quize.questions);
|
||||||
let page: any = null;
|
let page: any = null;
|
||||||
|
|
||||||
|
|
||||||
if (view === 'start') {
|
if (view === 'start') {
|
||||||
page = (
|
page = (
|
||||||
<Start
|
<Start
|
||||||
|
@ -62,7 +61,6 @@ function QuizePage({
|
||||||
page = (
|
page = (
|
||||||
<Question
|
<Question
|
||||||
question={question}
|
question={question}
|
||||||
progress={30}
|
|
||||||
onClick={(answer: IAnswer) => {
|
onClick={(answer: IAnswer) => {
|
||||||
const nextById = questions.byId[answer.nextQuestionId || ''];
|
const nextById = questions.byId[answer.nextQuestionId || ''];
|
||||||
const nextByIndex = questions.byIndex[question.index + 1];
|
const nextByIndex = questions.byIndex[question.index + 1];
|
||||||
|
@ -116,7 +114,7 @@ function QuizePage({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={style.quize_container}
|
className={style.quize_container}
|
||||||
style={{ backgroundImage: 'url(./assets/games/quize.png)' }}
|
style={{ backgroundImage: 'url(./assets/games/quize/air.jpg)' }}
|
||||||
>
|
>
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{page}
|
{page}
|
||||||
|
|
|
@ -1,27 +1,23 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.quize_answer {
|
.quize_answer {
|
||||||
width: 250px;
|
--temp-width: 160px;
|
||||||
|
--temp-small: calc(var(--temp-width) - 32px);
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
width: var(--temp-width);
|
||||||
padding-bottom: var(--space-m);
|
padding-bottom: var(--space-m);
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: var(--border-radius-s);
|
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: 0 0 5px var(--color-grey);
|
box-shadow: none;
|
||||||
transition: width 0.5s;
|
transition: width 0.5s;
|
||||||
|
|
||||||
background-color: white;
|
|
||||||
|
|
||||||
animation-duration: 10s;
|
|
||||||
animation-iteration-count: infinite;
|
|
||||||
animation-name: quize_answer;
|
|
||||||
|
|
||||||
&_wrapper {
|
&_wrapper {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
vertical-align: top;
|
vertical-align: bottom;
|
||||||
border-radius: var(--border-radius-s);
|
|
||||||
transition: padding 0.5s;
|
transition: padding 0.5s;
|
||||||
|
|
||||||
&_small {
|
&_small {
|
||||||
|
@ -29,27 +25,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&_selected {
|
|
||||||
box-shadow: 0 0 var(--space-l) var(--color-13), 0 0 var(--space-xxl) var(--color-13);
|
|
||||||
background-color: var(--color-13);
|
|
||||||
animation-name: quize_answer_selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_correct {
|
|
||||||
box-shadow: 0 0 var(--space-l) var(--color-23), 0 0 var(--space-xxl) var(--color-23);
|
|
||||||
background-color: var(--color-23);
|
|
||||||
animation-name: quize_answer_selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_error {
|
|
||||||
width: 218px;
|
|
||||||
box-shadow: 0 0 var(--space-l) var(--color-12), 0 0 var(--space-xxl) var(--color-12);
|
|
||||||
background-color: var(--color-12);
|
|
||||||
animation-name: quize_answer_selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
&_small {
|
&_small {
|
||||||
width: 218px;
|
width: var(--temp-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
|
@ -57,7 +34,6 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto var(--space-l);
|
margin: 0 auto var(--space-l);
|
||||||
|
|
||||||
border-radius: var(--border-radius-s) var(--border-radius-s) 0 0;
|
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: auto 100%;
|
background-size: auto 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
@ -69,44 +45,81 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&_text {
|
&_text {
|
||||||
|
--temp-bg: var(--color-white);
|
||||||
|
|
||||||
|
&_selected {
|
||||||
|
--temp-bg: var(--color-13);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_correct {
|
||||||
|
--temp-bg: var(--color-23);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_error {
|
||||||
|
--temp-bg: var(--color-12);
|
||||||
|
}
|
||||||
|
|
||||||
font-size: var(--font-m);
|
font-size: var(--font-m);
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
display: block;
|
display: flex;
|
||||||
margin: 0 auto;
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 80%;
|
||||||
|
height: 40px;
|
||||||
|
margin: var(--space-xxs) auto 0;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
border-radius: var(--border-radius-m);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
|
background-color: var(--temp-bg);
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: ' ';
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
left: 45%;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
|
||||||
|
border: 12px solid var(--temp-bg);
|
||||||
|
border-bottom: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.quize_answer_wrapper + .quize_answer_wrapper {
|
.quize_answer_wrapper + .quize_answer_wrapper {
|
||||||
margin-left: var(--space-xxl);
|
margin-left: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quize_answer_wrapper_small {
|
||||||
|
padding: var(--space-s) var(--space-l);
|
||||||
|
|
||||||
|
& .quize_answer {
|
||||||
|
width: var(--temp-small);
|
||||||
|
|
||||||
|
animation-delay: 1s;
|
||||||
|
animation-duration: 2s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
animation-name: quize_answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .quize_answer_text {
|
||||||
|
font-size: var(--font-s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@keyframes quize_answer {
|
@keyframes quize_answer {
|
||||||
from {
|
from {
|
||||||
box-shadow: none;
|
top: 0;
|
||||||
}
|
|
||||||
86% {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
93% {
|
|
||||||
box-shadow: 0 0 10px var(--color-13), 0 0 20px var(--color-13);
|
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
box-shadow: none;
|
top: 800px;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes quize_answer_selected {
|
|
||||||
from {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
box-shadow: 0 0 10px var(--color-13), 0 0 20px var(--color-13);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,15 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 400px;
|
height: 500px;
|
||||||
margin: 0 auto var(--space-xxl);
|
margin: 0 auto;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
background-color: #F0AE7A;
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: 10%;
|
background-size: auto 100%;
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +48,30 @@
|
||||||
&_title,
|
&_title,
|
||||||
&_description {
|
&_description {
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
width: 500px;
|
||||||
|
padding: var(--space-xxl) 64px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
line-height: 1.5;
|
||||||
|
box-sizing: border-box;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_title {
|
&_title {
|
||||||
font-size: var(--font-l);
|
font-size: var(--font-l);
|
||||||
margin: 0 auto var(--space-xxl);
|
margin: 0 auto var(--space-xxl);
|
||||||
|
border-radius: var(--border-radius-m);
|
||||||
|
background: radial-gradient(ellipse farthest-corner at 50% 50%, rgba(255, 255, 255, 1) 0%, rgba(240, 174, 122, 0.5) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_description {
|
&_description {
|
||||||
font-size: var(--font-m);
|
font-size: var(--font-m);
|
||||||
|
margin: 100px auto 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
|
@ -67,9 +80,9 @@
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
margin: 0 auto var(--space-xxl);
|
margin: 0 auto var(--space-xxl);
|
||||||
|
|
||||||
border: var(--space-s) solid var(--color-border);
|
border: var(--space-s) solid #E8816E;
|
||||||
box-shadow: 0 0 5px var(--color-grey);
|
box-shadow: 0 0 5px var(--color-grey);
|
||||||
background-color: var(--color-border);
|
background-color: #E8816E;
|
||||||
|
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-size: auto 100%;
|
background-size: auto 100%;
|
||||||
|
@ -79,21 +92,21 @@
|
||||||
|
|
||||||
@keyframes quize_slider {
|
@keyframes quize_slider {
|
||||||
from {
|
from {
|
||||||
right: 0;
|
bottom: 0;
|
||||||
left: auto;
|
left: auto;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
49% {
|
49% {
|
||||||
right: 100%;
|
bottom: 100%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
51% {
|
51% {
|
||||||
right: auto;
|
right: auto;
|
||||||
left: 100%;
|
top: 100%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
left: 0;
|
top: 0;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
&_title {
|
&_title {
|
||||||
font-size: var(--font-l);
|
font-size: var(--font-l);
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
|
|
||||||
margin: 0 auto var(--space-xxl);
|
margin: 0 auto var(--space-xxl);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_answer {
|
&_answer {
|
||||||
|
|
|
@ -17,19 +17,4 @@
|
||||||
&_description {
|
&_description {
|
||||||
font-size: var(--font-m);
|
font-size: var(--font-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_icon {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 300px;
|
|
||||||
margin: 0 auto var(--space-xxl);
|
|
||||||
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
box-shadow: 0 0 5px var(--color-grey);
|
|
||||||
background-color: var(--color-border);
|
|
||||||
|
|
||||||
background-position: center center;
|
|
||||||
background-size: auto 100%;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ function Car({
|
||||||
</div>
|
</div>
|
||||||
<img
|
<img
|
||||||
className={style.races_track_car_cover}
|
className={style.races_track_car_cover}
|
||||||
src="./assets/games/car.png"
|
src="./assets/games/races/car.png"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -27,7 +27,12 @@ function Track({
|
||||||
const duration = DURATION.MIN + (DURATION.BASE * (1 - speed)) * 3;
|
const duration = DURATION.MIN + (DURATION.BASE * (1 - speed)) * 3;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${style.races_track} ${type || ''}`}>
|
<div
|
||||||
|
className={`${style.races_track} ${type || ''}`}
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(./assets/games/races/road.png)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
{canStart && (
|
{canStart && (
|
||||||
<Info
|
<Info
|
||||||
title={title}
|
title={title}
|
||||||
|
|
|
@ -39,7 +39,7 @@ function Races({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<GameBanner src="./assets/games/races.jpg">
|
<GameBanner src="./assets/games/races/bg.png">
|
||||||
{!showAnimation && (
|
{!showAnimation && (
|
||||||
<UiKitButton
|
<UiKitButton
|
||||||
className={style.races_button}
|
className={style.races_button}
|
||||||
|
@ -51,9 +51,21 @@ function Races({
|
||||||
</UiKitButton>
|
</UiKitButton>
|
||||||
)}
|
)}
|
||||||
</GameBanner>
|
</GameBanner>
|
||||||
|
<div
|
||||||
|
className={style.races_green}
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(./assets/games/races/greenTop.png)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div className={style.races}>
|
<div className={style.races}>
|
||||||
{lines}
|
{lines}
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className={style.races_green}
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(./assets/games/races/greenBottom.png)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
.races_track_car {
|
.races_track_car {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: -8px;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
width: 10%;
|
width: 10%;
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
border: 1px solid var(--color-grey);
|
border: 1px solid var(--color-grey);
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
content: ' ';
|
content: ' ';
|
||||||
|
@ -39,16 +39,16 @@
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
|
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&_cover {
|
&_cover {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
height: 50%;
|
height: 50%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_animation {
|
&_animation {
|
||||||
|
|
|
@ -2,12 +2,20 @@
|
||||||
|
|
||||||
.races {
|
.races {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto var(--space-xxl);
|
margin: 0 auto;
|
||||||
border: var(--space-xxl) solid var(--color-13);
|
|
||||||
border-left: none;
|
|
||||||
border-right: none;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
&_green {
|
||||||
|
display: block;
|
||||||
|
height: var(--space-xxl);
|
||||||
|
|
||||||
|
background-color: var(--color-13);
|
||||||
|
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-size: auto 100%;
|
||||||
|
background-position: top left;
|
||||||
|
}
|
||||||
|
|
||||||
&_track {
|
&_track {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
@ -15,11 +23,14 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
text-align: right;
|
text-align: right;
|
||||||
border-bottom: var(--space-xxs) dashed var(--color-border);
|
|
||||||
background-color: var(--color-grey);
|
background-color: var(--color-grey);
|
||||||
|
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-size: auto 100%;
|
||||||
|
background-position: top left;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
border-top: var(--space-xxs) dashed var(--color-border);
|
// border-top: var(--space-xxs) dashed var(--color-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: var(--space-xxs) solid var(--color-border);
|
border: var(--space-xxs) solid var(--color-border);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
animation-name: races_track_info;
|
animation-name: races_track_info;
|
||||||
animation-iteration-count: 1;
|
animation-iteration-count: 1;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
@import 'src/styles/variables';
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
.show_symbol_wrapper {
|
.show_symbol_wrapper {
|
||||||
|
display: inline-block;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show_symbol {
|
.show_symbol {
|
||||||
|
@ -33,9 +35,9 @@
|
||||||
line-height: var(--temp-height);
|
line-height: var(--temp-height);
|
||||||
transform: rotateY(180deg);
|
transform: rotateY(180deg);
|
||||||
|
|
||||||
border: 1px solid var(--color-border);
|
// border: 1px solid var(--color-border);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&_hide {
|
&_hide {
|
||||||
animation-name: show_symbol;
|
animation-name: show_symbol;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
color: white;
|
color: var(--color-white);
|
||||||
background-color: green;
|
background-color: green;
|
||||||
background-size: 23px 22px;
|
background-size: 23px 22px;
|
||||||
|
|
||||||
|
@ -66,4 +66,4 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-size: 23px 44px;
|
background-size: 23px 44px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ class SponsorStore {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!isMobile && !themeSettings.getConfig()) {
|
if (!isMobile && !themeSettings.getConfig()) {
|
||||||
this.setTimer();
|
// this.setTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class SponsorStore {
|
||||||
this.type = Math.random() > 0.5
|
this.type = Math.random() > 0.5
|
||||||
? MODAL_TYPE.SHARE
|
? MODAL_TYPE.SHARE
|
||||||
: MODAL_TYPE.SHARE;
|
: MODAL_TYPE.SHARE;
|
||||||
}, 6 * ONE_MINUTE);
|
}, 10 * ONE_MINUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
color: var(--color-button);
|
color: var(--color-button);
|
||||||
|
|
||||||
|
|
58
src/ts/components/SwimmingPool/components/Track.tsx
Normal file
58
src/ts/components/SwimmingPool/components/Track.tsx
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import ShowSymbol from 'ts/components/ShowSymbol';
|
||||||
|
|
||||||
|
import style from '../styles/track.module.scss';
|
||||||
|
|
||||||
|
function getProps(className: string, src?: string) {
|
||||||
|
return src ? {
|
||||||
|
className,
|
||||||
|
style: {
|
||||||
|
backgroundImage: `url(${src})`,
|
||||||
|
},
|
||||||
|
} : {
|
||||||
|
className,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ITrackProps {
|
||||||
|
title: string;
|
||||||
|
value: number;
|
||||||
|
maxValue: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Track({
|
||||||
|
title,
|
||||||
|
value,
|
||||||
|
maxValue,
|
||||||
|
}: ITrackProps): React.ReactElement | null {
|
||||||
|
if (!title) return null;
|
||||||
|
console.log(maxValue);
|
||||||
|
const percent = (maxValue * 1.1) / 100;
|
||||||
|
const width = Math.ceil(value / percent);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div {...getProps(style.swimming_pool_track, './assets/games/swimmingPool/track_title.png')}>
|
||||||
|
<ShowSymbol
|
||||||
|
text={title}
|
||||||
|
length={10}
|
||||||
|
/>
|
||||||
|
<div {...getProps(style.swimming_pool_track_value)}>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
<div {...getProps(style.swimming_pool_track_line)}>
|
||||||
|
<div
|
||||||
|
className={style.swimming_pool_track_chart}
|
||||||
|
style={{ width: `${width}%` }}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className={style.swimming_pool_track_man}
|
||||||
|
src="./assets/games/swimmingPool/man.png"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Track;
|
52
src/ts/components/SwimmingPool/index.tsx
Normal file
52
src/ts/components/SwimmingPool/index.tsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
import GameBanner from 'ts/components/GameBanner';
|
||||||
|
import { shuffle } from 'ts/helpers/random';
|
||||||
|
|
||||||
|
import Track from './components/Track';
|
||||||
|
|
||||||
|
import style from './styles/index.module.scss';
|
||||||
|
|
||||||
|
interface IRacesProps {
|
||||||
|
tracks: any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
function SwimmingPool({
|
||||||
|
tracks,
|
||||||
|
}: IRacesProps): React.ReactElement | null {
|
||||||
|
const [shuffleTracks] = useState<any>([...shuffle(tracks)]);
|
||||||
|
|
||||||
|
if (!tracks.length) return null;
|
||||||
|
|
||||||
|
const lines = shuffleTracks.map((track: any) => {
|
||||||
|
return (
|
||||||
|
<Track
|
||||||
|
key={track.title}
|
||||||
|
title={track.title}
|
||||||
|
value={track.value}
|
||||||
|
maxValue={300}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<GameBanner src="./assets/games/races/bg.png" />
|
||||||
|
<div
|
||||||
|
className={style.swimming_pool_top_border}
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(./assets/games/swimmingPool/track_title.png)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{lines}
|
||||||
|
<div
|
||||||
|
className={style.swimming_pool_bottom_border}
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(./assets/games/swimmingPool/track_title.png)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SwimmingPool;
|
20
src/ts/components/SwimmingPool/styles/index.module.scss
Normal file
20
src/ts/components/SwimmingPool/styles/index.module.scss
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.swimming_pool {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&_top_border,
|
||||||
|
&_bottom_border {
|
||||||
|
display: block;
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
background-color: var(--color-border);
|
||||||
|
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-size: auto 100%;
|
||||||
|
background-position: top left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
54
src/ts/components/SwimmingPool/styles/track.module.scss
Normal file
54
src/ts/components/SwimmingPool/styles/track.module.scss
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.swimming_pool_track {
|
||||||
|
display: block;
|
||||||
|
height: 84px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
background-size: auto 100%;
|
||||||
|
background-position: top left;
|
||||||
|
|
||||||
|
&_value,
|
||||||
|
&_line,
|
||||||
|
&_chart {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_value {
|
||||||
|
width: 80px;
|
||||||
|
line-height: 80px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-black);
|
||||||
|
background-color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_line {
|
||||||
|
width: calc(100% - 505px);
|
||||||
|
border-left: 16px solid var(--color-12);
|
||||||
|
border-right: 16px solid var(--color-12);
|
||||||
|
border-bottom: 6px dashed white;
|
||||||
|
background-color: var(--color-31);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_chart {
|
||||||
|
width: 50%;
|
||||||
|
text-align: right;
|
||||||
|
background-color: var(--color-button-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_man {
|
||||||
|
position: relative;
|
||||||
|
top: 15px;
|
||||||
|
left: 25px;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,8 +12,8 @@
|
||||||
transform: rotateZ(-45deg);
|
transform: rotateZ(-45deg);
|
||||||
|
|
||||||
border: 6px solid var(--color-grey);
|
border: 6px solid var(--color-grey);
|
||||||
border-left-color: white;
|
border-left-color: var(--color-white);
|
||||||
border-bottom-color: white;
|
border-bottom-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_sort_down {
|
&_sort_down {
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
height: var(--table-cell-height);
|
height: var(--table-cell-height);
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
line-height: var(--table-cell-height);
|
line-height: var(--table-cell-height);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_cell:first-child,
|
&_cell:first-child,
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
.ui_kit_button {
|
.ui_kit_button {
|
||||||
--button-color-bg: var(--color-button);
|
--button-color-bg: var(--color-button);
|
||||||
--button-color-text: #FFFFFF;
|
--button-color-text: var(--color-white);
|
||||||
--button-color-border: var(--color-button);
|
--button-color-border: var(--color-button);
|
||||||
--button-color-hover: var(--color-button-2);
|
--button-color-hover: var(--color-button-2);
|
||||||
--button-color-active: var(--color-button-3);
|
--button-color-active: var(--color-button-3);
|
||||||
|
|
||||||
&_slim,
|
&_slim,
|
||||||
&_second {
|
&_second {
|
||||||
--button-color-bg: #FFFFFF;
|
--button-color-bg: var(--color-white);
|
||||||
--button-color-text: var(--color-black);
|
--button-color-text: var(--color-black);
|
||||||
--button-color-border: var(--color-border);
|
--button-color-border: var(--color-border);
|
||||||
--button-color-hover: var(--color-border);
|
--button-color-hover: var(--color-border);
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui_kit_button_menu {
|
.ui_kit_button_menu {
|
||||||
--button-color-bg: #FFFFFF;
|
--button-color-bg: var(--color-white);
|
||||||
--button-color-text: var(--color-black);
|
--button-color-text: var(--color-black);
|
||||||
--button-color-border: var(--color-border);
|
--button-color-border: var(--color-border);
|
||||||
--button-color-hover: var(--color-border);
|
--button-color-hover: var(--color-border);
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui_kit_dialog {
|
.ui_kit_dialog {
|
||||||
|
@ -35,6 +35,6 @@
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
box-shadow: 0 0 5px #C0C0C0;
|
box-shadow: 0 0 5px #C0C0C0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,11 @@
|
||||||
border: 1px solid #E2E9F0;
|
border: 1px solid #E2E9F0;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
color: #84858D;
|
color: #84858D;
|
||||||
|
|
||||||
&_selected {
|
&_selected {
|
||||||
color: #FFFFFF;
|
color: var(--color-white);
|
||||||
border-top: 1px solid var(--color-button);
|
border-top: 1px solid var(--color-button);
|
||||||
border-bottom: 1px solid var(--color-button);
|
border-bottom: 1px solid var(--color-button);
|
||||||
background-color: var(--color-button);
|
background-color: var(--color-button);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
border: none;
|
border: none;
|
||||||
border-bottom: 3px solid #E2E9F0;
|
border-bottom: 3px solid #E2E9F0;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
|
|
||||||
&_selected {
|
&_selected {
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
border: 16px solid white;
|
border: 16px solid white;
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_info {
|
&_info {
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
border-radius: var(--border-radius-m);
|
border-radius: var(--border-radius-m);
|
||||||
box-shadow: 2px 2px 5px var(--color-border);
|
box-shadow: 2px 2px 5px var(--color-border);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,15 +42,23 @@ export default class RecommendationsTeamByAuthor {
|
||||||
projectType,
|
projectType,
|
||||||
|
|
||||||
(lotOfLazy.length ? {
|
(lotOfLazy.length ? {
|
||||||
title: lotOfLazy,
|
title: 'recommendations.author.lotOfLazy.title',
|
||||||
description: 'recommendations.author.lotOfLazy',
|
description: 'recommendations.author.lotOfLazy.description',
|
||||||
type: RECOMMENDATION_TYPES.ALERT,
|
type: RECOMMENDATION_TYPES.ALERT,
|
||||||
|
arguments: {
|
||||||
|
title: lotOfLazy.length,
|
||||||
|
description: lotOfLazy.join(';\n- '),
|
||||||
|
},
|
||||||
} : null),
|
} : null),
|
||||||
|
|
||||||
(manyLazy.length ? {
|
(manyLazy.length ? {
|
||||||
title: manyLazy,
|
title: 'recommendations.author.manyLazy.title',
|
||||||
description: 'recommendations.author.manyLazy',
|
description: 'recommendations.author.manyLazy.description',
|
||||||
type: RECOMMENDATION_TYPES.WARNING,
|
type: RECOMMENDATION_TYPES.WARNING,
|
||||||
|
arguments: {
|
||||||
|
title: manyLazy.length,
|
||||||
|
description: manyLazy.join(';\n- '),
|
||||||
|
},
|
||||||
} : null),
|
} : null),
|
||||||
|
|
||||||
(oneTypeMans.length ? {
|
(oneTypeMans.length ? {
|
||||||
|
|
|
@ -115,10 +115,6 @@ export function getShortNumber(value: number) {
|
||||||
return (value || 0).toFixed(fractionDigits);
|
return (value || 0).toFixed(fractionDigits);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getShortName(name: string) {
|
|
||||||
return name?.split(/[\s.]+/gm)[1] || name;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getShortDateRange({ from, to }: any) {
|
export function getShortDateRange({ from, to }: any) {
|
||||||
return from && to
|
return from && to
|
||||||
? `${getShortDate(from)} — ${getDate(to)}`
|
? `${getShortDate(from)} — ${getDate(to)}`
|
||||||
|
|
|
@ -46,13 +46,13 @@
|
||||||
&:nth-child(4n+2):hover,
|
&:nth-child(4n+2):hover,
|
||||||
&_selected {
|
&_selected {
|
||||||
background-color: #35353F;
|
background-color: #35353F;
|
||||||
--temp-color: white;
|
--temp-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child:active,
|
&:first-child:active,
|
||||||
&:nth-child(4n+2):active {
|
&:nth-child(4n+2):active {
|
||||||
background-color: #45454F;
|
background-color: #45454F;
|
||||||
--temp-color: white;
|
--temp-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_text {
|
&_text {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
padding: 20px 34px 20px 24px;
|
padding: 20px 34px 20px 24px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
|
|
||||||
&_title {
|
&_title {
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: white;
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&_main,
|
&_main,
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
|
|
||||||
.sidebar_item:hover,
|
.sidebar_item:hover,
|
||||||
.sidebar_item.selected {
|
.sidebar_item.selected {
|
||||||
color: #FFFFFF;
|
color: var(--color-white);
|
||||||
background-color: #252735;
|
background-color: #252735;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
color: #84858D;
|
color: #84858D;
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
color: #FFFFFF;
|
color: var(--color-white);
|
||||||
background-color: #37394B;
|
background-color: #37394B;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,14 @@ const Month = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||||
const max = statistic.commitsByTimestampCounter.max;
|
const max = statistic.commitsByTimestampCounter.max;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageWrapper template="table">
|
||||||
<PageWrapper template="table">
|
<YearChart
|
||||||
<YearChart
|
showEvents={false}
|
||||||
showEvents={false}
|
maxCommits={max}
|
||||||
maxCommits={max}
|
authors={[author]}
|
||||||
authors={[author]}
|
wordDays={statistic.allCommitsByTimestamp}
|
||||||
wordDays={statistic.allCommitsByTimestamp}
|
/>
|
||||||
/>
|
</PageWrapper>
|
||||||
</PageWrapper>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: #FFFFFF;
|
background-color: var(--color-white);
|
||||||
color: var(--color-grey);
|
color: var(--color-grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { observer } from 'mobx-react-lite';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import ISort from 'ts/interfaces/Sort';
|
import ISort from 'ts/interfaces/Sort';
|
||||||
|
import ICommit from 'ts/interfaces/Commit';
|
||||||
import IHashMap from 'ts/interfaces/HashMap';
|
import IHashMap from 'ts/interfaces/HashMap';
|
||||||
import { IPaginationRequest, IPagination } from 'ts/interfaces/Pagination';
|
import { IPaginationRequest, IPagination } from 'ts/interfaces/Pagination';
|
||||||
import { getMoney, getShortNumber } from 'ts/helpers/formatter';
|
import { getDate, getMoney, getShortNumber } from 'ts/helpers/formatter';
|
||||||
import dataGripStore from 'ts/store/DataGrip';
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||||
|
@ -67,6 +68,7 @@ function AuthorView({ response, updateSort, rowsForExcel, mode }: IAuthorViewPro
|
||||||
width={200}
|
width={200}
|
||||||
/>
|
/>
|
||||||
<Column
|
<Column
|
||||||
|
title="page.team.author.status"
|
||||||
template={(row: any) => {
|
template={(row: any) => {
|
||||||
let value = works;
|
let value = works;
|
||||||
if (row.isDismissed) value = dismissed;
|
if (row.isDismissed) value = dismissed;
|
||||||
|
@ -75,6 +77,19 @@ function AuthorView({ response, updateSort, rowsForExcel, mode }: IAuthorViewPro
|
||||||
}}
|
}}
|
||||||
width={100}
|
width={100}
|
||||||
/>
|
/>
|
||||||
|
<Column
|
||||||
|
template={ColumnTypesEnum.STRING}
|
||||||
|
properties="firstCommit"
|
||||||
|
title="page.team.author.firstCommit"
|
||||||
|
width={130}
|
||||||
|
formatter={(commit: ICommit) => getDate(commit.timestamp)}
|
||||||
|
/>
|
||||||
|
<Column
|
||||||
|
template={ColumnTypesEnum.SHORT_NUMBER}
|
||||||
|
title="page.team.author.daysAll"
|
||||||
|
properties="daysAll"
|
||||||
|
width={90}
|
||||||
|
/>
|
||||||
<Column
|
<Column
|
||||||
isSortable="daysWorked"
|
isSortable="daysWorked"
|
||||||
title="page.team.author.workedLosses"
|
title="page.team.author.workedLosses"
|
||||||
|
|
|
@ -130,7 +130,7 @@ const Extension = observer(({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title="sidebar.team.extension"/>
|
<Title title="page.team.extension.extension"/>
|
||||||
<DataLoader
|
<DataLoader
|
||||||
to="response"
|
to="response"
|
||||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||||
|
|
|
@ -130,7 +130,7 @@ const Type = observer(({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title="sidebar.team.extension"/>
|
<Title title="page.team.extension.type"/>
|
||||||
<DataLoader
|
<DataLoader
|
||||||
to="response"
|
to="response"
|
||||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Table from 'ts/components/Table';
|
import PieChart from 'ts/components/PieChart';
|
||||||
import Column from 'ts/components/Table/components/Column';
|
|
||||||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
|
||||||
import LineChart from 'ts/components/LineChart';
|
|
||||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||||
|
import Description from 'ts/components/Description';
|
||||||
|
import PageWrapper from 'ts/components/Page/wrapper';
|
||||||
|
import PageColumn from 'ts/components/Page/column';
|
||||||
|
|
||||||
import dataGripStore from 'ts/store/DataGrip';
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
import DataGripByPR from 'ts/helpers/DataGrip/components/pr';
|
import DataGripByPR from 'ts/helpers/DataGrip/components/pr';
|
||||||
|
|
||||||
function Total() {
|
function Total() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const allPR = dataGripStore.dataGrip.pr.statistic;
|
const allPR = dataGripStore.dataGrip.pr.statistic;
|
||||||
|
|
||||||
const workChart = DataGripByPR.getPRByGroups(allPR, 'workDays');
|
const workChart = DataGripByPR.getPRByGroups(allPR, 'workDays');
|
||||||
|
@ -27,59 +30,36 @@ function Total() {
|
||||||
suffix: 'page.team.pr.days',
|
suffix: 'page.team.pr.days',
|
||||||
});
|
});
|
||||||
|
|
||||||
const rows = [
|
console.log(weightedAverage.toFixed(1));
|
||||||
{
|
|
||||||
workDays: workChart.details,
|
|
||||||
delayDays: delayChart.details,
|
|
||||||
weightedAverage: weightedAverage.toFixed(1),
|
|
||||||
weightedAverageDetails: {
|
|
||||||
workDays: workDaysWeightedAverage,
|
|
||||||
delayDays: delayDaysWeightedAverage,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table rows={rows}>
|
<PageWrapper>
|
||||||
<Column
|
<PageColumn>
|
||||||
title="page.team.pr.workDays"
|
<PieChart
|
||||||
properties="workDays"
|
title="page.team.pr.workDays"
|
||||||
template={(details: any) => (
|
options={workChartOptions}
|
||||||
<LineChart
|
details={workChart.details}
|
||||||
options={workChartOptions}
|
/>
|
||||||
details={details}
|
<PieChart
|
||||||
/>
|
title="page.team.pr.middleTimeRelease"
|
||||||
)}
|
options={weightedAverageChart}
|
||||||
/>
|
details={{
|
||||||
<Column
|
'page.team.pr.work': workDaysWeightedAverage,
|
||||||
title="page.team.pr.delayDays"
|
'page.team.pr.delay': delayDaysWeightedAverage,
|
||||||
properties="delayDays"
|
}}
|
||||||
template={(details: any) => (
|
/>
|
||||||
<LineChart
|
</PageColumn>
|
||||||
options={delayChartOptions}
|
<PageColumn>
|
||||||
details={details}
|
<PieChart
|
||||||
/>
|
title="page.team.pr.delayDays"
|
||||||
)}
|
options={delayChartOptions}
|
||||||
/>
|
details={delayChart.details}
|
||||||
<Column
|
/>
|
||||||
properties="weightedAverage"
|
<Description text={t('page.team.pr.description1')} />
|
||||||
template={ColumnTypesEnum.SHORT_NUMBER}
|
<Description text={t('page.team.pr.description2')} />
|
||||||
/>
|
<Description text={t('page.team.pr.description3')} />
|
||||||
<Column
|
</PageColumn>
|
||||||
title="page.team.pr.middleTimeRelease"
|
</PageWrapper>
|
||||||
properties="weightedAverageDetails"
|
|
||||||
width={300}
|
|
||||||
template={(item: any) => (
|
|
||||||
<LineChart
|
|
||||||
options={weightedAverageChart}
|
|
||||||
details={{
|
|
||||||
'page.team.pr.work': item.workDays,
|
|
||||||
'page.team.pr.delay': item.delayDays,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Table>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
import ISort from 'ts/interfaces/Sort';
|
import ISort from 'ts/interfaces/Sort';
|
||||||
import { IPaginationRequest } from 'ts/interfaces/Pagination';
|
import { IPaginationRequest } from 'ts/interfaces/Pagination';
|
||||||
import dataGripStore from 'ts/store/DataGrip';
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||||
import PageWrapper from 'ts/components/Page/wrapper';
|
|
||||||
import PageColumn from 'ts/components/Page/column';
|
|
||||||
import Description from 'ts/components/Description';
|
|
||||||
import DataLoader from 'ts/components/DataLoader';
|
import DataLoader from 'ts/components/DataLoader';
|
||||||
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
||||||
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
||||||
|
@ -24,7 +20,6 @@ import All from './All';
|
||||||
const PR = observer(({
|
const PR = observer(({
|
||||||
mode,
|
mode,
|
||||||
}: ICommonPageProps): React.ReactElement | null => {
|
}: ICommonPageProps): React.ReactElement | null => {
|
||||||
const { t } = useTranslation();
|
|
||||||
const allPR = dataGripStore.dataGrip.pr.statistic;
|
const allPR = dataGripStore.dataGrip.pr.statistic;
|
||||||
const rows = allPR.filter((item: any) => item.delayDays > 3);
|
const rows = allPR.filter((item: any) => item.delayDays > 3);
|
||||||
if (rows?.length < 2) return mode !== 'print' ? (<NothingFound />) : null;
|
if (rows?.length < 2) return mode !== 'print' ? (<NothingFound />) : null;
|
||||||
|
@ -37,24 +32,6 @@ const PR = observer(({
|
||||||
<Title title="page.team.pr.oneTaskDays"/>
|
<Title title="page.team.pr.oneTaskDays"/>
|
||||||
<Total/>
|
<Total/>
|
||||||
|
|
||||||
<PageWrapper>
|
|
||||||
<PageColumn>
|
|
||||||
<Description
|
|
||||||
text={t('page.team.pr.description1')}
|
|
||||||
/>
|
|
||||||
<Description
|
|
||||||
text={t('page.team.pr.description2')}
|
|
||||||
/>
|
|
||||||
</PageColumn>
|
|
||||||
<PageColumn>
|
|
||||||
<Description
|
|
||||||
text={t('page.team.pr.description3')}
|
|
||||||
/>
|
|
||||||
</PageColumn>
|
|
||||||
</PageWrapper>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<Title title="page.team.pr.statByAuthors"/>
|
<Title title="page.team.pr.statByAuthors"/>
|
||||||
<DataLoader
|
<DataLoader
|
||||||
to="response"
|
to="response"
|
||||||
|
|
|
@ -7,15 +7,9 @@ import Title from 'ts/components/Title';
|
||||||
import Races from 'ts/components/Races';
|
import Races from 'ts/components/Races';
|
||||||
import CityBuilder from 'ts/components/CityBuilder';
|
import CityBuilder from 'ts/components/CityBuilder';
|
||||||
|
|
||||||
import DataView from 'ts/components/DataView';
|
|
||||||
import ShowSymbol from 'ts/components/ShowSymbol';
|
|
||||||
import Column from 'ts/components/Table/components/Column';
|
|
||||||
import LineChart from 'ts/components/LineChart';
|
|
||||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
|
||||||
import GameConsole from 'ts/components/GameConsole';
|
import GameConsole from 'ts/components/GameConsole';
|
||||||
import GameBanner from 'ts/components/GameBanner';
|
import SwimmingPool from 'ts/components/SwimmingPool';
|
||||||
import Quize from 'ts/components/Quize';
|
import Quize from 'ts/components/Quize';
|
||||||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
|
||||||
|
|
||||||
const TeamBuilding = observer((): React.ReactElement => {
|
const TeamBuilding = observer((): React.ReactElement => {
|
||||||
const filesByAuthor = dataGripStore.fileGrip.author?.statisticByName || {};
|
const filesByAuthor = dataGripStore.fileGrip.author?.statisticByName || {};
|
||||||
|
@ -37,86 +31,21 @@ const TeamBuilding = observer((): React.ReactElement => {
|
||||||
const maxMessageLength = [...tracksAuth]
|
const maxMessageLength = [...tracksAuth]
|
||||||
.sort((a: any, b: any) => b.maxMessageLength - a.maxMessageLength)
|
.sort((a: any, b: any) => b.maxMessageLength - a.maxMessageLength)
|
||||||
.map((item: any) => ({ title: item.author, value: item.maxMessageLength }));
|
.map((item: any) => ({ title: item.author, value: item.maxMessageLength }));
|
||||||
const chartMessageLength = getOptions({ max: maxMessageLength[0].value, suffix: 'сиволов' });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title="Скорость коммитов в день"/>
|
|
||||||
<GameConsole />
|
|
||||||
|
|
||||||
<Title title="Квиз"/>
|
<Title title="Квиз"/>
|
||||||
<Quize />
|
<Quize />
|
||||||
<Title title="Скорость закрытия задач"/>
|
<Title title="Скорость закрытия задач"/>
|
||||||
<Races tracks={tracks} />
|
<Races tracks={tracks} />
|
||||||
|
|
||||||
<Title title="Максимальная длинна подписи коммита"/>
|
<Title title="Максимальная длинна подписи коммита"/>
|
||||||
<GameBanner src="./assets/games/wheel.jpg" />
|
<SwimmingPool tracks={maxMessageLength}/>
|
||||||
<DataView rows={maxMessageLength}>
|
|
||||||
<Column
|
|
||||||
isFixed
|
|
||||||
title="Сотрудник"
|
|
||||||
properties="title"
|
|
||||||
template={(text: string) => (
|
|
||||||
<ShowSymbol
|
|
||||||
text={text}
|
|
||||||
length={14}
|
|
||||||
mode="table-row"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
width={360}
|
|
||||||
/>
|
|
||||||
<Column
|
|
||||||
template={ColumnTypesEnum.SHORT_NUMBER}
|
|
||||||
properties="value"
|
|
||||||
width={50}
|
|
||||||
/>
|
|
||||||
<Column
|
|
||||||
title="Количество символов"
|
|
||||||
properties="value"
|
|
||||||
template={(messageLength: number) => (
|
|
||||||
<LineChart
|
|
||||||
options={chartMessageLength}
|
|
||||||
value={messageLength}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</DataView>
|
|
||||||
|
|
||||||
<Title title="Количество созданных файлов, если бы это был город"/>
|
<Title title="Количество созданных файлов, если бы это был город"/>
|
||||||
<CityBuilder valuesByTitle={addedFilesByAuthor} />
|
<CityBuilder valuesByTitle={addedFilesByAuthor} />
|
||||||
|
<Title title="Скорость коммитов в день"/>
|
||||||
<Title title="Количество созданных папок"/>
|
<GameConsole />
|
||||||
<DataView rows={maxMessageLength}>
|
|
||||||
<Column
|
|
||||||
isFixed
|
|
||||||
title="Сотрудник"
|
|
||||||
properties="title"
|
|
||||||
template={(text: string) => (
|
|
||||||
<ShowSymbol
|
|
||||||
text={text}
|
|
||||||
length={14}
|
|
||||||
mode="table-row"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
width={360}
|
|
||||||
/>
|
|
||||||
<Column
|
|
||||||
template={ColumnTypesEnum.SHORT_NUMBER}
|
|
||||||
properties="value"
|
|
||||||
width={50}
|
|
||||||
/>
|
|
||||||
<Column
|
|
||||||
title="Количество символов"
|
|
||||||
properties="value"
|
|
||||||
template={(messageLength: number) => (
|
|
||||||
<LineChart
|
|
||||||
options={chartMessageLength}
|
|
||||||
value={messageLength}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</DataView>
|
|
||||||
{'Квиз'}
|
|
||||||
{'Небоскребы вверх ввиде графика'}
|
{'Небоскребы вверх ввиде графика'}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,7 +22,9 @@ export default `
|
||||||
§ sidebar.team.removedTree: Gelöschte dateien
|
§ sidebar.team.removedTree: Gelöschte dateien
|
||||||
§ sidebar.team.files: Dateien
|
§ sidebar.team.files: Dateien
|
||||||
§ sidebar.team.removedFiles: Gelöschte Dateien
|
§ sidebar.team.removedFiles: Gelöschte Dateien
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: Aufgabenliste
|
§ sidebar.team.tasks: Aufgabenliste
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: Zeitplan
|
§ sidebar.team.hours: Zeitplan
|
||||||
§ sidebar.team.commits: All commits
|
§ sidebar.team.commits: All commits
|
||||||
§ sidebar.team.changes: Alle Änderungen
|
§ sidebar.team.changes: Alle Änderungen
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Employee statistics
|
§ 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.
|
§ 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.
|
||||||
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Types of work
|
§ page.team.author.types: Types of work
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -122,11 +125,11 @@ export default `
|
||||||
§ page.team.pr.lastCommitTime: Last
|
§ page.team.pr.lastCommitTime: Last
|
||||||
§ page.team.pr.workDays: Development days
|
§ page.team.pr.workDays: Development days
|
||||||
§ page.team.pr.delayDays: Days waiting for merge
|
§ page.team.pr.delayDays: Days waiting for merge
|
||||||
|
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: Merge Date
|
§ page.team.pr.date: Merge Date
|
||||||
§ page.team.pr.mergeAuthor: Merged by
|
§ page.team.pr.mergeAuthor: Merged by
|
||||||
§ page.team.pr.author: Employee
|
§ page.team.pr.author: Employee
|
||||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
|
||||||
§ page.team.pr.work: development
|
§ page.team.pr.work: development
|
||||||
§ page.team.pr.delay: waiting
|
§ page.team.pr.delay: waiting
|
||||||
§ page.team.pr.days: days
|
§ page.team.pr.days: days
|
||||||
|
@ -146,6 +149,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Merged by user
|
§ page.team.tasks.prAuthor: Merged by user
|
||||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||||
§ page.team.tasks.comments: Comments
|
§ page.team.tasks.comments: Comments
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
§ page.person.print.photo.description: space for a photo
|
§ page.person.print.photo.description: space for a photo
|
||||||
§ page.person.total.title: Main characteristics
|
§ page.person.total.title: Main characteristics
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
|
@ -97,22 +97,22 @@ export default `
|
||||||
§ achievements.oneExtension.description: только он работает с файлами определенного расширения
|
§ achievements.oneExtension.description: только он работает с файлами определенного расширения
|
||||||
§ achievements.fileRush.title: Zerg Rush
|
§ achievements.fileRush.title: Zerg Rush
|
||||||
§ achievements.fileRush.description: created the most files in the project
|
§ achievements.fileRush.description: created the most files in the project
|
||||||
§ achievements.moreLintHint.title: Грамар-наци
|
§ achievements.moreLintHint.title: Grammar Nazi
|
||||||
§ achievements.moreLintHint.description: больше всех создал или изменил в правилах авто-проверки кода
|
§ achievements.moreLintHint.description: more than anyone created or changed the code-style rules
|
||||||
§ achievements.moreReadMe.title: Летописец
|
§ achievements.moreReadMe.title: Chronicler
|
||||||
§ achievements.moreReadMe.description: больше всех создал или изменил файлов MD
|
§ achievements.moreReadMe.description: more than anyone created or modified MD files
|
||||||
§ achievements.moreDevOps.title: DevOps
|
§ achievements.moreDevOps.title: DevOps
|
||||||
§ achievements.moreDevOps.description: больше всех создал или изменил файлов для CI/CD
|
§ achievements.moreDevOps.description: more than anyone created or modified files for CI/CD
|
||||||
§ achievements.moreTests.title: Тестировщик
|
§ achievements.moreTests.title: Tester
|
||||||
§ achievements.moreTests.description: больше всех создал или изменил файлов для тестирования
|
§ achievements.moreTests.description: more than anyone created or modified files for testing
|
||||||
§ achievements.allRelease.title: Фулл хаус
|
§ achievements.allRelease.title: Full house
|
||||||
§ achievements.allRelease.description: есть релиз, собранный только из его задач
|
§ achievements.allRelease.description: there is a release compiled only from his tasks
|
||||||
§ achievements.firstCommit.title: First come, first served
|
§ achievements.firstCommit.title: First come, first served
|
||||||
§ achievements.firstCommit.description: first commit in this project
|
§ achievements.firstCommit.description: first commit on the project
|
||||||
§ achievements.lastCommit.title: I've finished
|
§ achievements.lastCommit.title: I've finished
|
||||||
§ achievements.lastCommit.description: последний коммит на проекте
|
§ achievements.lastCommit.description: last commit on the project
|
||||||
§ achievements.firstLastCommit.title: From beginning to end
|
§ achievements.firstLastCommit.title: From beginning to end
|
||||||
§ achievements.firstLastCommit.description: первый и последний коммит на проекте
|
§ achievements.firstLastCommit.description: first and last commit on the project
|
||||||
§ achievements.longFilePath.title: Закрома родины
|
§ achievements.longFilePath.title: Закрома родины
|
||||||
§ achievements.longFilePath.description: the first created the file with the deepest directory
|
§ achievements.longFilePath.description: the first created the file with the deepest directory
|
||||||
§ achievements.longFileName.title: Size matters
|
§ achievements.longFileName.title: Size matters
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Employee statistics
|
§ 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.
|
§ 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.
|
||||||
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Types of work
|
§ page.team.author.types: Types of work
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: tasks
|
§ page.team.pr.tasks: tasks
|
||||||
§ page.team.pr.firstCommitTime: First commit
|
§ page.team.pr.firstCommitTime: First commit
|
||||||
§ page.team.pr.lastCommitTime: Last
|
§ page.team.pr.lastCommitTime: Last
|
||||||
§ page.team.pr.workDays: Development days
|
§ page.team.pr.workDays: Average time spent working on a task
|
||||||
§ page.team.pr.delayDays: Days waiting for merge
|
§ page.team.pr.delayDays: Average time of the PR review
|
||||||
|
§ page.team.pr.middleTimeRelease: The ratio of development time to review time
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: Merge Date
|
§ page.team.pr.date: Merge Date
|
||||||
§ page.team.pr.mergeAuthor: Merged by
|
§ page.team.pr.mergeAuthor: Merged by
|
||||||
§ page.team.pr.author: Employee
|
§ page.team.pr.author: Employee
|
||||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
|
||||||
§ page.team.pr.work: development
|
§ page.team.pr.work: development
|
||||||
§ page.team.pr.delay: waiting
|
§ page.team.pr.delay: waiting
|
||||||
§ page.team.pr.days: days
|
§ page.team.pr.days: days
|
||||||
|
@ -146,14 +149,16 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Merged by user
|
§ page.team.tasks.prAuthor: Merged by user
|
||||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||||
§ page.team.tasks.comments: Comments
|
§ page.team.tasks.comments: Comments
|
||||||
§ page.team.extension.name: Extension
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
§ page.team.extension.path: Path
|
§ page.team.extension.path: Path
|
||||||
§ page.team.extension.current.count: Number
|
§ page.team.extension.current.count: Number
|
||||||
§ page.team.extension.removed.count: Number of removed
|
§ page.team.extension.removed.count: Number of removed
|
||||||
§ page.team.extension.files: files
|
§ page.team.extension.files: files
|
||||||
§ page.team.release.title: Release
|
§ page.team.release.title: Release
|
||||||
§ page.team.release.from: Create date
|
§ page.team.release.from: Created date
|
||||||
§ page.team.release.to: Last merge date
|
§ page.team.release.to: Delivery date
|
||||||
§ page.team.release.delay: Preparation days
|
§ page.team.release.delay: Preparation days
|
||||||
§ page.team.release.waiting: Days of waiting for next release
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
|
@ -22,7 +22,9 @@ export default `
|
||||||
§ sidebar.team.removedTree: Archivos eliminados
|
§ sidebar.team.removedTree: Archivos eliminados
|
||||||
§ sidebar.team.files: Ficheros
|
§ sidebar.team.files: Ficheros
|
||||||
§ sidebar.team.removedFiles: Archivos eliminados
|
§ sidebar.team.removedFiles: Archivos eliminados
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: Lista de tareas
|
§ sidebar.team.tasks: Lista de tareas
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: Horario
|
§ sidebar.team.hours: Horario
|
||||||
§ sidebar.team.commits: All commits
|
§ sidebar.team.commits: All commits
|
||||||
§ sidebar.team.changes: Todos los cambios
|
§ sidebar.team.changes: Todos los cambios
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Estadísticas de los empleados
|
§ page.team.author.title: Estadísticas de los empleados
|
||||||
§ page.team.author.description1: Parte de las estadísticas (la velocidad del trabajo, el dinero gastado, etc.) para los empleados con el tipo de "Asistente" no cuenta, ya que no es un rol permanente en el proyecto. Su trabajo es insignificante y puede ser ignorado.
|
§ page.team.author.description1: Parte de las estadísticas (la velocidad del trabajo, el dinero gastado, etc.) para los empleados con el tipo de "Asistente" no cuenta, ya que no es un rol permanente en el proyecto. Su trabajo es insignificante y puede ser ignorado.
|
||||||
§ page.team.author.description2: La clasificación predeterminada es la clasificación por número de tareas y grupos(empleados actuales, despedidos, ayudantes).
|
§ page.team.author.description2: La clasificación predeterminada es la clasificación por número de tareas y grupos(empleados actuales, despedidos, ayudantes).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Tipo de trabajo
|
§ page.team.author.types: Tipo de trabajo
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: tareas
|
§ page.team.pr.tasks: tareas
|
||||||
§ page.team.pr.firstCommitTime: Primer commits
|
§ page.team.pr.firstCommitTime: Primer commits
|
||||||
§ page.team.pr.lastCommitTime: Last
|
§ page.team.pr.lastCommitTime: Last
|
||||||
§ page.team.pr.workDays: Days of development
|
§ page.team.pr.workDays: Average time spent working on a task
|
||||||
§ page.team.pr.delayDays: Days of waiting for the infusion
|
§ page.team.pr.delayDays: Average time of the PR review
|
||||||
|
§ page.team.pr.middleTimeRelease: The ratio of development time to review time
|
||||||
§ page.team.pr.commits: commits
|
§ page.team.pr.commits: commits
|
||||||
§ page.team.pr.date: Date of injection
|
§ page.team.pr.date: Date of injection
|
||||||
§ page.team.pr.mergeAuthor: I poured it in
|
§ page.team.pr.mergeAuthor: I poured it in
|
||||||
§ page.team.pr.author: Employee
|
§ page.team.pr.author: Employee
|
||||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
|
||||||
§ page.team.pr.work: development
|
§ page.team.pr.work: development
|
||||||
§ page.team.pr.delay: expectation
|
§ page.team.pr.delay: expectation
|
||||||
§ page.team.pr.days: days
|
§ page.team.pr.days: days
|
||||||
|
@ -146,6 +149,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: I poured it in
|
§ page.team.tasks.prAuthor: I poured it in
|
||||||
§ page.team.tasks.prDelayDays: Days of waiting for the infusion
|
§ page.team.tasks.prDelayDays: Days of waiting for the infusion
|
||||||
§ page.team.tasks.comments: Comments
|
§ page.team.tasks.comments: Comments
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
§ page.person.print.photo.description: a place for a photo
|
§ page.person.print.photo.description: a place for a photo
|
||||||
§ page.person.total.title: Main Features
|
§ page.person.total.title: Main Features
|
||||||
|
|
|
@ -1,506 +1,515 @@
|
||||||
export default `
|
export default `
|
||||||
|
§ recommendations.modal.cancel: Ok
|
||||||
|
§ recommendations.modal.open: More
|
||||||
§ recommendations.title
|
§ recommendations.title
|
||||||
Рекомендации и факты
|
Recommendations and facts
|
||||||
|
|
||||||
§ recommendations.timestamp.firstCommit.description
|
§ recommendations.timestamp.firstCommit.description
|
||||||
сделал первый коммит
|
made the first commit
|
||||||
|
|
||||||
День недели: $1
|
Day of the Week: $1
|
||||||
|
|
||||||
§ recommendations.timestamp.lastCommit.description
|
§ recommendations.timestamp.lastCommit.description
|
||||||
сделал последний коммит
|
made the last commit
|
||||||
|
|
||||||
День недели: $1
|
Day of the Week: $1
|
||||||
|
|
||||||
§ recommendations.timestamp.common.title: $1 дней
|
§ recommendations.timestamp.common.title: $1 days
|
||||||
§ recommendations.timestamp.allDays.description: от первого до последнего коммита (включая выходные и праздники).
|
§ recommendations.timestamp.allDays.description: from the first to the last commit (including weekends and holidays).
|
||||||
§ recommendations.timestamp.lossesDays.description: без коммитов, даже с учётом выходных, отпуска и государственных праздников.
|
§ recommendations.timestamp.lossesDays.description: days without commits, even considering weekends, vacation, and public holidays.
|
||||||
§ recommendations.timestamp.weekendDays.description
|
§ recommendations.timestamp.weekendDays.description
|
||||||
работы на выходных
|
working on weekends
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
- the client pays double the price for work on a weekend day;
|
||||||
- сотрудники быстрее выгорают;
|
- employees burn out faster;
|
||||||
|
|
||||||
§ recommendations.timestamp.regularWeekendWord.title: Регулярные переработки
|
§ recommendations.timestamp.regularWeekendWord.title: Regular Overtime
|
||||||
§ recommendations.timestamp.sometimeWeekendWord.title: Бывают переработки
|
§ recommendations.timestamp.sometimeWeekendWord.title: Occasional Overtime
|
||||||
§ recommendations.timestamp.weekendWord.description
|
§ recommendations.timestamp.weekendWord.description
|
||||||
Вероятно, стоит сменить менеджера проекта, аналитика и архитектора.
|
It might be advisable to change the project manager, analyst, and architect.
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
- the client pays double the price for work on a weekend day;
|
||||||
- качество продукта, как правило, получается низкое;
|
- the quality of the product is usually low;
|
||||||
- часть сотрудников увольняется;
|
- some employees resign;
|
||||||
- из-за спешки появляются новые ошибки;
|
- new errors emerge due to the rush;
|
||||||
|
|
||||||
# Скорее всего:
|
# Most likely:
|
||||||
- неверно оценили сроки в самом начале;
|
- deadlines were incorrectly estimated at the beginning;
|
||||||
- тех. задание отсутствует;
|
- technical specifications are missing;
|
||||||
- слабая аналитика;
|
- weak analytics;
|
||||||
- слабая архитектура (архитектора не нанимали, а команда состоит из мидл разработчиков);
|
- weak architecture (no architect was hired, and the team consists of mid-level developers);
|
||||||
- сначала начали писать код, потом проектировать;
|
- started writing code first, then planning;
|
||||||
- нет нормальных процессов, чтобы понять ошибки;
|
- lack of proper processes to understand mistakes;
|
||||||
|
|
||||||
§ recommendations.timestamp.neverWeekendWord.title: Обычно без переработок
|
§ recommendations.timestamp.neverWeekendWord.title: Usually Without Overtime
|
||||||
§ recommendations.timestamp.neverWeekendWord.description
|
§ recommendations.timestamp.neverWeekendWord.description
|
||||||
Но иногда бывают.
|
But sometimes it happens.
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
- the client pays double the price for work on a weekend day;
|
||||||
- сотрудники быстрее выгорают;
|
- employees burn out faster;
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.title
|
§ recommendations.scope.parallelism.not.title
|
||||||
Нет параллельных работ
|
No Parallel Work
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.description
|
§ recommendations.scope.parallelism.not.description
|
||||||
любую фичу в один момент времени делает один человек.
|
any feature at any given time is done by one person.
|
||||||
|
|
||||||
# Метод расчёта:
|
# Calculation method:
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
- person-days are divided by the actual days for each feature;
|
||||||
- находим среднее арифметическое;
|
- we find the arithmetic mean;
|
||||||
- если результат меньше 1.3 считаем, что параллельных работ в рамках большинства фичей обычно нет;
|
- if the result is less than 1.3, we consider that there is usually no parallel work within most features;
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- повышается bus factor;
|
- increases bus factor;
|
||||||
- сотрудники медленнее развиваются;
|
- employees develop more slowly;
|
||||||
- трудно качественно проверить работу сотрудника;
|
- difficult to properly check an employee's work;
|
||||||
|
|
||||||
# Почему это хорошо:
|
# Why this is good:
|
||||||
- появляются эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
- experts emerge who are deeply immersed in the subject area and can offer more quality solutions;
|
||||||
- скорее всего не бывает merge конфликтов;
|
- most likely there are no merge conflicts;
|
||||||
- проект может очень быстро параллельно развиваться в разные стороны;
|
- the project can quickly develop in different directions simultaneously;
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.title
|
§ recommendations.scope.parallelism.has.title
|
||||||
Часть работ параллельно
|
Some Work Done in Parallel
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.description
|
§ recommendations.scope.parallelism.has.description
|
||||||
Иногда фичу делают одновременно несколько человек.
|
Sometimes a feature is worked on simultaneously by several people.
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делается параллельно;
|
|
||||||
|
|
||||||
|
# Calculation method:
|
||||||
|
- person-days are divided by the actual days for each feature;
|
||||||
|
- we find the arithmetic mean;
|
||||||
|
- if the result is from 1.3 to 2.0, we consider that some of the work within different features is sometimes done in parallel;
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.title
|
§ recommendations.scope.parallelism.every.title
|
||||||
Параллельные работы
|
Parallel Work
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.description
|
§ recommendations.scope.parallelism.every.description
|
||||||
любую фичу в один момент времени делают несколько человек
|
any feature at any given time is worked on by several people
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат больше двух считаем, что большая часть работ в рамках разных фичей обычно делается параллельно;
|
|
||||||
|
|
||||||
|
# Calculation method:
|
||||||
|
- person-days are divided by the actual days for each feature;
|
||||||
|
- we find the arithmetic mean;
|
||||||
|
- if the result is more than two, we consider that most of the work within different features is usually done in parallel;
|
||||||
|
|
||||||
§ recommendations.scope.money
|
§ recommendations.scope.money
|
||||||
в такую сумму можно оценить работу по данному проекту.
|
this is the estimated cost for the work on this project.
|
||||||
|
|
||||||
# Метод расчёта:
|
# Calculation method:
|
||||||
- человеко-дни затраченные на разработку умножаются на индивидуальную зарплату разработчиков;
|
- person-days spent on development are multiplied by the individual salaries of the developers;
|
||||||
|
|
||||||
Изменить зарплату каждого разработчика, для более точной суммы, можно в разделе «Настройки»
|
To change the salary of each developer for a more accurate total, go to the "Settings" section.
|
||||||
|
|
||||||
# Это много или мало?
|
# Is this too much or too little?
|
||||||
Для ответа на этот вопрос, нужно ответить на следующие:
|
To answer this question, consider the following:
|
||||||
- Можно ли за эти деньги было купить готовое решение?
|
- Could a ready-made solution have been purchased for this amount of money?
|
||||||
- Можно ли за эти деньги сделать более хороший продукт?
|
- Could a better product have been developed for this amount of money?
|
||||||
|
|
||||||
Если ответ на оба вопроса «да», то возможно, разработка с нуля не стоила потраченных на неё денег.
|
If the answer to both questions is "yes," then perhaps developing from scratch was not worth the money spent.
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.title
|
§ recommendations.scope.bus.everyHasOne.title
|
||||||
Bus factor = 1
|
Bus factor = 1
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.description
|
§ recommendations.scope.bus.everyHasOne.description
|
||||||
В большинство фич погружен один человек.
|
Most features are deeply understood by only one person.
|
||||||
Надо переключать людей.
|
It's necessary to rotate people.
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- если сотрудники будут увольняться, будет трудно продолжить их работу;
|
- if employees resign, it will be difficult to continue their work;
|
||||||
- невозможно контролировать качество его кода;
|
- it’s impossible to control the quality of their code;
|
||||||
|
|
||||||
# Как делается выборка:
|
# How the sample is chosen:
|
||||||
- более 80% коммитов в фичу делает один человек;
|
- more than 80% of commits in a feature are made by one person;
|
||||||
- проект имеет более 60% таких фичей;
|
- the project has more than 60% of such features;
|
||||||
|
|
||||||
§ recommendations.scope.bus.oneMaintainer
|
§ recommendations.scope.bus.oneMaintainer
|
||||||
в фичи погружен один человек.
|
one person is deeply involved in a feature.
|
||||||
|
|
||||||
# Почему это плохо:
|
# Why this is bad:
|
||||||
- если он уволится, будет трудно продолжить разработку;
|
- if they resign, it will be hard to continue development;
|
||||||
- снижается качество code-review;
|
- the quality of code-review decreases;
|
||||||
- трудно запараллелить разработку при необходимости;
|
- it’s difficult to parallelize development when needed;
|
||||||
|
|
||||||
# Как делается выборка:
|
# How the sample is chosen:
|
||||||
- более 80% коммитов в фичу сделал один человек;
|
- more than 80% of commits in a feature are made by one person;
|
||||||
|
|
||||||
§ recommendations.scope.types.process.title
|
§ recommendations.scope.types.process.title
|
||||||
Плохие процессы
|
Poor Processes
|
||||||
|
|
||||||
§ recommendations.scope.types.process.description
|
§ recommendations.scope.types.process.description
|
||||||
Большинство фич содержат один тип задач.
|
Most features contain one type of task.
|
||||||
|
|
||||||
§ recommendations.scope.types.one
|
§ recommendations.scope.types.one
|
||||||
фичи содержат один тип задач.
|
features contain one type of task.
|
||||||
|
|
||||||
§ recommendations.scope.types.common
|
§ recommendations.scope.types.common
|
||||||
Возможно, разработчики неправильно подписывают коммиты или менеджер заводит один и тот же тип задач.
|
It's possible that developers are incorrectly signing commits or the manager is entering the same type of tasks.
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
- невозможно передать поддержку другой команде;
|
- it's impossible to hand over support to another team;
|
||||||
- невозможно выпустить "коробочную" версию;
|
- it's impossible to release a "boxed" version;
|
||||||
- сильная зависимость от конкретных разработчиков;
|
- strong dependence on specific developers;
|
||||||
- большое количество ошибок и низкое качество кода;
|
- a high number of errors and low code quality;
|
||||||
- вероятное замедление разработки в будущем;
|
- potential slowdown in development in the future;
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
# The manager's mistake:
|
||||||
- взгляд на продукт, только с позиции «работающей демки»;
|
- viewing the product only from the perspective of a "working demo";
|
||||||
|
|
||||||
# Что должно быть:
|
# What should be done:
|
||||||
- тесты;
|
- tests;
|
||||||
- ошибки (выявленные по результатам тестов);
|
- bugs (identified through testing);
|
||||||
- рефакторинг (т.к. архитектура может измениться);
|
- refactoring (as architecture may change);
|
||||||
- документация;
|
- documentation;
|
||||||
- правки стиля (как результат опроса фокус-группы);
|
- style revisions (as a result of focus group feedback);
|
||||||
|
|
||||||
§ recommendations.scope.plan.title
|
§ recommendations.scope.plan.title
|
||||||
Постройте долгосрочный план
|
Develop a Long-Term Plan
|
||||||
|
|
||||||
§ recommendations.scope.plan.description
|
§ recommendations.scope.plan.description
|
||||||
с учетом архитектуры.
|
taking architecture into account.
|
||||||
|
|
||||||
При том опираться этот план должен сразу на самые трудные задачи.
|
This plan should immediately focus on the most challenging tasks.
|
||||||
|
|
||||||
# Почему отсутствие плана плохо:
|
# Why the lack of a plan is bad:
|
||||||
- сотрудники делают минимально работающую версию, не закладывая точки расширения. После этого пишется не масштабируемый код, который тормозит следующие фичи;
|
- employees create a minimally viable version without planning for expansion points. After this, unscalable code is written, which slows down future features;
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
# The manager's mistake:
|
||||||
- он не показал, как продукт будет развиваться далее и в каких точках будет рост;
|
- they haven't shown how the product will develop further and where the growth points will be;
|
||||||
|
|
||||||
# Как должно быть:
|
# How it should be done:
|
||||||
- составляется глобальный план развития продукта;
|
- a global product development plan is created;
|
||||||
- составляется глобальный план развития архитектуры (с разработчиками и DBA);
|
- a global architecture development plan is created (with developers and DBAs);
|
||||||
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
- potential significant changes are discussed upfront at the schematic level;
|
||||||
|
|
||||||
§ recommendations.scope.cost.title
|
§ recommendations.scope.cost.title
|
||||||
Оцените инвестиции в фичу
|
Evaluate Investment in a Feature
|
||||||
|
|
||||||
§ recommendations.scope.cost.description
|
§ recommendations.scope.cost.description
|
||||||
с количеством потенциальной прибыли.
|
in terms of potential profit.
|
||||||
|
|
||||||
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более коммерчески успешным.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
пишет слишком мало кода.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Может уволить?
|
# Composition:
|
||||||
- он тимлид, архитектор, аналитик?
|
- $1;
|
||||||
- это его основной проект?
|
|
||||||
- есть какие-то зависимости от него?
|
|
||||||
|
|
||||||
# Почему нет смысла исправлять
|
# Answer the questions:
|
||||||
Суммарные затраты на разработчика уже больше чем прибыль от его работы.
|
- are they a team leader, architect, or analyst?
|
||||||
Если мы считаем, что объективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
- is this their primary project?
|
||||||
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
- are there any dependencies on them?
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
# Why it makes no sense to correct
|
||||||
пишет мало кода. Нужно взять на контроль.
|
The total costs for the developer are already more than the profit from their work.
|
||||||
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
# Как делается выборка:
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
§ recommendations.author.manyLazy.description
|
||||||
- в данном случае показатель от 60% до 80%;
|
Needs to be monitored.
|
||||||
|
|
||||||
# Как контролировать:
|
# Composition:
|
||||||
- дробить задачи на 1..2 дня;
|
- $1;
|
||||||
- каждый день спрашивать статус;
|
|
||||||
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
# How the sample is chosen:
|
||||||
- устроить парное программирование, чтобы проверить фактическую скорость;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
- in this case, the indicator is between 60% and 80%;
|
||||||
|
|
||||||
|
# How to monitor:
|
||||||
|
- break tasks into 1..2 days;
|
||||||
|
- ask for a status update every day;
|
||||||
|
- ensure tasks are well defined and ready for development;
|
||||||
|
- arrange pair programming to check actual speed;
|
||||||
|
|
||||||
§ recommendations.author.oneTypeMans
|
§ recommendations.author.oneTypeMans
|
||||||
получает слишком однообразные задачи по типу. Может выгореть.
|
receives too many monotonous tasks of the same type. Risk of burnout.
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
- если сотрудник выгорит, его скорость работы снизится;
|
- if an employee burns out, their work speed will decrease;
|
||||||
- замедляется профессиональный рост;
|
- professional growth slows down;
|
||||||
- повышается вероятность увольнения;
|
- the likelihood of resignation increases;
|
||||||
|
|
||||||
# Как делается выборка:
|
# How the sample is chosen:
|
||||||
- для каждого коммита определятся тип задачи;
|
- the type of task is determined for each commit;
|
||||||
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
- if more than 70% of tasks are of the same type, it means the person is doing the same thing repeatedly;
|
||||||
|
|
||||||
§ recommendations.author.workToday.title: Работает $1
|
§ recommendations.author.workToday.title: Working $1
|
||||||
§ recommendations.author.workToday.description
|
§ recommendations.author.workToday.description
|
||||||
над проектом в данный момент.
|
on the project at this moment.
|
||||||
|
|
||||||
# Состав:
|
# Composition:
|
||||||
- $1;
|
- $1;
|
||||||
|
|
||||||
# Почему именно они:
|
# Why specifically them:
|
||||||
- рабочих дней более 50%;
|
- more than 50% of workdays;
|
||||||
- работали в течении последних 30 дней;
|
- have worked during the last 30 days;
|
||||||
|
|
||||||
§ recommendations.author.dismissed.title: Уволилось $1
|
§ recommendations.author.dismissed.title: Dismissed $1
|
||||||
§ recommendations.author.dismissed.description
|
§ recommendations.author.dismissed.description
|
||||||
или работало короткий промежуток времени.
|
or worked for a short period.
|
||||||
|
|
||||||
# Состав:
|
# Composition:
|
||||||
- $1;
|
- $1;
|
||||||
|
|
||||||
# Почему именно они:
|
# Why specifically them:
|
||||||
- работали в нормальном ритме (видимо, это их основной репозиторий);
|
- worked at a normal pace (apparently, this is their main repository);
|
||||||
- за последний месяц не было ни одного коммита;
|
- no commits in the last month;
|
||||||
- отпуск обычно 14 дней (их отсутствие не похоже на отпуск);
|
- vacation usually lasts 14 days (their absence does not resemble a vacation);
|
||||||
|
|
||||||
§ recommendations.author.staff.title: Помогают $1
|
§ recommendations.author.staff.title: Assisting $1
|
||||||
§ recommendations.author.staff.description
|
§ recommendations.author.staff.description
|
||||||
Люди другой специализации, которые что-либо коммитили.
|
People of other specializations who have committed something.
|
||||||
|
|
||||||
# Состав:
|
# Composition:
|
||||||
- $1;
|
- $1;
|
||||||
|
|
||||||
# Почему именно они:
|
# Why specifically them:
|
||||||
- это не open-source проект;
|
- this is not an open-source project;
|
||||||
- рабочих дней менее 15% от общего числа;
|
- workdays less than 15% of the total number;
|
||||||
- изменяют примерно одни и те же файлы;
|
- modify roughly the same files;
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.title
|
§ recommendations.author.projectType.openSource.title
|
||||||
Открытый проект
|
Open Project
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.description
|
§ recommendations.author.projectType.openSource.description
|
||||||
пять дней в неделю тут не работают.
|
they do not work five days a week here.
|
||||||
|
|
||||||
Проект может быть и закрытым, просто такой темп работы обычно у открытых библиотек на GitHub.
|
The project may be closed, but this work pace is typical for open libraries on GitHub.
|
||||||
|
|
||||||
# Метод оценки:
|
# Assessment method:
|
||||||
- берется статистика по всем активным разработчикам;
|
- statistics are taken for all active developers;
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
- the average number of working days and days without commits is calculated;
|
||||||
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
- for open-source libraries, working days are usually a maximum of 15..20%;
|
||||||
|
|
||||||
# Последствия
|
# Consequences
|
||||||
Для проектов, где работа не постоянна, нет смысла во многих показателях. Поэтому показатели без коммитов, скорости и т.п. будут скрыты.
|
For projects where work is not constant, many indicators do not make sense. Therefore, indicators like days without commits, speed, etc., will be hidden.
|
||||||
|
|
||||||
Как правило, оценку таких проектов делают перед началом разработки своей закрытой версии. Самые интересные показатели в этом случае вероятная стоимость и суммарное время на разработку.
|
|
||||||
|
|
||||||
|
Typically, such projects are assessed before starting the development of their own closed version. The most interesting indicators in this case are the probable cost and total development time.
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.title
|
§ recommendations.author.projectType.easy.title
|
||||||
Слабая загрузка
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
too many days without commits.
|
||||||
|
|
||||||
# Метод оценки:
|
It is necessary to understand why the team is not writing code.
|
||||||
- берется статистика по всем активным разработчикам;
|
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
|
||||||
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
|
||||||
|
|
||||||
# Возможные причины:
|
# Assessment method:
|
||||||
- фактически нет задач;
|
- take statistics from all active developers;
|
||||||
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
- calculate the average number of working days and days without commits;
|
||||||
- разработчиков отвлекают совещаниями;
|
- workload is considered light if the percentage of days without commits is between 5% and 20%;
|
||||||
- команда не работает;
|
|
||||||
|
|
||||||
# Варианты решения:
|
# Possible reasons:
|
||||||
- обсудить проблему с командой;
|
- there are actually no tasks;
|
||||||
- уменьшить гранулярность задач, чтобы за день можно было успеть сделать одну или две задачи;
|
- there are tasks, but they fit well with the current architecture;
|
||||||
- ввести ежедневные совещания, чтобы проверять движение задач по статусу;
|
- developers are distracted by meetings;
|
||||||
- устроить сеансы парного программирования, чтобы убедиться, что разработчик может работать быстрее;
|
- the team is not working;
|
||||||
|
|
||||||
|
# Solutions:
|
||||||
|
- discuss the issue with the team;
|
||||||
|
- reduce task granularity so that one or two tasks can be completed in a day;
|
||||||
|
- introduce daily meetings to check the status of tasks;
|
||||||
|
- arrange pair programming sessions to ensure that the developer can work faster;
|
||||||
|
|
||||||
§ recommendations.author.manager.title
|
§ recommendations.author.manager.title
|
||||||
Обозначьте дедлайны
|
Set Deadlines
|
||||||
|
|
||||||
§ recommendations.author.manager.description
|
§ recommendations.author.manager.description
|
||||||
У любой задачи должен быть чёткий дедлайн.
|
Every task should have a clear deadline.
|
||||||
|
|
||||||
Это позволит не затягивать её выполнение на несколько дней или недель.
|
This will prevent dragging out its completion for several days or weeks.
|
||||||
|
|
||||||
# Какие показатели стоит проверить:
|
# Indicators to check:
|
||||||
- количество дней на одну задачу, которое тратит работник;
|
- the number of days spent on one task by an employee;
|
||||||
- количество дней ожидания влития PR (страница статистики по PR);
|
- the number of days waiting for PR merge (PR statistics page);
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.title
|
§ recommendations.author.shorTalk.title
|
||||||
Проводите ежедневные совещания
|
Conduct Daily Meetings
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.description
|
§ recommendations.author.shorTalk.description
|
||||||
они помогают быть в курсе проекта.
|
they help stay informed about the project.
|
||||||
|
|
||||||
Не растягивайте их отвлекаясь на посторонние темы.
|
Do not stretch them by getting sidetracked on irrelevant topics.
|
||||||
|
|
||||||
# На какие вопросы должен ответить сотрудник:
|
# Questions the employee should answer:
|
||||||
- что было сделано;
|
- what was done;
|
||||||
- что будет сделано;
|
- what will be done;
|
||||||
- есть ли какие-либо проблемы;
|
- are there any issues;
|
||||||
|
|
||||||
# Следует обрывать монолог, если:
|
# Interruptions should occur if:
|
||||||
- начинают подробно описывать мелкие детали, которые не важны;
|
- they start describing minor details in-depth, which are not important;
|
||||||
- уводят диалог в сторону, от первоначального плана;
|
- they steer the conversation away from the original plan;
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
Часто сотрудник, который ничего не делает, старается уйти от ответа. Для этого он рассказывает кучу ненужных подробностей свой работы. Это позволяет усыпить внимание участников и растянуть время ответа. Создается ощущение что он чем-то занят, хотя по факту работы не было.
|
Often an employee who does nothing tries to avoid the answer by telling a bunch of unnecessary details of their work. This lulls the participants' attention and stretches the time for a response. It creates an impression that they are busy, even though there was no actual work done.
|
||||||
|
|
||||||
§ recommendations.author.ipr.title
|
§ recommendations.author.ipr.title
|
||||||
Составьте план обучения
|
Develop a Training Plan
|
||||||
|
|
||||||
§ recommendations.author.ipr.description
|
§ recommendations.author.ipr.description
|
||||||
на каждого сотрудника.
|
for each employee.
|
||||||
|
|
||||||
*Индивидуальный план обучения* — это список целей и задач, которые помогают человеку развиваться в определенной области.
|
*Individual training plan* is a list of goals and tasks that help a person develop in a certain area.
|
||||||
|
|
||||||
# Как составить план:
|
# How to create a plan:
|
||||||
- составить матрицу компетенций;
|
- create a competency matrix;
|
||||||
- определить по каким компетенциям меньше всего знаний и опыта;
|
- identify which competencies have the least knowledge and experience;
|
||||||
- узнать какие из этих компетенций интересны сотруднику;
|
- find out which of these competencies are of interest to the employee;
|
||||||
- придумать 3..5 целей в рамках каждой такой компетенции на полпостороние года или год;
|
- come up with 3..5 goals within each such competency for the next six months or a year;
|
||||||
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
- try to do something every month to achieve one goal;
|
||||||
- каждый месяц напоминать об общем плане достижения этих целей;
|
- remind every month about the overall plan to achieve these goals;
|
||||||
|
|
||||||
# Нужен ли план руководителю?
|
# Does a manager need a plan?
|
||||||
Да, руководитель так же должен составить план на себя. Если нет вышестоящего руководителя, то он должен проверять сам себя.
|
Yes, the manager should also make a plan for themselves. If there is no higher-level manager, they should self-assess.
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
- сотрудники становятся более лояльны к компании;
|
- employees become more loyal to the company;
|
||||||
- за теже деньги вы получаете более квалифицированные кадры;
|
- you get more qualified personnel for the same money;
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.title
|
§ recommendations.author.oneToOne.title
|
||||||
Проводите 1-1 каждый месяц
|
Conduct One-on-One Meetings Every Month
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.description
|
§ recommendations.author.oneToOne.description
|
||||||
это поможет выявить проблемы на ранней стадии.
|
it helps to identify problems at an early stage.
|
||||||
|
|
||||||
*One-to-one* — это регулярные личные встречи руководителя с подчиненным. На таких встречах обычно обсуждают всё, что важно для сотрудника, что его волнует, и то, чем он может поделиться с руководителем только наедине.
|
*One-to-one* is a regular personal meeting of a manager with a subordinate. Such meetings typically discuss everything important to the employee, what concerns them, and what they can share with the manager in private.
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
- легко выяснить, кто из сотрудников перегружен, а у кого есть свободное время;
|
- easy to find out who is overburdened and who has free time;
|
||||||
- можно предотвратить выгорание сотрудника;
|
- possible to prevent employee burnout;
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
- quick feedback can be obtained about processes that you might not notice;
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
- trust is built, making employees more loyal to the company;
|
||||||
- повышается мотивация и вовлеченность сотрудников;
|
- increases employee motivation and engagement;
|
||||||
|
|
||||||
§ recommendations.author.club.title
|
§ recommendations.author.club.title
|
||||||
Ходите в бар
|
Go to a Bar
|
||||||
|
|
||||||
§ recommendations.author.club.description
|
§ recommendations.author.club.description
|
||||||
один раз в месяц или два.
|
once a month or two.
|
||||||
|
|
||||||
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
|
This will help build informal communication within the team and bring the team together, even if the interaction is brief.
|
||||||
|
|
||||||
# Почему это важно:
|
# Why this is important:
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
- quick feedback can be obtained about processes that you might not notice;
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
- trust is built, making employees more loyal to the company;
|
||||||
- повышается вовлеченность сотрудников;
|
- increases employee engagement;
|
||||||
|
|
||||||
§ recommendations.hour.onlyWork.title: Выходных тут нет
|
§ recommendations.hour.onlyWork.title: No Weekends Here
|
||||||
§ recommendations.hour.onlyWork.description: Вероятно, стоит уволить менеджера проекта.
|
§ recommendations.hour.onlyWork.description: The project manager should probably be fired.
|
||||||
§ recommendations.hour.weekends.title: Работа на выходных
|
§ recommendations.hour.weekends.title: Working on Weekends
|
||||||
§ recommendations.hour.weekends.description: Вероятно, стоит проверить менеджера проекта.
|
§ recommendations.hour.weekends.description: The project manager should probably be checked.
|
||||||
§ recommendations.hour.easy.title: Бывают проблемы
|
§ recommendations.hour.easy.title: There Are Problems
|
||||||
§ recommendations.hour.easy.description: Вероятно, бывают завалы и приходится работать на выходных.
|
§ recommendations.hour.easy.description: There are likely crunch times and work is needed on weekends.
|
||||||
§ recommendations.week.lazyDays.down.title: Стало меньше прогулов
|
§ recommendations.week.lazyDays.down.title: Fewer Absences
|
||||||
§ recommendations.week.lazyDays.down.description: за последние три недели этот показатель упал
|
§ recommendations.week.lazyDays.down.description: this indicator has dropped over the last three weeks
|
||||||
§ recommendations.week.lazyDays.up.title: Стало больше прогулов
|
§ recommendations.week.lazyDays.up.title: More Absences
|
||||||
§ recommendations.week.lazyDays.up.description: нет задач или нужен более жесткий контроль
|
§ recommendations.week.lazyDays.up.description: no tasks or stricter control is needed
|
||||||
§ recommendations.week.notWork.title: Стабильно не дорабатывает
|
§ recommendations.week.notWork.title: Consistently Underperforms
|
||||||
§ recommendations.week.notWork.description: т.к. каждую неделю пишет код не 100% времени
|
§ recommendations.week.notWork.description: as every week the code is not 100% of the time
|
||||||
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
§ recommendations.week.upWork.title: Consistently Overworks
|
||||||
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
§ recommendations.week.upWork.description: as every week code is written on weekend days
|
||||||
§ recommendations.week.task.up.title: Растёт производительность
|
§ recommendations.week.task.up.title: Productivity is growing
|
||||||
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
§ recommendations.week.task.up.description: or tasks have become too small. Need to check. If granularity is the same - reinforce the result.
|
||||||
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
§ recommendations.week.task.lazyMaintainer.description: consistently leads in absences. Fire?
|
||||||
§ recommendations.week.task.down.title: Падает производительность
|
§ recommendations.week.task.down.title: Productivity is Falling
|
||||||
§ recommendations.week.task.down.description
|
§ recommendations.week.task.down.description
|
||||||
или задачи хуже разбивают. Нужно проверить. Если гранулярность та же - взять на контроль.
|
or tasks are poorly split. Need to check. If granularity is the same - take control.
|
||||||
|
|
||||||
# Метод оценки:
|
# Assessment method:
|
||||||
- количество задач в день, над которыми работают, на протяжении последних трех недель стабильно падает.
|
- the number of tasks per day that are being worked on has been steadily decreasing over the last three weeks.
|
||||||
|
|
||||||
# Возможные ошибки:
|
# Possible errors:
|
||||||
- задачи могли быть сложнее, чем казались;
|
- tasks could have been more complex than they seemed;
|
||||||
- задачи могли иметь большой объём работы (нужно проверить количество изменений, падают они или нет за этот же период)
|
- tasks could have had a large volume of work (need to check if the number of changes is also decreasing during this period)
|
||||||
|
|
||||||
§ recommendations.type.everyHasOne.title: Не подписывают тип задачи
|
§ recommendations.type.everyHasOne.title: Not Signing Task Types
|
||||||
§ recommendations.type.everyHasOne.description: большинство типов задач делает один человек.
|
§ recommendations.type.everyHasOne.description: Most task types are done by one person.
|
||||||
§ recommendations.type.oneMaintainer.title: Узкая специализация
|
§ recommendations.type.oneMaintainer.title: Narrow Specialization
|
||||||
§ recommendations.type.oneMaintainer.description
|
§ recommendations.type.oneMaintainer.description
|
||||||
большинство задач одного типа делают одни и те же люди.
|
most tasks of one type are done by the same people.
|
||||||
|
|
||||||
# Типы задач:
|
# Task types:
|
||||||
|
|
||||||
§ recommendations.type.common
|
§ recommendations.type.common
|
||||||
# Возможно, это не так
|
# It might not be the case
|
||||||
|
|
||||||
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
Make sure that other employees correctly sign commits.
|
||||||
|
|
||||||
Шаги, которые помогут это сделать:
|
Steps to ensure this:
|
||||||
- настроить пре-коммит проверку для commit message;
|
- set up a pre-commit check for commit messages;
|
||||||
- объяснить команде, что нужно указывать тип;
|
- explain to the team the need to indicate the type;
|
||||||
- проверить в новых ветках, что сотрудники следуют правилу;
|
- check in new branches that employees follow this rule;
|
||||||
|
|
||||||
# Если это действительно так
|
# If it is indeed the case
|
||||||
|
|
||||||
Вы настроили проверки и убедились что один и тот же сотрудник, делает задачи одного и того же типа.
|
You have set up checks and ensured that the same employee does tasks of the same type.
|
||||||
|
|
||||||
Почему это плохо:
|
Why this is bad:
|
||||||
- его увольнение остановит целую пачку процессов;
|
- their resignation will halt a whole bunch of processes;
|
||||||
- уменьшается компетенция остальных членов команды;
|
- it reduces the competence of other team members;
|
||||||
- трудно верхнеуровнево понять его правки;
|
- difficult to understand their edits at a higher level;
|
||||||
|
|
||||||
Как это исправить:
|
How to fix this:
|
||||||
- распределять разные типы задач равномерно;
|
- distribute different types of tasks evenly;
|
||||||
- менять область работы (тесты, документация, ошибки) между сотрудниками через спринт;
|
- change the area of work (tests, documentation, bugs) among employees every sprint;
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.title
|
§ recommendations.type.fewTypes.title
|
||||||
Это локальный продукт
|
This is a Local Product
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.description
|
§ recommendations.type.fewTypes.description
|
||||||
для конкретного заказчика или проблемы.
|
for a specific customer or problem.
|
||||||
|
|
||||||
# Какие признаки есть у «глобального» продукта:
|
# Signs of a "global" product:
|
||||||
- локализация;
|
- localization;
|
||||||
- документация;
|
- documentation;
|
||||||
- большой объём тестов;
|
- a large volume of tests;
|
||||||
- визуальная кастомизация;
|
- visual customization;
|
||||||
- рефакторинг узких мест;
|
- refactoring of bottlenecks;
|
||||||
- и т.п.
|
- etc.
|
||||||
|
|
||||||
# Почему этот продукт выглядит как «локальный»:
|
# Why this product looks like a "local" one:
|
||||||
- у каждого «глобального» признака будет перевес по своему типу задач;
|
- each "global" sign will be outweighed by its type of task;
|
||||||
- чем больше «глобальных» признаков, тем больше вероятность «глобального» продукта;
|
- the more "global" signs, the more likely a "global" product;
|
||||||
|
|
||||||
В данном случае мы видим небольшое число типов, а следовательно, скорее всего есть недоработки, мешающие легко масштабировать продукт на мировой рынок и продавать его в других странах.
|
In this case, we see a small number of types, which likely indicates shortcomings that prevent the product from being easily scaled to the global market and sold in other countries.
|
||||||
|
|
||||||
# Возможно, это не так
|
# It might not be the case
|
||||||
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
Based on file types, we can assume the type of program (website, server application, DevOps scripts, etc.). For a frontend application, our hypothesis will be more accurate than for DevOps scripts, which might just be a micro-module of initialization.
|
||||||
|
|
||||||
§ recommendations.type.diff.title
|
§ recommendations.type.diff.title
|
||||||
Разбейте лидирующий тип на подтипы
|
Break Down the Leading Type into Subtypes
|
||||||
|
|
||||||
§ recommendations.type.diff.description
|
§ recommendations.type.diff.description
|
||||||
для детализации ошибок.
|
to detail errors.
|
||||||
|
|
||||||
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
|
Typically, the task type labeled "bug fixing" is leading. This makes the statistics weakly detailed.
|
||||||
|
|
||||||
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
|
*If you encounter this situation*, you can break down this type into subtypes (e.g., based on the location of detection).
|
||||||
|
|
||||||
Рассмотрим несколько вариантов подтипов:
|
Consider several options for subtypes:
|
||||||
- fix_dev (ошибка выявленная в процессе разработки);
|
- fix_dev (error detected during development);
|
||||||
- fix_test (ошибка выявленная в процессе тестирования);
|
- fix_test (error detected during testing);
|
||||||
- fix (ошибка выявленная в проде);
|
- fix (error detected in production);
|
||||||
|
|
||||||
§ recommendations.type.buddy.title
|
§ recommendations.type.buddy.title
|
||||||
Копите мелкие задачи
|
Accumulate Minor Tasks
|
||||||
|
|
||||||
§ recommendations.type.buddy.description
|
§ recommendations.type.buddy.description
|
||||||
для новых сотрудников.
|
for new employees.
|
||||||
|
|
||||||
# Если задача:
|
# If a task is:
|
||||||
- не важная;
|
- not important;
|
||||||
- не большая;
|
- not big;
|
||||||
- не требует сильного погружения в контекст;
|
- doesn't require deep immersion in the context;
|
||||||
- больше про рефакторинг, чем про новый код;
|
- more about refactoring than new code;
|
||||||
|
|
||||||
# Положите её в backlog с меткой «для новичков».
|
# Put it in the backlog with the label "for beginners".
|
||||||
|
|
||||||
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
|
When a new employee arrives, you will be able to immediately pull out a bunch of small and varied tasks for them to get acquainted with the project.
|
||||||
|
|
||||||
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
|
Also, if you have a lull in work, you can pull out one such minor task from the backlog.
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -20,7 +20,9 @@ export default `
|
||||||
§ sidebar.team.month: Par mois
|
§ sidebar.team.month: Par mois
|
||||||
§ sidebar.team.files: Fichiers
|
§ sidebar.team.files: Fichiers
|
||||||
§ sidebar.team.removedFiles: Fichiers supprimés
|
§ sidebar.team.removedFiles: Fichiers supprimés
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: Liste des tâches
|
§ sidebar.team.tasks: Liste des tâches
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: Horaire
|
§ sidebar.team.hours: Horaire
|
||||||
§ sidebar.team.commits: all commits
|
§ sidebar.team.commits: all commits
|
||||||
§ sidebar.team.changes: Tous les changements
|
§ sidebar.team.changes: Tous les changements
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Statistiques du personnel
|
§ page.team.author.title: Statistiques du personnel
|
||||||
§ page.team.author.description1: Partie des statistiques (vitesse de travail, argent dépensé, etc.) pour les collaborateurs de type “Assistant”, ce n’est pas une rôle permanente dans le projet. Leur travail est insignifiant et peut être ignoré.
|
§ page.team.author.description1: Partie des statistiques (vitesse de travail, argent dépensé, etc.) pour les collaborateurs de type “Assistant”, ce n’est pas une rôle permanente dans le projet. Leur travail est insignifiant et peut être ignoré.
|
||||||
§ page.team.author.description2: Le tri par défaut est le tri par nombre de tâches et de groupes (employés actuels, licenciés et aidants).
|
§ page.team.author.description2: Le tri par défaut est le tri par nombre de tâches et de groupes (employés actuels, licenciés et aidants).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Type de travaux
|
§ page.team.author.types: Type de travaux
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: tâches
|
§ page.team.pr.tasks: tâches
|
||||||
§ page.team.pr.firstCommitTime: Premier commit
|
§ page.team.pr.firstCommitTime: Premier commit
|
||||||
§ page.team.pr.lastCommitTime: Dernier
|
§ page.team.pr.lastCommitTime: Dernier
|
||||||
§ page.team.pr.workDays: Jours de développement
|
§ page.team.pr.workDays: Average time spent working on a task
|
||||||
§ page.team.pr.delayDays: Jours d'attente
|
§ page.team.pr.delayDays: Average time of the PR review
|
||||||
|
§ page.team.pr.middleTimeRelease: The ratio of development time to review time
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: Date de diffusion
|
§ page.team.pr.date: Date de diffusion
|
||||||
§ page.team.pr.mergeAuthor: Versai
|
§ page.team.pr.mergeAuthor: Versai
|
||||||
§ page.team.pr.author: Employé
|
§ page.team.pr.author: Employé
|
||||||
§ page.team.pr.middleTimeRelease: Délai de Livraison moyen (jours)
|
|
||||||
§ page.team.pr.work: développement
|
§ page.team.pr.work: développement
|
||||||
§ page.team.pr.delay: attente
|
§ page.team.pr.delay: attente
|
||||||
§ page.team.pr.days: jours
|
§ page.team.pr.days: jours
|
||||||
|
@ -146,6 +149,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Versai
|
§ page.team.tasks.prAuthor: Versai
|
||||||
§ page.team.tasks.prDelayDays: Jours d'attente
|
§ page.team.tasks.prDelayDays: Jours d'attente
|
||||||
§ page.team.tasks.comments: Commentaires
|
§ page.team.tasks.comments: Commentaires
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
§ page.person.print.photo.description: place à la photographie
|
§ page.person.print.photo.description: place à la photographie
|
||||||
§ page.person.total.title: Caractéristiques de base
|
§ page.person.total.title: Caractéristiques de base
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
||||||
§ sidebar.team.tree: ファイルの分析
|
§ sidebar.team.tree: ファイルの分析
|
||||||
§ sidebar.team.files: ファイル
|
§ sidebar.team.files: ファイル
|
||||||
§ sidebar.team.removedFiles: 削除されたファイル
|
§ sidebar.team.removedFiles: 削除されたファイル
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: タスクリスト
|
§ sidebar.team.tasks: タスクリスト
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: スケジュール
|
§ sidebar.team.hours: スケジュール
|
||||||
§ sidebar.team.commits: All commits
|
§ sidebar.team.commits: All commits
|
||||||
§ sidebar.team.changes: すべての変更
|
§ sidebar.team.changes: すべての変更
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Employee statistics
|
§ 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.
|
§ 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.
|
||||||
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Types of work
|
§ page.team.author.types: Types of work
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: tasks
|
§ page.team.pr.tasks: tasks
|
||||||
§ page.team.pr.firstCommitTime: First commit
|
§ page.team.pr.firstCommitTime: First commit
|
||||||
§ page.team.pr.lastCommitTime: Last
|
§ page.team.pr.lastCommitTime: Last
|
||||||
§ page.team.pr.workDays: Development days
|
§ page.team.pr.workDays: Average time spent working on a task
|
||||||
§ page.team.pr.delayDays: Days waiting for merge
|
§ page.team.pr.delayDays: Average time of the PR review
|
||||||
|
§ page.team.pr.middleTimeRelease: The ratio of development time to review time
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: Merge Date
|
§ page.team.pr.date: Merge Date
|
||||||
§ page.team.pr.mergeAuthor: Merged by
|
§ page.team.pr.mergeAuthor: Merged by
|
||||||
§ page.team.pr.author: Employee
|
§ page.team.pr.author: Employee
|
||||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
|
||||||
§ page.team.pr.work: development
|
§ page.team.pr.work: development
|
||||||
§ page.team.pr.delay: waiting
|
§ page.team.pr.delay: waiting
|
||||||
§ page.team.pr.days: days
|
§ page.team.pr.days: days
|
||||||
|
@ -146,6 +149,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Merged by user
|
§ page.team.tasks.prAuthor: Merged by user
|
||||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||||
§ page.team.tasks.comments: Comments
|
§ page.team.tasks.comments: Comments
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
§ page.person.print.photo.description: space for a photo
|
§ page.person.print.photo.description: space for a photo
|
||||||
§ page.person.total.title: Main characteristics
|
§ page.person.total.title: Main characteristics
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
||||||
§ sidebar.team.tree: Análise de arquivos
|
§ sidebar.team.tree: Análise de arquivos
|
||||||
§ sidebar.team.files: Ficheiros
|
§ sidebar.team.files: Ficheiros
|
||||||
§ sidebar.team.removedFiles: Arquivos excluídos
|
§ sidebar.team.removedFiles: Arquivos excluídos
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: Lista de Tarefas
|
§ sidebar.team.tasks: Lista de Tarefas
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: Horário
|
§ sidebar.team.hours: Horário
|
||||||
§ sidebar.team.commits: All commits
|
§ sidebar.team.commits: All commits
|
||||||
§ sidebar.team.changes: Todas as alterações
|
§ sidebar.team.changes: Todas as alterações
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Employee statistics
|
§ 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.
|
§ 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.
|
||||||
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Types of work
|
§ page.team.author.types: Types of work
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: tasks
|
§ page.team.pr.tasks: tasks
|
||||||
§ page.team.pr.firstCommitTime: First commit
|
§ page.team.pr.firstCommitTime: First commit
|
||||||
§ page.team.pr.lastCommitTime: Last
|
§ page.team.pr.lastCommitTime: Last
|
||||||
§ page.team.pr.workDays: Development days
|
§ page.team.pr.workDays: Average time spent working on a task
|
||||||
§ page.team.pr.delayDays: Days waiting for merge
|
§ page.team.pr.delayDays: Average time of the PR review
|
||||||
|
§ page.team.pr.middleTimeRelease: The ratio of development time to review time
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: Merge Date
|
§ page.team.pr.date: Merge Date
|
||||||
§ page.team.pr.mergeAuthor: Merged by
|
§ page.team.pr.mergeAuthor: Merged by
|
||||||
§ page.team.pr.author: Employee
|
§ page.team.pr.author: Employee
|
||||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
|
||||||
§ page.team.pr.work: development
|
§ page.team.pr.work: development
|
||||||
§ page.team.pr.delay: waiting
|
§ page.team.pr.delay: waiting
|
||||||
§ page.team.pr.days: days
|
§ page.team.pr.days: days
|
||||||
|
@ -146,6 +149,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Merged by user
|
§ page.team.tasks.prAuthor: Merged by user
|
||||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||||
§ page.team.tasks.comments: Comments
|
§ page.team.tasks.comments: Comments
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: Photo
|
§ page.person.print.photo.title: Photo
|
||||||
§ page.person.print.photo.description: space for a photo
|
§ page.person.print.photo.description: space for a photo
|
||||||
§ page.person.total.title: Main characteristics
|
§ page.person.total.title: Main characteristics
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Статистика по сотрудникам
|
§ page.team.author.title: Статистика по сотрудникам
|
||||||
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||||
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
||||||
|
§ page.team.author.status: Статус
|
||||||
|
§ page.team.author.firstCommit: Первый коммит
|
||||||
|
§ page.team.author.daysAll: Всего дней
|
||||||
§ page.team.author.types: Тип работ
|
§ page.team.author.types: Тип работ
|
||||||
§ page.team.author.commits: Коммитов
|
§ page.team.author.commits: Коммитов
|
||||||
§ page.team.author.commitsSmall: коммитов
|
§ page.team.author.commitsSmall: коммитов
|
||||||
|
@ -120,13 +123,13 @@ export default `
|
||||||
§ page.team.pr.tasks: задач
|
§ page.team.pr.tasks: задач
|
||||||
§ page.team.pr.firstCommitTime: Первый коммит
|
§ page.team.pr.firstCommitTime: Первый коммит
|
||||||
§ page.team.pr.lastCommitTime: Последний
|
§ page.team.pr.lastCommitTime: Последний
|
||||||
§ page.team.pr.workDays: Дней разработки
|
§ page.team.pr.workDays: Среднее время работы над задачей
|
||||||
§ page.team.pr.delayDays: Дней ожидания влития
|
§ page.team.pr.delayDays: Среднее время ревью PR
|
||||||
|
§ page.team.pr.middleTimeRelease: Отношение времени разработки к времени ревью
|
||||||
§ page.team.pr.commits: Коммиты
|
§ page.team.pr.commits: Коммиты
|
||||||
§ page.team.pr.date: Дата влития
|
§ page.team.pr.date: Дата влития
|
||||||
§ page.team.pr.mergeAuthor: Влил
|
§ page.team.pr.mergeAuthor: Влил
|
||||||
§ page.team.pr.author: Сотрудник
|
§ page.team.pr.author: Сотрудник
|
||||||
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
|
||||||
§ page.team.pr.work: разработка
|
§ page.team.pr.work: разработка
|
||||||
§ page.team.pr.delay: ожидание
|
§ page.team.pr.delay: ожидание
|
||||||
§ page.team.pr.days: дней
|
§ page.team.pr.days: дней
|
||||||
|
@ -146,6 +149,8 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: Влил
|
§ page.team.tasks.prAuthor: Влил
|
||||||
§ page.team.tasks.prDelayDays: Дней ожидания влития
|
§ page.team.tasks.prDelayDays: Дней ожидания влития
|
||||||
§ page.team.tasks.comments: Комментарии
|
§ page.team.tasks.comments: Комментарии
|
||||||
|
§ page.team.extension.extension: Расширения файлов
|
||||||
|
§ page.team.extension.type: Подтип файлов
|
||||||
§ page.team.extension.name: Тип
|
§ page.team.extension.name: Тип
|
||||||
§ page.team.extension.path: Путь
|
§ page.team.extension.path: Путь
|
||||||
§ page.team.extension.current.count: Количество
|
§ page.team.extension.current.count: Количество
|
||||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
||||||
§ page.team.author.title: Статистика по сотрудникам
|
§ page.team.author.title: Статистика по сотрудникам
|
||||||
§ page.team.author.description1: Часть статистики (скорость работы, затраченные деньги и т.п.) по сотрудникам с типом «Помощник» не считается, т.к. это не постоянная роль в проекте. Их работа незначительно и её можно не учитывать.
|
§ page.team.author.description1: Часть статистики (скорость работы, затраченные деньги и т.п.) по сотрудникам с типом «Помощник» не считается, т.к. это не постоянная роль в проекте. Их работа незначительно и её можно не учитывать.
|
||||||
§ page.team.author.description2: Сортировка по умолчанию — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
§ page.team.author.description2: Сортировка по умолчанию — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
||||||
|
§ page.team.author.status: Status
|
||||||
|
§ page.team.author.firstCommit: First commit
|
||||||
|
§ page.team.author.daysAll: Total days
|
||||||
§ page.team.author.types: Тип работ
|
§ page.team.author.types: Тип работ
|
||||||
§ page.team.author.commits: Commits
|
§ page.team.author.commits: Commits
|
||||||
§ page.team.author.commitsSmall: commits
|
§ page.team.author.commitsSmall: commits
|
||||||
|
|
|
@ -193,10 +193,14 @@ Bus factor = 1
|
||||||
|
|
||||||
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более коммерчески успешным.
|
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более коммерчески успешным.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Слишком мало кода: $1
|
||||||
пишет слишком мало кода.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Может уволить?
|
||||||
|
|
||||||
# Может уволить?
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Ответьте себе на вопросы:
|
||||||
- он тимлид, архитектор, аналитик?
|
- он тимлид, архитектор, аналитик?
|
||||||
- это его основной проект?
|
- это его основной проект?
|
||||||
- есть какие-то зависимости от него?
|
- есть какие-то зависимости от него?
|
||||||
|
@ -206,8 +210,12 @@ Bus factor = 1
|
||||||
Если мы считаем, что объективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
Если мы считаем, что объективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
||||||
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Пишут мало кода: $1
|
||||||
пишет мало кода. Нужно взять на контроль.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Нужно взять на контроль.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# Как делается выборка:
|
# Как делается выборка:
|
||||||
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
||||||
|
@ -289,7 +297,9 @@ Bus factor = 1
|
||||||
Слабая загрузка
|
Слабая загрузка
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
слишком много дней без коммитов.
|
||||||
|
|
||||||
|
Нужно понять почему команда не пишет код.
|
||||||
|
|
||||||
# Метод оценки:
|
# Метод оценки:
|
||||||
- берется статистика по всем активным разработчикам;
|
- берется статистика по всем активным разработчикам;
|
||||||
|
@ -406,7 +416,10 @@ Bus factor = 1
|
||||||
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
||||||
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
||||||
§ recommendations.week.task.up.title: Растёт производительность
|
§ recommendations.week.task.up.title: Растёт производительность
|
||||||
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
§ recommendations.week.task.up.description
|
||||||
|
или задачи стали слишком мелкие.
|
||||||
|
|
||||||
|
Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||||
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
||||||
§ recommendations.week.task.down.title: Падает производительность
|
§ recommendations.week.task.down.title: Падает производительность
|
||||||
§ recommendations.week.task.down.description
|
§ recommendations.week.task.down.description
|
||||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
||||||
§ sidebar.team.tree: 文件分析
|
§ sidebar.team.tree: 文件分析
|
||||||
§ sidebar.team.files: 档案
|
§ sidebar.team.files: 档案
|
||||||
§ sidebar.team.removedFiles: 删除的文件
|
§ sidebar.team.removedFiles: 删除的文件
|
||||||
|
§ sidebar.team.extension: Extensions
|
||||||
§ sidebar.team.tasks: 任务列表
|
§ sidebar.team.tasks: 任务列表
|
||||||
|
§ sidebar.team.release: Releases
|
||||||
§ sidebar.team.hours: 时间表
|
§ sidebar.team.hours: 时间表
|
||||||
§ sidebar.team.commits: All commits
|
§ sidebar.team.commits: All commits
|
||||||
§ sidebar.team.changes: 所有更改
|
§ sidebar.team.changes: 所有更改
|
||||||
|
|
|
@ -120,13 +120,13 @@ export default `
|
||||||
§ page.team.pr.tasks: 任务
|
§ page.team.pr.tasks: 任务
|
||||||
§ page.team.pr.firstCommitTime: 第一个 Commits
|
§ page.team.pr.firstCommitTime: 第一个 Commits
|
||||||
§ page.team.pr.lastCommitTime: 最后一次
|
§ page.team.pr.lastCommitTime: 最后一次
|
||||||
§ page.team.pr.workDays: 发展的日子
|
§ page.team.pr.workDays: 完成任务的平均时间
|
||||||
§ page.team.pr.delayDays: 等待输液的日子
|
§ page.team.pr.delayDays: PR审查的平均时间
|
||||||
|
§ page.team.pr.middleTimeRelease: 开发时间与审查时间的比率
|
||||||
§ page.team.pr.commits: Commits
|
§ page.team.pr.commits: Commits
|
||||||
§ page.team.pr.date: 注射日期
|
§ page.team.pr.date: 注射日期
|
||||||
§ page.team.pr.mergeAuthor: 填写
|
§ page.team.pr.mergeAuthor: 填写
|
||||||
§ page.team.pr.author: 雇员
|
§ page.team.pr.author: 雇员
|
||||||
§ page.team.pr.middleTimeRelease: 平均派递时间 (天数)
|
|
||||||
§ page.team.pr.work: 发展
|
§ page.team.pr.work: 发展
|
||||||
§ page.team.pr.delay: 期望
|
§ page.team.pr.delay: 期望
|
||||||
§ page.team.pr.days: 天数
|
§ page.team.pr.days: 天数
|
||||||
|
@ -146,6 +146,18 @@ export default `
|
||||||
§ page.team.tasks.prAuthor: 灌
|
§ page.team.tasks.prAuthor: 灌
|
||||||
§ page.team.tasks.prDelayDays: 等待输液的日子
|
§ page.team.tasks.prDelayDays: 等待输液的日子
|
||||||
§ page.team.tasks.comments: 评论
|
§ page.team.tasks.comments: 评论
|
||||||
|
§ page.team.extension.extension: File extensions
|
||||||
|
§ page.team.extension.type: File sub types
|
||||||
|
§ page.team.extension.name: Type
|
||||||
|
§ page.team.extension.path: Path
|
||||||
|
§ page.team.extension.current.count: Number
|
||||||
|
§ page.team.extension.removed.count: Number of removed
|
||||||
|
§ page.team.extension.files: files
|
||||||
|
§ page.team.release.title: Release
|
||||||
|
§ page.team.release.from: Created date
|
||||||
|
§ page.team.release.to: Delivery date
|
||||||
|
§ page.team.release.delay: Preparation days
|
||||||
|
§ page.team.release.waiting: Days of waiting for next release
|
||||||
§ page.person.print.photo.title: 照片
|
§ page.person.print.photo.title: 照片
|
||||||
§ page.person.print.photo.description: 拍照的地方
|
§ page.person.print.photo.description: 拍照的地方
|
||||||
§ page.person.total.title: 主要特点
|
§ page.person.total.title: 主要特点
|
||||||
|
|
|
@ -191,10 +191,14 @@ in terms of potential profit.
|
||||||
|
|
||||||
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
Features that are expensive to develop but bring little profit may need to be postponed or even canceled. This will make the project more commercially successful.
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||||
writes too little code.
|
§ recommendations.author.lotOfLazy.description
|
||||||
|
Should they be fired?
|
||||||
|
|
||||||
# Should they be fired?
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Answer the questions:
|
||||||
- are they a team leader, architect, or analyst?
|
- are they a team leader, architect, or analyst?
|
||||||
- is this their primary project?
|
- is this their primary project?
|
||||||
- are there any dependencies on them?
|
- are there any dependencies on them?
|
||||||
|
@ -204,8 +208,12 @@ The total costs for the developer are already more than the profit from their wo
|
||||||
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
If we believe that there were no objective hindrances to their work, then the person either does not want to work at all or is working on two projects simultaneously.
|
||||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
§ recommendations.author.manyLazy.title: Little code: $1
|
||||||
writes little code. Needs to be monitored.
|
§ recommendations.author.manyLazy.description
|
||||||
|
Needs to be monitored.
|
||||||
|
|
||||||
|
# Composition:
|
||||||
|
- $1;
|
||||||
|
|
||||||
# How the sample is chosen:
|
# How the sample is chosen:
|
||||||
- in test samples, a good programmer writes code for more than 80% of the time;
|
- in test samples, a good programmer writes code for more than 80% of the time;
|
||||||
|
@ -286,7 +294,9 @@ Typically, such projects are assessed before starting the development of their o
|
||||||
Light Workload
|
Light Workload
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
§ recommendations.author.projectType.easy.description
|
||||||
too many days without commits. It is necessary to understand why the team is not writing code.
|
too many days without commits.
|
||||||
|
|
||||||
|
It is necessary to understand why the team is not writing code.
|
||||||
|
|
||||||
# Assessment method:
|
# Assessment method:
|
||||||
- take statistics from all active developers;
|
- take statistics from all active developers;
|
||||||
|
|
Loading…
Reference in a new issue