mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 16:21:41 +00:00
update
This commit is contained in:
parent
599bb1079d
commit
36d57c2737
|
@ -23,6 +23,7 @@
|
|||
--color-second: #ED675F;
|
||||
|
||||
--color-black: #12131B;
|
||||
--color-white: #FFFFFF;
|
||||
--color-grey: #CBCBCD;
|
||||
--color-border: #E2E9F0;
|
||||
--color-button: #1A73E8;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
.achievement:last-child {
|
||||
|
@ -50,7 +50,7 @@
|
|||
border-radius: 40px;
|
||||
letter-spacing: 2px;
|
||||
|
||||
color: white;
|
||||
color: var(--color-white);
|
||||
background-color: var(--color-border);
|
||||
border-color: var(--color-border);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@
|
|||
width: 56px;
|
||||
height: 56px;
|
||||
margin: 4px auto;
|
||||
fill: #FFFFFF;
|
||||
fill: var(--color-white);
|
||||
}
|
||||
|
||||
.achievement_title,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
text-decoration: none;
|
||||
border-radius: var(--border-radius-s);
|
||||
|
||||
color: #FFFFFF;
|
||||
color: var(--color-white);
|
||||
background-color: #A7B6FE;
|
||||
//background: linear-gradient(135deg, rgba(64,117,252,1) 0%, rgba(172,179,246,1) 100%);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
|
||||
background-repeat: repeat;
|
||||
background-size: auto 100%;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
page-break-inside: avoid;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top;
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&_wrapper {
|
||||
width: calc(100% + 24px);
|
||||
|
|
|
@ -31,6 +31,6 @@
|
|||
|
||||
&_text {
|
||||
margin: var(--space-s) auto;
|
||||
color: white;
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
.infinite_scroll_border_bottom {
|
||||
position: sticky;
|
||||
z-index: 3;
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
.infinite_scroll_border_top {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 3;
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&_icon {
|
||||
display: block;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
padding: 24px;
|
||||
vertical-align: top;
|
||||
border-radius: var(--border-radius-l);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&_icon {
|
||||
display: block;
|
||||
|
|
|
@ -28,6 +28,6 @@
|
|||
|
||||
&_text {
|
||||
margin: var(--space-s) auto;
|
||||
color: white;
|
||||
color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--border-radius-s);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_title {
|
||||
|
@ -40,7 +40,7 @@
|
|||
|
||||
border-radius: var(--border-radius-s);
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
|
@ -57,7 +57,7 @@
|
|||
box-sizing: border-box;
|
||||
|
||||
transform: rotateZ(45deg);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
border-right: 1px solid var(--color-border);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
}
|
||||
|
||||
&_hour {
|
||||
color: white;
|
||||
color: var(--color-white);
|
||||
border-radius: 6px;
|
||||
border: 1px solid #FFFFFF;
|
||||
background-color: var(--color-first);
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
&_count {
|
||||
color: var(--color-black);
|
||||
border: 1px solid var(--color-grey);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_title {
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
overflow: hidden;
|
||||
line-height: var(--line_chart-height);
|
||||
text-align: left;
|
||||
color: #FFFFFF;
|
||||
color: var(--color-white);
|
||||
background-color: #D0D1D2;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
}
|
||||
|
||||
&_center {
|
||||
fill: white;
|
||||
fill: var(--color-white);
|
||||
stroke: none;
|
||||
stroke-width: 0;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 5px gray;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
@ -111,16 +111,16 @@
|
|||
@keyframes modal_window_halo {
|
||||
from {
|
||||
transform: rotateZ(0deg);
|
||||
opacity: 0;
|
||||
opacity: 0.4;
|
||||
}
|
||||
11% {
|
||||
opacity: 0.4;
|
||||
opacity: 0.7;
|
||||
}
|
||||
89% {
|
||||
opacity: 0.4;
|
||||
opacity: 0.7;
|
||||
}
|
||||
to {
|
||||
transform: rotateZ(360deg);
|
||||
opacity: 0;
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,19 @@ function Card({ message }: ICardProps) {
|
|||
info: 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 (
|
||||
<div className={`${style.notifications_item} ${className}`}>
|
||||
<img
|
||||
className={style.notifications_item_icon}
|
||||
src={icon}
|
||||
/>
|
||||
{message.title && (
|
||||
<h6 className={style.notifications_item_title}>
|
||||
{message.title}
|
||||
|
|
|
@ -8,30 +8,41 @@
|
|||
display: inline-block;
|
||||
|
||||
&_item {
|
||||
position: relative;
|
||||
|
||||
display: block;
|
||||
width: 300px;
|
||||
padding: 24px;
|
||||
padding: var(--space-xxl) var(--space-xxl) var(--space-xxl) 56px;
|
||||
margin: 0 12px 12px;
|
||||
|
||||
box-sizing: border-box;
|
||||
box-shadow: 2px 2px 3px var(--color-grey);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 8px solid var(--color-border);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-s);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
animation: notification_item 3s linear 0.5s forwards;
|
||||
|
||||
&_icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 12px;
|
||||
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
&_error {
|
||||
border-color: var(--color-12);
|
||||
background-color: var(--color-12);
|
||||
}
|
||||
|
||||
&_warning {
|
||||
border-color: var(--color-32);
|
||||
background-color: var(--color-32);
|
||||
}
|
||||
|
||||
&_success {
|
||||
border-color: var(--color-13);
|
||||
background-color: #35D081;
|
||||
}
|
||||
|
||||
&_info {
|
||||
|
@ -44,7 +55,7 @@
|
|||
font-weight: 100;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
color: var(--color-black);
|
||||
color: var(--color-white);
|
||||
animation: notification_title 3s linear 0.5s forwards;
|
||||
}
|
||||
|
||||
|
@ -62,12 +73,12 @@
|
|||
80% {
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
padding: 24px;
|
||||
padding: var(--space-xxl) var(--space-xxl) var(--space-xxl) 56px;
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
padding: 0 24px;
|
||||
padding: 0 var(--space-xxl) 0 64px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
break-inside: auto;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_icons {
|
||||
|
@ -56,7 +56,7 @@
|
|||
vertical-align: top;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
.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 style from '../styles/answer.module.scss';
|
||||
|
||||
const IS_WRAPPER_MODE = {
|
||||
error: true,
|
||||
small: true,
|
||||
};
|
||||
|
||||
interface IAnswerProps {
|
||||
answer: IAnswer;
|
||||
mode: string;
|
||||
|
@ -19,28 +14,27 @@ function Answer({
|
|||
mode,
|
||||
onClick,
|
||||
}: IAnswerProps): React.ReactElement | null {
|
||||
const className = [style.quize_answer];
|
||||
if (mode === 'selected') className.push(style.quize_answer_selected);
|
||||
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 className = [style.quize_answer_wrapper];
|
||||
const textClasName = [style.quize_answer_text];
|
||||
|
||||
const wrapperClass = [style.quize_answer_wrapper];
|
||||
if (IS_WRAPPER_MODE[mode]) wrapperClass.push(style.quize_answer_wrapper_small);
|
||||
if (mode === 'small' || mode === 'error') className.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 (
|
||||
<div className={wrapperClass.join(' ')}>
|
||||
<div className={className.join(' ')}>
|
||||
<figure
|
||||
className={className.join(' ')}
|
||||
className={style.quize_answer}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
}}
|
||||
>
|
||||
<img
|
||||
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}
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
|
|
@ -4,7 +4,6 @@ import UiKitButton from 'ts/components/UiKit/components/Button';
|
|||
|
||||
import IQuestion from '../interfaces/Question';
|
||||
import IAnswer from '../interfaces/Answer';
|
||||
import Progress from './Progress';
|
||||
import Answer from './Answer';
|
||||
|
||||
import stylePage from '../styles/question.module.scss';
|
||||
|
@ -20,13 +19,11 @@ function getModes(answers: IAnswer[], selected: IAnswer | null) {
|
|||
|
||||
interface IQuestionProps {
|
||||
question: IQuestion;
|
||||
progress: number;
|
||||
onClick: Function;
|
||||
}
|
||||
|
||||
function Question({
|
||||
question,
|
||||
progress,
|
||||
onClick,
|
||||
}: IQuestionProps): React.ReactElement | null {
|
||||
const [selected, setSelected] = useState<IAnswer | null>(null);
|
||||
|
@ -71,7 +68,6 @@ function Question({
|
|||
|
||||
return (
|
||||
<div className={stylePage.quize_question}>
|
||||
<Progress progress={progress}/>
|
||||
<div className={stylePage.quize_question_body}>
|
||||
<div className={style.quize_title}>
|
||||
{question.title}
|
||||
|
|
|
@ -21,11 +21,6 @@ function Result({
|
|||
<h4 className={style.quize_title}>
|
||||
{result.title}
|
||||
</h4>
|
||||
<img
|
||||
className={style.quize_icon}
|
||||
style={{ backgroundImage: `url(${result.icon})` }}
|
||||
src="./assets/games/4x3.png"
|
||||
/>
|
||||
<p className={style.quize_description}>
|
||||
{result.description}
|
||||
</p>
|
||||
|
|
|
@ -21,11 +21,6 @@ function Start({
|
|||
<h4 className={style.quize_title}>
|
||||
{quize.title}
|
||||
</h4>
|
||||
<img
|
||||
className={style.quize_icon}
|
||||
style={{ backgroundImage: `url(${quize.icon})` }}
|
||||
src="./assets/games/4x3.png"
|
||||
/>
|
||||
<p className={style.quize_description}>
|
||||
{quize.description}
|
||||
</p>
|
||||
|
|
|
@ -44,7 +44,6 @@ function QuizePage({
|
|||
const questions = getQuestionByGroups(quize.questions);
|
||||
let page: any = null;
|
||||
|
||||
|
||||
if (view === 'start') {
|
||||
page = (
|
||||
<Start
|
||||
|
@ -62,7 +61,6 @@ function QuizePage({
|
|||
page = (
|
||||
<Question
|
||||
question={question}
|
||||
progress={30}
|
||||
onClick={(answer: IAnswer) => {
|
||||
const nextById = questions.byId[answer.nextQuestionId || ''];
|
||||
const nextByIndex = questions.byIndex[question.index + 1];
|
||||
|
@ -116,7 +114,7 @@ function QuizePage({
|
|||
return (
|
||||
<div
|
||||
className={style.quize_container}
|
||||
style={{ backgroundImage: 'url(./assets/games/quize.png)' }}
|
||||
style={{ backgroundImage: 'url(./assets/games/quize/air.jpg)' }}
|
||||
>
|
||||
<div className={className}>
|
||||
{page}
|
||||
|
|
|
@ -1,27 +1,23 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.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);
|
||||
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius-s);
|
||||
border: none;
|
||||
box-shadow: 0 0 5px var(--color-grey);
|
||||
box-shadow: none;
|
||||
transition: width 0.5s;
|
||||
|
||||
background-color: white;
|
||||
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: quize_answer;
|
||||
|
||||
&_wrapper {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
|
||||
vertical-align: top;
|
||||
border-radius: var(--border-radius-s);
|
||||
vertical-align: bottom;
|
||||
transition: padding 0.5s;
|
||||
|
||||
&_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 {
|
||||
width: 218px;
|
||||
width: var(--temp-small);
|
||||
}
|
||||
|
||||
&_icon {
|
||||
|
@ -57,7 +34,6 @@
|
|||
width: 100%;
|
||||
margin: 0 auto var(--space-l);
|
||||
|
||||
border-radius: var(--border-radius-s) var(--border-radius-s) 0 0;
|
||||
background-position: center center;
|
||||
background-size: auto 100%;
|
||||
background-repeat: no-repeat;
|
||||
|
@ -69,44 +45,81 @@
|
|||
}
|
||||
|
||||
&_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-weight: 100;
|
||||
position: relative;
|
||||
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 80%;
|
||||
height: 40px;
|
||||
margin: var(--space-xxs) auto 0;
|
||||
|
||||
text-align: center;
|
||||
border-radius: var(--border-radius-m);
|
||||
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 {
|
||||
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 {
|
||||
from {
|
||||
box-shadow: none;
|
||||
}
|
||||
86% {
|
||||
box-shadow: none;
|
||||
}
|
||||
93% {
|
||||
box-shadow: 0 0 10px var(--color-13), 0 0 20px var(--color-13);
|
||||
top: 0;
|
||||
}
|
||||
to {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
top: 800px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
margin: 0 auto var(--space-xxl);
|
||||
height: 500px;
|
||||
margin: 0 auto;
|
||||
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: #F0AE7A;
|
||||
background-position: center center;
|
||||
background-size: 10%;
|
||||
background-size: auto 100%;
|
||||
background-repeat: repeat;
|
||||
}
|
||||
|
||||
|
@ -47,18 +48,30 @@
|
|||
&_title,
|
||||
&_description {
|
||||
font-weight: 100;
|
||||
|
||||
display: block;
|
||||
width: 500px;
|
||||
padding: var(--space-xxl) 64px;
|
||||
margin: 0 auto;
|
||||
|
||||
line-height: 1.5;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
|
||||
color: var(--color-black);
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-size: var(--font-l);
|
||||
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 {
|
||||
font-size: var(--font-m);
|
||||
margin: 100px auto 0;
|
||||
}
|
||||
|
||||
&_icon {
|
||||
|
@ -67,9 +80,9 @@
|
|||
max-width: 300px;
|
||||
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);
|
||||
background-color: var(--color-border);
|
||||
background-color: #E8816E;
|
||||
|
||||
background-position: center center;
|
||||
background-size: auto 100%;
|
||||
|
@ -79,21 +92,21 @@
|
|||
|
||||
@keyframes quize_slider {
|
||||
from {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
49% {
|
||||
right: 100%;
|
||||
bottom: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
51% {
|
||||
right: auto;
|
||||
left: 100%;
|
||||
top: 100%;
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
&_title {
|
||||
font-size: var(--font-l);
|
||||
font-weight: 100;
|
||||
|
||||
margin: 0 auto var(--space-xxl);
|
||||
text-align: center;
|
||||
|
||||
color: var(--color-black);
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_answer {
|
||||
|
|
|
@ -17,19 +17,4 @@
|
|||
&_description {
|
||||
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>
|
||||
<img
|
||||
className={style.races_track_car_cover}
|
||||
src="./assets/games/car.png"
|
||||
src="./assets/games/races/car.png"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -27,7 +27,12 @@ function Track({
|
|||
const duration = DURATION.MIN + (DURATION.BASE * (1 - speed)) * 3;
|
||||
|
||||
return (
|
||||
<div className={`${style.races_track} ${type || ''}`}>
|
||||
<div
|
||||
className={`${style.races_track} ${type || ''}`}
|
||||
style={{
|
||||
backgroundImage: 'url(./assets/games/races/road.png)',
|
||||
}}
|
||||
>
|
||||
{canStart && (
|
||||
<Info
|
||||
title={title}
|
||||
|
|
|
@ -39,7 +39,7 @@ function Races({
|
|||
|
||||
return (
|
||||
<>
|
||||
<GameBanner src="./assets/games/races.jpg">
|
||||
<GameBanner src="./assets/games/races/bg.png">
|
||||
{!showAnimation && (
|
||||
<UiKitButton
|
||||
className={style.races_button}
|
||||
|
@ -51,9 +51,21 @@ function Races({
|
|||
</UiKitButton>
|
||||
)}
|
||||
</GameBanner>
|
||||
<div
|
||||
className={style.races_green}
|
||||
style={{
|
||||
backgroundImage: 'url(./assets/games/races/greenTop.png)',
|
||||
}}
|
||||
/>
|
||||
<div className={style.races}>
|
||||
{lines}
|
||||
</div>
|
||||
<div
|
||||
className={style.races_green}
|
||||
style={{
|
||||
backgroundImage: 'url(./assets/games/races/greenBottom.png)',
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.races_track_car {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: -8px;
|
||||
left: 0;
|
||||
|
||||
width: 10%;
|
||||
|
@ -26,7 +26,7 @@
|
|||
border: 1px solid var(--color-grey);
|
||||
border-radius: var(--border-radius-s);
|
||||
color: var(--color-black);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&:before {
|
||||
content: ' ';
|
||||
|
@ -39,16 +39,16 @@
|
|||
padding: 4px;
|
||||
transform: rotate(45deg);
|
||||
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
&_cover {
|
||||
font-size: 12px;
|
||||
|
||||
display: block;
|
||||
height: 50%;
|
||||
margin: 0 auto;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&_animation {
|
||||
|
|
|
@ -2,12 +2,20 @@
|
|||
|
||||
.races {
|
||||
position: relative;
|
||||
margin: 0 auto var(--space-xxl);
|
||||
border: var(--space-xxl) solid var(--color-13);
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
margin: 0 auto;
|
||||
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 {
|
||||
position: relative;
|
||||
height: 80px;
|
||||
|
@ -15,11 +23,14 @@
|
|||
margin: 0 auto;
|
||||
|
||||
text-align: right;
|
||||
border-bottom: var(--space-xxs) dashed var(--color-border);
|
||||
background-color: var(--color-grey);
|
||||
|
||||
background-repeat: repeat-x;
|
||||
background-size: auto 100%;
|
||||
background-position: top left;
|
||||
|
||||
&: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;
|
||||
border: var(--space-xxs) solid var(--color-border);
|
||||
color: var(--color-black);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
animation-name: races_track_info;
|
||||
animation-iteration-count: 1;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
@import 'src/styles/variables';
|
||||
|
||||
.show_symbol_wrapper {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.show_symbol {
|
||||
|
@ -33,9 +35,9 @@
|
|||
line-height: var(--temp-height);
|
||||
transform: rotateY(180deg);
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
// border: 1px solid var(--color-border);
|
||||
color: var(--color-black);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&_hide {
|
||||
animation-name: show_symbol;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
word-wrap: break-word;
|
||||
border-radius: 4px;
|
||||
|
||||
color: white;
|
||||
color: var(--color-white);
|
||||
background-color: green;
|
||||
background-size: 23px 22px;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class SponsorStore {
|
|||
});
|
||||
|
||||
if (!isMobile && !themeSettings.getConfig()) {
|
||||
this.setTimer();
|
||||
// this.setTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class SponsorStore {
|
|||
this.type = Math.random() > 0.5
|
||||
? MODAL_TYPE.SHARE
|
||||
: MODAL_TYPE.SHARE;
|
||||
}, 6 * ONE_MINUTE);
|
||||
}, 10 * ONE_MINUTE);
|
||||
}
|
||||
|
||||
open() {
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
white-space: nowrap;
|
||||
border-radius: var(--border-radius-s);
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
|
||||
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);
|
||||
|
||||
border: 6px solid var(--color-grey);
|
||||
border-left-color: white;
|
||||
border-bottom-color: white;
|
||||
border-left-color: var(--color-white);
|
||||
border-bottom-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_sort_down {
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
height: var(--table-cell-height);
|
||||
padding: 0 4px;
|
||||
line-height: var(--table-cell-height);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_cell:first-child,
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
.ui_kit_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-hover: var(--color-button-2);
|
||||
--button-color-active: var(--color-button-3);
|
||||
|
||||
&_slim,
|
||||
&_second {
|
||||
--button-color-bg: #FFFFFF;
|
||||
--button-color-bg: var(--color-white);
|
||||
--button-color-text: var(--color-black);
|
||||
--button-color-border: var(--color-border);
|
||||
--button-color-hover: var(--color-border);
|
||||
|
@ -111,7 +111,7 @@
|
|||
}
|
||||
|
||||
.ui_kit_button_menu {
|
||||
--button-color-bg: #FFFFFF;
|
||||
--button-color-bg: var(--color-white);
|
||||
--button-color-text: var(--color-black);
|
||||
--button-color-border: var(--color-border);
|
||||
--button-color-hover: var(--color-border);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
border-radius: var(--border-radius-s);
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-black);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
.ui_kit_dialog {
|
||||
|
@ -35,6 +35,6 @@
|
|||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-radius: 8px;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
box-shadow: 0 0 5px #C0C0C0;
|
||||
}
|
||||
|
|
|
@ -34,11 +34,11 @@
|
|||
border: 1px solid #E2E9F0;
|
||||
border-right: none;
|
||||
border-radius: 0;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
color: #84858D;
|
||||
|
||||
&_selected {
|
||||
color: #FFFFFF;
|
||||
color: var(--color-white);
|
||||
border-top: 1px solid var(--color-button);
|
||||
border-bottom: 1px solid var(--color-button);
|
||||
background-color: var(--color-button);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
border: none;
|
||||
border-bottom: 3px solid #E2E9F0;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
color: var(--color-black);
|
||||
|
||||
&_selected {
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
border: 16px solid white;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_info {
|
||||
|
@ -90,7 +90,7 @@
|
|||
border-radius: var(--border-radius-m);
|
||||
box-shadow: 2px 2px 5px 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,
|
||||
|
||||
(lotOfLazy.length ? {
|
||||
title: lotOfLazy,
|
||||
description: 'recommendations.author.lotOfLazy',
|
||||
title: 'recommendations.author.lotOfLazy.title',
|
||||
description: 'recommendations.author.lotOfLazy.description',
|
||||
type: RECOMMENDATION_TYPES.ALERT,
|
||||
arguments: {
|
||||
title: lotOfLazy.length,
|
||||
description: lotOfLazy.join(';\n- '),
|
||||
},
|
||||
} : null),
|
||||
|
||||
(manyLazy.length ? {
|
||||
title: manyLazy,
|
||||
description: 'recommendations.author.manyLazy',
|
||||
title: 'recommendations.author.manyLazy.title',
|
||||
description: 'recommendations.author.manyLazy.description',
|
||||
type: RECOMMENDATION_TYPES.WARNING,
|
||||
arguments: {
|
||||
title: manyLazy.length,
|
||||
description: manyLazy.join(';\n- '),
|
||||
},
|
||||
} : null),
|
||||
|
||||
(oneTypeMans.length ? {
|
||||
|
|
|
@ -115,10 +115,6 @@ export function getShortNumber(value: number) {
|
|||
return (value || 0).toFixed(fractionDigits);
|
||||
}
|
||||
|
||||
export function getShortName(name: string) {
|
||||
return name?.split(/[\s.]+/gm)[1] || name;
|
||||
}
|
||||
|
||||
export function getShortDateRange({ from, to }: any) {
|
||||
return from && to
|
||||
? `${getShortDate(from)} — ${getDate(to)}`
|
||||
|
|
|
@ -46,13 +46,13 @@
|
|||
&:nth-child(4n+2):hover,
|
||||
&_selected {
|
||||
background-color: #35353F;
|
||||
--temp-color: white;
|
||||
--temp-color: var(--color-white);
|
||||
}
|
||||
|
||||
&:first-child:active,
|
||||
&:nth-child(4n+2):active {
|
||||
background-color: #45454F;
|
||||
--temp-color: white;
|
||||
--temp-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_text {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
padding: 20px 34px 20px 24px;
|
||||
box-sizing: border-box;
|
||||
text-align: right;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
|
||||
&_title {
|
||||
float: left;
|
||||
|
@ -52,7 +52,7 @@
|
|||
right: 0;
|
||||
|
||||
padding: 0;
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
display: block;
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
|
||||
&_main,
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
.sidebar_item:hover,
|
||||
.sidebar_item.selected {
|
||||
color: #FFFFFF;
|
||||
color: var(--color-white);
|
||||
background-color: #252735;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
color: #84858D;
|
||||
|
||||
&.selected {
|
||||
color: #FFFFFF;
|
||||
color: var(--color-white);
|
||||
background-color: #37394B;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,16 +13,14 @@ const Month = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
|||
const max = statistic.commitsByTimestampCounter.max;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageWrapper template="table">
|
||||
<YearChart
|
||||
showEvents={false}
|
||||
maxCommits={max}
|
||||
authors={[author]}
|
||||
wordDays={statistic.allCommitsByTimestamp}
|
||||
/>
|
||||
</PageWrapper>
|
||||
</>
|
||||
<PageWrapper template="table">
|
||||
<YearChart
|
||||
showEvents={false}
|
||||
maxCommits={max}
|
||||
authors={[author]}
|
||||
wordDays={statistic.allCommitsByTimestamp}
|
||||
/>
|
||||
</PageWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
background-color: #FFFFFF;
|
||||
background-color: var(--color-white);
|
||||
color: var(--color-grey);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@ import { observer } from 'mobx-react-lite';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ISort from 'ts/interfaces/Sort';
|
||||
import ICommit from 'ts/interfaces/Commit';
|
||||
import IHashMap from 'ts/interfaces/HashMap';
|
||||
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 ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||
|
@ -67,6 +68,7 @@ function AuthorView({ response, updateSort, rowsForExcel, mode }: IAuthorViewPro
|
|||
width={200}
|
||||
/>
|
||||
<Column
|
||||
title="page.team.author.status"
|
||||
template={(row: any) => {
|
||||
let value = works;
|
||||
if (row.isDismissed) value = dismissed;
|
||||
|
@ -75,6 +77,19 @@ function AuthorView({ response, updateSort, rowsForExcel, mode }: IAuthorViewPro
|
|||
}}
|
||||
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
|
||||
isSortable="daysWorked"
|
||||
title="page.team.author.workedLosses"
|
||||
|
|
|
@ -130,7 +130,7 @@ const Extension = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Title title="sidebar.team.extension"/>
|
||||
<Title title="page.team.extension.extension"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||
|
|
|
@ -130,7 +130,7 @@ const Type = observer(({
|
|||
|
||||
return (
|
||||
<>
|
||||
<Title title="sidebar.team.extension"/>
|
||||
<Title title="page.team.extension.type"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import Table from 'ts/components/Table';
|
||||
import Column from 'ts/components/Table/components/Column';
|
||||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import PieChart from 'ts/components/PieChart';
|
||||
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 DataGripByPR from 'ts/helpers/DataGrip/components/pr';
|
||||
|
||||
function Total() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const allPR = dataGripStore.dataGrip.pr.statistic;
|
||||
|
||||
const workChart = DataGripByPR.getPRByGroups(allPR, 'workDays');
|
||||
|
@ -27,59 +30,36 @@ function Total() {
|
|||
suffix: 'page.team.pr.days',
|
||||
});
|
||||
|
||||
const rows = [
|
||||
{
|
||||
workDays: workChart.details,
|
||||
delayDays: delayChart.details,
|
||||
weightedAverage: weightedAverage.toFixed(1),
|
||||
weightedAverageDetails: {
|
||||
workDays: workDaysWeightedAverage,
|
||||
delayDays: delayDaysWeightedAverage,
|
||||
},
|
||||
},
|
||||
];
|
||||
console.log(weightedAverage.toFixed(1));
|
||||
|
||||
return (
|
||||
<Table rows={rows}>
|
||||
<Column
|
||||
title="page.team.pr.workDays"
|
||||
properties="workDays"
|
||||
template={(details: any) => (
|
||||
<LineChart
|
||||
options={workChartOptions}
|
||||
details={details}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Column
|
||||
title="page.team.pr.delayDays"
|
||||
properties="delayDays"
|
||||
template={(details: any) => (
|
||||
<LineChart
|
||||
options={delayChartOptions}
|
||||
details={details}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Column
|
||||
properties="weightedAverage"
|
||||
template={ColumnTypesEnum.SHORT_NUMBER}
|
||||
/>
|
||||
<Column
|
||||
title="page.team.pr.middleTimeRelease"
|
||||
properties="weightedAverageDetails"
|
||||
width={300}
|
||||
template={(item: any) => (
|
||||
<LineChart
|
||||
options={weightedAverageChart}
|
||||
details={{
|
||||
'page.team.pr.work': item.workDays,
|
||||
'page.team.pr.delay': item.delayDays,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
<PageWrapper>
|
||||
<PageColumn>
|
||||
<PieChart
|
||||
title="page.team.pr.workDays"
|
||||
options={workChartOptions}
|
||||
details={workChart.details}
|
||||
/>
|
||||
<PieChart
|
||||
title="page.team.pr.middleTimeRelease"
|
||||
options={weightedAverageChart}
|
||||
details={{
|
||||
'page.team.pr.work': workDaysWeightedAverage,
|
||||
'page.team.pr.delay': delayDaysWeightedAverage,
|
||||
}}
|
||||
/>
|
||||
</PageColumn>
|
||||
<PageColumn>
|
||||
<PieChart
|
||||
title="page.team.pr.delayDays"
|
||||
options={delayChartOptions}
|
||||
details={delayChart.details}
|
||||
/>
|
||||
<Description text={t('page.team.pr.description1')} />
|
||||
<Description text={t('page.team.pr.description2')} />
|
||||
<Description text={t('page.team.pr.description3')} />
|
||||
</PageColumn>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ISort from 'ts/interfaces/Sort';
|
||||
import { IPaginationRequest } from 'ts/interfaces/Pagination';
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
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 Pagination from 'ts/components/DataLoader/components/Pagination';
|
||||
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
||||
|
@ -24,7 +20,6 @@ import All from './All';
|
|||
const PR = observer(({
|
||||
mode,
|
||||
}: ICommonPageProps): React.ReactElement | null => {
|
||||
const { t } = useTranslation();
|
||||
const allPR = dataGripStore.dataGrip.pr.statistic;
|
||||
const rows = allPR.filter((item: any) => item.delayDays > 3);
|
||||
if (rows?.length < 2) return mode !== 'print' ? (<NothingFound />) : null;
|
||||
|
@ -37,24 +32,6 @@ const PR = observer(({
|
|||
<Title title="page.team.pr.oneTaskDays"/>
|
||||
<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"/>
|
||||
<DataLoader
|
||||
to="response"
|
||||
|
|
|
@ -7,15 +7,9 @@ import Title from 'ts/components/Title';
|
|||
import Races from 'ts/components/Races';
|
||||
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 GameBanner from 'ts/components/GameBanner';
|
||||
import SwimmingPool from 'ts/components/SwimmingPool';
|
||||
import Quize from 'ts/components/Quize';
|
||||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
|
||||
const TeamBuilding = observer((): React.ReactElement => {
|
||||
const filesByAuthor = dataGripStore.fileGrip.author?.statisticByName || {};
|
||||
|
@ -37,86 +31,21 @@ const TeamBuilding = observer((): React.ReactElement => {
|
|||
const maxMessageLength = [...tracksAuth]
|
||||
.sort((a: any, b: any) => b.maxMessageLength - a.maxMessageLength)
|
||||
.map((item: any) => ({ title: item.author, value: item.maxMessageLength }));
|
||||
const chartMessageLength = getOptions({ max: maxMessageLength[0].value, suffix: 'сиволов' });
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title title="Скорость коммитов в день"/>
|
||||
<GameConsole />
|
||||
|
||||
<Title title="Квиз"/>
|
||||
<Quize />
|
||||
<Title title="Скорость закрытия задач"/>
|
||||
<Races tracks={tracks} />
|
||||
|
||||
<Title title="Максимальная длинна подписи коммита"/>
|
||||
<GameBanner src="./assets/games/wheel.jpg" />
|
||||
<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>
|
||||
<SwimmingPool tracks={maxMessageLength}/>
|
||||
|
||||
<Title title="Количество созданных файлов, если бы это был город"/>
|
||||
<CityBuilder valuesByTitle={addedFilesByAuthor} />
|
||||
|
||||
<Title title="Количество созданных папок"/>
|
||||
<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="Скорость коммитов в день"/>
|
||||
<GameConsole />
|
||||
{'Небоскребы вверх ввиде графика'}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -22,7 +22,9 @@ export default `
|
|||
§ sidebar.team.removedTree: Gelöschte dateien
|
||||
§ sidebar.team.files: Dateien
|
||||
§ sidebar.team.removedFiles: Gelöschte Dateien
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: Aufgabenliste
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: Zeitplan
|
||||
§ sidebar.team.commits: All commits
|
||||
§ sidebar.team.changes: Alle Änderungen
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -122,11 +125,11 @@ export default `
|
|||
§ page.team.pr.lastCommitTime: Last
|
||||
§ page.team.pr.workDays: Development days
|
||||
§ page.team.pr.delayDays: Days waiting for merge
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.commits: Commits
|
||||
§ page.team.pr.date: Merge Date
|
||||
§ page.team.pr.mergeAuthor: Merged by
|
||||
§ page.team.pr.author: Employee
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.work: development
|
||||
§ page.team.pr.delay: waiting
|
||||
§ page.team.pr.days: days
|
||||
|
@ -146,6 +149,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Merged by user
|
||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||
§ 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.description: space for a photo
|
||||
§ 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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
|
@ -97,22 +97,22 @@ export default `
|
|||
§ achievements.oneExtension.description: только он работает с файлами определенного расширения
|
||||
§ achievements.fileRush.title: Zerg Rush
|
||||
§ achievements.fileRush.description: created the most files in the project
|
||||
§ achievements.moreLintHint.title: Грамар-наци
|
||||
§ achievements.moreLintHint.description: больше всех создал или изменил в правилах авто-проверки кода
|
||||
§ achievements.moreReadMe.title: Летописец
|
||||
§ achievements.moreReadMe.description: больше всех создал или изменил файлов MD
|
||||
§ achievements.moreLintHint.title: Grammar Nazi
|
||||
§ achievements.moreLintHint.description: more than anyone created or changed the code-style rules
|
||||
§ achievements.moreReadMe.title: Chronicler
|
||||
§ achievements.moreReadMe.description: more than anyone created or modified MD files
|
||||
§ achievements.moreDevOps.title: DevOps
|
||||
§ achievements.moreDevOps.description: больше всех создал или изменил файлов для CI/CD
|
||||
§ achievements.moreTests.title: Тестировщик
|
||||
§ achievements.moreTests.description: больше всех создал или изменил файлов для тестирования
|
||||
§ achievements.allRelease.title: Фулл хаус
|
||||
§ achievements.allRelease.description: есть релиз, собранный только из его задач
|
||||
§ achievements.moreDevOps.description: more than anyone created or modified files for CI/CD
|
||||
§ achievements.moreTests.title: Tester
|
||||
§ achievements.moreTests.description: more than anyone created or modified files for testing
|
||||
§ achievements.allRelease.title: Full house
|
||||
§ achievements.allRelease.description: there is a release compiled only from his tasks
|
||||
§ 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.description: последний коммит на проекте
|
||||
§ achievements.lastCommit.description: last commit on the project
|
||||
§ 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.description: the first created the file with the deepest directory
|
||||
§ achievements.longFileName.title: Size matters
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: tasks
|
||||
§ page.team.pr.firstCommitTime: First commit
|
||||
§ page.team.pr.lastCommitTime: Last
|
||||
§ page.team.pr.workDays: Development days
|
||||
§ page.team.pr.delayDays: Days waiting for merge
|
||||
§ page.team.pr.workDays: Average time spent working on a task
|
||||
§ 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.date: Merge Date
|
||||
§ page.team.pr.mergeAuthor: Merged by
|
||||
§ page.team.pr.author: Employee
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.work: development
|
||||
§ page.team.pr.delay: waiting
|
||||
§ page.team.pr.days: days
|
||||
|
@ -146,14 +149,16 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Merged by user
|
||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||
§ 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.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: Create date
|
||||
§ page.team.release.to: Last merge date
|
||||
§ 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
|
||||
|
|
|
@ -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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
|
@ -22,7 +22,9 @@ export default `
|
|||
§ sidebar.team.removedTree: Archivos eliminados
|
||||
§ sidebar.team.files: Ficheros
|
||||
§ sidebar.team.removedFiles: Archivos eliminados
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: Lista de tareas
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: Horario
|
||||
§ sidebar.team.commits: All commits
|
||||
§ sidebar.team.changes: Todos los cambios
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: tareas
|
||||
§ page.team.pr.firstCommitTime: Primer commits
|
||||
§ page.team.pr.lastCommitTime: Last
|
||||
§ page.team.pr.workDays: Days of development
|
||||
§ page.team.pr.delayDays: Days of waiting for the infusion
|
||||
§ page.team.pr.workDays: Average time spent working on a task
|
||||
§ 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.date: Date of injection
|
||||
§ page.team.pr.mergeAuthor: I poured it in
|
||||
§ page.team.pr.author: Employee
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.work: development
|
||||
§ page.team.pr.delay: expectation
|
||||
§ page.team.pr.days: days
|
||||
|
@ -146,6 +149,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: I poured it in
|
||||
§ page.team.tasks.prDelayDays: Days of waiting for the infusion
|
||||
§ 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.description: a place for a photo
|
||||
§ page.person.total.title: Main Features
|
||||
|
|
|
@ -1,506 +1,515 @@
|
|||
export default `
|
||||
§ recommendations.modal.cancel: Ok
|
||||
§ recommendations.modal.open: More
|
||||
§ recommendations.title
|
||||
Рекомендации и факты
|
||||
Recommendations and facts
|
||||
|
||||
§ recommendations.timestamp.firstCommit.description
|
||||
сделал первый коммит
|
||||
made the first commit
|
||||
|
||||
День недели: $1
|
||||
Day of the Week: $1
|
||||
|
||||
§ recommendations.timestamp.lastCommit.description
|
||||
сделал последний коммит
|
||||
made the last commit
|
||||
|
||||
День недели: $1
|
||||
Day of the Week: $1
|
||||
|
||||
§ recommendations.timestamp.common.title: $1 дней
|
||||
§ recommendations.timestamp.allDays.description: от первого до последнего коммита (включая выходные и праздники).
|
||||
§ recommendations.timestamp.lossesDays.description: без коммитов, даже с учётом выходных, отпуска и государственных праздников.
|
||||
§ recommendations.timestamp.common.title: $1 days
|
||||
§ recommendations.timestamp.allDays.description: from the first to the last commit (including weekends and holidays).
|
||||
§ recommendations.timestamp.lossesDays.description: days without commits, even considering weekends, vacation, and public holidays.
|
||||
§ 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.sometimeWeekendWord.title: Бывают переработки
|
||||
§ recommendations.timestamp.regularWeekendWord.title: Regular Overtime
|
||||
§ recommendations.timestamp.sometimeWeekendWord.title: Occasional Overtime
|
||||
§ 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
|
||||
Но иногда бывают.
|
||||
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
|
||||
Нет параллельных работ
|
||||
No Parallel Work
|
||||
|
||||
§ recommendations.scope.parallelism.not.description
|
||||
любую фичу в один момент времени делает один человек.
|
||||
any feature at any given time is done by one person.
|
||||
|
||||
# Метод расчёта:
|
||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||
- находим среднее арифметическое;
|
||||
- если результат меньше 1.3 считаем, что параллельных работ в рамках большинства фичей обычно нет;
|
||||
# Calculation method:
|
||||
- person-days are divided by the actual days for each feature;
|
||||
- we find the arithmetic mean;
|
||||
- if the result is less than 1.3, we consider that there is usually no parallel work within most features;
|
||||
|
||||
# Почему это плохо:
|
||||
- повышается bus factor;
|
||||
- сотрудники медленнее развиваются;
|
||||
- трудно качественно проверить работу сотрудника;
|
||||
# Why this is bad:
|
||||
- increases bus factor;
|
||||
- employees develop more slowly;
|
||||
- difficult to properly check an employee's work;
|
||||
|
||||
# Почему это хорошо:
|
||||
- появляются эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
||||
- скорее всего не бывает merge конфликтов;
|
||||
- проект может очень быстро параллельно развиваться в разные стороны;
|
||||
# Why this is good:
|
||||
- experts emerge who are deeply immersed in the subject area and can offer more quality solutions;
|
||||
- most likely there are no merge conflicts;
|
||||
- the project can quickly develop in different directions simultaneously;
|
||||
|
||||
§ recommendations.scope.parallelism.has.title
|
||||
Часть работ параллельно
|
||||
Some Work Done in Parallel
|
||||
|
||||
§ recommendations.scope.parallelism.has.description
|
||||
Иногда фичу делают одновременно несколько человек.
|
||||
|
||||
# Метод расчёта:
|
||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||
- находим среднее арифметическое;
|
||||
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делается параллельно;
|
||||
Sometimes a feature is worked on simultaneously 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 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
|
||||
Параллельные работы
|
||||
Parallel Work
|
||||
|
||||
§ 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
|
||||
в такую сумму можно оценить работу по данному проекту.
|
||||
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
|
||||
Bus factor = 1
|
||||
|
||||
§ 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;
|
||||
|
||||
# Как делается выборка:
|
||||
- более 80% коммитов в фичу делает один человек;
|
||||
- проект имеет более 60% таких фичей;
|
||||
# How the sample is chosen:
|
||||
- more than 80% of commits in a feature are made by one person;
|
||||
- the project has more than 60% of such features;
|
||||
|
||||
§ recommendations.scope.bus.oneMaintainer
|
||||
в фичи погружен один человек.
|
||||
one person is deeply involved in a feature.
|
||||
|
||||
# Почему это плохо:
|
||||
- если он уволится, будет трудно продолжить разработку;
|
||||
- снижается качество code-review;
|
||||
- трудно запараллелить разработку при необходимости;
|
||||
# Why this is bad:
|
||||
- if they resign, it will be hard to continue development;
|
||||
- the quality of code-review decreases;
|
||||
- it’s difficult to parallelize development when needed;
|
||||
|
||||
# Как делается выборка:
|
||||
- более 80% коммитов в фичу сделал один человек;
|
||||
# How the sample is chosen:
|
||||
- more than 80% of commits in a feature are made by one person;
|
||||
|
||||
§ recommendations.scope.types.process.title
|
||||
Плохие процессы
|
||||
Poor Processes
|
||||
|
||||
§ recommendations.scope.types.process.description
|
||||
Большинство фич содержат один тип задач.
|
||||
Most features contain one type of task.
|
||||
|
||||
§ recommendations.scope.types.one
|
||||
фичи содержат один тип задач.
|
||||
features contain one type of task.
|
||||
|
||||
§ 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
|
||||
Постройте долгосрочный план
|
||||
Develop a Long-Term Plan
|
||||
|
||||
§ 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;
|
||||
|
||||
# Как должно быть:
|
||||
- составляется глобальный план развития продукта;
|
||||
- составляется глобальный план развития архитектуры (с разработчиками и DBA);
|
||||
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
||||
# How it should be done:
|
||||
- a global product development plan is created;
|
||||
- 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
|
||||
Оцените инвестиции в фичу
|
||||
Evaluate Investment in a Feature
|
||||
|
||||
§ 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.
|
||||
|
||||
# Как делается выборка:
|
||||
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
||||
- в данном случае показатель от 60% до 80%;
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Как контролировать:
|
||||
- дробить задачи на 1..2 дня;
|
||||
- каждый день спрашивать статус;
|
||||
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
||||
- устроить парное программирование, чтобы проверить фактическую скорость;
|
||||
# Composition:
|
||||
- $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
|
||||
получает слишком однообразные задачи по типу. Может выгореть.
|
||||
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;
|
||||
|
||||
# Как делается выборка:
|
||||
- для каждого коммита определятся тип задачи;
|
||||
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
||||
# How the sample is chosen:
|
||||
- the type of task is determined for each commit;
|
||||
- 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
|
||||
над проектом в данный момент.
|
||||
on the project at this moment.
|
||||
|
||||
# Состав:
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# Почему именно они:
|
||||
- рабочих дней более 50%;
|
||||
- работали в течении последних 30 дней;
|
||||
# Why specifically them:
|
||||
- more than 50% of workdays;
|
||||
- have worked during the last 30 days;
|
||||
|
||||
§ recommendations.author.dismissed.title: Уволилось $1
|
||||
§ recommendations.author.dismissed.title: Dismissed $1
|
||||
§ recommendations.author.dismissed.description
|
||||
или работало короткий промежуток времени.
|
||||
or worked for a short period.
|
||||
|
||||
# Состав:
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# Почему именно они:
|
||||
- работали в нормальном ритме (видимо, это их основной репозиторий);
|
||||
- за последний месяц не было ни одного коммита;
|
||||
- отпуск обычно 14 дней (их отсутствие не похоже на отпуск);
|
||||
# Why specifically them:
|
||||
- worked at a normal pace (apparently, this is their main repository);
|
||||
- no commits in the last month;
|
||||
- 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
|
||||
Люди другой специализации, которые что-либо коммитили.
|
||||
People of other specializations who have committed something.
|
||||
|
||||
# Состав:
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# Почему именно они:
|
||||
- это не open-source проект;
|
||||
- рабочих дней менее 15% от общего числа;
|
||||
- изменяют примерно одни и те же файлы;
|
||||
# Why specifically them:
|
||||
- this is not an open-source project;
|
||||
- workdays less than 15% of the total number;
|
||||
- modify roughly the same files;
|
||||
|
||||
§ recommendations.author.projectType.openSource.title
|
||||
Открытый проект
|
||||
Open Project
|
||||
|
||||
§ 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.
|
||||
|
||||
# Метод оценки:
|
||||
- берется статистика по всем активным разработчикам;
|
||||
- подсчитывается среднее число дней работы и без коммитов;
|
||||
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
||||
# Assessment method:
|
||||
- statistics are taken for all active developers;
|
||||
- the average number of working days and days without commits is calculated;
|
||||
- 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
|
||||
Слабая загрузка
|
||||
Light Workload
|
||||
|
||||
§ recommendations.author.projectType.easy.description
|
||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
||||
too many days without commits.
|
||||
|
||||
# Метод оценки:
|
||||
- берется статистика по всем активным разработчикам;
|
||||
- подсчитывается среднее число дней работы и без коммитов;
|
||||
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
||||
It is necessary to understand why the team is not writing code.
|
||||
|
||||
# Возможные причины:
|
||||
- фактически нет задач;
|
||||
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
||||
- разработчиков отвлекают совещаниями;
|
||||
- команда не работает;
|
||||
# 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
|
||||
Обозначьте дедлайны
|
||||
Set Deadlines
|
||||
|
||||
§ recommendations.author.manager.description
|
||||
У любой задачи должен быть чёткий дедлайн.
|
||||
Every task should have a clear deadline.
|
||||
|
||||
Это позволит не затягивать её выполнение на несколько дней или недель.
|
||||
This will prevent dragging out its completion for several days or weeks.
|
||||
|
||||
# Какие показатели стоит проверить:
|
||||
- количество дней на одну задачу, которое тратит работник;
|
||||
- количество дней ожидания влития PR (страница статистики по PR);
|
||||
# Indicators to check:
|
||||
- the number of days spent on one task by an employee;
|
||||
- the number of days waiting for PR merge (PR statistics page);
|
||||
|
||||
§ recommendations.author.shorTalk.title
|
||||
Проводите ежедневные совещания
|
||||
Conduct Daily Meetings
|
||||
|
||||
§ 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
|
||||
Составьте план обучения
|
||||
Develop a Training Plan
|
||||
|
||||
§ 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.
|
||||
|
||||
# Как составить план:
|
||||
- составить матрицу компетенций;
|
||||
- определить по каким компетенциям меньше всего знаний и опыта;
|
||||
- узнать какие из этих компетенций интересны сотруднику;
|
||||
- придумать 3..5 целей в рамках каждой такой компетенции на полпостороние года или год;
|
||||
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
||||
- каждый месяц напоминать об общем плане достижения этих целей;
|
||||
# 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;
|
||||
- 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
|
||||
Проводите 1-1 каждый месяц
|
||||
Conduct One-on-One Meetings Every Month
|
||||
|
||||
§ 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
|
||||
Ходите в бар
|
||||
Go to a Bar
|
||||
|
||||
§ 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.description: Вероятно, стоит уволить менеджера проекта.
|
||||
§ recommendations.hour.weekends.title: Работа на выходных
|
||||
§ recommendations.hour.weekends.description: Вероятно, стоит проверить менеджера проекта.
|
||||
§ recommendations.hour.easy.title: Бывают проблемы
|
||||
§ recommendations.hour.easy.description: Вероятно, бывают завалы и приходится работать на выходных.
|
||||
§ recommendations.week.lazyDays.down.title: Стало меньше прогулов
|
||||
§ recommendations.week.lazyDays.down.description: за последние три недели этот показатель упал
|
||||
§ recommendations.week.lazyDays.up.title: Стало больше прогулов
|
||||
§ recommendations.week.lazyDays.up.description: нет задач или нужен более жесткий контроль
|
||||
§ recommendations.week.notWork.title: Стабильно не дорабатывает
|
||||
§ recommendations.week.notWork.description: т.к. каждую неделю пишет код не 100% времени
|
||||
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
||||
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
||||
§ recommendations.week.task.up.title: Растёт производительность
|
||||
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
||||
§ recommendations.week.task.down.title: Падает производительность
|
||||
§ recommendations.hour.onlyWork.title: No Weekends Here
|
||||
§ recommendations.hour.onlyWork.description: The project manager should probably be fired.
|
||||
§ recommendations.hour.weekends.title: Working on Weekends
|
||||
§ recommendations.hour.weekends.description: The project manager should probably be checked.
|
||||
§ recommendations.hour.easy.title: There Are Problems
|
||||
§ recommendations.hour.easy.description: There are likely crunch times and work is needed on weekends.
|
||||
§ recommendations.week.lazyDays.down.title: Fewer Absences
|
||||
§ recommendations.week.lazyDays.down.description: this indicator has dropped over the last three weeks
|
||||
§ recommendations.week.lazyDays.up.title: More Absences
|
||||
§ recommendations.week.lazyDays.up.description: no tasks or stricter control is needed
|
||||
§ recommendations.week.notWork.title: Consistently Underperforms
|
||||
§ recommendations.week.notWork.description: as every week the code is not 100% of the time
|
||||
§ recommendations.week.upWork.title: Consistently Overworks
|
||||
§ recommendations.week.upWork.description: as every week code is written on weekend days
|
||||
§ recommendations.week.task.up.title: Productivity is growing
|
||||
§ 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: consistently leads in absences. Fire?
|
||||
§ recommendations.week.task.down.title: Productivity is Falling
|
||||
§ 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.description: большинство типов задач делает один человек.
|
||||
§ recommendations.type.oneMaintainer.title: Узкая специализация
|
||||
§ recommendations.type.everyHasOne.title: Not Signing Task Types
|
||||
§ recommendations.type.everyHasOne.description: Most task types are done by one person.
|
||||
§ recommendations.type.oneMaintainer.title: Narrow Specialization
|
||||
§ recommendations.type.oneMaintainer.description
|
||||
большинство задач одного типа делают одни и те же люди.
|
||||
most tasks of one type are done by the same people.
|
||||
|
||||
# Типы задач:
|
||||
# Task types:
|
||||
|
||||
§ recommendations.type.common
|
||||
# Возможно, это не так
|
||||
# It might not be the case
|
||||
|
||||
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
||||
Make sure that other employees correctly sign commits.
|
||||
|
||||
Шаги, которые помогут это сделать:
|
||||
- настроить пре-коммит проверку для commit message;
|
||||
- объяснить команде, что нужно указывать тип;
|
||||
- проверить в новых ветках, что сотрудники следуют правилу;
|
||||
Steps to ensure this:
|
||||
- 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
|
||||
Это локальный продукт
|
||||
This is a Local Product
|
||||
|
||||
§ 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.
|
||||
|
||||
# Возможно, это не так
|
||||
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
||||
# It might not be the case
|
||||
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
|
||||
Разбейте лидирующий тип на подтипы
|
||||
Break Down the Leading Type into Subtypes
|
||||
|
||||
§ 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).
|
||||
|
||||
Рассмотрим несколько вариантов подтипов:
|
||||
- fix_dev (ошибка выявленная в процессе разработки);
|
||||
- fix_test (ошибка выявленная в процессе тестирования);
|
||||
- fix (ошибка выявленная в проде);
|
||||
Consider several options for subtypes:
|
||||
- fix_dev (error detected during development);
|
||||
- fix_test (error detected during testing);
|
||||
- fix (error detected in production);
|
||||
|
||||
§ recommendations.type.buddy.title
|
||||
Копите мелкие задачи
|
||||
Accumulate Minor Tasks
|
||||
|
||||
§ 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.files: Fichiers
|
||||
§ sidebar.team.removedFiles: Fichiers supprimés
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: Liste des tâches
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: Horaire
|
||||
§ sidebar.team.commits: all commits
|
||||
§ sidebar.team.changes: Tous les changements
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: tâches
|
||||
§ page.team.pr.firstCommitTime: Premier commit
|
||||
§ page.team.pr.lastCommitTime: Dernier
|
||||
§ page.team.pr.workDays: Jours de développement
|
||||
§ page.team.pr.delayDays: Jours d'attente
|
||||
§ page.team.pr.workDays: Average time spent working on a task
|
||||
§ 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.date: Date de diffusion
|
||||
§ page.team.pr.mergeAuthor: Versai
|
||||
§ page.team.pr.author: Employé
|
||||
§ page.team.pr.middleTimeRelease: Délai de Livraison moyen (jours)
|
||||
§ page.team.pr.work: développement
|
||||
§ page.team.pr.delay: attente
|
||||
§ page.team.pr.days: jours
|
||||
|
@ -146,6 +149,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Versai
|
||||
§ page.team.tasks.prDelayDays: Jours d'attente
|
||||
§ 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.description: place à la photographie
|
||||
§ 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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
|||
§ sidebar.team.tree: ファイルの分析
|
||||
§ sidebar.team.files: ファイル
|
||||
§ sidebar.team.removedFiles: 削除されたファイル
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: タスクリスト
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: スケジュール
|
||||
§ sidebar.team.commits: All commits
|
||||
§ sidebar.team.changes: すべての変更
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: tasks
|
||||
§ page.team.pr.firstCommitTime: First commit
|
||||
§ page.team.pr.lastCommitTime: Last
|
||||
§ page.team.pr.workDays: Development days
|
||||
§ page.team.pr.delayDays: Days waiting for merge
|
||||
§ page.team.pr.workDays: Average time spent working on a task
|
||||
§ 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.date: Merge Date
|
||||
§ page.team.pr.mergeAuthor: Merged by
|
||||
§ page.team.pr.author: Employee
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.work: development
|
||||
§ page.team.pr.delay: waiting
|
||||
§ page.team.pr.days: days
|
||||
|
@ -146,6 +149,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Merged by user
|
||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||
§ 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.description: space for a photo
|
||||
§ 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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
|||
§ sidebar.team.tree: Análise de arquivos
|
||||
§ sidebar.team.files: Ficheiros
|
||||
§ sidebar.team.removedFiles: Arquivos excluídos
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: Lista de Tarefas
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: Horário
|
||||
§ sidebar.team.commits: All commits
|
||||
§ sidebar.team.changes: Todas as alterações
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ 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.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.commits: Commits
|
||||
§ page.team.author.commitsSmall: commits
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: tasks
|
||||
§ page.team.pr.firstCommitTime: First commit
|
||||
§ page.team.pr.lastCommitTime: Last
|
||||
§ page.team.pr.workDays: Development days
|
||||
§ page.team.pr.delayDays: Days waiting for merge
|
||||
§ page.team.pr.workDays: Average time spent working on a task
|
||||
§ 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.date: Merge Date
|
||||
§ page.team.pr.mergeAuthor: Merged by
|
||||
§ page.team.pr.author: Employee
|
||||
§ page.team.pr.middleTimeRelease: Average delivery time (days)
|
||||
§ page.team.pr.work: development
|
||||
§ page.team.pr.delay: waiting
|
||||
§ page.team.pr.days: days
|
||||
|
@ -146,6 +149,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Merged by user
|
||||
§ page.team.tasks.prDelayDays: Delay before merge in days
|
||||
§ 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.description: space for a photo
|
||||
§ 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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ page.team.author.title: Статистика по сотрудникам
|
||||
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
||||
§ page.team.author.status: Статус
|
||||
§ page.team.author.firstCommit: Первый коммит
|
||||
§ page.team.author.daysAll: Всего дней
|
||||
§ page.team.author.types: Тип работ
|
||||
§ page.team.author.commits: Коммитов
|
||||
§ page.team.author.commitsSmall: коммитов
|
||||
|
@ -120,13 +123,13 @@ export default `
|
|||
§ page.team.pr.tasks: задач
|
||||
§ page.team.pr.firstCommitTime: Первый коммит
|
||||
§ page.team.pr.lastCommitTime: Последний
|
||||
§ page.team.pr.workDays: Дней разработки
|
||||
§ page.team.pr.delayDays: Дней ожидания влития
|
||||
§ page.team.pr.workDays: Среднее время работы над задачей
|
||||
§ page.team.pr.delayDays: Среднее время ревью PR
|
||||
§ page.team.pr.middleTimeRelease: Отношение времени разработки к времени ревью
|
||||
§ page.team.pr.commits: Коммиты
|
||||
§ page.team.pr.date: Дата влития
|
||||
§ page.team.pr.mergeAuthor: Влил
|
||||
§ page.team.pr.author: Сотрудник
|
||||
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
||||
§ page.team.pr.work: разработка
|
||||
§ page.team.pr.delay: ожидание
|
||||
§ page.team.pr.days: дней
|
||||
|
@ -146,6 +149,8 @@ export default `
|
|||
§ page.team.tasks.prAuthor: Влил
|
||||
§ page.team.tasks.prDelayDays: Дней ожидания влития
|
||||
§ page.team.tasks.comments: Комментарии
|
||||
§ page.team.extension.extension: Расширения файлов
|
||||
§ page.team.extension.type: Подтип файлов
|
||||
§ page.team.extension.name: Тип
|
||||
§ page.team.extension.path: Путь
|
||||
§ page.team.extension.current.count: Количество
|
||||
|
|
|
@ -23,6 +23,9 @@ export default `
|
|||
§ page.team.author.title: Статистика по сотрудникам
|
||||
§ page.team.author.description1: Часть статистики (скорость работы, затраченные деньги и т.п.) по сотрудникам с типом «Помощник» не считается, т.к. это не постоянная роль в проекте. Их работа незначительно и её можно не учитывать.
|
||||
§ 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.commits: 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% времени;
|
||||
|
@ -289,7 +297,9 @@ Bus factor = 1
|
|||
Слабая загрузка
|
||||
|
||||
§ recommendations.author.projectType.easy.description
|
||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
||||
слишком много дней без коммитов.
|
||||
|
||||
Нужно понять почему команда не пишет код.
|
||||
|
||||
# Метод оценки:
|
||||
- берется статистика по всем активным разработчикам;
|
||||
|
@ -406,7 +416,10 @@ Bus factor = 1
|
|||
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
||||
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
||||
§ recommendations.week.task.up.title: Растёт производительность
|
||||
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||
§ recommendations.week.task.up.description
|
||||
или задачи стали слишком мелкие.
|
||||
|
||||
Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
||||
§ recommendations.week.task.down.title: Падает производительность
|
||||
§ recommendations.week.task.down.description
|
||||
|
|
|
@ -21,7 +21,9 @@ export default `
|
|||
§ sidebar.team.tree: 文件分析
|
||||
§ sidebar.team.files: 档案
|
||||
§ sidebar.team.removedFiles: 删除的文件
|
||||
§ sidebar.team.extension: Extensions
|
||||
§ sidebar.team.tasks: 任务列表
|
||||
§ sidebar.team.release: Releases
|
||||
§ sidebar.team.hours: 时间表
|
||||
§ sidebar.team.commits: All commits
|
||||
§ sidebar.team.changes: 所有更改
|
||||
|
|
|
@ -120,13 +120,13 @@ export default `
|
|||
§ page.team.pr.tasks: 任务
|
||||
§ page.team.pr.firstCommitTime: 第一个 Commits
|
||||
§ page.team.pr.lastCommitTime: 最后一次
|
||||
§ page.team.pr.workDays: 发展的日子
|
||||
§ page.team.pr.delayDays: 等待输液的日子
|
||||
§ page.team.pr.workDays: 完成任务的平均时间
|
||||
§ page.team.pr.delayDays: PR审查的平均时间
|
||||
§ page.team.pr.middleTimeRelease: 开发时间与审查时间的比率
|
||||
§ page.team.pr.commits: Commits
|
||||
§ page.team.pr.date: 注射日期
|
||||
§ page.team.pr.mergeAuthor: 填写
|
||||
§ page.team.pr.author: 雇员
|
||||
§ page.team.pr.middleTimeRelease: 平均派递时间 (天数)
|
||||
§ page.team.pr.work: 发展
|
||||
§ page.team.pr.delay: 期望
|
||||
§ page.team.pr.days: 天数
|
||||
|
@ -146,6 +146,18 @@ export default `
|
|||
§ page.team.tasks.prAuthor: 灌
|
||||
§ page.team.tasks.prDelayDays: 等待输液的日子
|
||||
§ 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.description: 拍照的地方
|
||||
§ 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.
|
||||
|
||||
§ recommendations.author.lotOfLazy
|
||||
writes too little code.
|
||||
§ recommendations.author.lotOfLazy.title: Too little code: $1
|
||||
§ 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?
|
||||
- is this their primary project?
|
||||
- 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.
|
||||
Firing and replacing them with a new employee seems justified from a statistical point of view.
|
||||
|
||||
§ recommendations.author.manyLazy
|
||||
writes little code. Needs to be monitored.
|
||||
§ recommendations.author.manyLazy.title: Little code: $1
|
||||
§ recommendations.author.manyLazy.description
|
||||
Needs to be monitored.
|
||||
|
||||
# Composition:
|
||||
- $1;
|
||||
|
||||
# How the sample is chosen:
|
||||
- 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
|
||||
|
||||
§ 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:
|
||||
- take statistics from all active developers;
|
||||
|
|
Loading…
Reference in a new issue