This commit is contained in:
bakhirev 2024-11-20 23:25:06 +03:00
parent 2eda46e00d
commit c36b4c4752
49 changed files with 1141 additions and 438 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -23,12 +23,12 @@
}, },
"scripts": { "scripts": {
"dev": "set PORT=3006 && react-app-rewired start", "dev": "set PORT=3006 && react-app-rewired start",
"build": "react-scripts build", "build": "react-app-rewired build",
"build:website": "react-scripts build && cd scripts && node add-analytics.js", "build:website": "react-app-rewired build && cd scripts && node add-analytics.js",
"build:local": "react-scripts build && cd scripts && node remove-hash.js && node add-local.js", "build:local": "react-app-rewired build && cd scripts && node remove-hash.js && node add-local.js",
"build:docker": "react-scripts build", "build:docker": "react-app-rewired build",
"test": "react-scripts test", "test": "react-app-rewired test",
"eject": "react-scripts eject", "eject": "react-app-rewired eject",
"js:check": "npx eslint \"src/**/*.{ts,tsx,js}\"", "js:check": "npx eslint \"src/**/*.{ts,tsx,js}\"",
"js:fix": "npx eslint \"src/**/*.{ts,tsx,js}\" --fix", "js:fix": "npx eslint \"src/**/*.{ts,tsx,js}\" --fix",
"css:check": "npx stylelint \"src/**/*.{css,scss,sass}\"", "css:check": "npx stylelint \"src/**/*.{css,scss,sass}\"",

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#84858D"><path d="M6.32 13.01c.96.02 1.85.5 2.45 1.34C9.5 15.38 10.71 16 12 16s2.5-.62 3.23-1.66c.6-.84 1.49-1.32 2.45-1.34-.72-1.22-3.6-2-5.68-2-2.07 0-4.96.78-5.68 2.01M4 13c1.66 0 3-1.34 3-3S5.66 7 4 7s-3 1.34-3 3 1.34 3 3 3m16 0c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3m-8-3c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3"></path><path d="M21 14h-3.27c-.77 0-1.35.45-1.68.92-.04.06-1.36 2.08-4.05 2.08-1.43 0-3.03-.64-4.05-2.08-.39-.55-1-.92-1.68-.92H3c-1.1 0-2 .9-2 2v4h7v-2.26c1.15.8 2.54 1.26 4 1.26s2.85-.46 4-1.26V20h7v-4c0-1.1-.9-2-2-2"></path></svg>

After

Width:  |  Height:  |  Size: 644 B

View file

@ -44171,7 +44171,7 @@ R(f`2021-02-09T16:08:15+03:00>Albert Einstein>instein@emap.de>Initialize project
:100644 100644 5d0b5c105 4b4f0cbf4 M src/ts/pages/Builder/components/modals/DiffTemplateModal.tsx :100644 100644 5d0b5c105 4b4f0cbf4 M src/ts/pages/Builder/components/modals/DiffTemplateModal.tsx
1 1 src/ts/pages/Builder/components/modals/DiffTemplateModal.tsx 1 1 src/ts/pages/Builder/components/modals/DiffTemplateModal.tsx
2022-09-27T08:19:12+03:00>Albert Einstein>instein@emap.de>TASK-5115 feat: add sort by alpabet in Catalogue 2022-09-27T08:19:12+03:00>Albert Einstein>instein@emap.tt>TASK-5115 feat: add sort by alpabet in Catalogue
:100644 100644 0ad4bfef3 d1ce9040c M src/ts/helpers/converter.ts :100644 100644 0ad4bfef3 d1ce9040c M src/ts/helpers/converter.ts
:100644 100644 5a84c2fc1 91a2e24a5 M src/ts/pages/DemoCatalogue/store/CatalogueStore.ts :100644 100644 5a84c2fc1 91a2e24a5 M src/ts/pages/DemoCatalogue/store/CatalogueStore.ts
:100644 100644 8d73c71e2 2a0bf8c71 M src/ts/snippets/AccessGroups/components/Roles.tsx :100644 100644 8d73c71e2 2a0bf8c71 M src/ts/snippets/AccessGroups/components/Roles.tsx
@ -52085,7 +52085,7 @@ R(f`2021-02-09T16:08:15+03:00>Albert Einstein>instein@emap.de>Initialize project
4 0 src/ts/pages/Authorization/components/Success.tsx 4 0 src/ts/pages/Authorization/components/Success.tsx
40 0 src/ts/pages/AuthSchema/index.tsx 40 0 src/ts/pages/AuthSchema/index.tsx
2023-01-27T14:10:02+03:00>Albert Einstein>instein@emap.de>Pull request #2187: TASK-8461 fix(profile): change file limit for 478 2023-01-27T14:10:02+03:00>Albert einstein>instein@emap.de>Pull request #2187: TASK-8461 fix(profile): change file limit for 478
2023-01-27T14:34:52+03:00>Albert Einstein>instein@emap.de>TASK-8466 fix: validation for old OIR is incorrect 2023-01-27T14:34:52+03:00>Albert Einstein>instein@emap.de>TASK-8466 fix: validation for old OIR is incorrect
:100644 100644 62a6c932b ada52dd9e M src/ts/api/request.ts :100644 100644 62a6c932b ada52dd9e M src/ts/api/request.ts
14 1 src/ts/api/request.ts 14 1 src/ts/api/request.ts
@ -53400,11 +53400,11 @@ R(f`2021-02-09T16:08:15+03:00>Albert Einstein>instein@emap.de>Initialize project
1 1 src/setupProxy.js 1 1 src/setupProxy.js
25 25 src/ts/pages/Template/components/SideBar.tsx 25 25 src/ts/pages/Template/components/SideBar.tsx
2023-02-15T14:34:46+03:00>Albert Einstein>instein@emap.de>TASK-9120 fix(profile): change style for code 2023-02-15T14:34:46+03:00>Albert-Einstein>instein@emap.de>TASK-9120 fix(profile): change style for code
:100644 100644 fed043f4c bd1973c4c M src/ts/interfaces/Category.ts :100644 100644 fed043f4c bd1973c4c M src/ts/interfaces/Category.ts
1 1 src/ts/interfaces/Category.ts 1 1 src/ts/interfaces/Category.ts
2023-02-15T14:37:52+03:00>Albert Einstein>instein@emap.de>TASK-9120 fix(profile): change style for code 2023-02-15T14:37:52+03:00>Albert Einste.in>instein@emap.de>TASK-9120 fix(profile): change style for code
:100644 100644 80e2a3270 74941b107 M src/ts/pages/Template/components/SideBar.tsx :100644 100644 80e2a3270 74941b107 M src/ts/pages/Template/components/SideBar.tsx
3 2 src/ts/pages/Template/components/SideBar.tsx 3 2 src/ts/pages/Template/components/SideBar.tsx

View file

@ -48,7 +48,7 @@ export function getOption(value: any, index: number): IOption {
return { return {
id: getId(value, index), id: getId(value, index),
title, title,
_textForSearch: title.toLowerCase(), _textForSearch: title?.toLowerCase() || '',
source: value, source: value,
}; };
} }

View file

@ -10,14 +10,14 @@
background-color: var(--color-white); background-color: var(--color-white);
&_data { &_data {
display: block; display: flex;
white-space: nowrap; justify-content: flex-start;
align-items: center;
} }
&_icon, &_icon,
&_legend { &_legend {
display: inline-block; display: inline-block;
width: 50%;
height: 100%; height: 100%;
} }
@ -27,6 +27,7 @@
} }
&_legend { &_legend {
width: fit-content;
padding-left: var(--space-xxl); padding-left: var(--space-xxl);
vertical-align: middle; vertical-align: middle;
} }
@ -71,7 +72,8 @@
@media (max-width: 700px) { @media (max-width: 700px) {
.pie_chart_icon, .pie_chart_icon,
.pie_chart_legend { .pie_chart_legend,
.pie_chart_data {
display: block; display: block;
height: auto; height: auto;
margin: 0 auto; margin: 0 auto;

View file

@ -37,11 +37,15 @@ function PieChart({
const formattedDetails = details || getDefaultDetails(value || 100, options.max || 100); const formattedDetails = details || getDefaultDetails(value || 100, options.max || 100);
const parts = getSubLines(formattedDetails, options); const parts = getSubLines(formattedDetails, options);
const alignItems = parts.length > 6 ? 'flex-start' : 'center';
return ( return (
<div className={`${style.pie_chart} ${className || ''}`}> <div className={`${style.pie_chart} ${className || ''}`}>
<Title title={title || ''} /> <Title title={title || ''} />
<div className={style.pie_chart_data}> <div
className={style.pie_chart_data}
style={{ alignItems }}
>
<div className={style.pie_chart_icon}> <div className={style.pie_chart_icon}>
<PieSVG <PieSVG
parts={parts} parts={parts}

View file

@ -3,7 +3,6 @@
.ui_kit_select_with_buttons_wrapper + .ui_kit_wrapper, .ui_kit_select_with_buttons_wrapper + .ui_kit_wrapper,
.ui_kit_wrapper + .ui_kit_wrapper { .ui_kit_wrapper + .ui_kit_wrapper {
vertical-align: top; vertical-align: top;
margin-top: var(--space-l);
} }
.ui_kit_title, .ui_kit_title,

View file

@ -0,0 +1,71 @@
import ICommit from 'ts/interfaces/Commit';
import { HashMap } from 'ts/interfaces/HashMap';
import { ONE_DAY } from 'ts/helpers/formatter';
export default class DataGripByTaskCodes {
commits: HashMap<any> = new Map();
statistic: any = [];
clear() {
this.commits.clear();
this.statistic = [];
}
addCommit(commit: ICommit) {
if (!commit.taskCode) return;
const statistic = this.commits.get(commit.taskCode);
if (statistic) {
this.#updateCommitByTaskCode(statistic, commit);
} else {
this.#addCommitByTaskCode(commit);
}
}
#updateCommitByTaskCode(statistic: any, commit: ICommit) {
statistic.commits += 1;
statistic.lastCommit = commit;
statistic.days.set(commit.timestamp, true);
statistic.authors.add(commit.author);
}
#addCommitByTaskCode(commit: ICommit) {
this.commits.set(commit.taskCode, {
taskCode: commit.taskCode,
commits: 1,
firstCommit: commit,
lastCommit: commit,
days: new Map([[commit.timestamp, true]]),
authors: new Set([commit.author]),
});
}
updateTotalInfo(lastCommit: ICommit, dataGripByAuthor: any) {
const dismissedLimit = lastCommit?.milliseconds - 32 * ONE_DAY;
this.statistic = Array.from(this.commits.values())
.map((dot: any) => {
const authors = Array.from(dot.authors);
const totalWorked = authors.reduce((sum: any, name: any) => {
const author = dataGripByAuthor.statisticByName[name];
const value = (author.isStaff || author.isDismissed) ? 0 : 1;
return sum + value;
}, 0);
return {
taskCode: dot.taskCode,
commits: dot.commits,
from: dot.firstCommit.timestamp,
to: dot.lastCommit.timestamp,
authors,
totalDays: (dot.lastCommit.milliseconds - dot.firstCommit.milliseconds) / ONE_DAY,
totalDaysWorked: dot.days.size,
totalAuthors: authors.length,
totalWorked,
isActive: dot.lastCommit.milliseconds > dismissedLimit,
};
})
.sort((dotA: any, dotB: any) => dotB.totalDays - dotA.totalDays);
this.commits.clear();
}
}

View file

@ -14,6 +14,7 @@ import DataGripByPR from './components/pr';
import DataGripByTasks from './components/tasks'; import DataGripByTasks from './components/tasks';
import DataGripByRelease from './components/release'; import DataGripByRelease from './components/release';
import DataGripByScoring from './components/scoring'; import DataGripByScoring from './components/scoring';
import DataGripByTaskCodes from './components/taskCodes';
import DataGripByCompany from './components/company'; import DataGripByCompany from './components/company';
import DataGripByCountry from './components/country'; import DataGripByCountry from './components/country';
@ -48,6 +49,8 @@ class DataGrip {
scoring: any = new DataGripByScoring(); scoring: any = new DataGripByScoring();
taskCodes: any = new DataGripByTaskCodes();
clear() { clear() {
this.firstLastCommit.clear(); this.firstLastCommit.clear();
this.author.clear(); this.author.clear();
@ -64,6 +67,7 @@ class DataGrip {
this.tasks.clear(); this.tasks.clear();
this.release.clear(); this.release.clear();
this.scoring.clear(); this.scoring.clear();
this.taskCodes.clear();
} }
addCommit(commit: ICommit | ISystemCommit, totalCommits: number) { addCommit(commit: ICommit | ISystemCommit, totalCommits: number) {
@ -79,6 +83,7 @@ class DataGrip {
this.get.addCommit(commit); this.get.addCommit(commit);
this.week.addCommit(commit); this.week.addCommit(commit);
this.tasks.addCommit(commit); this.tasks.addCommit(commit);
this.taskCodes.addCommit(commit);
} }
} }
@ -96,6 +101,7 @@ class DataGrip {
this.scoring.updateTotalInfo(this.author, this.timestamp); this.scoring.updateTotalInfo(this.author, this.timestamp);
this.company.updateTotalInfo(this.author); this.company.updateTotalInfo(this.author);
this.country.updateTotalInfo(this.author); this.country.updateTotalInfo(this.author);
this.taskCodes.updateTotalInfo(this.firstLastCommit.maxData, this.author);
} }
} }

View file

@ -60,6 +60,7 @@ export default class FileGripByType {
updateTotalInfo() { updateTotalInfo() {
this.statistic = Array.from(this.statisticByName.values()) this.statistic = Array.from(this.statisticByName.values())
.filter((data: any) => data.type.indexOf('#') === -1)
.sort((a: any, b: any) => b.count - a.count); .sort((a: any, b: any) => b.count - a.count);
} }
} }

View file

@ -1,10 +1,13 @@
import ICommit, { COMMIT_TYPE, ISystemCommit } from 'ts/interfaces/Commit'; import ICommit, { COMMIT_TYPE, ISystemCommit } from 'ts/interfaces/Commit';
import IHashMap from 'ts/interfaces/HashMap';
import { getTypeAndScope, getTask, getTaskNumber } from './getTypeAndScope'; import {
import getInfoFromNameAndEmail from './getCompany'; getTypeAndScope,
getTask,
getTaskNumber,
getTaskCode,
} from './getTypeAndScope';
import { getGithubPrInfo, getGitlabPrInfo } from './getMergeInfo'; import { getGithubPrInfo, getGitlabPrInfo } from './getMergeInfo';
import getCountryByTimeZone from './getCountryByTimeZone'; import getEmailAuthor from './getEmailAuthor';
const MASTER_BRANCH = { const MASTER_BRANCH = {
master: true, master: true,
@ -24,10 +27,7 @@ export function clearCache() {
refTimestampTime.clear(); refTimestampTime.clear();
} }
export default function getCommitInfo( export default function getCommitInfo(logString: string): ICommit | ISystemCommit {
logString: string,
refEmailAuthor: IHashMap<string>,
): ICommit | ISystemCommit {
// "2021-02-09T12:59:17+03:00>Frolov Ivan>frolov@mail.ru>profile" // "2021-02-09T12:59:17+03:00>Frolov Ivan>frolov@mail.ru>profile"
const parts = logString.split('>'); const parts = logString.split('>');
@ -47,41 +47,13 @@ export default function getCommitInfo(
refTimestampTime.set(timestamp, milliseconds); refTimestampTime.set(timestamp, milliseconds);
} }
let author = parts[1]?.replace(/[._]/gm, ' ') || ''; const {
let email = parts[2] || ''; author,
if (email.indexOf('@') === -1) email = ''; email,
device,
const companyKey = `${author}>mail>${email}`; company,
if (!refEmailAuthor[companyKey]) { // @ts-ignore country,
refEmailAuthor[companyKey] = getInfoFromNameAndEmail(author, email); } = getEmailAuthor(parts, timezone);
} // @ts-ignore
const { company, domain, device } = refEmailAuthor[companyKey];
const countryKey = `${author}>time>${timezone}`;
if (!refEmailAuthor[countryKey]) {// @ts-ignore
refEmailAuthor[countryKey] = getCountryByTimeZone(timezone, domain, author);
} // @ts-ignore
const country = refEmailAuthor[countryKey];
const authorID = author.replace(/\s|\t/gm, '');
if (authorID && refEmailAuthor[authorID] && refEmailAuthor[authorID] !== author) {
// console.log(`PARSE WARNING: Rename "${author}" to "${refEmailAuthor[authorID]}"`);
author = refEmailAuthor[authorID];
}
if (email && refEmailAuthor[email] && refEmailAuthor[email] !== author) {
// console.log(`PARSE WARNING: Rename "${author}" to "${refEmailAuthor[email]}" by "${email}"`);
author = refEmailAuthor[email];
}
if (author && refEmailAuthor[author] && refEmailAuthor[author] !== email) {
// console.log(`PARSE WARNING: Rename "${email}" to "${refEmailAuthor[author]}" by "${author}"`);
email = refEmailAuthor[author];
}
refEmailAuthor[email] = author;
refEmailAuthor[author] = email;
refEmailAuthor[authorID] = author;
// performance // performance
const message = logString.substring(parts[0]?.length + parts[1]?.length + parts[2]?.length + 3); const message = logString.substring(parts[0]?.length + parts[1]?.length + parts[2]?.length + 3);
@ -160,6 +132,7 @@ export default function getCommitInfo(
} }
} }
taskNumber = getTaskNumber(task); taskNumber = getTaskNumber(task);
const taskCode = getTaskCode(task);
return { return {
...commonInfo, ...commonInfo,
@ -168,6 +141,7 @@ export default function getCommitInfo(
prId: prId || '', prId: prId || '',
task: task || '', task: task || '',
taskNumber: taskNumber || '', taskNumber: taskNumber || '',
taskCode,
repository: repository || '', repository: repository || '',
branch: branch || '', branch: branch || '',
toBranch: toBranch || '', toBranch: toBranch || '',
@ -180,11 +154,13 @@ export default function getCommitInfo(
: message; : message;
const task = getTask(message); const task = getTask(message);
const taskNumber = getTaskNumber(task); const taskNumber = getTaskNumber(task);
const taskCode = getTaskCode(task);
const [type, scope] = getTypeAndScope(message, task); const [type, scope] = getTypeAndScope(message, task);
return { return {
...commonInfo, ...commonInfo,
task, task,
taskNumber, taskNumber,
taskCode,
text, text,
type: type || '', type: type || '',
scope: scope || '', scope: scope || '',

View file

@ -81,7 +81,7 @@ const LINE = {
}, },
}, },
'+03:00': { '+03:00': {
countries: ['ru', 'tr'], countries: ['ru', 'by', 'tr'],
name: { name: {
ru: FAMILY.ru, ru: FAMILY.ru,
tr: FAMILY.tr, tr: FAMILY.tr,

View file

@ -0,0 +1,112 @@
import getCompanyDomainDevice from './getCompany';
import getCountryByTimeZone from './getCountryByTimeZone';
const cacheByAuthorId = new Map();
const cacheByAuthor = new Map();
const cacheByEmail = new Map();
const cacheByAuthorEmail = new Map();
const cacheForCompany = new Map();
const cacheForCountry = new Map();
export function clearRenameCache() {
cacheByAuthorId.clear();
cacheByAuthor.clear();
cacheByEmail.clear();
cacheByAuthorEmail.clear();
cacheForCompany.clear();
cacheForCountry.clear();
}
function getAuthorIdByName(name: string) {
return name.toLowerCase().replace(/[\s\t.\-_]+/gm, '');
}
function getFormattedName(name: string) {
return name
.replace(/[.\-_]+/gm, ' ')
.replace(/([a-z])([A-Z])/gm, '$1 $2')
.trim();
}
interface Response {
author: string;
email: string;
device: string;
company: string;
country: string;
}
export default function getEmailAuthor(
parts: string[],
timezone: string,
): Response {
let author = parts[1] || '';
let email = parts[2] || '';
if (email.indexOf('@') === -1) email = '';
// Company, domain, device
const key = `${author}>${email}`;
let data = cacheForCompany.get(key);
if (!data) {
data = getCompanyDomainDevice(author, email);
cacheForCompany.set(key, data);
}
const {
company,
domain,
device,
} = data;
// Country
const countryKey = `${author}>${timezone}`;
let country = cacheForCountry.get(countryKey);
if (!country) {
country = getCountryByTimeZone(timezone, domain, author);
cacheForCountry.set(key, data);
}
const authorEmail = cacheByAuthorEmail.get(key);
if (authorEmail) {
author = authorEmail.author;
email = authorEmail.email;
} else {
// Author, email
const authorId = getAuthorIdByName(author);
const authorById = cacheByAuthorId.get(authorId);
if (authorId && authorById && authorById !== author) {
// console.log(`PARSE WARNING: Rename "${author}" to "${authorById}"`);
cacheByAuthorId.set(authorId, authorById);
author = authorById;
}
const authorByEmail = cacheByEmail.get(email);
if (email && authorByEmail && authorByEmail !== author) {
// console.log(`PARSE WARNING: Rename "${author}" to "${authorByEmail}"`);
cacheByEmail.set(email, authorByEmail);
author = authorByEmail;
}
const emailByAuthor = cacheByAuthor.get(author);
if (author && emailByAuthor && emailByAuthor !== email) {
// console.log(`PARSE WARNING: Rename "${email}" to "${emailByAuthor}"`);
cacheByAuthor.set(author, emailByAuthor);
email = emailByAuthor;
}
const newAuthorId = getAuthorIdByName(author);
author = getFormattedName(author);
cacheByAuthorId.set(newAuthorId, author);
cacheByEmail.set(email, author);
cacheByAuthor.set(author, email);
cacheByAuthorEmail.set(key, { author, email });
}
return {
author,
email,
device,
company,
country,
};
}

View file

@ -78,3 +78,8 @@ export function getTask(message: string) {
export function getTaskNumber(task?: string) { export function getTaskNumber(task?: string) {
return (task || '').replace(/[^0-9]+/gim, ''); return (task || '').replace(/[^0-9]+/gim, '');
} }
// ABC-123 => 'ABC';
export function getTaskCode(task?: string) {
return (task || '').replace(/[^A-Z]+/gim, '');
}

View file

@ -1,9 +1,9 @@
import ICommit, { IFileChange, ISystemCommit } from 'ts/interfaces/Commit'; import ICommit, { IFileChange, ISystemCommit } from 'ts/interfaces/Commit';
import IHashMap from 'ts/interfaces/HashMap';
import { ONE_DAY, ONE_WEEK } from 'ts/helpers/formatter'; import { ONE_DAY, ONE_WEEK } from 'ts/helpers/formatter';
import getCommitInfo, { clearCache } from './getCommitInfo'; import getCommitInfo, { clearCache } from './getCommitInfo';
import { clearRenameCache } from './getEmailAuthor';
import { import {
getInfoFromPath, getInfoFromPath,
getNumStatInfo, getNumStatInfo,
@ -30,7 +30,6 @@ export default function Parser(report: string[]) {
let commit = null; let commit = null;
const commits: Array<ICommit | ISystemCommit> = []; const commits: Array<ICommit | ISystemCommit> = [];
let refEmailAuthor: IHashMap<string> = {};
let files: Map<string, IFileChange> = new Map(); let files: Map<string, IFileChange> = new Map();
let fileChanges: IFileChange | null = null; let fileChanges: IFileChange | null = null;
@ -70,7 +69,7 @@ export default function Parser(report: string[]) {
// "2021-02-09T16:08:15+03:00>Albert>instein@mail.de>feat(init): added the speed of light" // "2021-02-09T16:08:15+03:00>Albert>instein@mail.de>feat(init): added the speed of light"
if (commit) commit.fileChanges = Array.from(files.values()); if (commit) commit.fileChanges = Array.from(files.values());
files.clear(); files.clear();
commit = getCommitInfo(message, refEmailAuthor); commit = getCommitInfo(message);
const monday = commit.milliseconds - commit.day * ONE_DAY; const monday = commit.milliseconds - commit.day * ONE_DAY;
if (firstMonday) { if (firstMonday) {
@ -83,6 +82,7 @@ export default function Parser(report: string[]) {
} }
} }
clearRenameCache();
clearCache(); clearCache();
return commits; return commits;

View file

@ -38,6 +38,7 @@ export interface ILog {
text: string; // "add new avatar" text: string; // "add new avatar"
task: string; // "JIRA-0000", task: string; // "JIRA-0000",
taskNumber: string; // "0000", taskNumber: string; // "0000",
taskCode: string; // "JIRA",
type: string; // feat|fix|docs|style|refactor|test|chore type: string; // feat|fix|docs|style|refactor|test|chore
scope: string; // table, sale, profile and etc. scope: string; // table, sale, profile and etc.

View file

@ -42,6 +42,12 @@ export const TEAM = [
title: 'sidebar.team.company', title: 'sidebar.team.company',
icon: './assets/menu/company.svg', icon: './assets/menu/company.svg',
}, },
{
id: 'department',
link: '/team/department',
title: 'sidebar.team.department',
icon: './assets/menu/department.svg',
},
{ {
id: 'country', id: 'country',
link: '/team/country', link: '/team/country',

View file

@ -13,6 +13,10 @@
&_select { &_select {
min-width: 350px; min-width: 350px;
} }
&_checkbox {
margin-top: var(--space-l);
}
} }
@media (max-width: 900px) { @media (max-width: 900px) {

View file

@ -0,0 +1,84 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import dataGripStore from 'ts/store/DataGrip';
import PageWrapper from 'ts/components/Page/wrapper';
import PageColumn from 'ts/components/Page/column';
import getOptions from 'ts/components/LineChart/helpers/getOptions';
import PieChart from 'ts/components/PieChart';
import { increment } from 'ts/helpers/Math';
import { WORK_DAYS } from '../../Author/contstants';
import { EMPLOYMENTS } from '../contstants';
function getEmploymentsChart(rows: any[]) {
const order = Object.values(EMPLOYMENTS);
const options = getOptions({ order, limit: 1, suffix: 'page.team.department.employments.item' });
const details = rows.reduce((acc: any, row: any) => {
if (!row.isActive) return acc;
if (row.totalWorked <= 1) increment(acc, EMPLOYMENTS.LESS1);
else if (row.totalWorked <= 2) increment(acc, EMPLOYMENTS.LESS2);
else if (row.totalWorked <= 3) increment(acc, EMPLOYMENTS.LESS3);
else if (row.totalWorked <= 6) increment(acc, EMPLOYMENTS.LESS6);
else if (row.totalWorked <= 9) increment(acc, EMPLOYMENTS.LESS9);
else if (row.totalWorked <= 12) increment(acc, EMPLOYMENTS.LESS12);
else if (row.totalWorked <= 15) increment(acc, EMPLOYMENTS.LESS15);
else increment(acc, EMPLOYMENTS.MORE);
return acc;
}, {});
return [options, details];
}
function getDaysChart(rows: any[]) {
const order = Object.values(WORK_DAYS);
const options = getOptions({ order, limit: 1, suffix: 'page.team.department.daysChart.item' });
const details = rows.reduce((acc: any, row: any) => {
if (row.totalDays < 183) increment(acc, WORK_DAYS.HALF);
else if (row.totalDays < 365) increment(acc, WORK_DAYS.ONE);
else if (row.totalDays < 547) increment(acc, WORK_DAYS.HALF_ONE);
else if (row.totalDays < 730) increment(acc, WORK_DAYS.TWO);
else increment(acc, WORK_DAYS.MORE);
return acc;
}, {});
return [options, details];
}
// активные и закрытые
const PieCharts = observer((): React.ReactElement | null => {
const rows = dataGripStore.dataGrip.taskCodes.statistic
.filter((item: any) => item.totalDaysWorked > 10);
const [employmentsOptions, employmentsDetails] = getEmploymentsChart(rows);
const [daysOptions, daysDetails] = getDaysChart(rows);
const hasEmploymentsChart = Object.keys(employmentsDetails).length;
return hasEmploymentsChart ? (
<PageWrapper>
<PageColumn>
<PieChart
title="page.team.department.daysChart.title"
options={daysOptions}
details={daysDetails}
/>
</PageColumn>
<PageColumn>
<PieChart
title="page.team.department.employments.title"
options={employmentsOptions}
details={employmentsDetails}
/>
</PageColumn>
</PageWrapper>
) : (
<PageWrapper>
<PieChart
title="page.team.department.daysChart.title"
options={daysOptions}
details={daysDetails}
/>
</PageWrapper>
);
});
export default PieCharts;

View file

@ -0,0 +1,155 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { IPagination } from 'ts/interfaces/Pagination';
import { getDate } from 'ts/helpers/formatter';
import dataGripStore from 'ts/store/DataGrip';
import DataView from 'ts/components/DataView';
import UiKitTags from 'ts/components/UiKit/components/Tags';
import Column from 'ts/components/Table/components/Column';
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
import LineChart from 'ts/components/LineChart';
import getOptions from 'ts/components/LineChart/helpers/getOptions';
import { getMax } from 'ts/pages/Common/helpers/getMax';
import { increment } from 'ts/helpers/Math';
import Employments from '../../Company/components/Employments';
interface DepartmentsProps {
response?: IPagination<any>;
updateSort?: Function;
rowsForExcel?: any[];
mode?: string;
}
function Departments({ response, updateSort, rowsForExcel, mode }: DepartmentsProps) {
const { t } = useTranslation();
if (!response) return null;
const [active, notActive] = [
t('page.team.company.active.yes'),
t('page.team.company.active.no'),
];
const [works, dismissed, staff] = [
t('page.team.author.type.work'),
t('page.team.author.type.dismissed'),
t('page.team.author.type.staff'),
];
const authorsChart = getOptions({
order: [works, dismissed, staff],
max: getMax(response, 'totalAuthors'),
suffix: 'page.team.department.authors',
});
const daysChart = getOptions({ max: getMax(response, 'totalDays'), suffix: 'page.team.author.days' });
return (
<DataView
rowsForExcel={rowsForExcel}
rows={response.content}
sort={response.sort}
updateSort={updateSort}
type={mode === 'print' ? 'cards' : undefined}
columnCount={mode === 'print' ? 3 : undefined}
>
<Column
isFixed
template={ColumnTypesEnum.DETAILS}
width={40}
formatter={(row: any) => {
const content = dataGripStore.dataGrip.author.statistic
.filter((item: any) => row?.authors?.includes(item.author));
return (
<Employments // @ts-ignore
response={{ content }}
mode="details"
/>
);
}}
/>
<Column
isFixed
template={ColumnTypesEnum.STRING}
properties="taskCode"
title="page.team.department.code"
/>
<Column
title="page.team.author.status"
formatter={(row: any) => (row.isActive ? active : notActive)}
template={(value: string) => <UiKitTags value={value} />}
width={140}
/>
<Column
template={ColumnTypesEnum.STRING}
properties="from"
title="page.team.department.from"
width={130}
formatter={getDate}
/>
<Column
template={ColumnTypesEnum.STRING}
properties="to"
title="page.team.department.to"
width={130}
formatter={getDate}
/>
<Column
template={ColumnTypesEnum.SHORT_NUMBER}
properties="totalDaysWorked"
width={90}
/>
<Column
isSortable="totalDays"
title="page.team.department.totalDays"
properties="totalDaysWorked"
minWidth={150}
template={(value: number) => (
<LineChart
options={daysChart}
value={value}
/>
)}
/>
<Column
template={ColumnTypesEnum.SHORT_NUMBER}
properties="totalAuthors"
width={90}
/>
<Column
isSortable="totalAuthors"
title="page.team.department.totalAuthors"
minWidth={150}
template={(row: any) => {
const statisticByName = dataGripStore.dataGrip.author.statisticByName;
const details = row.authors.reduce((acc: any, name: string) => {
const author = statisticByName[name] || {};
if (author.isStaff) increment(acc, staff);
else if (author.isDismissed) increment(acc, dismissed);
else increment(acc, works);
return acc;
}, {});
return (
<LineChart
options={authorsChart}
value={row.totalAuthors}
details={details}
/>
);
}}
/>
</DataView>
);
// задач в день (неделю)
// активных сотрудников
// состав команд по активным сотрудникам
}
Departments.defaultProps = {
response: undefined,
};
export default Departments;

View file

@ -0,0 +1,12 @@
import { t } from 'ts/helpers/Localization';
export const EMPLOYMENTS = {
LESS1: t('page.team.author.employments.less1'),
LESS2: t('page.team.author.employments.less2'),
LESS3: t('page.team.author.employments.less3'),
LESS6: t('page.team.author.employments.less6'),
LESS9: t('page.team.author.employments.less9'),
LESS12: t('page.team.author.employments.less12'),
LESS15: t('page.team.author.employments.less15'),
MORE: t('page.team.author.employments.more'),
};

View file

@ -0,0 +1,47 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { IPaginationRequest } from 'ts/interfaces/Pagination';
import ISort from 'ts/interfaces/Sort';
import dataGripStore from 'ts/store/DataGrip';
import DataLoader from 'ts/components/DataLoader';
import Pagination from 'ts/components/DataLoader/components/Pagination';
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
import NothingFound from 'ts/components/NothingFound';
import Title from 'ts/components/Title';
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
import Departments from './components/Departments';
import DepartmentCharts from './components/Charts';
const Department = observer(({
mode,
}: ICommonPageProps): React.ReactElement | null => {
const content = dataGripStore.dataGrip.taskCodes.statistic
.filter((item: any) => item.totalDaysWorked > 10);
if (!content?.length) {
return <NothingFound />;
}
return (
<>
<DepartmentCharts/>
<Title title="page.team.department.title"/>
<DataLoader
to="response"
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
content, pagination, sort, mode,
})}
>
<Departments />
<Pagination />
</DataLoader>
</>
);
});
export default Department;

View file

@ -27,6 +27,7 @@ import Pr from './components/PR';
import Print from './components/Print'; import Print from './components/Print';
import Release from './components/Release'; import Release from './components/Release';
import Refactor from './components/Refactor'; import Refactor from './components/Refactor';
import Department from './components/Department';
interface ViewProps { interface ViewProps {
page?: string; page?: string;
@ -59,6 +60,7 @@ const View = observer(({ page }: ViewProps): React.ReactElement => {
if (page === 'print') return <Print/>; if (page === 'print') return <Print/>;
if (page === 'tasks') return <Tasks/>; if (page === 'tasks') return <Tasks/>;
if (page === 'refactor') return <Refactor/>; if (page === 'refactor') return <Refactor/>;
if (page === 'department') return <Department/>;
return <Total/>; return <Total/>;
}); });

View file

@ -1,16 +0,0 @@
@import 'src/styles/variables';
.team_country_filter {
margin-top: var(--space-m);
&_checkbox,
&_select {
display: inline-block;
margin-right: var(--space-xxl);
vertical-align: middle;
}
&_select {
min-width: 350px;
}
}

View file

@ -32,6 +32,7 @@ export default `
§ sidebar.team.building: Quiz § sidebar.team.building: Quiz
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: Die Einstellungen § sidebar.team.settings: Die Einstellungen
§ sidebar.person.total: Allgemeine Informationen § sidebar.person.total: Allgemeine Informationen

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work. § page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work.
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees). § page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
@ -217,6 +217,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: space for a photo § page.person.print.photo.description: space for a photo
§ page.person.total.title: Main characteristics § page.person.total.title: Main characteristics

View file

@ -30,6 +30,7 @@ export default `
§ sidebar.team.building: Quiz § sidebar.team.building: Quiz
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: Settings § sidebar.team.settings: Settings
§ sidebar.person.total: Common info § sidebar.person.total: Common info

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work. § page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work.
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees). § page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: space for a photo § page.person.print.photo.description: space for a photo
§ page.person.total.title: Main characteristics § page.person.total.title: Main characteristics

View file

@ -32,6 +32,7 @@ export default `
§ sidebar.team.building: Concurso § sidebar.team.building: Concurso
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: Ajustes § sidebar.team.settings: Ajustes
§ sidebar.person.total: Información general § sidebar.person.total: Información general

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: Parte de las estadísticas (la velocidad del trabajo, el dinero gastado, etc.) para los empleados con el tipo de "Asistente" no cuenta, ya que no es un rol permanente en el proyecto. Su trabajo es insignificante y puede ser ignorado. § page.team.author.description1: Parte de las estadísticas (la velocidad del trabajo, el dinero gastado, etc.) para los empleados con el tipo de "Asistente" no cuenta, ya que no es un rol permanente en el proyecto. Su trabajo es insignificante y puede ser ignorado.
§ page.team.author.description2: La clasificación predeterminada es la clasificación por número de tareas y grupos(empleados actuales, despedidos, ayudantes). § page.team.author.description2: La clasificación predeterminada es la clasificación por número de tareas y grupos(empleados actuales, despedidos, ayudantes).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: a place for a photo § page.person.print.photo.description: a place for a photo
§ page.person.total.title: Main Features § page.person.total.title: Main Features

View file

@ -30,6 +30,7 @@ export default `
§ sidebar.team.building: Quiz § sidebar.team.building: Quiz
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: Réglages § sidebar.team.settings: Réglages
§ sidebar.person.total: Informations générales § sidebar.person.total: Informations générales

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: Partie des statistiques (vitesse de travail, argent dépensé, etc.) pour les collaborateurs de type Assistant, ce nest pas une rôle permanente dans le projet. Leur travail est insignifiant et peut être ignoré. § page.team.author.description1: Partie des statistiques (vitesse de travail, argent dépensé, etc.) pour les collaborateurs de type Assistant, ce nest pas une rôle permanente dans le projet. Leur travail est insignifiant et peut être ignoré.
§ page.team.author.description2: Le tri par défaut est le tri par nombre de tâches et de groupes (employés actuels, licenciés et aidants). § page.team.author.description2: Le tri par défaut est le tri par nombre de tâches et de groupes (employés actuels, licenciés et aidants).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: place à la photographie § page.person.print.photo.description: place à la photographie
§ page.person.total.title: Caractéristiques de base § page.person.total.title: Caractéristiques de base

View file

@ -31,6 +31,7 @@ export default `
§ sidebar.team.building: クイズ § sidebar.team.building: クイズ
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: 設定 § sidebar.team.settings: 設定
§ sidebar.person.total: 一般的な情報 § sidebar.person.total: 一般的な情報

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work. § page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work.
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees). § page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: space for a photo § page.person.print.photo.description: space for a photo
§ page.person.total.title: Main characteristics § page.person.total.title: Main characteristics

View file

@ -30,6 +30,7 @@ export default `
§ sidebar.team.building: 퀴즈 § sidebar.team.building: 퀴즈
§ sidebar.team.refactor: 리팩토링 § sidebar.team.refactor: 리팩토링
§ sidebar.team.company: 회사 § sidebar.team.company: 회사
§ sidebar.team.department: Departments
§ sidebar.team.country: 위치 § sidebar.team.country: 위치
§ sidebar.team.settings: 설정 § sidebar.team.settings: 설정
§ sidebar.person.total: 일반 § sidebar.person.total: 일반

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: 1 § page.team.author.days.one: 1
§ page.team.author.days.15: § page.team.author.days.15:
§ page.team.author.days.two: 2 § page.team.author.days.two: 2
§ page.team.author.days.more: § page.team.author.days.more: more than two years
§ page.team.author.title: 세부 § page.team.author.title: 세부
§ page.team.author.description1: * *( , ))* "보조"* . , . § page.team.author.description1: * *( , ))* "보조"* . , .
§ page.team.author.description2: * * (,, ) . § page.team.author.description2: * * (,, ) .
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: 작업 § page.team.release.prLength: 작업
§ page.team.release.delay: 작업 § page.team.release.delay: 작업
§ page.team.release.waiting: 다음 § page.team.release.waiting: 다음
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: 사진 § page.person.print.photo.title: 사진
§ page.person.print.photo.description: 사진 § page.person.print.photo.description: 사진
§ page.person.total.title: 주요 § page.person.total.title: 주요

View file

@ -31,6 +31,7 @@ export default `
§ sidebar.team.building: Concurso § sidebar.team.building: Concurso
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: Sintonização § sidebar.team.settings: Sintonização
§ sidebar.person.total: Informação geral § sidebar.person.total: Informação geral

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work. § page.team.author.description1: *Part of the statistics* (work speed, costs, etc.) *for employees with the 'Assistant' type is not counted*, as it is an episodic role in the project. It is assumed that they do not affect the project, and their edits can be disregarded in the context of the overall volume of work.
§ page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees). § page.team.author.description2: *Default sorting* is by the number of tasks and groups (current, fired, assisting employees).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: Photo § page.person.print.photo.title: Photo
§ page.person.print.photo.description: space for a photo § page.person.print.photo.description: space for a photo
§ page.person.total.title: Main characteristics § page.person.total.title: Main characteristics

View file

@ -30,6 +30,7 @@ export default `
§ sidebar.team.building: Викторина § sidebar.team.building: Викторина
§ sidebar.team.refactor: Рефакторинг § sidebar.team.refactor: Рефакторинг
§ sidebar.team.company: Компании § sidebar.team.company: Компании
§ sidebar.team.department: Отделы
§ sidebar.team.country: Местоположение § sidebar.team.country: Местоположение
§ sidebar.team.settings: Настройки § sidebar.team.settings: Настройки
§ sidebar.person.total: Общая информация § sidebar.person.total: Общая информация

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: год § page.team.author.days.one: год
§ page.team.author.days.15: полтора § page.team.author.days.15: полтора
§ page.team.author.days.two: два года § page.team.author.days.two: два года
§ page.team.author.days.more: больше § page.team.author.days.more: больше двух лет
§ page.team.author.title: Детализация § page.team.author.title: Детализация
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы. § page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
§ page.team.author.description2: *Сортировка по умолчанию* это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники). § page.team.author.description2: *Сортировка по умолчанию* это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
@ -219,6 +219,26 @@ export default `
§ page.team.release.prLength: Задач § page.team.release.prLength: Задач
§ page.team.release.delay: Дней работы § page.team.release.delay: Дней работы
§ page.team.release.waiting: Дней до следующего релиза § page.team.release.waiting: Дней до следующего релиза
§ page.team.department.employments.title: Размер текущих команд
§ page.team.department.employments.item: команд
§ page.team.author.employments.less1: один сотрудник
§ page.team.author.employments.less2: два сотрудника
§ page.team.author.employments.less3: три сотрудника
§ page.team.author.employments.less6: до шести сотрудников
§ page.team.author.employments.less9: до девяти сотрудников
§ page.team.author.employments.less12: до 12 сотрудников
§ page.team.author.employments.less15: до 15 сотрудников
§ page.team.author.employments.more: больше 15
§ page.team.department.daysChart.title: Продолжительность проектов
§ page.team.department.daysChart.item: проекта
§ page.team.department.title: Список проектов
§ page.team.department.code: Код
§ page.team.department.from: Первый коммит
§ page.team.department.to: Последний
§ page.team.department.authors: человек
§ page.team.department.tasks: задач
§ page.team.department.totalDays: Дней работы
§ page.team.department.totalAuthors: Количество сотрудников
§ page.person.print.photo.title: Фотография § page.person.print.photo.title: Фотография
§ page.person.print.photo.description: место для фотографии § page.person.print.photo.description: место для фотографии
§ page.person.total.title: Основные характеристики § page.person.total.title: Основные характеристики

View file

@ -3,9 +3,9 @@ const fs = require('node:fs');
const PAGES = [ const PAGES = [
// 'achievements', // 'achievements',
// 'common', // 'common',
// 'navigation', 'navigation',
// 'pages', 'pages',
'recommendations', // 'recommendations',
// 'settings', // 'settings',
]; ];

View file

@ -1,47 +1,48 @@
export default ` export default `
§ sidebar.switch.team: § sidebar.switch.team: Команда
§ sidebar.switch.person: 직원 § sidebar.switch.person: Сотрудник
§ sidebar.buttons.settings: 설정 § sidebar.buttons.settings: Настройки
§ sidebar.buttons.print: 인쇄 § sidebar.buttons.print: Печать
§ sidebar.buttons.share: 그것을 § sidebar.buttons.share: Расшарить
§ sidebar.buttons.logout: 나가 § sidebar.buttons.logout: Выйти
§ sidebar.filters.all: 항상 § sidebar.filters.all: всё время
§ sidebar.filters.year: § sidebar.filters.year: год
§ sidebar.filters.halfYear: 반년 § sidebar.filters.halfYear: пол года
§ sidebar.filters.month: § sidebar.filters.month: месяц
§ sidebar.filters.week: § sidebar.filters.week: неделя
§ sidebar.team.total: 일반 § sidebar.team.total: Общая информация
§ sidebar.team.scope: 특징 § sidebar.team.scope: Фичи
§ sidebar.team.author: 직원 § sidebar.team.author: Сотрудники
§ sidebar.team.type: 작업 § sidebar.team.type: Типы задач
§ sidebar.team.pr: 코드 § sidebar.team.pr: Влитие кода
§ sidebar.team.day: 낮에 § sidebar.team.day: По дням
§ sidebar.team.week: 주별 § sidebar.team.week: По неделям
§ sidebar.team.month: 월별 § sidebar.team.month: По месяцам
§ sidebar.team.files: 파일 § sidebar.team.files: Файлы
§ sidebar.team.removedFiles: 삭제 § sidebar.team.removedFiles: Удалённые файлы
§ sidebar.team.extension: 파일 § sidebar.team.extension: Типы файлов
§ sidebar.team.tasks: 작업 § sidebar.team.tasks: Список задач
§ sidebar.team.release: 발매 § sidebar.team.release: Список релизов
§ sidebar.team.hours: 일정 § sidebar.team.hours: Расписание
§ sidebar.team.commits: 모든 § sidebar.team.commits: Все коммиты
§ sidebar.team.changes: 모든 § sidebar.team.changes: Все изменения
§ sidebar.team.words: 인기있는 § sidebar.team.words: Популярные слова
§ sidebar.team.building: 퀴즈 § sidebar.team.building: Викторина
§ sidebar.team.refactor: 리팩토링 § sidebar.team.refactor: Рефакторинг
§ sidebar.team.company: 회사 § sidebar.team.company: Компании
§ sidebar.team.country: 위치 § sidebar.team.department: Отделы
§ sidebar.team.settings: 설정 § sidebar.team.country: Местоположение
§ sidebar.person.total: 일반 § sidebar.team.settings: Настройки
§ sidebar.person.money: 작업 § sidebar.person.total: Общая информация
§ sidebar.person.speed: 속도 § sidebar.person.money: Стоимость работы
§ sidebar.person.day: 낮에 § sidebar.person.speed: Скорость
§ sidebar.person.week: 주별 § sidebar.person.day: По дням
§ sidebar.person.month: 월별 § sidebar.person.week: По неделям
§ sidebar.person.tasks: 작업 § sidebar.person.month: По месяцам
§ sidebar.person.hours: 일정 § sidebar.person.tasks: Список задач
§ sidebar.person.commits: 모든 § sidebar.person.hours: Расписание
§ sidebar.person.changes: 모든 § sidebar.person.commits: Все коммиты
§ sidebar.person.words: 인기있는 § sidebar.person.changes: Все изменения
§ sidebar.person.settings: 설정 § sidebar.person.words: Популярные слова
§ sidebar.person.settings: Настройки
`; `;

View file

@ -1,297 +1,317 @@
export default ` export default `
§ page.welcome.step1: 프로젝트 § page.welcome.step1: Выполните команду в корне вашего проекта
§ page.welcome.step3: 드래그 § page.welcome.step3: Перетащите
§ page.welcome.step4: 그리고 . § page.welcome.step4: файл log.txt на эту страницу
§ page.welcome.description: 힘내는 .- . . [. |<url>// ] . § page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
§ page.welcome.warning1: 서비스* ** * . . § page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
§ page.welcome.warning2: 서비스* * . . § page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].
§ page.common.words.title: 단어에 § page.common.words.title: Статистика по словам
§ page.common.words.description: 가장 . $1 . § page.common.words.description: самое популярное слово. Встречается $1 раза.
§ page.common.commits.title: 일별 § page.common.commits.title: Количество коммитов по дням
§ page.common.commits.description: ($1) . § page.common.commits.description: ($1) самый продуктивный день по числу коммитов.
§ page.common.commits.title2: $1 커밋:$2 § page.common.commits.title2: $1 сделано коммитов: $2
§ page.common.filter.allUsers: 그것은 § page.common.filter.allUsers: Не имеет значения
§ page.print.modal.title: 우리는 ? § page.print.modal.title: Что распечатываем?
§ page.print.modal.page: 현재 § page.print.modal.page: Текущую страницу
§ page.print.modal.type: 현재 § page.print.modal.type: Текущий раздел
§ page.print.modal.all: 모든 § page.print.modal.all: Всю статистику
§ page.print.modal.cancel: 취소 § page.print.modal.cancel: Отмена
§ page.print.tableOfContents: 내용 § page.print.tableOfContents: Оглавление
§ page.print.title: 자식 § page.print.title: Отчёт по git-репозиторию
§ page.print.sub_title: "$1" § page.print.sub_title: «$1»
§ page.print.description: 보고서의 . § page.print.description: Данные для отчёта были получены из истории коммитов.
§ page.team.author.statusChart.title: 현재 § page.team.author.statusChart.title: Текущий статус
§ page.team.author.daysChart.title: 근무 § page.team.author.daysChart.title: Время работы
§ page.team.author.daysChart.item: § page.team.author.daysChart.item: дней
§ page.team.author.days.half: § page.team.author.days.half: пол года
§ page.team.author.days.one: 1 § page.team.author.days.one: год
§ page.team.author.days.15: § page.team.author.days.15: полтора
§ page.team.author.days.two: 2 § page.team.author.days.two: два года
§ page.team.author.days.more: § page.team.author.days.more: больше двух лет
§ page.team.author.title: 세부 § page.team.author.title: Детализация
§ page.team.author.description1: * *( , ))* "보조"* . , . § page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
§ page.team.author.description2: * * (,, ) . § page.team.author.description2: *Сортировка по умолчанию* это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
§ page.team.author.status: 상태 § page.team.author.status: Статус
§ page.team.author.company: 회사소개 § page.team.author.company: Компания
§ page.team.author.firstCommit: § page.team.author.firstCommit: Первый коммит
§ page.team.author.lastCommit: 마지막 § page.team.author.lastCommit: Последний
§ page.team.author.daysAll: 그냥 § page.team.author.daysAll: Всего дней
§ page.team.author.types: 작업 § page.team.author.types: Тип работ
§ page.team.author.commits: 커밋 § page.team.author.commits: Коммитов
§ page.team.author.commitsSmall: 커밋 § page.team.author.commitsSmall: коммитов
§ page.team.author.tasks: 작업 § page.team.author.tasks: Задач
§ page.team.author.tasksSmall: 작업 § page.team.author.tasksSmall: задач
§ page.team.author.workedLosses: 커밋이 § page.team.author.workedLosses: Дни с коммитами и без
§ page.team.author.worked: § page.team.author.worked: работа
§ page.team.author.losses: 커밋 § page.team.author.losses: дни без коммитов
§ page.team.author.days: § page.team.author.days: дней
§ page.team.author.daysForTask: § page.team.author.daysForTask: Дней на задачу
§ page.team.author.scopes: 기능 § page.team.author.scopes: Фич
§ page.team.author.moneyAll: 수신 § page.team.author.moneyAll: Получил
§ page.team.author.moneyWorked: 밖으로 § page.team.author.moneyWorked: Отработал
§ page.team.author.moneyLosses: 초과 § page.team.author.moneyLosses: Переплата
§ page.team.author.type.work: 작동 § page.team.author.type.work: работает
§ page.team.author.type.dismissed: § page.team.author.type.dismissed: уволен § page.team.author.type.dismissed: уволен
§ page.team.author.type.staff: 조수가 § page.team.author.type.staff: помощник
§ page.team.hours.title: § page.team.hours.title: Распределение коммитов в течении каждого дня недели
§ page.team.month.title: 프로젝트 § page.team.month.title: Календарь работы по проекту
§ page.team.month.first: ( ) § page.team.month.first: (первый рабочий день)
§ page.team.month.last: ( ) § page.team.month.last: (последний рабочий день)
§ page.team.scope.title: 기능 § page.team.scope.title: Статистика по фичам
§ page.team.scope.scope: 특징 § page.team.scope.scope: Фича
§ page.team.scope.days: 노예 § page.team.scope.days: Раб. дней
§ page.team.scope.authorsDays: 남자 § page.team.scope.authorsDays: Человеко-дней
§ page.team.scope.tasks: 작업 § page.team.scope.tasks: Задач
§ page.team.scope.commits: 커밋 § page.team.scope.commits: Коммитов
§ page.team.scope.commitsSmall: 커밋 § page.team.scope.commitsSmall: коммитов
§ page.team.scope.types: 작업 § page.team.scope.types: Тип работ
§ page.team.scope.authors: 개인 § page.team.scope.authors: Персональный вклад
§ page.team.scope.cost: 비용 § page.team.scope.cost: Стоимость
§ page.team.type.title: 작업 § page.team.type.title: Статистика по типам задач
§ page.team.type.description: * * . "파일 분석" . § page.team.type.description: *Персональный вклад* считается по количеству коммитов, а не объему измененных строк или файлов. Поэтому следует так же смотреть раздел «Анализ файлов», чтобы оценить масштаб изменений.
§ page.team.type.type: 작업 § page.team.type.type: Тип работы
§ page.team.type.unknown: § page.team.type.unknown: неизвестный
§ page.team.type.tasks: 작업 § page.team.type.tasks: Задач
§ page.team.type.tasksSmall: 작업 § page.team.type.tasksSmall: задач
§ page.team.type.days: § page.team.type.days: Дней
§ page.team.type.daysSmall: § page.team.type.daysSmall: дней
§ page.team.type.authorsDays: 남자 § page.team.type.authorsDays: Человеко-дней
§ page.team.type.commits: 커밋 § page.team.type.commits: Коммитов
§ page.team.type.authors: 개인 § page.team.type.authors: Персональный вклад
§ page.team.total.titleA: 작업 § page.team.total.titleA: Объём работ
§ page.team.total.titleB: 비용 § page.team.total.titleB: Стоимость
§ page.team.total.daysWorked.title: 인간의 § page.team.total.daysWorked.title: человеко-дней
§ page.team.total.daysWorked.description: 약속이 . § page.team.total.daysWorked.description: Учтены только дни, в которые делались коммиты
§ page.team.total.commits.title: § page.team.total.commits.title: коммитов § page.team.total.commits.title: коммитов
§ page.team.total.commits.description: 삭제된 § page.team.total.commits.description: Удалённые ветки не считаются
§ page.team.total.daysLosses.title: 커밋 § page.team.total.daysLosses.title: дней без коммитов
§ page.team.total.daysLosses.description: 모든 빼기:휴일,,, § page.team.total.daysLosses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
§ page.team.total.employment.title: 작업/ § page.team.total.employment.title: работает / уволилось
§ page.team.total.employment.description: 직원이 § page.team.total.employment.description: Если сотрудник в течении месяца не сделал ни одного коммита, он считается уволенным
§ page.team.total.moneyAll.title: . § page.team.total.moneyAll.title: общая
§ page.team.total.moneyAll.description: 포의 § page.team.total.moneyAll.description: Суммарные затраты на зп
§ page.team.total.moneyWorked.title: 실제 § page.team.total.moneyWorked.title: фактическая
§ page.team.total.moneyWorked.description: 실제 § page.team.total.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
§ page.team.total.moneyLosses.title: 가능한 § page.team.total.moneyLosses.title: возможная переплата
§ page.team.total.moneyLosses.description: 커밋이 § page.team.total.moneyLosses.description: Оплаченные рабочие дни, когда коммитов не было
§ page.team.total.weekendPayment.title: 주말에 § page.team.total.weekendPayment.title: работа на выходных
§ page.team.total.weekendPayment.description: 주말 § page.team.total.weekendPayment.description: Суммарная переплата за работу в выходные дни
§ page.team.total.workSpeed.title: 일일 § page.team.total.workSpeed.title: задач в день
§ page.team.total.workSpeed.description: 현재 § page.team.total.workSpeed.description: Средняя скорость работы команды при текущем составе сотрудников
§ page.team.total.moneySpeed.title: § page.team.total.moneySpeed.title: в месяц
§ page.team.total.moneySpeed.description: 세금 § page.team.total.moneySpeed.description: Прогнозируемая сумма выплаты на зп при текущем составе сотрудников без учета налогов и сопутствующих затрат
§ page.team.total.description1: * * . , ,3 3 . § page.team.total.description1: *Человеко-дни* это работа одного сотрудника в течение одного рабочего дня. Например, за один календарный день, команда из трех сотрудников выдает объем работы в три человеко-дня.
§ page.team.total.description2: * * . , . § page.team.total.description2: *Днями прогулов* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют.
§ page.team.total.description3: 카드* * . "조수" . . § page.team.total.description3: Карточка *работает и уволилось* показывает фактический состав сотрудников, которые постоянно участвуют в работе. Кроме этого, есть «помощники» это сотрудники, как правило другой специализации, которые могут иногда делать коммиты в проект.
§ page.team.total.description4: * * . , . + != , . § page.team.total.description4: *Переплатой* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют. Именно поэтому переплата + фактическая стоимость != общей. В общей стоимости заложена оплата выходных, государственных праздников и отпусков.
§ page.team.total.description5: * * 2 . (1 ). . . § page.team.total.description5: *Работой на выходных* считается по коэффициенту х2 от оплаты обычного дня. Выше отображена именно переплата (х1), т.к. сам факт переработки в данном контексте не интересен. Мы не смотрим скорость сжигания бюджета. Мы смотрим переплату при увеличении скорости работы.
§ page.team.tree.title: 선택한 § page.team.tree.title: Дерево проекта с учётом выбранных фильтров
§ page.team.tree.filters.author: 직원 § page.team.tree.filters.author: Сотрудник
§ page.team.tree.filters.commits: 커밋 § page.team.tree.filters.commits: Количество коммитов
§ page.team.tree.filters.help: 직원이 § page.team.tree.filters.help: Минимальное количество коммитов, которое сделал сотрудник в файле
§ page.team.tree.filters.all: 모든 § page.team.tree.filters.all: Все сотрудники
§ page.team.tree.totalLines: 라인 § page.team.tree.totalLines: Строк
§ page.team.tree.totalTasks: 작업 § page.team.tree.totalTasks: Задач
§ page.team.tree.totalDays: § page.team.tree.totalDays: Дней
§ page.team.tree.tasks: 작업 § page.team.tree.tasks: задач
§ page.team.tree.days: § page.team.tree.days: дней
§ page.team.tree.add: 누가 § page.team.tree.add: Кто добавлял
§ page.team.tree.change: 누가 § page.team.tree.change: Кто менял
§ page.team.tree.remove: 누가 § page.team.tree.remove: Кто удалял
§ page.team.tree.line: 라인 § page.team.tree.line: строк
§ page.team.tree.linesAdded: 추가 § page.team.tree.linesAdded: добавили
§ page.team.tree.linesChanged: 변경 § page.team.tree.linesChanged: изменили
§ page.team.tree.linesRemoved: 삭제 § page.team.tree.linesRemoved: удалили
§ page.team.company.title: 세부 § page.team.company.title: Детализация
§ page.team.company.employments.title: 숫자로 § page.team.company.employments.title: По количеству сотрудников
§ page.team.company.employments.item: 직원의 § page.team.company.employments.item: сотрудников
§ page.team.company.daysChart.title: 기간에 § page.team.company.daysChart.title: По длительности контракта
§ page.team.company.daysChart.item: 회사의 § page.team.company.daysChart.item: компаний
§ page.team.company.active.yes: , § page.team.company.active.yes: активна
§ page.team.company.active.no: 계약이 . § page.team.company.active.no: контракт истёк
§ page.team.country.byTimezone: 마지막 § page.team.country.byTimezone: По времени последнего коммита
§ page.team.country.filters.active: 그들은 § page.team.country.filters.active: Работают
§ page.team.country.filters.dismissed: 해고 § page.team.country.filters.dismissed: Уволенные
§ page.team.country.filters.staff: 보조원 § page.team.country.filters.staff: Помощники
§ page.team.country.pieByDomain.title: 우편, § page.team.country.pieByDomain.title: По почте, времени и языку
§ page.team.country.pieByTimezone.title: § page.team.country.pieByTimezone.title: По времени
§ page.team.country.chart.item: 직원 § page.team.country.chart.item: сотрудников
§ page.team.country.table.title: 직원 § page.team.country.table.title: Список сотрудников
§ page.team.country.table.country: 위치 § page.team.country.table.country: Локация
§ page.team.country.table.employments: 직원 § page.team.country.table.employments: Сотрудники
§ page.team.country.travel.title: 비즈니스 ( ) § page.team.country.travel.title: Командировки (или VPN, или rebase)
§ page.team.country.travel.author: 직원 § page.team.country.travel.author: Сотрудник
§ page.team.country.travel.fly: 항공편 § page.team.country.travel.fly: Количество перелётов
§ page.team.country.travel.path: 위치 § page.team.country.travel.path: Список локаций
§ page.team.country.travel.date: 비행 § page.team.country.travel.date: Дата перлёта
§ page.team.country.travel.country: 위치 § page.team.country.travel.country: Локация
§ page.team.refactor.title: 리팩토링 § page.team.refactor.title: Кандидаты на рефакторинг
§ page.team.refactor.lines: § page.team.refactor.lines: строк § page.team.refactor.lines: строк
§ page.team.refactor.tasks: 작업 § page.team.refactor.tasks: задач
§ page.team.refactor.days: § page.team.refactor.days: дней
§ page.team.refactor.path: 방법 § page.team.refactor.path: Путь
§ page.team.refactor.firstCommit: § page.team.refactor.firstCommit: Первый коммит
§ page.team.refactor.totalLines: 라인 § page.team.refactor.totalLines: Строк
§ page.team.refactor.totalTasks: 작업 § page.team.refactor.totalTasks: Задач
§ page.team.refactor.totalDays: 개발 § page.team.refactor.totalDays: Дней в разработке
§ page.team.day.commits: 커밋 § page.team.day.commits: Коммиты
§ page.team.day.activity: 활동 § page.team.day.activity: Активность
§ page.team.week.title: 주별 § page.team.week.title: Статистика по неделям
§ page.team.week.date: 날짜 § page.team.week.date: Дата
§ page.team.week.numberTasks: 작업 § page.team.week.numberTasks: Количество задач
§ page.team.week.people: 사람 § page.team.week.people: Количество человек
§ page.team.week.line: 라인 § page.team.week.line: Изменение строк
§ page.team.week.days: 커밋이 § page.team.week.days: Дни с коммитами и без
§ page.team.week.lossesDetails: 커밋하지 § page.team.week.lossesDetails: Кто не коммитил
§ page.team.week.add: 추가 § page.team.week.add: добавили
§ page.team.week.change: 변경 § page.team.week.change: изменили
§ page.team.week.remove: 삭제 § page.team.week.remove: удалили
§ page.team.week.hasCommits: 커밋이 § page.team.week.hasCommits: были коммиты
§ page.team.week.hasNotCommits: , § page.team.week.hasNotCommits: небыло коммитов
§ page.team.week.days: § page.team.week.days: дней
§ page.team.week.tasks: 작업 § page.team.week.tasks: задач
§ page.team.pr.task: 작업 § page.team.pr.task: Задача
§ page.team.pr.tasks: 작업 § page.team.pr.tasks: задач
§ page.team.pr.firstCommitTime: § page.team.pr.firstCommitTime: Первый коммит
§ page.team.pr.lastCommitTime: 마지막 § page.team.pr.lastCommitTime: Последний
§ page.team.pr.workDays: 작업 § page.team.pr.workDays: Среднее время работы над задачей
§ page.team.pr.delayDays: 평균 § page.team.pr.delayDays: Среднее время ревью PR
§ page.team.pr.all.workDays: 작업 § page.team.pr.all.workDays: Время работы над задачей
§ page.team.pr.all.delayDays: 홍보 § page.team.pr.all.delayDays: Время ревью PR
§ page.team.pr.middleTimeRelease: 검토 § page.team.pr.middleTimeRelease: Отношение времени разработки к времени ревью
§ page.team.pr.chart.1day: 시간은 § page.team.pr.chart.1day: день
§ page.team.pr.chart.3day: 3 § page.team.pr.chart.3day: три дня
§ page.team.pr.chart.7day: § page.team.pr.chart.7day: неделя
§ page.team.pr.chart.14day: 2 § page.team.pr.chart.14day: две недели
§ page.team.pr.chart.30day: § page.team.pr.chart.30day: месяц
§ page.team.pr.chart.more: § page.team.pr.chart.more: более
§ page.team.pr.date: 주입 § page.team.pr.date: Дата влития
§ page.team.pr.mergeAuthor: 나는 § page.team.pr.mergeAuthor: Влил
§ page.team.pr.author: 직원 § page.team.pr.author: Сотрудник
§ page.team.pr.work: 개발 § page.team.pr.work: разработка
§ page.team.pr.delay: 대기 § page.team.pr.delay: ожидание
§ page.team.pr.days: § page.team.pr.days: дней
§ page.team.pr.oneTaskDays: § page.team.pr.oneTaskDays: Время потраченное на одну задачу
§ page.team.pr.description1: * * . . . § page.team.pr.description1: *Время разработки* это разница времени от первого до последнего коммита по задаче. Не важно были перерывы в несколько дней между коммитами или нет. Сам факт какого-либо коммита увеличивает время.
§ page.team.pr.description2: * * . . § page.team.pr.description2: *Время ожидания* это время между последним коммитом и влитием кода. Оно показывает фактический простой в ожидании чего-либо.
§ page.team.pr.description3: * * ? , . , , . § page.team.pr.description3: *Зачем отображать время разработки* без разбивки на кодинг и код-ревью? Затем, чтобы показать бизнесу фактическое время поставки кода. Ожидание тестирования, замечания на ревью, проблемы DevOps и прочие несовершенства процесса, как раз уже заложены в этот срок.
§ page.team.pr.statByAuthors: 직원 § page.team.pr.statByAuthors: Статистика по сотрудникам
§ page.team.pr.longDelay: 주입에 § page.team.pr.longDelay: Длительное ожидание влития
§ page.team.pr.anonymous: 문제 § page.team.pr.anonymous: PR без номера задачи
§ page.team.pr.branch: 지점 § page.team.pr.branch: Ветка
§ page.team.tasks.task: 작업 § page.team.tasks.task: Задача
§ page.team.tasks.author: § page.team.tasks.author: Автор первого коммита
§ page.team.tasks.from: § page.team.tasks.from: Первый коммит
§ page.team.tasks.to: 마지막 § page.team.tasks.to: Последний коммит
§ page.team.tasks.daysInWork: § page.team.tasks.daysInWork: Дней в работе
§ page.team.tasks.comments: 댓글 § page.team.tasks.comments: Комментарии
§ page.team.extension.extension: 파일 § page.team.extension.extension: Расширения файлов
§ page.team.extension.type: 파일 § page.team.extension.type: Подтип файлов
§ page.team.extension.name: 유형 § page.team.extension.name: Тип
§ page.team.extension.path: 경로 § page.team.extension.path: Путь
§ page.team.extension.current.count: 수량 § page.team.extension.current.count: Количество
§ page.team.extension.removed.count: 삭제된 § page.team.extension.removed.count: Количество удалённых
§ page.team.extension.files: 파일 § page.team.extension.files: файлов
§ page.team.release.download: 다운로드 § page.team.release.download: Скачать
§ page.team.release.title: 릴리스 § page.team.release.title: Релиз
§ page.team.release.from: 생성 § page.team.release.from: Дата создания
§ page.team.release.to: 완료 § page.team.release.to: Дата завершения
§ page.team.release.prLength: 작업 § page.team.release.prLength: Задач
§ page.team.release.delay: 작업 § page.team.release.delay: Дней работы
§ page.team.release.waiting: 다음 § page.team.release.waiting: Дней до следующего релиза
§ page.person.print.photo.title: 사진 § page.team.department.employments.title: The size of the current teams
§ page.person.print.photo.description: 사진 § page.team.department.employments.item: of teams
§ page.person.total.title: 주요 § page.team.author.employments.less1: is one employee
§ page.person.total.daysWorked.title: 작업 § page.team.author.employments.less2: two employees
§ page.person.total.daysWorked.description: § page.team.author.employments.less3: three employees
§ page.person.total.tasks.title: 고려되었다 § page.team.author.employments.less6: up to six employees
§ page.person.total.tasks.description: 커밋이 § page.team.author.employments.less9: up to nine employees
§ page.person.scoring.toolbar: , . . . § page.team.author.employments.less12: up to 12 employees
§ page.person.character.title: 캐릭터 § page.team.author.employments.less15: up to 15 employees
§ page.person.achievement.title: 진행 § page.team.author.employments.more: more than 15
§ page.person.achievement.positive: 긍정적 § page.team.department.daysChart.title: Duration of the project
§ page.person.achievement.normal: 중립 § page.team.department.daysChart.item: projects
§ page.person.achievement.negative: 부정 § page.team.department.title: List of projects
§ page.person.achievement.description: 직원이 . , . . § page.team.department.code: Code
§ page.person.gets.title: 작업 : § page.team.department.from: The first commit
§ page.person.gets.description: 메달은 "아름다운" . § page.team.department.to: The last
§ page.person.business.days.title: 작업 § page.team.department.authors: man
§ page.person.business.days.description: § page.team.department.tasks: of the tasks
§ page.person.business.tasks.title: 고려되었다 § page.team.department.totalDays: Working days
§ page.person.business.tasks.description: 커밋이 § page.team.department.totalAuthors: Number of employees
§ page.person.business.losses.title: , § page.person.print.photo.title: Фотография
§ page.person.business.losses.description: 모든 빼기:휴일,,, § page.person.print.photo.description: место для фотографии
§ page.person.business.commits.title: 커밋 § page.person.total.title: Основные характеристики
§ page.person.business.commits.description: 삭제된 § page.person.total.daysWorked.title: дней работы
§ page.person.business.time.description: ( ) § page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
§ page.person.business.time.title: 프로젝트 : § page.person.total.tasks.title: задач
§ page.person.business.time.dismissed: () § page.person.total.tasks.description: Если коммиты правильно подписаны
§ page.person.business.time.staff: () § page.person.scoring.toolbar: Позиция по этой метрике, относительно других. Два сотрудника могут занять одно место, если значение совпало. Поэтому, общее число мест может быть меньше, чем количество сотрудников.
§ page.person.business.achievements: 업적 § page.person.character.title: Персонаж
§ page.person.changes.title: 진행 § page.person.achievement.title: Достижения
§ page.person.changes.description: § page.person.achievement.positive: Позитивные
"삭제됨""추가됨" ., § page.person.achievement.normal: Нейтральные
"변경". , § page.person.achievement.negative: Негативные
, § page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
"삭제됨""추가됨" . § page.person.gets.title: Медали за номера задач:
§ page.person.changes.description: : § page.person.gets.description: Медаль выдается, если пользователь первым оставляет коммит к задаче с «красивым» номером.
§ page.person.commits.title: 커밋 : § page.person.business.days.title: дней работы
§ page.person.money.title.total: 모든 § page.person.business.days.description: Учтены только дни, в которые делались коммиты
§ page.person.money.title.middle: 평균 § page.person.business.tasks.title: задач
§ page.person.money.moneyAll.title: 수신 § page.person.business.tasks.description: Если коммиты правильно подписаны
§ page.person.money.moneyAll.description: 프로젝트에서 ( ) § page.person.business.losses.title: дней без коммитов
§ page.person.money.moneyWorked.title: 밖으로 § page.person.business.losses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
§ page.person.money.moneyWorked.description: 실제 § page.person.business.commits.title: коммитов
§ page.person.money.moneyLosses.title: 가능한 § page.person.business.commits.description: Удалённые ветки не считаются
§ page.person.money.moneyLosses.description: 커밋이 § page.person.business.time.description: Время от первого, до последнего коммита (в том числе, нерабочие дни)
§ page.person.money.tasks.title: 작업 § page.person.business.time.title: Дней на проекте:
§ page.person.money.tasks.description: 비용에 § page.person.business.time.dismissed: (уволен)
§ page.person.money.commits.title: 약속의 § page.person.business.time.staff: (помощник)
§ page.person.money.commits.description: 작업 § page.person.business.achievements: Достижения
§ page.person.speed.task: 평균적으로 § page.person.changes.title: Достижения
§ page.person.speed.max: 하루 § page.person.changes.description:
§ page.person.speed.days.title: При некоторых видах форматирования git отмечает строки как «удалённые» и «добавленные»,
§ page.person.speed.days.description: 이는 . хотя на самом деле они были «изменены». Поэтому, если вы провели большой рефакторинг,
§ page.person.speed.commits.title: 커밋 git может показать малое количество изменений в статистике, а фактический результат
§ page.person.speed.commits.description: 최대 10% будет отмечен, как скачок «удаленных» и «добавленных» строк.
§ page.person.speed.line.title: 코드 § page.person.changes.description: Список коммитов и количество изменений в них за этот день:
§ page.person.speed.line.description: 최대 10% § page.person.changes.description: Список коммитов:
§ page.person.speed.tasks.title: 작업 § page.person.commits.title: За всё время
§ page.person.speed.tasks.description: 작업이 § page.person.money.title.total: Средняя стоимость
§ page.person.speed.maxCommits.title: 커밋 § page.person.money.title.middle: получил
§ page.person.speed.maxCommits.description: 작업이 § page.person.money.moneyAll.title: Предполагаемая сумма зп с проекта (см. настройки)
§ page.person.hours.title: § page.person.money.moneyAll.description: отработал
§ page.person.week.date: 날짜 § page.person.money.moneyWorked.title: Фактически отработанные дни умноженные на среднюю зп
§ page.person.week.tasks: 작업 § page.person.money.moneyWorked.description: возможная переплата
§ page.person.week.workDays: 커밋이 § page.person.money.moneyLosses.title: Дни без коммитов умноженные на среднюю зп
§ page.person.week.taskInDay: 일일 § page.person.money.moneyLosses.description: задача
§ page.person.week.days: § page.person.money.tasks.title: Количество закрытых задач к стоимости дня
§ page.person.week.workDay: 평일 § page.person.money.tasks.description: коммит
§ page.person.week.weekends: 주말 § page.person.money.commits.title: Количество коммитов к стоимости рабочего дня
§ page.sponsor.title: 프로젝트 § page.person.money.commits.description: Одна задача в среднем это
§ page.sponsor.share.description: 소셜 [|<url>//] ! , , , , , , , , , , , , , , , , , § page.person.speed.task: Максимальная скорость в день
§ page.sponsor.share.button: 링크 § page.person.speed.max: дней
§ page.sponsor.money.description: 당신이 ! . § page.person.speed.days.title: Имеются ввиду рабочие дни, если коммиты правильно подписаны
§ page.sponsor.money.qr: 1 § page.person.speed.days.description: коммитов
§ page.sponsor.money.github: § page.person.speed.commits.title: Отрезаны 10% максимальных и минимальных значений
§ page.person.speed.commits.description: строк кода
§ page.person.speed.line.title: Отрезаны 10% максимальных и минимальных значений
§ page.person.speed.line.description: задач
§ page.person.speed.tasks.title: Задача может быть не доделана, но работа по ней должна быть
§ page.person.speed.tasks.description: коммитов
§ page.person.speed.maxCommits.title: Задача может быть не доделана, но работа по ней должна быть
§ page.person.speed.maxCommits.description: Распределение коммитов в течении каждого дня недели
§ page.person.hours.title: Дата
§ page.person.week.date: Количество задач
§ page.person.week.tasks: Дни с коммитами
§ page.person.week.workDays: Задач в день
§ page.person.week.taskInDay: дней
§ page.person.week.days: будни
§ page.person.week.workDay: выходные
§ page.person.week.weekends: Поддержите проект
§ page.sponsor.title: Расскажите о нашем [проекте|https://github.com/bakhirev/assayo] в соцсетях! Можно поделиться [статьей|https://habr.com/ru/articles/763342/], [постом|https://www.reddit.com/r/ITManagers/comments/1e5k291/the_visualization_and_analysis_of_git_commit/] или [видео|https://www.youtube.com/watch?v=jwCp_-bhrCQ].
§ page.sponsor.share.description: Копировать ссылку
§ page.sponsor.share.button: Мы будем рады, если вы поддержите нас любой суммой! Все средства пойдут на дальнейшее развитие проекта.
§ page.sponsor.money.description: Разовый платёж (СБП)
§ page.sponsor.money.qr: Подписка GitHub Sponsor
`; `;

View file

@ -30,6 +30,7 @@
Викторина Викторина
Рефакторинг Рефакторинг
Компании Компании
Отделы
Местоположение Местоположение
Настройки Настройки
Общая информация Общая информация

View file

@ -27,7 +27,7 @@ $1 сделано коммитов: $2
год год
полтора полтора
два года два года
больше больше двух лет
Детализация Детализация
*Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы. *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
*Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники). *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
@ -219,6 +219,26 @@ PR без номера задачи
Задач Задач
Дней работы Дней работы
Дней до следующего релиза Дней до следующего релиза
Размер текущих команд
команд
один сотрудник
два сотрудника
три сотрудника
до шести сотрудников
до девяти сотрудников
до 12 сотрудников
до 15 сотрудников
больше 15
Продолжительность проектов
проекта
Список проектов
Код
Первый коммит
Последний
человек
задач
Дней работы
Количество сотрудников
Фотография Фотография
место для фотографии место для фотографии
Основные характеристики Основные характеристики

View file

@ -31,6 +31,7 @@ export default `
§ sidebar.team.building: 测验 § sidebar.team.building: 测验
§ sidebar.team.refactor: Refactoring § sidebar.team.refactor: Refactoring
§ sidebar.team.company: Companies § sidebar.team.company: Companies
§ sidebar.team.department: Departments
§ sidebar.team.country: Locations § sidebar.team.country: Locations
§ sidebar.team.settings: 设置 § sidebar.team.settings: 设置
§ sidebar.person.total: 般资料 § sidebar.person.total: 般资料

View file

@ -27,7 +27,7 @@ export default `
§ page.team.author.days.one: year § page.team.author.days.one: year
§ page.team.author.days.15: year and a half § page.team.author.days.15: year and a half
§ page.team.author.days.two: two years § page.team.author.days.two: two years
§ page.team.author.days.more: more § page.team.author.days.more: more than two years
§ page.team.author.title: Details § page.team.author.title: Details
§ page.team.author.description1: 部分统计数字 (.) "助理" . § page.team.author.description1: 部分统计数字 (.) "助理" .
§ page.team.author.description2: 默认排序是按任务和组数排序 (). § page.team.author.description2: 默认排序是按任务和组数排序 ().
@ -214,6 +214,26 @@ export default `
§ page.team.release.prLength: Tasks § page.team.release.prLength: Tasks
§ page.team.release.delay: Preparation days § page.team.release.delay: Preparation days
§ page.team.release.waiting: Days of waiting for next release § page.team.release.waiting: Days of waiting for next release
§ page.team.department.employments.title: The size of the current teams
§ page.team.department.employments.item: of teams
§ page.team.author.employments.less1: one employee
§ page.team.author.employments.less2: two employees
§ page.team.author.employments.less3: three employees
§ page.team.author.employments.less6: up to six employees
§ page.team.author.employments.less9: up to nine employees
§ page.team.author.employments.less12: up to 12 employees
§ page.team.author.employments.less15: up to 15 employees
§ page.team.author.employments.more: more than 15
§ page.team.department.daysChart.title: Duration of the project
§ page.team.department.daysChart.item: projects
§ page.team.department.title: List of projects
§ page.team.department.code: Code
§ page.team.department.from: First commit
§ page.team.department.to: Last
§ page.team.department.authors: employees
§ page.team.department.tasks: tasks
§ page.team.department.totalDays: Working days
§ page.team.department.totalAuthors: Number of employees
§ page.person.print.photo.title: 照片 § page.person.print.photo.title: 照片
§ page.person.print.photo.description: 拍照的地方 § page.person.print.photo.description: 拍照的地方
§ page.person.total.title: 主要特点 § page.person.total.title: 主要特点