diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 1c0f034..15702a3 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -23,6 +23,7 @@ --color-second: #ED675F; --color-black: #12131B; + --color-white: #FFFFFF; --color-grey: #CBCBCD; --color-border: #E2E9F0; --color-button: #1A73E8; diff --git a/src/ts/components/Achievement/styles/index.module.scss b/src/ts/components/Achievement/styles/index.module.scss index 69b132d..dced402 100644 --- a/src/ts/components/Achievement/styles/index.module.scss +++ b/src/ts/components/Achievement/styles/index.module.scss @@ -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, diff --git a/src/ts/components/Banner/index.module.scss b/src/ts/components/Banner/index.module.scss index 012ddc2..f7ae70b 100644 --- a/src/ts/components/Banner/index.module.scss +++ b/src/ts/components/Banner/index.module.scss @@ -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%); diff --git a/src/ts/components/CardWithIcon/index.module.scss b/src/ts/components/CardWithIcon/index.module.scss index 9b2676b..77a4b8c 100644 --- a/src/ts/components/CardWithIcon/index.module.scss +++ b/src/ts/components/CardWithIcon/index.module.scss @@ -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%; diff --git a/src/ts/components/Cards/styles/index.module.scss b/src/ts/components/Cards/styles/index.module.scss index f42d7c7..01f6bd9 100644 --- a/src/ts/components/Cards/styles/index.module.scss +++ b/src/ts/components/Cards/styles/index.module.scss @@ -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); diff --git a/src/ts/components/CityBuilder/style/banner.module.scss b/src/ts/components/CityBuilder/style/banner.module.scss index b7ec4d9..7edc6ea 100644 --- a/src/ts/components/CityBuilder/style/banner.module.scss +++ b/src/ts/components/CityBuilder/style/banner.module.scss @@ -31,6 +31,6 @@ &_text { margin: var(--space-s) auto; - color: white; + color: var(--color-white); } } diff --git a/src/ts/components/DataLoader/styles/scroll.module.scss b/src/ts/components/DataLoader/styles/scroll.module.scss index fe79729..6f35feb 100644 --- a/src/ts/components/DataLoader/styles/scroll.module.scss +++ b/src/ts/components/DataLoader/styles/scroll.module.scss @@ -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 { diff --git a/src/ts/components/DropZone/index.module.scss b/src/ts/components/DropZone/index.module.scss index 2339e7d..7d521d3 100644 --- a/src/ts/components/DropZone/index.module.scss +++ b/src/ts/components/DropZone/index.module.scss @@ -11,7 +11,7 @@ width: 100vw; height: 100vh; z-index: 3; - background-color: white; + background-color: var(--color-white); &_icon { display: block; diff --git a/src/ts/components/Extension/styles/index.module.scss b/src/ts/components/Extension/styles/index.module.scss index c40d975..0a2837d 100644 --- a/src/ts/components/Extension/styles/index.module.scss +++ b/src/ts/components/Extension/styles/index.module.scss @@ -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; diff --git a/src/ts/components/GameBanner/index.module.scss b/src/ts/components/GameBanner/index.module.scss index 06c2d81..6ce56ba 100644 --- a/src/ts/components/GameBanner/index.module.scss +++ b/src/ts/components/GameBanner/index.module.scss @@ -28,6 +28,6 @@ &_text { margin: var(--space-s) auto; - color: white; + color: var(--color-white); } } diff --git a/src/ts/components/GetList/styles/index.module.scss b/src/ts/components/GetList/styles/index.module.scss index d301a42..dad58a9 100644 --- a/src/ts/components/GetList/styles/index.module.scss +++ b/src/ts/components/GetList/styles/index.module.scss @@ -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); } diff --git a/src/ts/components/HoursChart/index.module.scss b/src/ts/components/HoursChart/index.module.scss index 3a8f55e..f4bc94a 100644 --- a/src/ts/components/HoursChart/index.module.scss +++ b/src/ts/components/HoursChart/index.module.scss @@ -59,7 +59,7 @@ } &_hour { - color: white; + color: var(--color-white); border-radius: 6px; border: 1px solid #FFFFFF; background-color: var(--color-first); diff --git a/src/ts/components/HoursChart/styles/legend.module.scss b/src/ts/components/HoursChart/styles/legend.module.scss index 8d2957c..f8d6213 100644 --- a/src/ts/components/HoursChart/styles/legend.module.scss +++ b/src/ts/components/HoursChart/styles/legend.module.scss @@ -42,7 +42,7 @@ &_count { color: var(--color-black); border: 1px solid var(--color-grey); - background-color: #FFFFFF; + background-color: var(--color-white); } &_title { diff --git a/src/ts/components/LineChart/styles/index.module.scss b/src/ts/components/LineChart/styles/index.module.scss index f25e3d7..32f2cee 100644 --- a/src/ts/components/LineChart/styles/index.module.scss +++ b/src/ts/components/LineChart/styles/index.module.scss @@ -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; } diff --git a/src/ts/components/Locker/index.module.scss b/src/ts/components/Locker/index.module.scss index 1c9e8b5..e924865 100644 --- a/src/ts/components/Locker/index.module.scss +++ b/src/ts/components/Locker/index.module.scss @@ -21,7 +21,7 @@ } &_center { - fill: white; + fill: var(--color-white); stroke: none; stroke-width: 0; } diff --git a/src/ts/components/ModalWindow/styles/index.module.scss b/src/ts/components/ModalWindow/styles/index.module.scss index ea2b950..f1c85b5 100644 --- a/src/ts/components/ModalWindow/styles/index.module.scss +++ b/src/ts/components/ModalWindow/styles/index.module.scss @@ -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; } } diff --git a/src/ts/components/Notifications/components/Message.tsx b/src/ts/components/Notifications/components/Message.tsx index 9f723ed..0ca27ef 100644 --- a/src/ts/components/Notifications/components/Message.tsx +++ b/src/ts/components/Notifications/components/Message.tsx @@ -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 (
+ {message.title && (
{message.title} diff --git a/src/ts/components/Notifications/styles/index.module.scss b/src/ts/components/Notifications/styles/index.module.scss index bafc992..2db0744 100644 --- a/src/ts/components/Notifications/styles/index.module.scss +++ b/src/ts/components/Notifications/styles/index.module.scss @@ -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; } } diff --git a/src/ts/components/Page/index.module.scss b/src/ts/components/Page/index.module.scss index 52efff0..b6b7c76 100644 --- a/src/ts/components/Page/index.module.scss +++ b/src/ts/components/Page/index.module.scss @@ -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 { diff --git a/src/ts/components/PieChart/components/Legend.tsx b/src/ts/components/PieChart/components/Legend.tsx new file mode 100644 index 0000000..a3e1d55 --- /dev/null +++ b/src/ts/components/PieChart/components/Legend.tsx @@ -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 ( +

+ + + {`${item.width}%`} + + + {t(item.title)} + +

+ ); + }); + + return ( +
+ {lines} +
+ ); +} + +export default Legend; diff --git a/src/ts/components/PieChart/index.module.scss b/src/ts/components/PieChart/index.module.scss new file mode 100644 index 0000000..f8bd64d --- /dev/null +++ b/src/ts/components/PieChart/index.module.scss @@ -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; + } +} diff --git a/src/ts/components/PieChart/index.tsx b/src/ts/components/PieChart/index.tsx new file mode 100644 index 0000000..3e131ef --- /dev/null +++ b/src/ts/components/PieChart/index.tsx @@ -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; + 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_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; diff --git a/src/ts/components/PieSVG/helpers/index.ts b/src/ts/components/PieSVG/helpers/index.ts new file mode 100644 index 0000000..9d1f7ed --- /dev/null +++ b/src/ts/components/PieSVG/helpers/index.ts @@ -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(''); +} diff --git a/src/ts/components/PieSVG/index.module.scss b/src/ts/components/PieSVG/index.module.scss new file mode 100644 index 0000000..0e5955e --- /dev/null +++ b/src/ts/components/PieSVG/index.module.scss @@ -0,0 +1,12 @@ +@import 'src/styles/variables'; + +.pie_svg { + display: inline-block; + height: 100%; + + &_sector { + fill: #D0D1D2; + stroke: none; + stroke-width: 0; + } +} diff --git a/src/ts/components/PieSVG/index.tsx b/src/ts/components/PieSVG/index.tsx new file mode 100644 index 0000000..54c678f --- /dev/null +++ b/src/ts/components/PieSVG/index.tsx @@ -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 || ''}`} + + + ); + }); + + return ( + + {paths} + + ); +} + +PieSVG.defaultProps = { + className: '', +}; + +export default PieSVG; diff --git a/src/ts/components/Quize/components/Answer.tsx b/src/ts/components/Quize/components/Answer.tsx index ac88900..5a25a9a 100644 --- a/src/ts/components/Quize/components/Answer.tsx +++ b/src/ts/components/Quize/components/Answer.tsx @@ -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 ( -
+
{ onClick(); }} > -
+
{answer.title}
diff --git a/src/ts/components/Quize/components/Question.tsx b/src/ts/components/Quize/components/Question.tsx index 09dcad6..6a161a6 100644 --- a/src/ts/components/Quize/components/Question.tsx +++ b/src/ts/components/Quize/components/Question.tsx @@ -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(null); @@ -71,7 +68,6 @@ function Question({ return (
-
{question.title} diff --git a/src/ts/components/Quize/components/Result.tsx b/src/ts/components/Quize/components/Result.tsx index 483fac8..2b08422 100644 --- a/src/ts/components/Quize/components/Result.tsx +++ b/src/ts/components/Quize/components/Result.tsx @@ -21,11 +21,6 @@ function Result({

{result.title}

-

{result.description}

diff --git a/src/ts/components/Quize/components/Start.tsx b/src/ts/components/Quize/components/Start.tsx index 1102f82..c3e11bc 100644 --- a/src/ts/components/Quize/components/Start.tsx +++ b/src/ts/components/Quize/components/Start.tsx @@ -21,11 +21,6 @@ function Start({

{quize.title}

-

{quize.description}

diff --git a/src/ts/components/Quize/components/index.tsx b/src/ts/components/Quize/components/index.tsx index 308bec7..9ba66c3 100644 --- a/src/ts/components/Quize/components/index.tsx +++ b/src/ts/components/Quize/components/index.tsx @@ -44,7 +44,6 @@ function QuizePage({ const questions = getQuestionByGroups(quize.questions); let page: any = null; - if (view === 'start') { page = ( { const nextById = questions.byId[answer.nextQuestionId || '']; const nextByIndex = questions.byIndex[question.index + 1]; @@ -116,7 +114,7 @@ function QuizePage({ return (
{page} diff --git a/src/ts/components/Quize/styles/answer.module.scss b/src/ts/components/Quize/styles/answer.module.scss index 0f72cd4..3ea4e19 100644 --- a/src/ts/components/Quize/styles/answer.module.scss +++ b/src/ts/components/Quize/styles/answer.module.scss @@ -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; } } diff --git a/src/ts/components/Quize/styles/index.module.scss b/src/ts/components/Quize/styles/index.module.scss index 466b017..b610571 100644 --- a/src/ts/components/Quize/styles/index.module.scss +++ b/src/ts/components/Quize/styles/index.module.scss @@ -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; } } diff --git a/src/ts/components/Quize/styles/question.module.scss b/src/ts/components/Quize/styles/question.module.scss index e2349d9..82f0469 100644 --- a/src/ts/components/Quize/styles/question.module.scss +++ b/src/ts/components/Quize/styles/question.module.scss @@ -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 { diff --git a/src/ts/components/Quize/styles/result.module.scss b/src/ts/components/Quize/styles/result.module.scss index f32d97c..013b49e 100644 --- a/src/ts/components/Quize/styles/result.module.scss +++ b/src/ts/components/Quize/styles/result.module.scss @@ -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; - } } diff --git a/src/ts/components/Races/components/Car.tsx b/src/ts/components/Races/components/Car.tsx index 2e22020..3af3d2d 100644 --- a/src/ts/components/Races/components/Car.tsx +++ b/src/ts/components/Races/components/Car.tsx @@ -48,7 +48,7 @@ function Car({
); diff --git a/src/ts/components/Races/components/Track.tsx b/src/ts/components/Races/components/Track.tsx index 2d4190c..74345c8 100644 --- a/src/ts/components/Races/components/Track.tsx +++ b/src/ts/components/Races/components/Track.tsx @@ -27,7 +27,12 @@ function Track({ const duration = DURATION.MIN + (DURATION.BASE * (1 - speed)) * 3; return ( -
+
{canStart && ( - + {!showAnimation && ( )} +
{lines}
+
); } diff --git a/src/ts/components/Races/styles/car.module.scss b/src/ts/components/Races/styles/car.module.scss index b179a72..98fca8b 100644 --- a/src/ts/components/Races/styles/car.module.scss +++ b/src/ts/components/Races/styles/car.module.scss @@ -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 { diff --git a/src/ts/components/Races/styles/index.module.scss b/src/ts/components/Races/styles/index.module.scss index d7659f0..de9d780 100644 --- a/src/ts/components/Races/styles/index.module.scss +++ b/src/ts/components/Races/styles/index.module.scss @@ -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); } } diff --git a/src/ts/components/Races/styles/info.module.scss b/src/ts/components/Races/styles/info.module.scss index 860d616..e66cd65 100644 --- a/src/ts/components/Races/styles/info.module.scss +++ b/src/ts/components/Races/styles/info.module.scss @@ -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; diff --git a/src/ts/components/ShowSymbol/styles/index.module.scss b/src/ts/components/ShowSymbol/styles/index.module.scss index fce6e55..b93675c 100644 --- a/src/ts/components/ShowSymbol/styles/index.module.scss +++ b/src/ts/components/ShowSymbol/styles/index.module.scss @@ -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; diff --git a/src/ts/components/SplashScreen/progress.module.scss b/src/ts/components/SplashScreen/progress.module.scss index 9c83858..d8a6289 100644 --- a/src/ts/components/SplashScreen/progress.module.scss +++ b/src/ts/components/SplashScreen/progress.module.scss @@ -23,7 +23,7 @@ word-wrap: break-word; border-radius: 4px; - color: white; + color: var(--color-white); background-color: green; background-size: 23px 22px; @@ -66,4 +66,4 @@ width: 100%; background-size: 23px 44px; } -} \ No newline at end of file +} diff --git a/src/ts/components/Sponsor/store/index.ts b/src/ts/components/Sponsor/store/index.ts index 3116706..9c77c77 100644 --- a/src/ts/components/Sponsor/store/index.ts +++ b/src/ts/components/Sponsor/store/index.ts @@ -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() { diff --git a/src/ts/components/Sponsor/styles/index.module.scss b/src/ts/components/Sponsor/styles/index.module.scss index 59b56b0..8e0a67d 100644 --- a/src/ts/components/Sponsor/styles/index.module.scss +++ b/src/ts/components/Sponsor/styles/index.module.scss @@ -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); diff --git a/src/ts/components/SwimmingPool/components/Track.tsx b/src/ts/components/SwimmingPool/components/Track.tsx new file mode 100644 index 0000000..0ce98b9 --- /dev/null +++ b/src/ts/components/SwimmingPool/components/Track.tsx @@ -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 ( +
+ +
+ {value} +
+
+
+ +
+
+
+ ); +} + +export default Track; diff --git a/src/ts/components/SwimmingPool/index.tsx b/src/ts/components/SwimmingPool/index.tsx new file mode 100644 index 0000000..135fb92 --- /dev/null +++ b/src/ts/components/SwimmingPool/index.tsx @@ -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([...shuffle(tracks)]); + + if (!tracks.length) return null; + + const lines = shuffleTracks.map((track: any) => { + return ( + + ); + }); + + return ( + <> + +
+ {lines} +
+ + ); +} + +export default SwimmingPool; diff --git a/src/ts/components/SwimmingPool/styles/index.module.scss b/src/ts/components/SwimmingPool/styles/index.module.scss new file mode 100644 index 0000000..a404f11 --- /dev/null +++ b/src/ts/components/SwimmingPool/styles/index.module.scss @@ -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; + } +} + diff --git a/src/ts/components/SwimmingPool/styles/track.module.scss b/src/ts/components/SwimmingPool/styles/track.module.scss new file mode 100644 index 0000000..ba9236b --- /dev/null +++ b/src/ts/components/SwimmingPool/styles/track.module.scss @@ -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; + } +} diff --git a/src/ts/components/Table/styles/header.module.scss b/src/ts/components/Table/styles/header.module.scss index 0c87d0a..75a4cd9 100644 --- a/src/ts/components/Table/styles/header.module.scss +++ b/src/ts/components/Table/styles/header.module.scss @@ -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 { diff --git a/src/ts/components/Table/styles/index.module.scss b/src/ts/components/Table/styles/index.module.scss index 47917a3..966e312 100644 --- a/src/ts/components/Table/styles/index.module.scss +++ b/src/ts/components/Table/styles/index.module.scss @@ -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, diff --git a/src/ts/components/UiKit/styles/button.module.scss b/src/ts/components/UiKit/styles/button.module.scss index 277a471..444959c 100644 --- a/src/ts/components/UiKit/styles/button.module.scss +++ b/src/ts/components/UiKit/styles/button.module.scss @@ -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); diff --git a/src/ts/components/UiKit/styles/index.module.scss b/src/ts/components/UiKit/styles/index.module.scss index aecb819..2a95399 100644 --- a/src/ts/components/UiKit/styles/index.module.scss +++ b/src/ts/components/UiKit/styles/index.module.scss @@ -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; } diff --git a/src/ts/components/UiKit/styles/switch.module.scss b/src/ts/components/UiKit/styles/switch.module.scss index 6ab1f4c..74ee16f 100644 --- a/src/ts/components/UiKit/styles/switch.module.scss +++ b/src/ts/components/UiKit/styles/switch.module.scss @@ -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); diff --git a/src/ts/components/UiKit/styles/tabs.module.scss b/src/ts/components/UiKit/styles/tabs.module.scss index 00c03da..b936e95 100644 --- a/src/ts/components/UiKit/styles/tabs.module.scss +++ b/src/ts/components/UiKit/styles/tabs.module.scss @@ -30,7 +30,7 @@ border: none; border-bottom: 3px solid #E2E9F0; - background-color: #FFFFFF; + background-color: var(--color-white); color: var(--color-black); &_selected { diff --git a/src/ts/components/YearChart/styles/index.module.scss b/src/ts/components/YearChart/styles/index.module.scss index dd505c4..4d22add 100644 --- a/src/ts/components/YearChart/styles/index.module.scss +++ b/src/ts/components/YearChart/styles/index.module.scss @@ -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); } } } diff --git a/src/ts/helpers/Recommendations/components/TeamByAuthor.ts b/src/ts/helpers/Recommendations/components/TeamByAuthor.ts index 09cd967..68e179a 100644 --- a/src/ts/helpers/Recommendations/components/TeamByAuthor.ts +++ b/src/ts/helpers/Recommendations/components/TeamByAuthor.ts @@ -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 ? { diff --git a/src/ts/helpers/formatter.ts b/src/ts/helpers/formatter.ts index d7afcd7..a75e7ca 100644 --- a/src/ts/helpers/formatter.ts +++ b/src/ts/helpers/formatter.ts @@ -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)}` diff --git a/src/ts/pages/PageWrapper/styles/footer.module.scss b/src/ts/pages/PageWrapper/styles/footer.module.scss index 9e4bbd2..c910157 100644 --- a/src/ts/pages/PageWrapper/styles/footer.module.scss +++ b/src/ts/pages/PageWrapper/styles/footer.module.scss @@ -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 { diff --git a/src/ts/pages/PageWrapper/styles/header.module.scss b/src/ts/pages/PageWrapper/styles/header.module.scss index d827d07..d99629b 100644 --- a/src/ts/pages/PageWrapper/styles/header.module.scss +++ b/src/ts/pages/PageWrapper/styles/header.module.scss @@ -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); } } diff --git a/src/ts/pages/PageWrapper/styles/index.module.scss b/src/ts/pages/PageWrapper/styles/index.module.scss index 5f279a0..3e2e68f 100644 --- a/src/ts/pages/PageWrapper/styles/index.module.scss +++ b/src/ts/pages/PageWrapper/styles/index.module.scss @@ -18,7 +18,7 @@ display: block; height: 100px; width: 100%; - background-color: white; + background-color: var(--color-white); } &_main, diff --git a/src/ts/pages/PageWrapper/styles/sidebar.module.scss b/src/ts/pages/PageWrapper/styles/sidebar.module.scss index 9835047..7a8b1d8 100644 --- a/src/ts/pages/PageWrapper/styles/sidebar.module.scss +++ b/src/ts/pages/PageWrapper/styles/sidebar.module.scss @@ -41,7 +41,7 @@ .sidebar_item:hover, .sidebar_item.selected { - color: #FFFFFF; + color: var(--color-white); background-color: #252735; } diff --git a/src/ts/pages/PageWrapper/styles/switch.module.scss b/src/ts/pages/PageWrapper/styles/switch.module.scss index d463c55..5ee39ca 100644 --- a/src/ts/pages/PageWrapper/styles/switch.module.scss +++ b/src/ts/pages/PageWrapper/styles/switch.module.scss @@ -31,7 +31,7 @@ color: #84858D; &.selected { - color: #FFFFFF; + color: var(--color-white); background-color: #37394B; } diff --git a/src/ts/pages/Person/components/Month.tsx b/src/ts/pages/Person/components/Month.tsx index d7c5ae9..e31eb8f 100644 --- a/src/ts/pages/Person/components/Month.tsx +++ b/src/ts/pages/Person/components/Month.tsx @@ -13,16 +13,14 @@ const Month = observer(({ user }: IPersonCommonProps): React.ReactElement => { const max = statistic.commitsByTimestampCounter.max; return ( - <> - - - - + + + ); }); diff --git a/src/ts/pages/Person/styles/print.module.scss b/src/ts/pages/Person/styles/print.module.scss index 3c14334..69a13c4 100644 --- a/src/ts/pages/Person/styles/print.module.scss +++ b/src/ts/pages/Person/styles/print.module.scss @@ -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); } diff --git a/src/ts/pages/Team/components/Author.tsx b/src/ts/pages/Team/components/Author.tsx index 70d67e9..531a7d2 100644 --- a/src/ts/pages/Team/components/Author.tsx +++ b/src/ts/pages/Team/components/Author.tsx @@ -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} /> { let value = works; if (row.isDismissed) value = dismissed; @@ -75,6 +77,19 @@ function AuthorView({ response, updateSort, rowsForExcel, mode }: IAuthorViewPro }} width={100} /> + getDate(commit.timestamp)} + /> + - + <Title title="page.team.extension.extension"/> <DataLoader to="response" loader={(pagination?: IPaginationRequest) => getFakeLoader({ diff --git a/src/ts/pages/Team/components/FileAnalitics/Type.tsx b/src/ts/pages/Team/components/FileAnalitics/Type.tsx index 2e2168d..9569b44 100644 --- a/src/ts/pages/Team/components/FileAnalitics/Type.tsx +++ b/src/ts/pages/Team/components/FileAnalitics/Type.tsx @@ -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({ diff --git a/src/ts/pages/Team/components/PR/Total.tsx b/src/ts/pages/Team/components/PR/Total.tsx index 2fb4b82..255962f 100644 --- a/src/ts/pages/Team/components/PR/Total.tsx +++ b/src/ts/pages/Team/components/PR/Total.tsx @@ -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> ); } diff --git a/src/ts/pages/Team/components/PR/index.tsx b/src/ts/pages/Team/components/PR/index.tsx index 64c9be8..62170e2 100644 --- a/src/ts/pages/Team/components/PR/index.tsx +++ b/src/ts/pages/Team/components/PR/index.tsx @@ -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" diff --git a/src/ts/pages/Team/components/Top.tsx b/src/ts/pages/Team/components/Top.tsx index 34dbadb..3355072 100644 --- a/src/ts/pages/Team/components/Top.tsx +++ b/src/ts/pages/Team/components/Top.tsx @@ -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 /> {'Небоскребы вверх ввиде графика'} </> ); diff --git a/src/ts/translations/de/navigation.ts b/src/ts/translations/de/navigation.ts index a8ce8b9..d965cd4 100644 --- a/src/ts/translations/de/navigation.ts +++ b/src/ts/translations/de/navigation.ts @@ -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 diff --git a/src/ts/translations/de/pages.ts b/src/ts/translations/de/pages.ts index 0b47e5c..2dd74d9 100644 --- a/src/ts/translations/de/pages.ts +++ b/src/ts/translations/de/pages.ts @@ -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 diff --git a/src/ts/translations/de/recommendations.ts b/src/ts/translations/de/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/de/recommendations.ts +++ b/src/ts/translations/de/recommendations.ts @@ -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; diff --git a/src/ts/translations/en/achievements.ts b/src/ts/translations/en/achievements.ts index 064e936..67f5c8f 100644 --- a/src/ts/translations/en/achievements.ts +++ b/src/ts/translations/en/achievements.ts @@ -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 diff --git a/src/ts/translations/en/pages.ts b/src/ts/translations/en/pages.ts index ff6ac2d..9800b74 100644 --- a/src/ts/translations/en/pages.ts +++ b/src/ts/translations/en/pages.ts @@ -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 diff --git a/src/ts/translations/en/recommendations.ts b/src/ts/translations/en/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/en/recommendations.ts +++ b/src/ts/translations/en/recommendations.ts @@ -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; diff --git a/src/ts/translations/es/navigation.ts b/src/ts/translations/es/navigation.ts index 053d996..d8ee8a5 100644 --- a/src/ts/translations/es/navigation.ts +++ b/src/ts/translations/es/navigation.ts @@ -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 diff --git a/src/ts/translations/es/pages.ts b/src/ts/translations/es/pages.ts index e81e34c..ffc71ff 100644 --- a/src/ts/translations/es/pages.ts +++ b/src/ts/translations/es/pages.ts @@ -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 diff --git a/src/ts/translations/es/recommendations.ts b/src/ts/translations/es/recommendations.ts index 17e5aa9..27c955a 100644 --- a/src/ts/translations/es/recommendations.ts +++ b/src/ts/translations/es/recommendations.ts @@ -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. `; diff --git a/src/ts/translations/fr/navigation.ts b/src/ts/translations/fr/navigation.ts index c5acab4..3821365 100644 --- a/src/ts/translations/fr/navigation.ts +++ b/src/ts/translations/fr/navigation.ts @@ -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 diff --git a/src/ts/translations/fr/pages.ts b/src/ts/translations/fr/pages.ts index d402322..1e2e4af 100644 --- a/src/ts/translations/fr/pages.ts +++ b/src/ts/translations/fr/pages.ts @@ -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 diff --git a/src/ts/translations/fr/recommendations.ts b/src/ts/translations/fr/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/fr/recommendations.ts +++ b/src/ts/translations/fr/recommendations.ts @@ -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; diff --git a/src/ts/translations/ja/navigation.ts b/src/ts/translations/ja/navigation.ts index 50027e9..cd20dcc 100644 --- a/src/ts/translations/ja/navigation.ts +++ b/src/ts/translations/ja/navigation.ts @@ -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: すべての変更 diff --git a/src/ts/translations/ja/pages.ts b/src/ts/translations/ja/pages.ts index 0b47e5c..9800b74 100644 --- a/src/ts/translations/ja/pages.ts +++ b/src/ts/translations/ja/pages.ts @@ -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 diff --git a/src/ts/translations/ja/recommendations.ts b/src/ts/translations/ja/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/ja/recommendations.ts +++ b/src/ts/translations/ja/recommendations.ts @@ -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; diff --git a/src/ts/translations/pt/navigation.ts b/src/ts/translations/pt/navigation.ts index 4ffca81..6225764 100644 --- a/src/ts/translations/pt/navigation.ts +++ b/src/ts/translations/pt/navigation.ts @@ -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 diff --git a/src/ts/translations/pt/pages.ts b/src/ts/translations/pt/pages.ts index 0b47e5c..9800b74 100644 --- a/src/ts/translations/pt/pages.ts +++ b/src/ts/translations/pt/pages.ts @@ -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 diff --git a/src/ts/translations/pt/recommendations.ts b/src/ts/translations/pt/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/pt/recommendations.ts +++ b/src/ts/translations/pt/recommendations.ts @@ -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; diff --git a/src/ts/translations/ru/pages.ts b/src/ts/translations/ru/pages.ts index f7ee345..9c06a1b 100644 --- a/src/ts/translations/ru/pages.ts +++ b/src/ts/translations/ru/pages.ts @@ -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: Количество diff --git a/src/ts/translations/ru/pages_RU.txt b/src/ts/translations/ru/pages_RU.txt index ffa0a5c..89843c5 100644 --- a/src/ts/translations/ru/pages_RU.txt +++ b/src/ts/translations/ru/pages_RU.txt @@ -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 diff --git a/src/ts/translations/ru/recommendations.ts b/src/ts/translations/ru/recommendations.ts index eddb669..70c264e 100644 --- a/src/ts/translations/ru/recommendations.ts +++ b/src/ts/translations/ru/recommendations.ts @@ -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 diff --git a/src/ts/translations/zh/navigation.ts b/src/ts/translations/zh/navigation.ts index 29fe9b8..7c72109 100644 --- a/src/ts/translations/zh/navigation.ts +++ b/src/ts/translations/zh/navigation.ts @@ -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: 所有更改 diff --git a/src/ts/translations/zh/pages.ts b/src/ts/translations/zh/pages.ts index 239e09e..3e66d10 100644 --- a/src/ts/translations/zh/pages.ts +++ b/src/ts/translations/zh/pages.ts @@ -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: 主要特点 diff --git a/src/ts/translations/zh/recommendations.ts b/src/ts/translations/zh/recommendations.ts index 0e4b420..27c955a 100644 --- a/src/ts/translations/zh/recommendations.ts +++ b/src/ts/translations/zh/recommendations.ts @@ -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;