mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
JIRA-1234 fix(doc): some some
This commit is contained in:
parent
127d978b31
commit
c456f5c43e
16
README.md
16
README.md
|
@ -82,6 +82,16 @@ Git создаст файл `log.txt`.
|
||||||
- См. «Как посмотреть отчёт онлайн?». На последнем шаге перетащить сразу все файлы в окно браузера.
|
- См. «Как посмотреть отчёт онлайн?». На последнем шаге перетащить сразу все файлы в окно браузера.
|
||||||
- См. «Как посмотреть отчёт офлайн?». На втором шаге перетащить все файлы микросервисов (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.) в папку отчета (`/build`).
|
- См. «Как посмотреть отчёт офлайн?». На втором шаге перетащить все файлы микросервисов (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.) в папку отчета (`/build`).
|
||||||
|
|
||||||
|
### Как брендировать интерфейс?
|
||||||
|
Вы можете написать свою тему для интерфейса. Можно менять:
|
||||||
|
- **Заголовок**. Вы можете указать его в URL-параметре ```title```. Например: ```?title=You Company```
|
||||||
|
- **Визуальную тему**. Для этого нужно подготовить CSS файл с новыми стилями и указать его адрес в URL-параметре ```theme```. Например: ```?theme=//company.com/some.css```. Вы можете использовать имена классов в качестве селекторов. Большинство из них не меняется в при выходе новой версий.
|
||||||
|
- **Язык**. Вы можете указать его в URL-параметре ```lang```. Например: ```?lang=es```
|
||||||
|
|
||||||
|
### Как добавить или отредактировать перевод?
|
||||||
|
|
||||||
|
Вы можете добавить новый перевод или поправить текущий в разделе ```ts/translations/``` и создать Pull Request.
|
||||||
|
|
||||||
### Как подписывать коммиты?
|
### Как подписывать коммиты?
|
||||||
|
|
||||||
Следуйте практике [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Например:
|
Следуйте практике [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Например:
|
||||||
|
@ -93,7 +103,7 @@ JIRA-1234 feat(profile): Added avatar for user
|
||||||
- фича `(profile - раздел сайта, страница или новый функционал, одним словом)`
|
- фича `(profile - раздел сайта, страница или новый функционал, одним словом)`
|
||||||
- какую проблему решали `(Added avatar for user)`
|
- какую проблему решали `(Added avatar for user)`
|
||||||
|
|
||||||
### Как автоматизировать сбор данных
|
### Как автоматизировать сбор данных?
|
||||||
|
|
||||||
#### Без бекенда
|
#### Без бекенда
|
||||||
- создайте клон нужного вам репозитория;
|
- создайте клон нужного вам репозитория;
|
||||||
|
@ -122,6 +132,7 @@ assayo_url - URL адресс контейнера assayo, он слушает 8
|
||||||
you_url - URL адресс вашего контейнера с логами git;
|
you_url - URL адресс вашего контейнера с логами git;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
По умолчанию образ запустится по адресу ```http://127.0.0.1:80/```. Если не получилось проверьте свободен ли у вас 80 порт.
|
||||||
#### Обновление Docker-образа
|
#### Обновление Docker-образа
|
||||||
|
|
||||||
- удилить метрику, аллерты, старые билды;
|
- удилить метрику, аллерты, старые билды;
|
||||||
|
@ -136,11 +147,12 @@ you_url - URL адресс вашего контейнера с логами
|
||||||
- больше советов и достижений;
|
- больше советов и достижений;
|
||||||
- итоги года / месяца, печать отчётов;
|
- итоги года / месяца, печать отчётов;
|
||||||
- локализация и интернационализация;
|
- локализация и интернационализация;
|
||||||
|
- анализ файлов;
|
||||||
- разные роли для статистики (скрытие финансов);
|
- разные роли для статистики (скрытие финансов);
|
||||||
- разработка бекенда, интеграции с другими системами;
|
- разработка бекенда, интеграции с другими системами;
|
||||||
|
|
||||||
### Пожелания, предложения, замечания
|
### Пожелания, предложения, замечания
|
||||||
|
- telegramm [@bakhirev](https://t.me/bakhirev) (приоритетный способ связи)
|
||||||
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
|
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
|
||||||
- telegramm [@bakhirev](https://t.me/bakhirev)
|
|
||||||
- сайт [https://assayo.jp/](https://assayo.jp/)
|
- сайт [https://assayo.jp/](https://assayo.jp/)
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
{
|
{
|
||||||
"files": {
|
"files": {
|
||||||
"main.css": "./static/css/main.bd89a1c5.css",
|
"main.css": "./static/css/main.3c6bf65a.css",
|
||||||
"main.js": "./static/js/main.b114e843.js",
|
"main.js": "./static/js/main.7746635d.js",
|
||||||
"static/media/car.png": "./static/media/car.b8dd8738e37fe866285f.png",
|
"static/media/car.png": "./static/media/car.b8dd8738e37fe866285f.png",
|
||||||
"index.html": "./index.html",
|
"index.html": "./index.html",
|
||||||
"static/media/warning.svg": "./static/media/warning.e39a87773603f3ab157f.svg",
|
"static/media/warning.svg": "./static/media/warning.e39a87773603f3ab157f.svg",
|
||||||
"static/media/info.svg": "./static/media/info.954631f6b19e3fe9c495.svg",
|
"static/media/info.svg": "./static/media/info.954631f6b19e3fe9c495.svg",
|
||||||
"static/media/alert.svg": "./static/media/alert.41e2b99c481139c13074.svg",
|
"static/media/alert.svg": "./static/media/alert.41e2b99c481139c13074.svg",
|
||||||
"main.bd89a1c5.css.map": "./static/css/main.bd89a1c5.css.map",
|
"main.3c6bf65a.css.map": "./static/css/main.3c6bf65a.css.map",
|
||||||
"main.b114e843.js.map": "./static/js/main.b114e843.js.map"
|
"main.7746635d.js.map": "./static/js/main.7746635d.js.map"
|
||||||
},
|
},
|
||||||
"entrypoints": [
|
"entrypoints": [
|
||||||
"static/css/main.bd89a1c5.css",
|
"static/css/main.3c6bf65a.css",
|
||||||
"static/js/main.b114e843.js"
|
"static/js/main.7746635d.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"></path>
|
<path d="M19 5v2h-4V5h4M9 5v6H5V5h4m10 8v6h-4v-6h4M9 17v2H5v-2h4M21 3h-8v6h8V3zM11 3H3v10h8V3zm10 8h-8v10h8V11zm-10 4H3v6h8v-6z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 225 B |
3
build/assets/icons/Download.svg
Normal file
3
build/assets/icons/Download.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M18 15v3H6v-3H4v3c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-3h-2zm-1-4-1.41-1.41L13 12.17V4h-2v8.17L8.41 9.59 7 11l5 5 5-5z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 221 B |
|
@ -1,3 +1,3 @@
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M20 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 2v3H5V5h15zm-5 14h-5v-9h5v9zM5 10h3v9H5v-9zm12 9v-9h3v9h-3z"></path>
|
<path d="M20 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 2v3H5V5h15zm-5 14h-5v-9h5v9zM5 10h3v9H5v-9zm12 9v-9h3v9h-3z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 245 B |
16
build/assets/vds.css
Normal file
16
build/assets/vds.css
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
body {
|
||||||
|
--vds-color--main: #00AFD0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title,
|
||||||
|
.header_title,
|
||||||
|
.card_with_icon_value,
|
||||||
|
.card_with_icon_title,
|
||||||
|
.welcome_first_title,
|
||||||
|
.welcome_last_title {
|
||||||
|
/*color: var(--vds-color--main);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
<!doctype html><html lang="ru"><head><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no,maximum-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="cleartype" content="on"><meta name="HandheldFriendly" content="True"><meta name="format-detection" content="telephone=no"><meta name="format-detection" content="address=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script type="text/javascript">var report=[]</script><script src="/log.txt"></script><script src="./log.txt"></script><script src="../log.txt"></script><script src="./log-0.txt"></script><script src="./log-1.txt"></script><script src="./log-2.txt"></script><script src="./log-3.txt"></script><script src="./log-4.txt"></script><script src="./log-5.txt"></script><script src="./log-6.txt"></script><script src="./report/log-0.txt"></script><script src="./report/log-1.txt"></script><script src="./report/log-2.txt"></script><script src="./report/log-3.txt"></script><script src="./report/log-4.txt"></script><script src="./report/log-5.txt"></script><script src="./report/log-6.txt"></script><link rel="icon" href="./favicon.svg"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>Git статистика</title><meta name="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="keywords" content="git, статистика, аудит, история, log, мониторинг, контроль сотрудников"><meta name="author" content="Bakhirev Aleksei"><meta name="copyright" content="(c) Bakhirev Aleksei"><meta http-equiv="Reply-to" content="alexey-bakhirev@yandex.ru"><meta name="application-name" content="GIT Статистика"><meta name="msapplication-tooltip" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:title" content="GIT Статистика"><meta property="og:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="http://assayo.jp/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="GIT Статистика"><meta name="twitter:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="twitter:creator" content="Bakhirev Aleksei"><meta name="twitter:image:src" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.jp"><meta name="twitter:site" content="assayo.jp"><meta itemprop="name" content="GIT Статистика"><meta itemprop="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.b114e843.js"></script><link href="./static/css/main.bd89a1c5.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
<!doctype html><html lang="ru"><head><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no,maximum-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="cleartype" content="on"><meta name="HandheldFriendly" content="True"><meta name="format-detection" content="telephone=no"><meta name="format-detection" content="address=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script type="text/javascript">var report=[]</script><script src="/log.txt"></script><script src="./log.txt"></script><script src="../log.txt"></script><script src="./log-0.txt"></script><script src="./log-1.txt"></script><script src="./log-2.txt"></script><script src="./log-3.txt"></script><script src="./log-4.txt"></script><script src="./log-5.txt"></script><script src="./log-6.txt"></script><script src="./report/log-0.txt"></script><script src="./report/log-1.txt"></script><script src="./report/log-2.txt"></script><script src="./report/log-3.txt"></script><script src="./report/log-4.txt"></script><script src="./report/log-5.txt"></script><script src="./report/log-6.txt"></script><link rel="icon" href="./favicon.svg"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>Git статистика</title><meta name="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="keywords" content="git, статистика, аудит, история, log, мониторинг, контроль сотрудников"><meta name="author" content="Bakhirev Aleksei"><meta name="copyright" content="(c) Bakhirev Aleksei"><meta http-equiv="Reply-to" content="alexey-bakhirev@yandex.ru"><meta name="application-name" content="GIT Статистика"><meta name="msapplication-tooltip" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:title" content="GIT Статистика"><meta property="og:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="http://assayo.jp/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="GIT Статистика"><meta name="twitter:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="twitter:creator" content="Bakhirev Aleksei"><meta name="twitter:image:src" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.jp"><meta name="twitter:site" content="assayo.jp"><meta itemprop="name" content="GIT Статистика"><meta itemprop="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.7746635d.js"></script><link href="./static/css/main.3c6bf65a.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
2
build/static/css/main.3c6bf65a.css
Normal file
2
build/static/css/main.3c6bf65a.css
Normal file
File diff suppressed because one or more lines are too long
1
build/static/css/main.3c6bf65a.css.map
Normal file
1
build/static/css/main.3c6bf65a.css.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
build/static/js/main.7746635d.js
Normal file
3
build/static/js/main.7746635d.js
Normal file
File diff suppressed because one or more lines are too long
1
build/static/js/main.7746635d.js.map
Normal file
1
build/static/js/main.7746635d.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18
config-overrides.js
Normal file
18
config-overrides.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module.exports = {
|
||||||
|
webpack: (config) => {
|
||||||
|
|
||||||
|
|
||||||
|
const oneOfs = config.module.rules.find((rule) => !!rule.oneOf).oneOf;
|
||||||
|
for (const oneOf of oneOfs) {
|
||||||
|
oneOf?.use?.forEach((someUse) => {
|
||||||
|
if (!someUse?.options?.modules?.mode) return;
|
||||||
|
// someUse.options.modules.localIdentName = '[local]_';
|
||||||
|
someUse.options.modules.getLocalIdent = (context, localIdentName, localName, options) => {
|
||||||
|
return localName;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
};
|
176
package-lock.json
generated
176
package-lock.json
generated
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "my",
|
"name": "Assayo",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "my",
|
"name": "Assayo",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
|
@ -34,6 +34,8 @@
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-react": "^7.32.1",
|
"eslint-plugin-react": "^7.32.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"react-app-rewire-typings-for-css-module": "^4.0.3",
|
||||||
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-testing-library": "^8.0.1",
|
"react-testing-library": "^8.0.1",
|
||||||
"stylelint": "^14.16.1",
|
"stylelint": "^14.16.1",
|
||||||
"stylelint-group-selectors": "^1.0.9",
|
"stylelint-group-selectors": "^1.0.9",
|
||||||
|
@ -6304,6 +6306,45 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-modules-typescript-loader": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-modules-typescript-loader/-/css-modules-typescript-loader-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-vXrUAwPGcRaopnGdg7I5oqv/NSSKQRN5L80m3f49uSGinenU5DTNsMFHS+2roh5tXqpY5+yAAKAl7A2HDvumzg==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"line-diff": "^2.0.1",
|
||||||
|
"loader-utils": "^1.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-modules-typescript-loader/node_modules/json5": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"json5": "lib/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-modules-typescript-loader/node_modules/loader-utils": {
|
||||||
|
"version": "1.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
|
||||||
|
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css-prefers-color-scheme": {
|
"node_modules/css-prefers-color-scheme": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
|
||||||
|
@ -12031,6 +12072,13 @@
|
||||||
"language-subtag-registry": "~0.3.2"
|
"language-subtag-registry": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/levdist": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/levdist/-/levdist-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-YguwC2spb0pqpJM3a5OsBhih/GG2ZHoaSHnmBqhEI7997a36buhqcRTegEjozHxyxByIwLpZHZTVYMThq+Zd3g==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
|
@ -12059,6 +12107,16 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/line-diff": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/line-diff/-/line-diff-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-vswdynAI5AMPJacOo2o+JJ4caDJbnY2NEqms4MhMW0NJbjh3skP/brpVTAgBxrg55NRZ2Vtw88ef18hnagIpYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"levdist": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lines-and-columns": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
|
@ -14688,6 +14746,42 @@
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-app-rewire-typings-for-css-module": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-app-rewire-typings-for-css-module/-/react-app-rewire-typings-for-css-module-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-8Y1K07iLGilhRnSraPAKGgIs2PpZj9gjuBDATuIUqJZ8AL1ZXthoMFJXh8TcHzlmrNCqiUnv7kXRvRAgH5pn4w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"deepmerge": "^4.2.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"css-modules-typescript-loader": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-app-rewired": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^5.6.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"react-app-rewired": "bin/index.js"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react-scripts": ">=2.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-app-rewired/node_modules/semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dev-utils": {
|
"node_modules/react-dev-utils": {
|
||||||
"version": "12.0.1",
|
"version": "12.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
||||||
|
@ -22624,6 +22718,41 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"css-modules-typescript-loader": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-modules-typescript-loader/-/css-modules-typescript-loader-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-vXrUAwPGcRaopnGdg7I5oqv/NSSKQRN5L80m3f49uSGinenU5DTNsMFHS+2roh5tXqpY5+yAAKAl7A2HDvumzg==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"line-diff": "^2.0.1",
|
||||||
|
"loader-utils": "^1.2.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"json5": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"minimist": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"loader-utils": {
|
||||||
|
"version": "1.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
|
||||||
|
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"css-prefers-color-scheme": {
|
"css-prefers-color-scheme": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
|
||||||
|
@ -26788,6 +26917,13 @@
|
||||||
"language-subtag-registry": "~0.3.2"
|
"language-subtag-registry": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"levdist": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/levdist/-/levdist-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-YguwC2spb0pqpJM3a5OsBhih/GG2ZHoaSHnmBqhEI7997a36buhqcRTegEjozHxyxByIwLpZHZTVYMThq+Zd3g==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"leven": {
|
"leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
|
@ -26807,6 +26943,16 @@
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
|
||||||
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg=="
|
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg=="
|
||||||
},
|
},
|
||||||
|
"line-diff": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/line-diff/-/line-diff-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-vswdynAI5AMPJacOo2o+JJ4caDJbnY2NEqms4MhMW0NJbjh3skP/brpVTAgBxrg55NRZ2Vtw88ef18hnagIpYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"peer": true,
|
||||||
|
"requires": {
|
||||||
|
"levdist": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lines-and-columns": {
|
"lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||||
|
@ -28516,6 +28662,32 @@
|
||||||
"whatwg-fetch": "^3.6.2"
|
"whatwg-fetch": "^3.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-app-rewire-typings-for-css-module": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-app-rewire-typings-for-css-module/-/react-app-rewire-typings-for-css-module-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-8Y1K07iLGilhRnSraPAKGgIs2PpZj9gjuBDATuIUqJZ8AL1ZXthoMFJXh8TcHzlmrNCqiUnv7kXRvRAgH5pn4w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"deepmerge": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-app-rewired": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"semver": "^5.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "5.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||||
|
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-dev-utils": {
|
"react-dev-utils": {
|
||||||
"version": "12.0.1",
|
"version": "12.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "set PORT=3006 && react-scripts start",
|
"dev": "set PORT=3006 && react-app-rewired start",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject",
|
||||||
|
@ -58,6 +58,8 @@
|
||||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
"eslint-plugin-react": "^7.32.1",
|
"eslint-plugin-react": "^7.32.1",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"react-app-rewire-typings-for-css-module": "^4.0.3",
|
||||||
|
"react-app-rewired": "^2.2.1",
|
||||||
"react-testing-library": "^8.0.1",
|
"react-testing-library": "^8.0.1",
|
||||||
"stylelint": "^14.16.1",
|
"stylelint": "^14.16.1",
|
||||||
"stylelint-group-selectors": "^1.0.9",
|
"stylelint-group-selectors": "^1.0.9",
|
||||||
|
|
3
public/assets/icons/Download.svg
Normal file
3
public/assets/icons/Download.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg viewBox="0 0 24 24" fill="#84858D" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M18 15v3H6v-3H4v3c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-3h-2zm-1-4-1.41-1.41L13 12.17V4h-2v8.17L8.41 9.59 7 11l5 5 5-5z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 221 B |
16
public/assets/vds.css
Normal file
16
public/assets/vds.css
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
body {
|
||||||
|
--vds-color--main: #00AFD0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title,
|
||||||
|
.header_title,
|
||||||
|
.card_with_icon_value,
|
||||||
|
.card_with_icon_title,
|
||||||
|
.welcome_first_title,
|
||||||
|
.welcome_last_title {
|
||||||
|
/*color: var(--vds-color--main);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
|
@ -2,12 +2,14 @@ import React from 'react';
|
||||||
import { HashRouter } from 'react-router-dom';
|
import { HashRouter } from 'react-router-dom';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
import ru from 'ts/config/translations/ru';
|
import localization from 'ts/helpers/Localization';
|
||||||
import en from 'ts/config/translations/en';
|
import ru from 'ts/translations/ru/index';
|
||||||
|
import en from 'ts/translations/en/index';
|
||||||
import Authorization from 'ts/pages/Authorization';
|
import Authorization from 'ts/pages/Authorization';
|
||||||
import userSettings from 'ts/store/UserSettings';
|
import userSettings from 'ts/store/UserSettings';
|
||||||
import Notifications from 'ts/components/Notifications';
|
import Notifications from 'ts/components/Notifications';
|
||||||
import printStore from 'ts/pages/PageWrapper/store/Print';
|
import printStore from 'ts/pages/PageWrapper/store/Print';
|
||||||
|
import applyUrlCommands from 'ts/helpers/RPC';
|
||||||
|
|
||||||
import './styles/index.scss';
|
import './styles/index.scss';
|
||||||
|
|
||||||
|
@ -19,15 +21,8 @@ if (module.hot) {
|
||||||
module.hot.accept();
|
module.hot.accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
localization.parse('ru', ru);
|
||||||
console.dir(ru + en + '');
|
localization.parse('en', en);
|
||||||
|
|
||||||
function getParametersFromString(text: string) {
|
|
||||||
return Object.fromEntries((text || '')
|
|
||||||
.substring(1, Infinity)
|
|
||||||
.split('&')
|
|
||||||
.map((token: string) => token.split('=')));
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderReactApplication() {
|
function renderReactApplication() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -46,24 +41,6 @@ function renderReactApplication() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadApplication() {
|
|
||||||
const parameters = {
|
|
||||||
...getParametersFromString(location.search),
|
|
||||||
...getParametersFromString(location.hash),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!parameters.dump) {
|
|
||||||
return renderReactApplication();
|
|
||||||
}
|
|
||||||
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.src = parameters.dump;
|
|
||||||
script.async = true;
|
|
||||||
script.onload = renderReactApplication;
|
|
||||||
script.onerror = renderReactApplication;
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
userSettings.loadUserSettings().then(() => {
|
userSettings.loadUserSettings().then(() => {
|
||||||
loadApplication();
|
applyUrlCommands(renderReactApplication);
|
||||||
});
|
});
|
||||||
|
|
|
@ -100,4 +100,30 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.card_with_icon,
|
||||||
|
.card_with_icon_long {
|
||||||
|
min-height: 220px;
|
||||||
|
padding: 16px 0;
|
||||||
|
|
||||||
|
&_icon {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_value {
|
||||||
|
font-size: 22px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_title {
|
||||||
|
font-size: var(--font-s);
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_description {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -10,12 +10,14 @@ interface ICardProps {
|
||||||
item: any;
|
item: any;
|
||||||
lines: IColumn[];
|
lines: IColumn[];
|
||||||
className?: string;
|
className?: string;
|
||||||
|
customStyle?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Card({
|
function Card({
|
||||||
item,
|
item,
|
||||||
lines,
|
lines,
|
||||||
className,
|
className,
|
||||||
|
customStyle,
|
||||||
}: ICardProps) {
|
}: ICardProps) {
|
||||||
const parts = lines.map((line: IColumn, columnIndex: number) => {
|
const parts = lines.map((line: IColumn, columnIndex: number) => {
|
||||||
const value = line.properties
|
const value = line.properties
|
||||||
|
@ -54,7 +56,10 @@ function Card({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${style.card} ${className}`}>
|
<div
|
||||||
|
className={`${style.card} ${className}`}
|
||||||
|
style={customStyle || {}}
|
||||||
|
>
|
||||||
{parts}
|
{parts}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { useLayoutEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { IColumn } from 'ts/components/Table/interfaces/Column';
|
import { IColumn } from 'ts/components/Table/interfaces/Column';
|
||||||
import getDefaultProps from 'ts/components/Table/helpers/getDefaultProps';
|
import getDefaultProps from 'ts/components/Table/helpers/getDefaultProps';
|
||||||
|
@ -9,6 +9,7 @@ import style from './styles/index.module.scss';
|
||||||
|
|
||||||
interface ICardsProps {
|
interface ICardsProps {
|
||||||
items: any[];
|
items: any[];
|
||||||
|
columnCount?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode | React.ReactNode[];
|
children: React.ReactNode | React.ReactNode[];
|
||||||
}
|
}
|
||||||
|
@ -16,24 +17,46 @@ interface ICardsProps {
|
||||||
function Cards({
|
function Cards({
|
||||||
items = [],
|
items = [],
|
||||||
className,
|
className,
|
||||||
|
columnCount,
|
||||||
children,
|
children,
|
||||||
}: ICardsProps): React.ReactElement | null {
|
}: ICardsProps): React.ReactElement | null {
|
||||||
|
const [cardNumber, setCardNumber] = useState<number>(columnCount || 4);
|
||||||
|
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
|
||||||
|
|
||||||
if (!items || !items.length) return null;
|
if (!items || !items.length) return null;
|
||||||
|
|
||||||
const configs = getDefaultProps(children) as IColumn[];
|
const configs = getDefaultProps(children) as IColumn[];
|
||||||
const lines = getCardConfigs(configs) as IColumn[];
|
const lines = getCardConfigs(configs) as IColumn[];
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
const width = ref?.current?.offsetWidth;
|
||||||
|
let count = 4;
|
||||||
|
if (width < 1100) count = 3;
|
||||||
|
if (width < 850) count = 2;
|
||||||
|
if (width < 700) count = 1;
|
||||||
|
setCardNumber(columnCount || count);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const cards = items?.map((item: any, index: number) => (
|
const cards = items?.map((item: any, index: number) => (
|
||||||
<Card
|
<Card
|
||||||
key={index}
|
key={index}
|
||||||
item={item}
|
item={item}
|
||||||
lines={lines}
|
lines={lines}
|
||||||
|
customStyle={[
|
||||||
|
{ width: 'calc(100% - 24px)' },
|
||||||
|
{ width: 'calc(50% - 24px)' },
|
||||||
|
{ width: 'calc(33.33% - 24px)' },
|
||||||
|
{ width: 'calc(25% - 24px)' },
|
||||||
|
][cardNumber - 1]}
|
||||||
className={className}
|
className={className}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={style.card_wrapper}>
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={style.card_wrapper}
|
||||||
|
>
|
||||||
{cards}
|
{cards}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -42,6 +65,7 @@ function Cards({
|
||||||
Cards.defaultProps = {
|
Cards.defaultProps = {
|
||||||
items: [],
|
items: [],
|
||||||
className: undefined,
|
className: undefined,
|
||||||
|
columnCount: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Cards;
|
export default Cards;
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-s);
|
padding: var(--space-s);
|
||||||
margin: 0 0 var(--space-xxl) 0;
|
margin: 0 var(--space-xxl) var(--space-xxl) 0;
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-m);
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
vertical-align: top;
|
page-break-inside: avoid;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
box-shadow: 4px 4px 4px #CCCCCC;
|
vertical-align: top;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
&_wrapper {
|
&_wrapper {
|
||||||
margin-top: var(--space-xxl);
|
width: calc(100% + 24px);
|
||||||
column-count: 4;
|
margin: 0;
|
||||||
column-gap: var(--space-xxl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&_title {
|
&_title {
|
||||||
|
@ -64,21 +64,3 @@
|
||||||
.card_line + .card_line {
|
.card_line + .card_line {
|
||||||
border-top: 1px solid var(--color-border);
|
border-top: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1350px) {
|
|
||||||
.card_wrapper {
|
|
||||||
column-count: 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1100px) {
|
|
||||||
.card_wrapper {
|
|
||||||
column-count: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
|
||||||
.card_wrapper {
|
|
||||||
column-count: 1;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
.paginator {
|
.paginator {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 24px auto 0 auto;
|
margin: 0 auto 24px auto;
|
||||||
|
white-space: normal;
|
||||||
|
box-sizing: border-box;
|
||||||
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.paginator_text {
|
.paginator_text {
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
@import '../../../styles/variables';
|
@import '../../../styles/variables';
|
||||||
|
|
||||||
.data_view {
|
.data_view {
|
||||||
&_icon {
|
&_buttons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -48px;
|
top: -48px;
|
||||||
right: 24px;
|
right: 24px;
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: var(--space-xxl);
|
width: var(--space-xxl);
|
||||||
height: var(--space-xxl);
|
height: var(--space-xxl);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin-left: var(--space-l);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.data_view_buttons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,22 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import ISort from 'ts/interfaces/Sort';
|
import ISort from 'ts/interfaces/Sort';
|
||||||
import Table from 'ts/components/Table';
|
import Table from 'ts/components/Table';
|
||||||
import Cards from 'ts/components/Cards';
|
import Cards from 'ts/components/Cards';
|
||||||
|
import { downloadCsv } from 'ts/helpers/File';
|
||||||
|
|
||||||
import style from './index.module.scss';
|
import style from './index.module.scss';
|
||||||
|
import PageWrapper from '../Page/wrapper';
|
||||||
|
|
||||||
interface IDataViewProps {
|
interface IDataViewProps {
|
||||||
rows: any[];
|
rows: any[];
|
||||||
type?: string;
|
type?: string;
|
||||||
sort?: ISort[];
|
sort?: ISort[];
|
||||||
|
columnCount?: number,
|
||||||
className?: string,
|
className?: string,
|
||||||
disabledRow?: (row: any) => boolean;
|
disabledRow?: (row: any) => boolean;
|
||||||
|
converterToCsv?: Function,
|
||||||
updateSort?: Function,
|
updateSort?: Function,
|
||||||
children: React.ReactNode | React.ReactNode[];
|
children: React.ReactNode | React.ReactNode[];
|
||||||
}
|
}
|
||||||
|
@ -20,11 +25,13 @@ function DataView({
|
||||||
rows = [],
|
rows = [],
|
||||||
sort = [],
|
sort = [],
|
||||||
type,
|
type,
|
||||||
|
columnCount,
|
||||||
className,
|
className,
|
||||||
disabledRow,
|
disabledRow,
|
||||||
updateSort,
|
updateSort,
|
||||||
children,
|
children,
|
||||||
}: IDataViewProps): React.ReactElement | null {
|
}: IDataViewProps): React.ReactElement | null {
|
||||||
|
const urlParams = useParams<any>();
|
||||||
const [localType, setType] = useState<string>(type || 'table');
|
const [localType, setType] = useState<string>(type || 'table');
|
||||||
|
|
||||||
if (!rows || !rows.length) return null;
|
if (!rows || !rows.length) return null;
|
||||||
|
@ -41,29 +48,45 @@ function DataView({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<img
|
<div style={{ position: 'relative' }}>
|
||||||
title={title}
|
<div className={style.data_view_buttons}>
|
||||||
src={icon}
|
<img
|
||||||
className={style.data_view_icon}
|
title={'Скачать CSV'}
|
||||||
onClick={() => {
|
src="./assets/icons/Download.svg"
|
||||||
setType(localType === 'table' ? 'cards' : 'table');
|
className={style.data_view_icon}
|
||||||
}}
|
onClick={() => {
|
||||||
/>
|
const fileName = `${urlParams.type || ''} ${urlParams.page || ''}`;
|
||||||
|
downloadCsv(rows, children, fileName);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
title={title}
|
||||||
|
src={icon}
|
||||||
|
className={style.data_view_icon}
|
||||||
|
onClick={() => {
|
||||||
|
setType(localType === 'table' ? 'cards' : 'table');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{localType === 'table' && (
|
{localType === 'table' && (
|
||||||
<Table
|
<PageWrapper template="table">
|
||||||
rows={rows}
|
<Table
|
||||||
sort={sort}
|
rows={rows}
|
||||||
disabledRow={disabledRow}
|
sort={sort}
|
||||||
updateSort={updateSort}
|
disabledRow={disabledRow}
|
||||||
>
|
updateSort={updateSort}
|
||||||
{children}
|
>
|
||||||
</Table>
|
{children}
|
||||||
|
</Table>
|
||||||
|
</PageWrapper>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{localType === 'cards' && (
|
{localType === 'cards' && (
|
||||||
<Cards
|
<Cards
|
||||||
items={rows}
|
items={rows}
|
||||||
|
columnCount={columnCount}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -77,6 +100,7 @@ DataView.defaultProps = {
|
||||||
rows: [],
|
rows: [],
|
||||||
sort: [],
|
sort: [],
|
||||||
type: 'table',
|
type: 'table',
|
||||||
|
columnCount: undefined,
|
||||||
updateSort: () => {
|
updateSort: () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,11 +9,11 @@ import style from '../styles/card.module.scss';
|
||||||
function getClassName(recommendation?: any) {
|
function getClassName(recommendation?: any) {
|
||||||
const type = recommendation?.type;
|
const type = recommendation?.type;
|
||||||
return {
|
return {
|
||||||
[RECOMMENDATION_TYPES.INFO]: style.card_info,
|
[RECOMMENDATION_TYPES.INFO]: style.recommendations_card_info,
|
||||||
[RECOMMENDATION_TYPES.FACT]: style.card_fact,
|
[RECOMMENDATION_TYPES.FACT]: style.recommendations_card_fact,
|
||||||
[RECOMMENDATION_TYPES.WARNING]: style.card_warning,
|
[RECOMMENDATION_TYPES.WARNING]: style.recommendations_card_warning,
|
||||||
[RECOMMENDATION_TYPES.ALERT]: style.card_error,
|
[RECOMMENDATION_TYPES.ALERT]: style.recommendations_card_error,
|
||||||
}[type || RECOMMENDATION_TYPES.INFO] ?? style.card_fact;
|
}[type || RECOMMENDATION_TYPES.INFO] ?? style.recommendations_card_fact;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDescriptionText(recommendation?: any) {
|
function getDescriptionText(recommendation?: any) {
|
||||||
|
@ -52,17 +52,17 @@ function Card({
|
||||||
const mainText = parts.join('\n');
|
const mainText = parts.join('\n');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${style.card} ${className}`}>
|
<div className={`${style.recommendations_card} ${className}`}>
|
||||||
<div className={style.card_wrapper}>
|
<div className={style.recommendations_card_wrapper}>
|
||||||
<h5 className={style.card_title}>
|
<h5 className={style.recommendations_card_title}>
|
||||||
<span className={style.card_icon}></span>
|
<span className={style.recommendations_card_icon}></span>
|
||||||
{localization.get(formattedTitle, titleArgs)}
|
{localization.get(formattedTitle, titleArgs)}
|
||||||
</h5>
|
</h5>
|
||||||
<Description
|
<Description
|
||||||
style={{ color: '#12131B' }}
|
style={{ color: '#12131B' }}
|
||||||
text={previewText || ''}
|
text={previewText || ''}
|
||||||
/>
|
/>
|
||||||
<div className={style.card_shortcut}>
|
<div className={style.recommendations_card_shortcut}>
|
||||||
<Description
|
<Description
|
||||||
style={{ color: '#12131B' }}
|
style={{ color: '#12131B' }}
|
||||||
text={mainText || ''}
|
text={mainText || ''}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import React, { ReactNode } from 'react';
|
|
||||||
|
|
||||||
import style from './index.module.scss';
|
|
||||||
|
|
||||||
interface IRecommendationsProps {
|
|
||||||
children: ReactNode | string | null;
|
|
||||||
template?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Recommendations({
|
|
||||||
children,
|
|
||||||
template,
|
|
||||||
}: IRecommendationsProps) {
|
|
||||||
const className = template === 'box'
|
|
||||||
? `${style.main_wrapper} ${style.main_wrapper_white}`
|
|
||||||
: `${style.main_wrapper}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default Recommendations;
|
|
|
@ -1,26 +0,0 @@
|
||||||
import React, { ReactNode } from 'react';
|
|
||||||
|
|
||||||
import style from './index.module.scss';
|
|
||||||
|
|
||||||
interface IRecommendationsProps {
|
|
||||||
children: ReactNode | string | null;
|
|
||||||
template?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Recommendations({
|
|
||||||
children,
|
|
||||||
template,
|
|
||||||
}: IRecommendationsProps) {
|
|
||||||
const className = template === 'box'
|
|
||||||
? `${style.main_wrapper} ${style.main_wrapper_white}`
|
|
||||||
: `${style.main_wrapper}`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={className}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default Recommendations;
|
|
|
@ -1,73 +1,135 @@
|
||||||
@import '../../../../styles/variables';
|
@import '../../../../styles/variables';
|
||||||
|
|
||||||
.recommendations_short,
|
.recommendations {
|
||||||
.recommendations_full {
|
&_short,
|
||||||
position: relative;
|
&_full {
|
||||||
display: block;
|
position: relative;
|
||||||
max-height: 108px;
|
display: block;
|
||||||
margin: 0 0 16px 0;
|
max-height: 108px;
|
||||||
|
margin: 0 0 16px 0;
|
||||||
|
}
|
||||||
|
&_full {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_more,
|
||||||
|
&_card {
|
||||||
|
display: inline-block;
|
||||||
|
min-height: 100px;
|
||||||
|
max-height: 100px;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
box-sizing: border-box;
|
||||||
|
white-space: normal;
|
||||||
|
|
||||||
|
border-radius: var(--border-radius-m);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_more {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 30px;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_card {
|
||||||
|
position: relative;
|
||||||
|
width: 220px;
|
||||||
|
margin: 0 12px 16px 0;
|
||||||
|
border-left: none;
|
||||||
|
|
||||||
|
&_wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
min-height: 100px;
|
||||||
|
max-height: 100px;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
border-radius: var(--border-radius-m);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-left: 8px solid var(--color-border);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 16px;
|
||||||
|
left: 16px;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: 100% auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_info {
|
||||||
|
--color-temp-border: #97C2A9;
|
||||||
|
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||||
|
--color-temp-bg: #E3F8EC;
|
||||||
|
--color-temp-title: #58866B;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_fact {
|
||||||
|
--color-temp-border: var(--color-11);
|
||||||
|
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||||
|
--color-temp-bg: #EFF7FF;
|
||||||
|
--color-temp-title: var(--color-first);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_warning {
|
||||||
|
--color-temp-border: var(--color-21);
|
||||||
|
--color-temp-icon: url('/assets/recommendations/warning.svg');
|
||||||
|
--color-temp-bg: #FFF5F2;
|
||||||
|
--color-temp-title: #E8B06D;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_error {
|
||||||
|
--color-temp-border: var(--color-12);
|
||||||
|
--color-temp-icon: url('/assets/recommendations/alert.svg');
|
||||||
|
--color-temp-bg: #FFEFEE;
|
||||||
|
--color-temp-title: #DD8B87;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: var(--font-xs);
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
padding: 2px 0 0 24px;
|
||||||
|
margin: 0 auto 4px auto;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: bottom;
|
||||||
|
color: var(--color-temp-title);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_wrapper {
|
||||||
|
background-color: var(--color-temp-bg);
|
||||||
|
border-left-color: var(--color-temp-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.recommendations_full {
|
.recommendations_card:hover > .recommendations_card_wrapper {
|
||||||
max-height: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.more,
|
|
||||||
.card {
|
|
||||||
display: inline-block;
|
|
||||||
min-height: 100px;
|
|
||||||
max-height: 100px;
|
|
||||||
|
|
||||||
text-align: left;
|
|
||||||
vertical-align: top;
|
|
||||||
box-sizing: border-box;
|
|
||||||
white-space: normal;
|
|
||||||
|
|
||||||
border-radius: var(--border-radius-m);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.more {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 30px;
|
|
||||||
margin: 0 0 8px 0;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 100px;
|
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
color: #AAAAAA;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
position: relative;
|
|
||||||
width: 220px;
|
|
||||||
margin: 0 12px 16px 0;
|
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_wrapper {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
min-height: 100px;
|
|
||||||
max-height: 100px;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
border-radius: var(--border-radius-m);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
border-left: 8px solid var(--color-border);
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card:hover > .card_wrapper {
|
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
width: 170%;
|
width: 170%;
|
||||||
max-height: 450px;
|
max-height: 450px;
|
||||||
|
@ -75,91 +137,30 @@
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_wrapper::-webkit-scrollbar {
|
.recommendations_card_wrapper::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_wrapper::-webkit-scrollbar-thumb {
|
.recommendations_card_wrapper::-webkit-scrollbar-thumb {
|
||||||
background: #AAAAAA;
|
background: #AAAAAA;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 16px;
|
|
||||||
left: 16px;
|
|
||||||
|
|
||||||
display: inline-block;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center center;
|
|
||||||
background-size: 100% auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_info {
|
|
||||||
--color-temp-border: #97C2A9;
|
|
||||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
|
||||||
--color-temp-bg: #E3F8EC;
|
|
||||||
--color-temp-title: #58866B;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_fact {
|
|
||||||
--color-temp-border: var(--color-11);
|
|
||||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
|
||||||
--color-temp-bg: #EFF7FF;
|
|
||||||
--color-temp-title: var(--color-first);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_warning {
|
|
||||||
--color-temp-border: var(--color-21);
|
|
||||||
--color-temp-icon: url('/assets/recommendations/warning.svg');
|
|
||||||
--color-temp-bg: #FFF5F2;
|
|
||||||
--color-temp-title: #E8B06D;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_error {
|
|
||||||
--color-temp-border: var(--color-12);
|
|
||||||
--color-temp-icon: url('/assets/recommendations/alert.svg');
|
|
||||||
--color-temp-bg: #FFEFEE;
|
|
||||||
--color-temp-title: #DD8B87;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_title {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: var(--font-xs);
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
padding: 2px 0 0 24px;
|
|
||||||
margin: 0 auto 4px auto;
|
|
||||||
|
|
||||||
text-align: left;
|
|
||||||
text-decoration: none;
|
|
||||||
vertical-align: bottom;
|
|
||||||
color: var(--color-temp-title);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card_wrapper {
|
|
||||||
background-color: var(--color-temp-bg);
|
|
||||||
border-left-color: var(--color-temp-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.recommendations_title {
|
.recommendations_title {
|
||||||
color: var(--color-temp-border);
|
color: var(--color-temp-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_icon {
|
.recommendations_card_icon {
|
||||||
background-image: var(--color-temp-icon);
|
background-image: var(--color-temp-icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_shortcut {
|
.recommendations_card_shortcut {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 6px 0 0 0;
|
padding: 6px 0 0 0;
|
||||||
margin: 6px 0 0 0;
|
margin: 6px 0 0 0;
|
||||||
border-top: 1px solid var(--color-temp-border);
|
border-top: 1px solid var(--color-temp-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card:hover .card_shortcut {
|
.recommendations_card:hover .recommendations_card_shortcut {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
|
@ -16,9 +16,13 @@ function Title({
|
||||||
className,
|
className,
|
||||||
}: ITitleProps) {
|
}: ITitleProps) {
|
||||||
return (
|
return (
|
||||||
<h3 className={`${style.title} ${addPadding ? style.title_padding : ''} ${className || ''}`}>
|
<>
|
||||||
{localization.get(title || '')}
|
<a // @ts-ignore
|
||||||
</h3>
|
name={title}></a>
|
||||||
|
<h3 className={`${style.title} ${addPadding ? style.title_padding : ''} ${className || ''}`}>
|
||||||
|
{localization.get(title || '')}
|
||||||
|
</h3>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,747 +0,0 @@
|
||||||
import localization from 'ts/helpers/Localization';
|
|
||||||
|
|
||||||
localization.parse('en', `
|
|
||||||
§ uiKit.console: Copy
|
|
||||||
§ uiKit.dataLoader.page: Page
|
|
||||||
§ uiKit.dataLoader.size: Отображается по
|
|
||||||
§ uiKit.dataLoader.from: from
|
|
||||||
§ uiKit.dataLoader.all: Show all
|
|
||||||
§ uiKit.hoursChart.work: стандартное рабочее время (будни, с 07:00 до 20:00)
|
|
||||||
§ uiKit.hoursChart.weekend: выходные дни или время до/после рабочего дня
|
|
||||||
§ uiKit.hoursChart.days: суммарное количество коммитов за все время в конкретный день и час
|
|
||||||
§ uiKit.page.remove: Remove
|
|
||||||
§ uiKit.races.go: Поехали
|
|
||||||
§ uiKit.nothingFound.common.title: Нет или недостаточно данных для отображения
|
|
||||||
§ uiKit.nothingFound.common.description: Система обработает больше данных, если коммиты будут подписаны в формате [Git commit message convention|https://www.conventionalcommits.org/en/v1.0.0/]. Шаблон:
|
|
||||||
§ uiKit.nothingFound.common.console: Task_number type(фича): message
|
|
||||||
§ uiKit.nothingFound.common.example: Example:
|
|
||||||
§ uiKit.nothingFound.staff.title: Нет данных для этого сотрудника
|
|
||||||
§ uiKit.nothingFound.staff.description1:
|
|
||||||
Он вносил правки не каждый рабочий день и получил статус «Помошник».
|
|
||||||
Работой сотрудников с таким статусом по данному проекту можно пренебречь, т.к. его влад на общем фоне незначителен.
|
|
||||||
|
|
||||||
§ uiKit.nothingFound.staff.description2:
|
|
||||||
Поэтому система не рассчитывает для него ряд показателей.
|
|
||||||
Если это ошибка и данного сотрудника нужно рассчитать как обычного, перейдите в раздел «Настройки» и измените его тип.
|
|
||||||
|
|
||||||
§ common.filters: Filters
|
|
||||||
§ common.notifications.save: Изменения сохранены
|
|
||||||
§ common.notifications.setting: Настройки сохранены
|
|
||||||
§ sidebar.switch.team: Team
|
|
||||||
§ sidebar.switch.person: Employee
|
|
||||||
§ sidebar.buttons.settings: Settings
|
|
||||||
§ sidebar.buttons.print: Print
|
|
||||||
§ sidebar.filters.all: all time
|
|
||||||
§ sidebar.filters.year: year
|
|
||||||
§ sidebar.filters.halfYear: half year
|
|
||||||
§ sidebar.filters.month: month
|
|
||||||
§ sidebar.filters.week: week
|
|
||||||
§ sidebar.team.total: Common info
|
|
||||||
§ sidebar.team.scope: Features
|
|
||||||
§ sidebar.team.author: Employees
|
|
||||||
§ sidebar.team.type: Task types
|
|
||||||
§ sidebar.team.pr: Pull requests
|
|
||||||
§ sidebar.team.day: By day
|
|
||||||
§ sidebar.team.week: By week
|
|
||||||
§ sidebar.team.month: By month
|
|
||||||
§ sidebar.team.tree: Files
|
|
||||||
§ sidebar.team.hours: Расписание
|
|
||||||
§ sidebar.team.commits: All commits
|
|
||||||
§ sidebar.team.changes: All changes
|
|
||||||
§ sidebar.team.words: Popular words
|
|
||||||
§ sidebar.team.top: Викторина
|
|
||||||
§ sidebar.team.settings: Settings
|
|
||||||
§ sidebar.person.total: Common info
|
|
||||||
§ sidebar.person.money: Work cost
|
|
||||||
§ sidebar.person.speed: Speed
|
|
||||||
§ sidebar.person.day: By day
|
|
||||||
§ sidebar.person.week: By week
|
|
||||||
§ sidebar.person.month: By month
|
|
||||||
§ sidebar.person.hours: Расписание
|
|
||||||
§ sidebar.person.commits: All commits
|
|
||||||
§ sidebar.person.changes: All changes
|
|
||||||
§ sidebar.person.words: Popular words
|
|
||||||
§ sidebar.person.settings: Settings
|
|
||||||
§ page.welcome.step1: Run this command in your project folder
|
|
||||||
§ page.welcome.step2: Move the file log.txt to this page
|
|
||||||
§ page.welcome.description1: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл
|
|
||||||
§ page.welcome.description2: [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы обьединить статистику по сотрудникам.
|
|
||||||
§ page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы обьединить статистику по сотрудникам.
|
|
||||||
§ page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
|
|
||||||
§ page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].
|
|
||||||
§ page.common.words.title: Statistic by words
|
|
||||||
§ page.common.words.description: самое популярное слово. Встречается $1 раза.
|
|
||||||
§ page.common.commits.title: Commits number by days
|
|
||||||
§ page.common.commits.description: ($1) самый продуктивный день по числу коммитов.
|
|
||||||
§ page.common.commits.title2: $1 сделано коммитов: $2
|
|
||||||
§ page.common.filter.allUsers: Не имеет значения
|
|
||||||
§ page.settings.document.title: Display settings
|
|
||||||
§ page.settings.document.name: Page title
|
|
||||||
§ page.settings.document.language: Language
|
|
||||||
§ page.settings.links.title: Link prefixes
|
|
||||||
§ page.settings.links.task: For task number
|
|
||||||
§ page.settings.links.pr: For Pull Requests
|
|
||||||
§ page.settings.user.title: Employees settings
|
|
||||||
§ page.settings.user.notFound: Индивидуальных настроек нет. Данные по всем сотрудникам вычисляются по общим параметрам.
|
|
||||||
§ page.settings.user.subTitle: Дополнение к трудовому договору №$1
|
|
||||||
§ page.settings.user.from: Дата начала действия
|
|
||||||
§ page.settings.mailmap: .mailmap settings
|
|
||||||
§ page.settings.common.title: Общие данные по зарплате
|
|
||||||
§ page.settings.common.type.title: Work type
|
|
||||||
§ page.settings.common.type.full: Full-time
|
|
||||||
§ page.settings.common.type.part: Проектная работа
|
|
||||||
§ page.settings.common.salary: Зарплата в месяц
|
|
||||||
§ page.settings.common.currency: Currency
|
|
||||||
§ page.settings.common.workDaysInYear: Количество рабочих дней в году
|
|
||||||
§ page.settings.common.vacationDaysInYear: Количество дней отпуска в год
|
|
||||||
§ page.settings.common.workDaysInWeek: Рабочие дни
|
|
||||||
§ page.settings.form.save: Save
|
|
||||||
§ page.settings.form.cancel: Cancel
|
|
||||||
§ page.settings.form.remove: Remove
|
|
||||||
§ page.settings.form.addEmployee: Add employee
|
|
||||||
§ page.settings.form.addContract: Добавить трудовой договор
|
|
||||||
§ page.print.title: What are we printing?
|
|
||||||
§ page.print.page: This page
|
|
||||||
§ page.print.type: This section
|
|
||||||
§ page.print.all: All statistics
|
|
||||||
§ page.print.cancel: Cancel
|
|
||||||
§ page.team.author.title: Статистика по сотрудникам
|
|
||||||
§ page.team.author.description1: *Часть статитики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помошник» не считается*, т.к. это эпизодическая роль в проекте. Предпологаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
|
||||||
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
|
||||||
§ page.team.author.types: Types
|
|
||||||
§ page.team.author.commits: Commits
|
|
||||||
§ page.team.author.commitsSmall: commits
|
|
||||||
§ page.team.author.tasks: Tasks
|
|
||||||
§ page.team.author.tasksSmall: tasks
|
|
||||||
§ page.team.author.workedLosses: Days with and without commits
|
|
||||||
§ page.team.author.worked: work
|
|
||||||
§ page.team.author.losses: days without commits
|
|
||||||
§ page.team.author.days: days
|
|
||||||
§ page.team.author.daysForTask: Дней на задачу
|
|
||||||
§ page.team.author.scopes: Features
|
|
||||||
§ page.team.author.moneyAll: Получил
|
|
||||||
§ page.team.author.moneyWorked: Отработал
|
|
||||||
§ page.team.author.moneyLosses: Переплата
|
|
||||||
§ page.team.hours.title: Распределение коммитов в течении каждого дня недели
|
|
||||||
§ page.team.month.title: Календарь работы по проекту
|
|
||||||
§ page.team.scope.title: Statistic by features
|
|
||||||
§ page.team.scope.scope: Feature
|
|
||||||
§ page.team.scope.days: Раб. дней
|
|
||||||
§ page.team.scope.authorsDays: Человеко-дней
|
|
||||||
§ page.team.scope.tasks: Tasks
|
|
||||||
§ page.team.scope.commits: Commits
|
|
||||||
§ page.team.scope.commitsSmall: commits
|
|
||||||
§ page.team.scope.types: Types
|
|
||||||
§ page.team.scope.authors: Персональный вклад
|
|
||||||
§ page.team.scope.cost: Cost
|
|
||||||
§ page.team.type.title: Статистика по типам задач
|
|
||||||
§ page.team.type.description: *Персональный вклад* считается по количеству коммитов, а не объему измененных строк или файлов. Поэтому следует так же смотреть раздел «Анализ файлов», чтобы оценить масштаб изменений.
|
|
||||||
§ page.team.type.type: Task types
|
|
||||||
§ page.team.type.tasks: Tasks
|
|
||||||
§ page.team.type.tasksSmall: tasks
|
|
||||||
§ page.team.type.days: Days
|
|
||||||
§ page.team.type.daysSmall: days
|
|
||||||
§ page.team.type.authorsDays: Человеко-дней
|
|
||||||
§ page.team.type.commits: Commits
|
|
||||||
§ page.team.type.authors: Персональный вклад
|
|
||||||
§ page.team.total.titleA: Scope of work
|
|
||||||
§ page.team.total.titleB: Cost
|
|
||||||
§ page.team.total.daysWorked.title: человеко-дней
|
|
||||||
§ page.team.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.team.total.commits.title: commits
|
|
||||||
§ page.team.total.commits.description: Удалённые ветки не считаются
|
|
||||||
§ page.team.total.daysLosses.title: days without commits
|
|
||||||
§ page.team.total.daysLosses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
|
||||||
§ page.team.total.employment.title: работает / уволилось
|
|
||||||
§ page.team.total.employment.description: Если сотрудник в течении месяца не сделал ни одного коммита, он считается уволенным
|
|
||||||
§ page.team.total.moneyAll.title: общая
|
|
||||||
§ page.team.total.moneyAll.description: Суммарные затраты на зп
|
|
||||||
§ page.team.total.moneyWorked.title: фактическая
|
|
||||||
§ page.team.total.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
|
||||||
§ page.team.total.moneyLosses.title: possible overpayment
|
|
||||||
§ page.team.total.moneyLosses.description: Оплаченные рабочие дни, когда коммитов не было
|
|
||||||
§ page.team.total.weekendPayment.title: work on weekend
|
|
||||||
§ page.team.total.weekendPayment.description: Суммарная переплата за работу в выходные дни
|
|
||||||
§ page.team.total.workSpeed.title: tasks in day
|
|
||||||
§ page.team.total.workSpeed.description: Средняя скорость работы команды при текущем составе сотрудников
|
|
||||||
§ page.team.total.moneySpeed.title: в месяц
|
|
||||||
§ page.team.total.moneySpeed.description: Прогнозируемая сумма выплаты на зп при текущем составе сотрудников без учета налогов и сопутствующих затрат
|
|
||||||
§ page.team.total.description1: *Человеко-дни* — это работа одного сотрудника в течение одного рабочего дня. Например, за один календарный день, команда из трех сотрудников выдает объем работы в три человеко-дня.
|
|
||||||
§ page.team.total.description2: *Днями прогулов* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют.
|
|
||||||
§ page.team.total.description3: Карточка *работает и уволилось* показывает фактический состав сотрудников, которые постоянно участвуют в работе. Кроме этого, есть «помощники» — это сотрудники, как правило другой специализации, которые могут иногда делать коммиты в проект.
|
|
||||||
§ page.team.total.description4: *Переплатой* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют. Именно поэтому переплата + фактическая стоимость != общей. В общей стоимости заложена оплата выходных, государственных праздников и отпусков.
|
|
||||||
§ page.team.total.description5: *Работой на выходных* считается по коэфициенту х2 от оплаты обычного дня. Выше отображена именно переплата (х1), т.к. сам факт переработки в данном контексте не интересен. Мы не смотрим скорость сжигания бюджета. Мы смотрим переплату при увеличении скорости работы.
|
|
||||||
§ page.team.tree.title: Дерево проекта с учётом выбранных фильтров
|
|
||||||
§ page.team.tree.filters.author: Employee
|
|
||||||
§ page.team.tree.filters.commits: Commits number
|
|
||||||
§ page.team.tree.filters.help: Минимальное количество коммитов, которое сделал сотрудник в файле
|
|
||||||
§ page.team.tree.filters.all: All employees
|
|
||||||
§ page.team.tree.add: Who added it
|
|
||||||
§ page.team.tree.change: Who changed it
|
|
||||||
§ page.team.tree.remove: Who removed it
|
|
||||||
§ page.team.tree.line: lines
|
|
||||||
§ page.team.tree.lineAdd: added
|
|
||||||
§ page.team.tree.lineRemove: changed
|
|
||||||
§ page.team.week.date: Date
|
|
||||||
§ page.team.week.numberTasks: Количество задач
|
|
||||||
§ page.team.week.people: Количество человек
|
|
||||||
§ page.team.week.line: Изменение строк
|
|
||||||
§ page.team.week.days: Days with and without commits
|
|
||||||
§ page.team.week.lossesDetails: Кто не коммитил
|
|
||||||
§ page.team.week.add: added
|
|
||||||
§ page.team.week.change: changed
|
|
||||||
§ page.team.week.remove: removed
|
|
||||||
§ page.team.week.hasCommits: были коммиты
|
|
||||||
§ page.team.week.hasNotCommits: небыло коммитов
|
|
||||||
§ page.team.week.days: days
|
|
||||||
§ page.team.week.tasks: tasks
|
|
||||||
§ page.team.pr.task: Task
|
|
||||||
§ page.team.pr.tasks: tasks
|
|
||||||
§ page.team.pr.firstCommitTime: First commit
|
|
||||||
§ page.team.pr.lastCommitTime: Last
|
|
||||||
§ page.team.pr.workDays: Дней разработки
|
|
||||||
§ page.team.pr.delayDays: Дней ожидания влития
|
|
||||||
§ page.team.pr.commits: Commits
|
|
||||||
§ page.team.pr.date: Дата влития
|
|
||||||
§ page.team.pr.mergeAuthor: Влил
|
|
||||||
§ page.team.pr.author: Employee
|
|
||||||
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
|
||||||
§ page.team.pr.work: разработка
|
|
||||||
§ page.team.pr.delay: waiting
|
|
||||||
§ page.team.pr.days: days
|
|
||||||
§ page.team.pr.oneTaskDays: Время потраченное на одну задачу
|
|
||||||
§ page.team.pr.description1: *Время разработки* это разница времени от первого до последнего коммита по задаче. Не важно были перерывы в несколько дней между коммитами или нет. Сам факт какого-либо коммита увеличивает время.
|
|
||||||
§ page.team.pr.description2: *Время ожидания* это время между последним коммитом и влитием кода. Оно показывает фактический простой в ожидании чего-либо.
|
|
||||||
§ page.team.pr.description3: *Зачем отображать время разработки* без разбивки на кодинг и код-ревью? Затем, чтобы показать бизнесу фактическое время поставки кода. Ожидание тестирования, замечания на ревью, проблемы DevOps и прочие несовершенства процесса, как раз уже заложены в этот срок.
|
|
||||||
§ page.team.pr.statByAuthors: Statistics by employee
|
|
||||||
§ page.team.pr.longDelay: Длительное ожидание влития
|
|
||||||
§ page.person.print.photo.title: Photo
|
|
||||||
§ page.person.print.photo.description: место для фотографии
|
|
||||||
§ page.person.total.title: Основные характеристики
|
|
||||||
§ page.person.total.daysWorked.title: days of work
|
|
||||||
§ page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.person.total.tasks.title: tasks
|
|
||||||
§ page.person.total.tasks.description: Если коммиты правильно подписаны
|
|
||||||
§ page.person.character.title: Персонаж
|
|
||||||
§ page.person.achievement.title: Achievements
|
|
||||||
§ page.person.achievement.positive: Positive
|
|
||||||
§ page.person.achievement.normal: Neutral
|
|
||||||
§ page.person.achievement.negative: Negative
|
|
||||||
§ page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
|
|
||||||
§ page.person.gets.title: Взятые геты:
|
|
||||||
§ page.person.gets.description: «Взять гет» в данном случае означает первым оставить коммит к задаче с «красивым» номером.
|
|
||||||
§ page.person.business.days.title: дней работы
|
|
||||||
§ page.person.business.days.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.person.business.tasks.title: tasks
|
|
||||||
§ page.person.business.tasks.description: Если коммиты правильно подписаны
|
|
||||||
§ page.person.business.losses.title: days without commits
|
|
||||||
§ page.person.business.losses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
|
||||||
§ page.person.business.commits.title: commits
|
|
||||||
§ page.person.business.commits.description: Удалённые ветки не считаются
|
|
||||||
§ page.person.business.time.description: Время от первого, до последнего коммита (в том числе, нерабочие дни)
|
|
||||||
§ page.person.business.time.title: Дней на проекте:
|
|
||||||
§ page.person.business.time.dismissed: (dismissed)
|
|
||||||
§ page.person.business.time.staff: (not in the team)
|
|
||||||
§ page.person.business.achievements: Achievements
|
|
||||||
§ page.person.changes.title: Achievements
|
|
||||||
§ page.person.changes.description:
|
|
||||||
При некоторых видах форматирования git отмечает строки как «удалённые» и «добавленные»,
|
|
||||||
хотя на самом деле они были «изменёны». Поэтому, если вы провели большой рефакторинг,
|
|
||||||
git может показать малое количество изменений в статистике, а фактический результат
|
|
||||||
будет отмечен, как скачок «удаленных» и «добавленных» строк.
|
|
||||||
§ page.person.changes.description: Список коммитов и количество изменений в них за этот день:
|
|
||||||
§ page.person.commits.title: Commits list:
|
|
||||||
§ page.person.money.title.total: For all the time
|
|
||||||
§ page.person.money.title.middle: Middle cost
|
|
||||||
§ page.person.money.moneyAll.title: received
|
|
||||||
§ page.person.money.moneyAll.description: Предполагаемая сумма зп с проекта (см. настройки)
|
|
||||||
§ page.person.money.moneyWorked.title: отработал
|
|
||||||
§ page.person.money.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
|
||||||
§ page.person.money.moneyLosses.title: possible overpayment
|
|
||||||
§ page.person.money.moneyLosses.description: Дни без коммитов умноженные на среднюю зп
|
|
||||||
§ page.person.money.tasks.title: task
|
|
||||||
§ page.person.money.tasks.description: Количество закрытых задач к стоимости дня
|
|
||||||
§ page.person.money.commits.title: commit
|
|
||||||
§ page.person.money.commits.description: Количество коммитов к стоимости рабочего дня
|
|
||||||
§ page.person.speed.task: One task on average is
|
|
||||||
§ page.person.speed.max: Максимальная скорость в день
|
|
||||||
§ page.person.speed.days.title: days
|
|
||||||
§ page.person.speed.days.description: Имеются ввиду рабочие дни, если коммиты правильно подписаны
|
|
||||||
§ page.person.speed.commits.title: commits
|
|
||||||
§ page.person.speed.commits.description: Отрезаны 10% максимальных и минимальных значений
|
|
||||||
§ page.person.speed.line.title: code lines
|
|
||||||
§ page.person.speed.line.description: Отрезаны 10% максимальных и минимальных значений
|
|
||||||
§ page.person.speed.tasks.title: tasks
|
|
||||||
§ page.person.speed.tasks.description: Задача может быть не доделана, но работа по ней должна быть
|
|
||||||
§ page.person.speed.maxCommits.title: commits
|
|
||||||
§ page.person.speed.maxCommits.description: Задача может быть не доделана, но работа по ней должна быть
|
|
||||||
§ page.person.hours.title: Распределение коммитов в течении каждого дня недели
|
|
||||||
§ page.person.week.date: Date
|
|
||||||
§ page.person.week.tasks: Number of tasks
|
|
||||||
§ page.person.week.workDays: Days with commits
|
|
||||||
§ page.person.week.taskInDay: Tasks per day
|
|
||||||
§ page.person.week.days: days
|
|
||||||
§ page.person.week.workDay: weekdays
|
|
||||||
§ page.person.week.weekends: weekends
|
|
||||||
|
|
||||||
§ recommendations.title
|
|
||||||
Рекомендации и факты
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.title
|
|
||||||
Нет паралельных работ
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.description
|
|
||||||
любую фичу в один момент времени делает один человек.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат меньше 1.3 считаем, что паралельных работ в рамках большинства фичей обычно нет;
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- повышается bus factor;
|
|
||||||
- сотрудники медленее развиваются;
|
|
||||||
- трудно качественно проверить работу сотрудника;
|
|
||||||
|
|
||||||
# Почему это хорошо:
|
|
||||||
- появляюся эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
|
||||||
- скорее всего не бывает merge конфликтов;
|
|
||||||
- проект может очень быстро паралельно развиваться в разные стороны;
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.title
|
|
||||||
Часть работ паралельно
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.description
|
|
||||||
Иногда фичу делают одновременно несколько человек.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делалается паралельно;
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.title
|
|
||||||
Паралельные работы
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.description
|
|
||||||
любую фичу в один момент времени делают несколько человек
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат больше двух считаем, что большая часть работ в рамках разных фичей обычно делалается паралельно;
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.scope.money
|
|
||||||
в такую сумму можно оценить работу по данному проекту.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни затраченные на разработку умножаются на индивидуальную зарплату разработчиков;
|
|
||||||
|
|
||||||
Изменить зарплату каждого разработчика, для более точной суммы, можно в разделе «Настройки»
|
|
||||||
|
|
||||||
# Это много или мало?
|
|
||||||
Для ответа на этот вопрос, нужно ответить на следующие:
|
|
||||||
- Можно ли за эти деньги было купить готовое решение?
|
|
||||||
- Можно ли за эти деньги сделать более хороший продукт?
|
|
||||||
|
|
||||||
Если ответ на оба вопроса «да», то возможно, разработка с нуля не стоила потраченных на неё денег.
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.title
|
|
||||||
Bus factor = 1
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.description
|
|
||||||
В большинство фич погружен один человек.
|
|
||||||
Надо переключать людей.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- если сотрудники будут увольнятся, будет трудно продолжить их работу;
|
|
||||||
- невозможно контролировать качество его кода;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- более 80% коммитов в фичу делает один человек;
|
|
||||||
- проект имеет более 60% таких фичей;
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.oneMaintainer
|
|
||||||
в фичи погружен один человек.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- если он уволится, будет трудно продолжить разработку;
|
|
||||||
- снижается качество code-review;
|
|
||||||
- трудно запаралелить разработку при необходимости;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- более 80% коммитов в фичу сделал один человек;
|
|
||||||
|
|
||||||
§ recommendations.scope.types.process.title
|
|
||||||
Плохие процессы
|
|
||||||
|
|
||||||
§ recommendations.scope.types.process.description
|
|
||||||
Большинство фич содержат один тип задач.
|
|
||||||
|
|
||||||
§ recommendations.scope.types.one
|
|
||||||
фичи содержат один тип задач.
|
|
||||||
|
|
||||||
§ recommendations.scope.types.common
|
|
||||||
Возможно, разработчики неправильно подписывают коммиты или менеджер заводит один и тот же тип задач.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- невозможно передать поддержку другой команде;
|
|
||||||
- невозможно выпустить "коробочную" версию;
|
|
||||||
- сильная зависимость от конкретных разработчиков;
|
|
||||||
- большое количество ошибок и низкое качество кода;
|
|
||||||
- вероятное замедление разработки в будущем;
|
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
|
||||||
- взгляд на продукт, только с позиции «работающей демки»;
|
|
||||||
|
|
||||||
# Что должно быть:
|
|
||||||
- тесты;
|
|
||||||
- ошибки (выявленные по результатам тестов);
|
|
||||||
- рефакторинг (т.к. архитектура может измениться);
|
|
||||||
- документация;
|
|
||||||
- правки стиля (как результат опроса фокус-группы);
|
|
||||||
|
|
||||||
§ recommendations.scope.plan.title
|
|
||||||
Постройте долгосрочный план
|
|
||||||
|
|
||||||
§ recommendations.scope.plan.description
|
|
||||||
с учетом архитектуры.
|
|
||||||
|
|
||||||
При том опираться этот план должен сразу на самые трудные задачи.
|
|
||||||
|
|
||||||
# Почему отсутствие плана плохо:
|
|
||||||
- сотрудники делают минимально работающую версию, не закладывая точки расширения. После этого пишется не масштабируемый код, который тормозит следующие фичи;
|
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
|
||||||
- он не показал, как продукт будет развиваться далее и в каких точках будет рост;
|
|
||||||
|
|
||||||
# Как должно быть:
|
|
||||||
- составлятся глобальный план развития продукта;
|
|
||||||
- составлятся глобальный план развития архитектуры (с разработчиками и DBA);
|
|
||||||
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
|
||||||
|
|
||||||
§ recommendations.scope.cost.title
|
|
||||||
Оцените инвестиции в фичу
|
|
||||||
|
|
||||||
§ recommendations.scope.cost.description
|
|
||||||
с количеством потенциальной прибыли.
|
|
||||||
|
|
||||||
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более комерчески успешным.
|
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
|
||||||
пишет слишком мало кода.
|
|
||||||
|
|
||||||
# Может уволить?
|
|
||||||
- он тимлид, архитектор, аналитик?
|
|
||||||
- это его основной проект?
|
|
||||||
- есть какие-то зависимости от него?
|
|
||||||
|
|
||||||
# Почему нет смысла исправлять
|
|
||||||
Суммарные затраты на разработчика уже больше чем прибыль от его работы.
|
|
||||||
Если мы считаем, что обьективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
|
||||||
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
|
||||||
пишет мало кода. Нужно взять на контроль.
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
|
||||||
- в данном случае показатель от 60% до 80%;
|
|
||||||
|
|
||||||
# Как контролировать:
|
|
||||||
- дробить задачи на 1..2 дня;
|
|
||||||
- каждый день спрашивать статус;
|
|
||||||
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
|
||||||
- устроить парное программирование, чтобы проверить фактическую скорость;
|
|
||||||
|
|
||||||
§ recommendations.author.oneTypeMans
|
|
||||||
получает слишком однообразные задачи по типу. Может выгореть.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- если сотрудник выгорит, его скорость работы снизится;
|
|
||||||
- замедляется профессиональный рост;
|
|
||||||
- повышается вероятность увольнения;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- для каждого коммита определятся тип задачи;
|
|
||||||
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.title
|
|
||||||
Открытый проект
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.description
|
|
||||||
пять дней в неделю тут не работают.
|
|
||||||
|
|
||||||
Проект может быть и закрытым, просто такой темп работы обычно у открытых библиотек на GitHub.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- берется статистика по всем активным разработчикам;
|
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
|
||||||
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
|
||||||
|
|
||||||
# Последствия
|
|
||||||
Для проектов, где работа не постоянна, нет смысла во многих показателях. Поэтому показатели без коммитов, скорости и т.п. будут скрыты.
|
|
||||||
|
|
||||||
Как правило, оценку таких проектов делают перед началом разработки своей закрытой версии. Самые интересные показатели в этом случае вероятная стоимость и суммарное время на разработку.
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.title
|
|
||||||
Слабая загрузка
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
|
||||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- берется статистика по всем активным разработчикам;
|
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
|
||||||
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
|
||||||
|
|
||||||
# Возможные причины:
|
|
||||||
- фактически нет задач;
|
|
||||||
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
|
||||||
- разработчиков отвлекают совещаниями;
|
|
||||||
- команда не работает;
|
|
||||||
|
|
||||||
# Варианты решения:
|
|
||||||
- обсудить проблему с командой;
|
|
||||||
- уменьшить гранулярность задач, чтобы за день можно было успеть сделать одну или две задачи;
|
|
||||||
- ввести ежедневные совещания, чтобы проверять движение задач по статусу;
|
|
||||||
- устроить сеансы парного программирования, чтобы убедиться, что разработчик может работать быстрее;
|
|
||||||
|
|
||||||
§ recommendations.author.manager.title
|
|
||||||
Обозначьте дедлайны
|
|
||||||
|
|
||||||
§ recommendations.author.manager.description
|
|
||||||
У любой задачи должен быть чёткий дедлайн.
|
|
||||||
|
|
||||||
Это позволит не затягивать её выполнение на несколько дней или недель.
|
|
||||||
|
|
||||||
# Какие показатели стоит проверить:
|
|
||||||
- количество дней на одну задачу, которое тратит работник;
|
|
||||||
- количество дней ожидания влития PR (страница статистики по PR);
|
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.title
|
|
||||||
Проводите ежедневные совещания
|
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.description
|
|
||||||
они помогают быть в курсе проекта.
|
|
||||||
|
|
||||||
Не растягивайте их отвлекаясь на постороние темы.
|
|
||||||
|
|
||||||
# На какие вопросы должен ответить сотрудник:
|
|
||||||
- что было сделано;
|
|
||||||
- что будет сделано;
|
|
||||||
- есть ли какие-либо проблемы;
|
|
||||||
|
|
||||||
# Следует обрывать монолог, если:
|
|
||||||
- начинают подробно описывать мелкие детали, которые не важны;
|
|
||||||
- уводят диалог в сторону, от первоначального плана;
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
Часто сотрудник, который ничего не делает, старается уйти от ответа. Для этого он рассказывает кучу ненужных подробностей свой работы. Это позволяет усыпить внимание участников и растянуть время ответа. Создается ощущение что он чем-то занят, хотя по факту работы не было.
|
|
||||||
|
|
||||||
§ recommendations.author.ipr.title
|
|
||||||
Составьте план обучения
|
|
||||||
|
|
||||||
§ recommendations.author.ipr.description
|
|
||||||
на каждого сотрудника.
|
|
||||||
|
|
||||||
*Индивидуальный план обучения* — это список целей и задач, которые помогают человеку развиваться в определенной области.
|
|
||||||
|
|
||||||
# Как составить план:
|
|
||||||
- составить матрицу компетенций;
|
|
||||||
- определить по каким компетенциям меньше всего знаний и опыта;
|
|
||||||
- узнать какие из этих компетенций интересны сотруднику;
|
|
||||||
- придумать 3..5 целей в рамках каждой такой компетенции на пол-года или год;
|
|
||||||
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
|
||||||
- каждый месяц напоминать об общем плане достижения этих целей;
|
|
||||||
|
|
||||||
# Нужен ли план руководителю?
|
|
||||||
Да, руководитель так же должен составить план на себя. Если нет вышестоящего руководителя, то он должен проверять сам себя.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- сотрудники становятся более лояльны к компании;
|
|
||||||
- за теже деньги вы получаете более квалифицированные кадры;
|
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.title
|
|
||||||
Проводите 1-1 каждый месяц
|
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.description
|
|
||||||
это поможет выявить проблемы на ранней стадии.
|
|
||||||
|
|
||||||
*One-to-one* — это регулярные личные встречи руководителя с подчиненным. На таких встречах обычно обсуждают всё, что важно для сотрудника, что его волнует, и то, чем он может поделиться с руководителем только наедине.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- легко выяснить, кто из сотрудников перегружен, а у кого есть свободное время;
|
|
||||||
- можно предотвратить выгорание сотрудника;
|
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
|
||||||
- повышается мотивация и вовлеченность сотрудников;
|
|
||||||
|
|
||||||
§ recommendations.author.club.title
|
|
||||||
Ходите в бар
|
|
||||||
|
|
||||||
§ recommendations.author.club.description
|
|
||||||
один раз в месяц или два.
|
|
||||||
|
|
||||||
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
|
||||||
- повышается вовлеченность сотрудников;
|
|
||||||
|
|
||||||
§ recommendations.hour.onlyWork.title
|
|
||||||
Выходных тут нет
|
|
||||||
|
|
||||||
§ recommendations.hour.onlyWork.description
|
|
||||||
Вероятно, стоит уволить менеджера проекта.
|
|
||||||
|
|
||||||
§ recommendations.hour.weekends.title
|
|
||||||
Работа на выходных
|
|
||||||
|
|
||||||
§ recommendations.hour.weekends.description
|
|
||||||
Вероятно, стоит проверить менеджера проекта.
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.hour.easy.title
|
|
||||||
Бывают проблемы
|
|
||||||
|
|
||||||
§ recommendations.hour.easy.description
|
|
||||||
Вероятно, бывают завалы и приходится работать на выходных.
|
|
||||||
|
|
||||||
§ recommendations.week.lazyDays.down.title
|
|
||||||
Стало меньше прогулов
|
|
||||||
§ recommendations.week.lazyDays.down.description
|
|
||||||
за последние три недели этот показатель упал
|
|
||||||
|
|
||||||
§ recommendations.week.lazyDays.up.title
|
|
||||||
Стало больше прогулов
|
|
||||||
§ recommendations.week.lazyDays.up.description
|
|
||||||
нет задач или нужен более жесткий контроль
|
|
||||||
|
|
||||||
§ recommendations.week.notWork.title
|
|
||||||
Стабильно не дорабатывает
|
|
||||||
§ recommendations.week.notWork.description
|
|
||||||
т.к. каждую неделю пишет код не 100% времени
|
|
||||||
|
|
||||||
§ recommendations.week.upWork.title
|
|
||||||
Стабильно перерабатывает
|
|
||||||
§ recommendations.week.upWork.description
|
|
||||||
т.к. каждую неделю пишет код в выходные дни
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.week.task.up.title
|
|
||||||
Растёт производительность
|
|
||||||
§ recommendations.week.task.up.description
|
|
||||||
или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
|
||||||
|
|
||||||
§ recommendations.week.task.down.title
|
|
||||||
Падает производительность
|
|
||||||
§ recommendations.week.task.down.description
|
|
||||||
или задачи хуже разбивают. Нужно проверить. Если гранулярность та же - взять на контроль.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- количество задач в день, над которыми работают, на протяжении последних трех недель стабильно падает.
|
|
||||||
|
|
||||||
# Возможные ошибки:
|
|
||||||
- задачи могли быть сложнее, чем казались;
|
|
||||||
- задачи могли иметь большой объём работы (нужно проверить количество изменений, падают они или нет за этот же период)
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.type.everyHasOne.title
|
|
||||||
Не подписывают тип задачи
|
|
||||||
|
|
||||||
§ recommendations.type.everyHasOne.description
|
|
||||||
большинство типов задач делает один человек.
|
|
||||||
|
|
||||||
§ recommendations.type.oneMaintainer.title
|
|
||||||
Узкая специализация
|
|
||||||
|
|
||||||
§ recommendations.type.oneMaintainer.description
|
|
||||||
большинство задач одного типа делают одни и те же люди.
|
|
||||||
# Типы задач:
|
|
||||||
|
|
||||||
§ recommendations.type.common
|
|
||||||
# Возможно, это не так
|
|
||||||
|
|
||||||
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
|
||||||
|
|
||||||
Шаги, которые помогут это сделать:
|
|
||||||
- настроить пре-коммит проверку для commit message;
|
|
||||||
- объяснить команде, что нужно указывать тип;
|
|
||||||
- проверить в новых ветках, что сотрудники следуют правилу;
|
|
||||||
|
|
||||||
# Если это действительно так
|
|
||||||
|
|
||||||
Вы настроили проверки и убедились что один и тот же сотрудник, делает задачи одного и того же типа.
|
|
||||||
|
|
||||||
Почему это плохо:
|
|
||||||
- его увольнение остановит целую пачку процессов;
|
|
||||||
- уменьшается компетенция остальных членов команды;
|
|
||||||
- трудно верхнеуровнево понять его правки;
|
|
||||||
|
|
||||||
Как это исправить:
|
|
||||||
- распределять разные типы задач равномерно;
|
|
||||||
- менять область работы (тесты, документация, ошибки) между сотрудниками через спринт;
|
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.title
|
|
||||||
Это локальный продукт
|
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.description
|
|
||||||
для конкретного заказчика или проблемы.
|
|
||||||
|
|
||||||
# Какие признаки есть у «глобального» продукта:
|
|
||||||
- локализация;
|
|
||||||
- документация;
|
|
||||||
- большой обьем тестов;
|
|
||||||
- визуальная кастомизация;
|
|
||||||
- рефакторинг узких мест;
|
|
||||||
- и т.п.
|
|
||||||
|
|
||||||
# Почему этот продукт выглядит как «локальный»:
|
|
||||||
- у каждого «глобального» признака будет перевес по своему типу задач;
|
|
||||||
- чем больше «глобальных» признаков, тем больше вероятность «глобального» продукта;
|
|
||||||
|
|
||||||
В данном случае мы видим небольшое число типов, а следовательно, скорее всего есть недоработки, мешающие легко масштабировать продукт на мировой рынок и продавать его в других странах.
|
|
||||||
|
|
||||||
# Возможно, это не так
|
|
||||||
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
|
||||||
|
|
||||||
§ recommendations.type.diff.title
|
|
||||||
Разбейте лидирующий тип на подтипы
|
|
||||||
|
|
||||||
§ recommendations.type.diff.description
|
|
||||||
для детализации ошибок.
|
|
||||||
|
|
||||||
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
|
|
||||||
|
|
||||||
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
|
|
||||||
|
|
||||||
Рассмотрим несколько вариантов подтипов:
|
|
||||||
- fix_dev (ошибка выявленная в процессе разработки);
|
|
||||||
- fix_test (ошибка выявленная в процессе тестирования);
|
|
||||||
- fix (ошибка выявленная в проде);
|
|
||||||
|
|
||||||
§ recommendations.type.buddy.title
|
|
||||||
Копите мелкие задачи
|
|
||||||
|
|
||||||
§ recommendations.type.buddy.description
|
|
||||||
для новых сотрудников.
|
|
||||||
|
|
||||||
# Если задача:
|
|
||||||
- не важная;
|
|
||||||
- не большая;
|
|
||||||
- не требует сильного погружения в контекст;
|
|
||||||
- больше про рефакторинг, чем про новый код;
|
|
||||||
|
|
||||||
# Положите её в backlog с меткой «для новичков».
|
|
||||||
|
|
||||||
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
|
|
||||||
|
|
||||||
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
|
|
||||||
`);
|
|
||||||
|
|
||||||
export default {};
|
|
|
@ -1,889 +0,0 @@
|
||||||
import localization from 'ts/helpers/Localization';
|
|
||||||
|
|
||||||
localization.parse('ru', `
|
|
||||||
§ achievements.commitsAfter1500.title: Сова
|
|
||||||
§ achievements.commitsAfter1500.description: 70% коммитов после 15:00
|
|
||||||
§ achievements.commitsBefore1500.title: Ранняя пташка
|
|
||||||
§ achievements.commitsBefore1500.description: 70% коммитов до обеда
|
|
||||||
§ achievements.workEveryTime.title: Раб божий
|
|
||||||
§ achievements.workEveryTime.description: есть коммит на каждый час суток
|
|
||||||
§ achievements.workNotWork.title: Стрельба холостыми
|
|
||||||
§ achievements.workNotWork.description: коммиты есть, а закрытых задач нет
|
|
||||||
§ achievements.userNotWork.title: Залётный
|
|
||||||
§ achievements.userNotWork.description: это не его основной проект
|
|
||||||
§ achievements.userIsDied.title: Мёртвая душа
|
|
||||||
§ achievements.userIsDied.description: работал, но уволился
|
|
||||||
§ achievements.lessTasks.title: Зашел и вышел
|
|
||||||
§ achievements.lessTasks.description: меньше всего закрытых задач
|
|
||||||
§ achievements.moreTasks.title: Батя грит малаца
|
|
||||||
§ achievements.moreTasks.description: больше всего закрытых задач
|
|
||||||
§ achievements.everyMessageLong.title: Мастер красноречия
|
|
||||||
§ achievements.everyMessageLong.description: стабильно самые длинные подписи коммитов
|
|
||||||
§ achievements.everyMessageShort.title: Болтун находка для шпиона
|
|
||||||
§ achievements.everyMessageShort.description: стабильно, самые короткие подписи коммитов
|
|
||||||
§ achievements.shortestName.title: Размер не главное
|
|
||||||
§ achievements.shortestName.description: самое короткое имя
|
|
||||||
§ achievements.longestName.title: Азим Азиз Иль Ам Кадир Имран II
|
|
||||||
§ achievements.longestName.description: самое длинное имя
|
|
||||||
§ achievements.moreCommits.title: Мастер бекапов
|
|
||||||
§ achievements.moreCommits.description: больше всего коммитов
|
|
||||||
§ achievements.lessCommits.title: Редко но метко
|
|
||||||
§ achievements.lessCommits.description: меньше всего коммитов
|
|
||||||
§ achievements.oneCommitOneTask.title: Точно в цель
|
|
||||||
§ achievements.oneCommitOneTask.description: в среднем один коммит на задачу
|
|
||||||
§ achievements.moreLazyDays.title: Мысленно я с вами
|
|
||||||
§ achievements.moreLazyDays.description: больше всего дней без коммитов
|
|
||||||
§ achievements.lessLazyDays.title: Папа Карло
|
|
||||||
§ achievements.lessLazyDays.description: меньше всего дней без коммитов
|
|
||||||
§ achievements.zeroLazyDays.title: Ни единого разрыва
|
|
||||||
§ achievements.zeroLazyDays.description: ни одного дня без коммитов
|
|
||||||
§ achievements.moreWorkDays.title: Ценный работник
|
|
||||||
§ achievements.moreWorkDays.description: больше всего рабочих дней
|
|
||||||
§ achievements.moreScopes.title: Стартапер
|
|
||||||
§ achievements.moreScopes.description: сделал больше всего фичей
|
|
||||||
§ achievements.lessScopes.title: Щегол
|
|
||||||
§ achievements.lessScopes.description: сделал меньше всего фичей
|
|
||||||
§ achievements.moreDaysForTask.title: Улитка на склоне
|
|
||||||
§ achievements.moreDaysForTask.description: работа по задачам идёт медленнее чем у остальных
|
|
||||||
§ achievements.more2DaysForTask.title: Cо слоу
|
|
||||||
§ achievements.more2DaysForTask.description: больше двух дней на задачу
|
|
||||||
§ achievements.moreDaysInProject.title: Старожил
|
|
||||||
§ achievements.moreDaysInProject.description: больше всего дней на проекте
|
|
||||||
§ achievements.lessDaysInProject.title: А это кто?
|
|
||||||
§ achievements.lessDaysInProject.description: меньше всего дней на проекте
|
|
||||||
§ achievements.more90DaysInProject.title: Добро пожаловать
|
|
||||||
§ achievements.more90DaysInProject.description: не уволили на испытательном
|
|
||||||
§ achievements.lessDaysForTask.title: Скорострел
|
|
||||||
§ achievements.lessDaysForTask.description: одна задача занимает меньше дня
|
|
||||||
§ achievements.adam.title: Адам
|
|
||||||
§ achievements.adam.description: первый стабильный сотрудник на проекте
|
|
||||||
§ achievements.more666DaysInProject.title: Чёрт
|
|
||||||
§ achievements.more666DaysInProject.description: отработал 666 дней на проекте
|
|
||||||
§ achievements.more777DaysInProject.title: Азино 3 топора
|
|
||||||
§ achievements.more777DaysInProject.description: отработал 777 дней на проекте
|
|
||||||
§ achievements.moreRefactoring.title: Выпускающий редактор
|
|
||||||
§ achievements.moreRefactoring.description: сделал больше всех меток «рефакторинг»
|
|
||||||
§ achievements.longestMessage.title: А разговоров то было...
|
|
||||||
§ achievements.longestMessage.description: самая длинная подпись коммита за все время
|
|
||||||
§ achievements.moreTasksInDay.title: Спиди-гонщик
|
|
||||||
§ achievements.moreTasksInDay.description: рекорд по количеству закрытых задач в день
|
|
||||||
§ achievements.hasCommitFrom0to7.title: Ночной дозор
|
|
||||||
§ achievements.hasCommitFrom0to7.description: есть коммит на каждый час ночи
|
|
||||||
§ achievements.noCommitOnDay.title: Технический перерыв
|
|
||||||
§ achievements.noCommitOnDay.description: есть определенный час и день в рабочее время в который никогда не комитит
|
|
||||||
§ achievements.hasCommitEveryTime.title: Умер на работе
|
|
||||||
§ achievements.hasCommitEveryTime.description: есть коммит на час каждого дня (включая выходные)
|
|
||||||
§ achievements.commitsAfter1800.title: Делу время
|
|
||||||
§ achievements.commitsAfter1800.description: нет ни одного коммита после 18:00
|
|
||||||
§ achievements.more1488DaysInProject.title: им. Максима Марцинкевича
|
|
||||||
§ achievements.more1488DaysInProject.description: отработал 1488 дней на проекте
|
|
||||||
§ achievements.taskNumber300.title: Знаком с трактористом
|
|
||||||
§ achievements.taskNumber300.description: первый взял в работу задачу с номером 300
|
|
||||||
§ achievements.moreFix.title: Bug hunter
|
|
||||||
§ achievements.moreFix.description: больше всего закрытых багов
|
|
||||||
§ achievements.lessWorkDays.title: Дальше без меня
|
|
||||||
§ achievements.lessWorkDays.description: меньше всего рабочих дней
|
|
||||||
§ achievements.moreCreateCode.title: Созидатель
|
|
||||||
§ achievements.moreCreateCode.description: склонен больше остальных добавлять код
|
|
||||||
§ achievements.moreRemoveCode.title: Разрушитель
|
|
||||||
§ achievements.moreRemoveCode.description: склонен больше остальных удалять код
|
|
||||||
§ achievements.moreChangeCode.title: Реформатор
|
|
||||||
§ achievements.moreChangeCode.description: склонен больше остальных изменять код
|
|
||||||
§ achievements.moreStyle.title: Полиция моды
|
|
||||||
§ achievements.moreStyle.description: склонен больше остальных изменять CSS
|
|
||||||
§ achievements.moreOnHoliday.title: Нет жизни
|
|
||||||
§ achievements.moreOnHoliday.description: относительно много коммитов в нерабочее время
|
|
||||||
§ uiKit.console: Копировать
|
|
||||||
§ uiKit.dataLoader.page: Страница
|
|
||||||
§ uiKit.dataLoader.size: Отображается по
|
|
||||||
§ uiKit.dataLoader.from: из
|
|
||||||
§ uiKit.dataLoader.all: Показать все
|
|
||||||
§ uiKit.hoursChart.work: стандартное рабочее время (будни, с 07:00 до 20:00)
|
|
||||||
§ uiKit.hoursChart.weekend: выходные дни или время до/после рабочего дня
|
|
||||||
§ uiKit.hoursChart.days: суммарное количество коммитов за все время в конкретный день и час
|
|
||||||
§ uiKit.page.remove: Удалить
|
|
||||||
§ uiKit.races.go: Поехали
|
|
||||||
§ uiKit.nothingFound.common.title: Нет или недостаточно данных для отображения
|
|
||||||
§ uiKit.nothingFound.common.description: Система обработает больше данных, если коммиты будут подписаны в формате [Git commit message convention|https://www.conventionalcommits.org/en/v1.0.0/]. Шаблон:
|
|
||||||
§ uiKit.nothingFound.common.console: Номер_задачи тип(фича): пояснение
|
|
||||||
§ uiKit.nothingFound.common.example: Например:
|
|
||||||
§ uiKit.nothingFound.staff.title: Нет данных для этого сотрудника
|
|
||||||
§ uiKit.nothingFound.staff.description1:
|
|
||||||
Он вносил правки не каждый рабочий день и получил статус «Помошник».
|
|
||||||
Работой сотрудников с таким статусом по данному проекту можно пренебречь, т.к. его влад на общем фоне незначителен.
|
|
||||||
|
|
||||||
§ uiKit.nothingFound.staff.description2:
|
|
||||||
Поэтому система не рассчитывает для него ряд показателей.
|
|
||||||
Если это ошибка и данного сотрудника нужно рассчитать как обычного, перейдите в раздел «Настройки» и измените его тип.
|
|
||||||
|
|
||||||
§ common.filters: Фильтры
|
|
||||||
§ common.notifications.save: Изменения сохранены
|
|
||||||
§ common.notifications.setting: Настройки сохранены
|
|
||||||
§ sidebar.switch.team: Команда
|
|
||||||
§ sidebar.switch.person: Сотрудник
|
|
||||||
§ sidebar.buttons.settings: Настройки
|
|
||||||
§ sidebar.buttons.print: Печать
|
|
||||||
§ sidebar.filters.all: всё время
|
|
||||||
§ sidebar.filters.year: год
|
|
||||||
§ sidebar.filters.halfYear: пол года
|
|
||||||
§ sidebar.filters.month: месяц
|
|
||||||
§ sidebar.filters.week: неделя
|
|
||||||
§ sidebar.team.total: Общая информация
|
|
||||||
§ sidebar.team.scope: Фичи
|
|
||||||
§ sidebar.team.author: Сотрудники
|
|
||||||
§ sidebar.team.type: Типы задач
|
|
||||||
§ sidebar.team.pr: Влитие кода
|
|
||||||
§ sidebar.team.day: По дням
|
|
||||||
§ sidebar.team.week: По неделям
|
|
||||||
§ sidebar.team.month: По месяцам
|
|
||||||
§ sidebar.team.tree: Анализ файлов
|
|
||||||
§ sidebar.team.hours: Расписание
|
|
||||||
§ sidebar.team.commits: Все коммиты
|
|
||||||
§ sidebar.team.changes: Все изменения
|
|
||||||
§ sidebar.team.words: Популярные слова
|
|
||||||
§ sidebar.team.top: Викторина
|
|
||||||
§ sidebar.team.settings: Настройки
|
|
||||||
§ sidebar.person.total: Общая информация
|
|
||||||
§ sidebar.person.money: Стоимость работы
|
|
||||||
§ sidebar.person.speed: Скорость
|
|
||||||
§ sidebar.person.day: По дням
|
|
||||||
§ sidebar.person.week: По неделям
|
|
||||||
§ sidebar.person.month: По месяцам
|
|
||||||
§ sidebar.person.hours: Расписание
|
|
||||||
§ sidebar.person.commits: Все коммиты
|
|
||||||
§ sidebar.person.changes: Все изменения
|
|
||||||
§ sidebar.person.words: Популярные слова
|
|
||||||
§ sidebar.person.settings: Настройки
|
|
||||||
§ page.welcome.step1: Выполните команду в корне вашего проекта
|
|
||||||
§ page.welcome.step3: Перетащите
|
|
||||||
§ page.welcome.step4: файл log.txt на эту страницу
|
|
||||||
§ page.welcome.description1: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл
|
|
||||||
§ page.welcome.description2: [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы обьединить статистику по сотрудникам.
|
|
||||||
§ page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы обьединить статистику по сотрудникам.
|
|
||||||
§ page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
|
|
||||||
§ page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].
|
|
||||||
§ page.common.words.title: Статистика по словам
|
|
||||||
§ page.common.words.description: самое популярное слово. Встречается $1 раза.
|
|
||||||
§ page.common.commits.title: Количество коммитов по дням
|
|
||||||
§ page.common.commits.description: ($1) самый продуктивный день по числу коммитов.
|
|
||||||
§ page.common.commits.title2: $1 сделано коммитов: $2
|
|
||||||
§ page.common.filter.allUsers: Не имеет значения
|
|
||||||
§ page.settings.document.title: Настройки отображения
|
|
||||||
§ page.settings.document.name: Заголовок страницы
|
|
||||||
§ page.settings.document.language: Язык интерфейса
|
|
||||||
§ page.settings.links.title: Префиксы ссылок
|
|
||||||
§ page.settings.links.task: Для номеров задач
|
|
||||||
§ page.settings.links.pr: Для PR
|
|
||||||
§ page.settings.user.title: Индивидуальные настройки
|
|
||||||
§ page.settings.user.notFound: Индивидуальных настроек нет. Данные по всем сотрудникам вычисляются по общим параметрам.
|
|
||||||
§ page.settings.user.subTitle: Дополнение к трудовому договору №$1
|
|
||||||
§ page.settings.user.from: Дата начала действия
|
|
||||||
§ page.settings.mailmap: Настройки .mailmap
|
|
||||||
§ page.settings.common.title: Общие данные по зарплате
|
|
||||||
§ page.settings.common.type.title: Тип работы над проектом
|
|
||||||
§ page.settings.common.type.full: Полная занятость
|
|
||||||
§ page.settings.common.type.part: Проектная работа
|
|
||||||
§ page.settings.common.salary: Зарплата в месяц
|
|
||||||
§ page.settings.common.currency: Валюта
|
|
||||||
§ page.settings.common.workDaysInYear: Количество рабочих дней в году
|
|
||||||
§ page.settings.common.vacationDaysInYear: Количество дней отпуска в год
|
|
||||||
§ page.settings.common.workDaysInWeek: Рабочие дни
|
|
||||||
§ page.settings.form.save: Сохранить
|
|
||||||
§ page.settings.form.cancel: Отмена
|
|
||||||
§ page.settings.form.remove: Удалить
|
|
||||||
§ page.settings.form.addEmployee: Добавить сотрудника
|
|
||||||
§ page.settings.form.addContract: Добавить трудовой договор
|
|
||||||
§ page.print.modal.title: Что распечатываем?
|
|
||||||
§ page.print.modal.page: Текущую страницу
|
|
||||||
§ page.print.modal.type: Текущий раздел
|
|
||||||
§ page.print.modal.all: Всю статистику
|
|
||||||
§ page.print.modal.cancel: Отмена
|
|
||||||
§ page.print.tableOfContents: Оглавление
|
|
||||||
§ page.print.title: Отчёт по git-репозиторию «$1»
|
|
||||||
§ page.print.description: Данные для отчёта были получены из истории коммитов.
|
|
||||||
§ page.team.author.title: Статистика по сотрудникам
|
|
||||||
§ page.team.author.description1: *Часть статитики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помошник» не считается*, т.к. это эпизодическая роль в проекте. Предпологаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
|
||||||
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
|
||||||
§ page.team.author.types: Тип работ
|
|
||||||
§ page.team.author.commits: Коммитов
|
|
||||||
§ page.team.author.commitsSmall: коммитов
|
|
||||||
§ page.team.author.tasks: Задач
|
|
||||||
§ page.team.author.tasksSmall: задач
|
|
||||||
§ page.team.author.workedLosses: Дни с коммитами и без
|
|
||||||
§ page.team.author.worked: работа
|
|
||||||
§ page.team.author.losses: дни без коммитов
|
|
||||||
§ page.team.author.days: дней
|
|
||||||
§ page.team.author.daysForTask: Дней на задачу
|
|
||||||
§ page.team.author.scopes: Фич
|
|
||||||
§ page.team.author.moneyAll: Получил
|
|
||||||
§ page.team.author.moneyWorked: Отработал
|
|
||||||
§ page.team.author.moneyLosses: Переплата
|
|
||||||
§ page.team.hours.title: Распределение коммитов в течении каждого дня недели
|
|
||||||
§ page.team.month.title: Календарь работы по проекту
|
|
||||||
§ page.team.scope.title: Статистика по фичам
|
|
||||||
§ page.team.scope.scope: Фича
|
|
||||||
§ page.team.scope.days: Раб. дней
|
|
||||||
§ page.team.scope.authorsDays: Человеко-дней
|
|
||||||
§ page.team.scope.tasks: Задач
|
|
||||||
§ page.team.scope.commits: Коммитов
|
|
||||||
§ page.team.scope.commitsSmall: коммитов
|
|
||||||
§ page.team.scope.types: Тип работ
|
|
||||||
§ page.team.scope.authors: Персональный вклад
|
|
||||||
§ page.team.scope.cost: Стоимость
|
|
||||||
§ page.team.type.title: Статистика по типам задач
|
|
||||||
§ page.team.type.description: *Персональный вклад* считается по количеству коммитов, а не объему измененных строк или файлов. Поэтому следует так же смотреть раздел «Анализ файлов», чтобы оценить масштаб изменений.
|
|
||||||
§ page.team.type.type: Тип работы
|
|
||||||
§ page.team.type.tasks: Задач
|
|
||||||
§ page.team.type.tasksSmall: задач
|
|
||||||
§ page.team.type.days: Дней
|
|
||||||
§ page.team.type.daysSmall: дней
|
|
||||||
§ page.team.type.authorsDays: Человеко-дней
|
|
||||||
§ page.team.type.commits: Коммитов
|
|
||||||
§ page.team.type.authors: Персональный вклад
|
|
||||||
§ page.team.total.titleA: Объём работ
|
|
||||||
§ page.team.total.titleB: Стоимость
|
|
||||||
§ page.team.total.daysWorked.title: человеко-дней
|
|
||||||
§ page.team.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.team.total.commits.title: коммитов
|
|
||||||
§ page.team.total.commits.description: Удалённые ветки не считаются
|
|
||||||
§ page.team.total.daysLosses.title: дней без коммитов
|
|
||||||
§ page.team.total.daysLosses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
|
||||||
§ page.team.total.employment.title: работает / уволилось
|
|
||||||
§ page.team.total.employment.description: Если сотрудник в течении месяца не сделал ни одного коммита, он считается уволенным
|
|
||||||
§ page.team.total.moneyAll.title: общая
|
|
||||||
§ page.team.total.moneyAll.description: Суммарные затраты на зп
|
|
||||||
§ page.team.total.moneyWorked.title: фактическая
|
|
||||||
§ page.team.total.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
|
||||||
§ page.team.total.moneyLosses.title: возможная переплата
|
|
||||||
§ page.team.total.moneyLosses.description: Оплаченные рабочие дни, когда коммитов не было
|
|
||||||
§ page.team.total.weekendPayment.title: работа на выходных
|
|
||||||
§ page.team.total.weekendPayment.description: Суммарная переплата за работу в выходные дни
|
|
||||||
§ page.team.total.workSpeed.title: задач в день
|
|
||||||
§ page.team.total.workSpeed.description: Средняя скорость работы команды при текущем составе сотрудников
|
|
||||||
§ page.team.total.moneySpeed.title: в месяц
|
|
||||||
§ page.team.total.moneySpeed.description: Прогнозируемая сумма выплаты на зп при текущем составе сотрудников без учета налогов и сопутствующих затрат
|
|
||||||
§ page.team.total.description1: *Человеко-дни* — это работа одного сотрудника в течение одного рабочего дня. Например, за один календарный день, команда из трех сотрудников выдает объем работы в три человеко-дня.
|
|
||||||
§ page.team.total.description2: *Днями прогулов* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют.
|
|
||||||
§ page.team.total.description3: Карточка *работает и уволилось* показывает фактический состав сотрудников, которые постоянно участвуют в работе. Кроме этого, есть «помощники» — это сотрудники, как правило другой специализации, которые могут иногда делать коммиты в проект.
|
|
||||||
§ page.team.total.description4: *Переплатой* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют. Именно поэтому переплата + фактическая стоимость != общей. В общей стоимости заложена оплата выходных, государственных праздников и отпусков.
|
|
||||||
§ page.team.total.description5: *Работой на выходных* считается по коэфициенту х2 от оплаты обычного дня. Выше отображена именно переплата (х1), т.к. сам факт переработки в данном контексте не интересен. Мы не смотрим скорость сжигания бюджета. Мы смотрим переплату при увеличении скорости работы.
|
|
||||||
§ page.team.tree.title: Дерево проекта с учётом выбранных фильтров
|
|
||||||
§ page.team.tree.filters.author: Сотрудник
|
|
||||||
§ page.team.tree.filters.commits: Количество коммитов
|
|
||||||
§ page.team.tree.filters.help: Минимальное количество коммитов, которое сделал сотрудник в файле
|
|
||||||
§ page.team.tree.filters.all: Все сотрудники
|
|
||||||
§ page.team.tree.add: Кто добавлял
|
|
||||||
§ page.team.tree.change: Кто менял
|
|
||||||
§ page.team.tree.remove: Кто удалял
|
|
||||||
§ page.team.tree.line: строк
|
|
||||||
§ page.team.tree.lineAdd: добавили
|
|
||||||
§ page.team.tree.lineRemove: изменили
|
|
||||||
§ page.team.week.date: Дата
|
|
||||||
§ page.team.week.numberTasks: Количество задач
|
|
||||||
§ page.team.week.people: Количество человек
|
|
||||||
§ page.team.week.line: Изменение строк
|
|
||||||
§ page.team.week.days: Дни с коммитами и без
|
|
||||||
§ page.team.week.lossesDetails: Кто не коммитил
|
|
||||||
§ page.team.week.add: добавили
|
|
||||||
§ page.team.week.change: изменили
|
|
||||||
§ page.team.week.remove: удалили
|
|
||||||
§ page.team.week.hasCommits: были коммиты
|
|
||||||
§ page.team.week.hasNotCommits: небыло коммитов
|
|
||||||
§ page.team.week.days: дней
|
|
||||||
§ page.team.week.tasks: задач
|
|
||||||
§ page.team.pr.task: Задача
|
|
||||||
§ page.team.pr.tasks: задач
|
|
||||||
§ page.team.pr.firstCommitTime: Первый коммит
|
|
||||||
§ page.team.pr.lastCommitTime: Последний
|
|
||||||
§ page.team.pr.workDays: Дней разработки
|
|
||||||
§ page.team.pr.delayDays: Дней ожидания влития
|
|
||||||
§ page.team.pr.commits: Коммиты
|
|
||||||
§ page.team.pr.date: Дата влития
|
|
||||||
§ page.team.pr.mergeAuthor: Влил
|
|
||||||
§ page.team.pr.author: Сотрудник
|
|
||||||
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
|
||||||
§ page.team.pr.work: разработка
|
|
||||||
§ page.team.pr.delay: ожидание
|
|
||||||
§ page.team.pr.days: дней
|
|
||||||
§ page.team.pr.oneTaskDays: Время потраченное на одну задачу
|
|
||||||
§ page.team.pr.description1: *Время разработки* это разница времени от первого до последнего коммита по задаче. Не важно были перерывы в несколько дней между коммитами или нет. Сам факт какого-либо коммита увеличивает время.
|
|
||||||
§ page.team.pr.description2: *Время ожидания* это время между последним коммитом и влитием кода. Оно показывает фактический простой в ожидании чего-либо.
|
|
||||||
§ page.team.pr.description3: *Зачем отображать время разработки* без разбивки на кодинг и код-ревью? Затем, чтобы показать бизнесу фактическое время поставки кода. Ожидание тестирования, замечания на ревью, проблемы DevOps и прочие несовершенства процесса, как раз уже заложены в этот срок.
|
|
||||||
§ page.team.pr.statByAuthors: Статистика по сотрудникам
|
|
||||||
§ page.team.pr.longDelay: Длительное ожидание влития
|
|
||||||
§ page.person.print.photo.title: Фотография
|
|
||||||
§ page.person.print.photo.description: место для фотографии
|
|
||||||
§ page.person.total.title: Основные характеристики
|
|
||||||
§ page.person.total.daysWorked.title: дней работы
|
|
||||||
§ page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.person.total.tasks.title: задач
|
|
||||||
§ page.person.total.tasks.description: Если коммиты правильно подписаны
|
|
||||||
§ page.person.character.title: Персонаж
|
|
||||||
§ page.person.achievement.title: Достижения
|
|
||||||
§ page.person.achievement.positive: Позитивные
|
|
||||||
§ page.person.achievement.normal: Нейтральные
|
|
||||||
§ page.person.achievement.negative: Негативные
|
|
||||||
§ page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
|
|
||||||
§ page.person.gets.title: Взятые геты:
|
|
||||||
§ page.person.gets.description: «Взять гет» в данном случае означает первым оставить коммит к задаче с «красивым» номером.
|
|
||||||
§ page.person.business.days.title: дней работы
|
|
||||||
§ page.person.business.days.description: Учтены только дни, в которые делались коммиты
|
|
||||||
§ page.person.business.tasks.title: задач
|
|
||||||
§ page.person.business.tasks.description: Если коммиты правильно подписаны
|
|
||||||
§ page.person.business.losses.title: дней без коммитов
|
|
||||||
§ page.person.business.losses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
|
||||||
§ page.person.business.commits.title: коммитов
|
|
||||||
§ page.person.business.commits.description: Удалённые ветки не считаются
|
|
||||||
§ page.person.business.time.description: Время от первого, до последнего коммита (в том числе, нерабочие дни)
|
|
||||||
§ page.person.business.time.title: Дней на проекте:
|
|
||||||
§ page.person.business.time.dismissed: (уволен)
|
|
||||||
§ page.person.business.time.staff: (не в команде)
|
|
||||||
§ page.person.business.achievements: Достижения
|
|
||||||
§ page.person.changes.title: Достижения
|
|
||||||
§ page.person.changes.description:
|
|
||||||
При некоторых видах форматирования git отмечает строки как «удалённые» и «добавленные»,
|
|
||||||
хотя на самом деле они были «изменёны». Поэтому, если вы провели большой рефакторинг,
|
|
||||||
git может показать малое количество изменений в статистике, а фактический результат
|
|
||||||
будет отмечен, как скачок «удаленных» и «добавленных» строк.
|
|
||||||
§ page.person.changes.description: Список коммитов и количество изменений в них за этот день:
|
|
||||||
§ page.person.commits.title: Список коммитов:
|
|
||||||
§ page.person.money.title.total: За всё время
|
|
||||||
§ page.person.money.title.middle: Средняя стоимость
|
|
||||||
§ page.person.money.moneyAll.title: получил
|
|
||||||
§ page.person.money.moneyAll.description: Предполагаемая сумма зп с проекта (см. настройки)
|
|
||||||
§ page.person.money.moneyWorked.title: отработал
|
|
||||||
§ page.person.money.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
|
||||||
§ page.person.money.moneyLosses.title: возможная переплата
|
|
||||||
§ page.person.money.moneyLosses.description: Дни без коммитов умноженные на среднюю зп
|
|
||||||
§ page.person.money.tasks.title: задача
|
|
||||||
§ page.person.money.tasks.description: Количество закрытых задач к стоимости дня
|
|
||||||
§ page.person.money.commits.title: коммит
|
|
||||||
§ page.person.money.commits.description: Количество коммитов к стоимости рабочего дня
|
|
||||||
§ page.person.speed.task: Одна задача в среднем это
|
|
||||||
§ page.person.speed.max: Максимальная скорость в день
|
|
||||||
§ page.person.speed.days.title: дней
|
|
||||||
§ page.person.speed.days.description: Имеются ввиду рабочие дни, если коммиты правильно подписаны
|
|
||||||
§ page.person.speed.commits.title: коммитов
|
|
||||||
§ page.person.speed.commits.description: Отрезаны 10% максимальных и минимальных значений
|
|
||||||
§ page.person.speed.line.title: строк кода
|
|
||||||
§ page.person.speed.line.description: Отрезаны 10% максимальных и минимальных значений
|
|
||||||
§ 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: выходные
|
|
||||||
|
|
||||||
§ recommendations.title
|
|
||||||
Рекомендации и факты
|
|
||||||
|
|
||||||
§ recommendations.timestamp.firstCommit.description
|
|
||||||
сделал первый коммит
|
|
||||||
|
|
||||||
День недели: $1
|
|
||||||
|
|
||||||
§ recommendations.timestamp.lastCommit.description
|
|
||||||
сделал последний коммит
|
|
||||||
|
|
||||||
День недели: $1
|
|
||||||
|
|
||||||
§ recommendations.timestamp.common.title: $1 дней
|
|
||||||
§ recommendations.timestamp.allDays.description: от первого до последнего коммита (включая выходные и праздники).
|
|
||||||
§ recommendations.timestamp.lossesDays.description: без коммитов, даже с учётом выходных, отпуска и государственных праздников.
|
|
||||||
§ recommendations.timestamp.weekendDays.description
|
|
||||||
работы на выходных
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
|
||||||
- сотрудники быстрее выгорают;
|
|
||||||
|
|
||||||
§ recommendations.timestamp.regularWeekendWord.title: Регулярные переработки
|
|
||||||
§ recommendations.timestamp.sometimeWeekendWord.title: Бывают переработки
|
|
||||||
§ recommendations.timestamp.weekendWord.description
|
|
||||||
Вероятно, стоит сменить менеджера проекта, аналитика и архитектора.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
|
||||||
- качество продуката, как правило, получается низкое;
|
|
||||||
- часть сотрудников увольняется;
|
|
||||||
- из-за спешки появляются новые ошибки;
|
|
||||||
|
|
||||||
# Скорее всего:
|
|
||||||
- неверно оценили сроки в самом начале;
|
|
||||||
- тех. задание отсутствует;
|
|
||||||
- слабая аналитика;
|
|
||||||
- слабая архитектура (архитектора не нанимали, а команда состоит из мидл разработчиков);
|
|
||||||
- сначала начали писать код, потом проектировать;
|
|
||||||
- нет нормальных процессов, чтобы понять ошибки;
|
|
||||||
|
|
||||||
§ recommendations.timestamp.neverWeekendWord.title: Обычно без переработок
|
|
||||||
§ recommendations.timestamp.neverWeekendWord.description
|
|
||||||
Но иногда бывают.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- заказчик платит двойную цену за работу в выходной день;
|
|
||||||
- сотрудники быстрее выгорают;
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.title
|
|
||||||
Нет паралельных работ
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.not.description
|
|
||||||
любую фичу в один момент времени делает один человек.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат меньше 1.3 считаем, что паралельных работ в рамках большинства фичей обычно нет;
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- повышается bus factor;
|
|
||||||
- сотрудники медленее развиваются;
|
|
||||||
- трудно качественно проверить работу сотрудника;
|
|
||||||
|
|
||||||
# Почему это хорошо:
|
|
||||||
- появляюся эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
|
||||||
- скорее всего не бывает merge конфликтов;
|
|
||||||
- проект может очень быстро паралельно развиваться в разные стороны;
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.title
|
|
||||||
Часть работ паралельно
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.has.description
|
|
||||||
Иногда фичу делают одновременно несколько человек.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делалается паралельно;
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.title
|
|
||||||
Паралельные работы
|
|
||||||
|
|
||||||
§ recommendations.scope.parallelism.every.description
|
|
||||||
любую фичу в один момент времени делают несколько человек
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни делятся на фактические дни для каждой фичи;
|
|
||||||
- находим среднее арифметическое;
|
|
||||||
- если результат больше двух считаем, что большая часть работ в рамках разных фичей обычно делалается паралельно;
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.scope.money
|
|
||||||
в такую сумму можно оценить работу по данному проекту.
|
|
||||||
|
|
||||||
# Метод расчёта:
|
|
||||||
- человеко-дни затраченные на разработку умножаются на индивидуальную зарплату разработчиков;
|
|
||||||
|
|
||||||
Изменить зарплату каждого разработчика, для более точной суммы, можно в разделе «Настройки»
|
|
||||||
|
|
||||||
# Это много или мало?
|
|
||||||
Для ответа на этот вопрос, нужно ответить на следующие:
|
|
||||||
- Можно ли за эти деньги было купить готовое решение?
|
|
||||||
- Можно ли за эти деньги сделать более хороший продукт?
|
|
||||||
|
|
||||||
Если ответ на оба вопроса «да», то возможно, разработка с нуля не стоила потраченных на неё денег.
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.title
|
|
||||||
Bus factor = 1
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.everyHasOne.description
|
|
||||||
В большинство фич погружен один человек.
|
|
||||||
Надо переключать людей.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- если сотрудники будут увольнятся, будет трудно продолжить их работу;
|
|
||||||
- невозможно контролировать качество его кода;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- более 80% коммитов в фичу делает один человек;
|
|
||||||
- проект имеет более 60% таких фичей;
|
|
||||||
|
|
||||||
§ recommendations.scope.bus.oneMaintainer
|
|
||||||
в фичи погружен один человек.
|
|
||||||
|
|
||||||
# Почему это плохо:
|
|
||||||
- если он уволится, будет трудно продолжить разработку;
|
|
||||||
- снижается качество code-review;
|
|
||||||
- трудно запаралелить разработку при необходимости;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- более 80% коммитов в фичу сделал один человек;
|
|
||||||
|
|
||||||
§ recommendations.scope.types.process.title
|
|
||||||
Плохие процессы
|
|
||||||
|
|
||||||
§ recommendations.scope.types.process.description
|
|
||||||
Большинство фич содержат один тип задач.
|
|
||||||
|
|
||||||
§ recommendations.scope.types.one
|
|
||||||
фичи содержат один тип задач.
|
|
||||||
|
|
||||||
§ recommendations.scope.types.common
|
|
||||||
Возможно, разработчики неправильно подписывают коммиты или менеджер заводит один и тот же тип задач.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- невозможно передать поддержку другой команде;
|
|
||||||
- невозможно выпустить "коробочную" версию;
|
|
||||||
- сильная зависимость от конкретных разработчиков;
|
|
||||||
- большое количество ошибок и низкое качество кода;
|
|
||||||
- вероятное замедление разработки в будущем;
|
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
|
||||||
- взгляд на продукт, только с позиции «работающей демки»;
|
|
||||||
|
|
||||||
# Что должно быть:
|
|
||||||
- тесты;
|
|
||||||
- ошибки (выявленные по результатам тестов);
|
|
||||||
- рефакторинг (т.к. архитектура может измениться);
|
|
||||||
- документация;
|
|
||||||
- правки стиля (как результат опроса фокус-группы);
|
|
||||||
|
|
||||||
§ recommendations.scope.plan.title
|
|
||||||
Постройте долгосрочный план
|
|
||||||
|
|
||||||
§ recommendations.scope.plan.description
|
|
||||||
с учетом архитектуры.
|
|
||||||
|
|
||||||
При том опираться этот план должен сразу на самые трудные задачи.
|
|
||||||
|
|
||||||
# Почему отсутствие плана плохо:
|
|
||||||
- сотрудники делают минимально работающую версию, не закладывая точки расширения. После этого пишется не масштабируемый код, который тормозит следующие фичи;
|
|
||||||
|
|
||||||
# В чём ошибка менеджера:
|
|
||||||
- он не показал, как продукт будет развиваться далее и в каких точках будет рост;
|
|
||||||
|
|
||||||
# Как должно быть:
|
|
||||||
- составлятся глобальный план развития продукта;
|
|
||||||
- составлятся глобальный план развития архитектуры (с разработчиками и DBA);
|
|
||||||
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
|
||||||
|
|
||||||
§ recommendations.scope.cost.title
|
|
||||||
Оцените инвестиции в фичу
|
|
||||||
|
|
||||||
§ recommendations.scope.cost.description
|
|
||||||
с количеством потенциальной прибыли.
|
|
||||||
|
|
||||||
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более комерчески успешным.
|
|
||||||
|
|
||||||
§ recommendations.author.lotOfLazy
|
|
||||||
пишет слишком мало кода.
|
|
||||||
|
|
||||||
# Может уволить?
|
|
||||||
- он тимлид, архитектор, аналитик?
|
|
||||||
- это его основной проект?
|
|
||||||
- есть какие-то зависимости от него?
|
|
||||||
|
|
||||||
# Почему нет смысла исправлять
|
|
||||||
Суммарные затраты на разработчика уже больше чем прибыль от его работы.
|
|
||||||
Если мы считаем, что обьективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
|
||||||
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
|
||||||
|
|
||||||
§ recommendations.author.manyLazy
|
|
||||||
пишет мало кода. Нужно взять на контроль.
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
|
||||||
- в данном случае показатель от 60% до 80%;
|
|
||||||
|
|
||||||
# Как контролировать:
|
|
||||||
- дробить задачи на 1..2 дня;
|
|
||||||
- каждый день спрашивать статус;
|
|
||||||
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
|
||||||
- устроить парное программирование, чтобы проверить фактическую скорость;
|
|
||||||
|
|
||||||
§ recommendations.author.oneTypeMans
|
|
||||||
получает слишком однообразные задачи по типу. Может выгореть.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- если сотрудник выгорит, его скорость работы снизится;
|
|
||||||
- замедляется профессиональный рост;
|
|
||||||
- повышается вероятность увольнения;
|
|
||||||
|
|
||||||
# Как делается выборка:
|
|
||||||
- для каждого коммита определятся тип задачи;
|
|
||||||
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
|
||||||
|
|
||||||
§ recommendations.author.workToday.title: Работает $1
|
|
||||||
§ recommendations.author.workToday.description
|
|
||||||
над проектом в данный момент.
|
|
||||||
|
|
||||||
# Состав:
|
|
||||||
- $1;
|
|
||||||
|
|
||||||
# Почему именно они:
|
|
||||||
- рабочих дней более 50%;
|
|
||||||
- работали в течении последних 30 дней;
|
|
||||||
|
|
||||||
§ recommendations.author.dismissed.title: Уволилось $1
|
|
||||||
§ recommendations.author.dismissed.description
|
|
||||||
или работало короткий промежуток времени.
|
|
||||||
|
|
||||||
# Состав:
|
|
||||||
- $1;
|
|
||||||
|
|
||||||
# Почему именно они:
|
|
||||||
- работали в нормальном ритме (видимо, это их основной репозиторий);
|
|
||||||
- за последний месяц не было ни одного коммита;
|
|
||||||
- отпуск обычно 14 дней (их отсутствие не похоже на отпуск);
|
|
||||||
|
|
||||||
§ recommendations.author.staff.title: Помогают $1
|
|
||||||
§ recommendations.author.staff.description
|
|
||||||
Люди другой специализации, которые что-либо коммитили.
|
|
||||||
|
|
||||||
# Состав:
|
|
||||||
- $1;
|
|
||||||
|
|
||||||
# Почему именно они:
|
|
||||||
- это не open-source проект;
|
|
||||||
- рабочих дней менее 15% от общего числа;
|
|
||||||
- изменяют примерно одни и те же файлы;
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.title
|
|
||||||
Открытый проект
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.openSource.description
|
|
||||||
пять дней в неделю тут не работают.
|
|
||||||
|
|
||||||
Проект может быть и закрытым, просто такой темп работы обычно у открытых библиотек на GitHub.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- берется статистика по всем активным разработчикам;
|
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
|
||||||
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
|
||||||
|
|
||||||
# Последствия
|
|
||||||
Для проектов, где работа не постоянна, нет смысла во многих показателях. Поэтому показатели без коммитов, скорости и т.п. будут скрыты.
|
|
||||||
|
|
||||||
Как правило, оценку таких проектов делают перед началом разработки своей закрытой версии. Самые интересные показатели в этом случае вероятная стоимость и суммарное время на разработку.
|
|
||||||
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.title
|
|
||||||
Слабая загрузка
|
|
||||||
|
|
||||||
§ recommendations.author.projectType.easy.description
|
|
||||||
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- берется статистика по всем активным разработчикам;
|
|
||||||
- подсчитывается среднее число дней работы и без коммитов;
|
|
||||||
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
|
||||||
|
|
||||||
# Возможные причины:
|
|
||||||
- фактически нет задач;
|
|
||||||
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
|
||||||
- разработчиков отвлекают совещаниями;
|
|
||||||
- команда не работает;
|
|
||||||
|
|
||||||
# Варианты решения:
|
|
||||||
- обсудить проблему с командой;
|
|
||||||
- уменьшить гранулярность задач, чтобы за день можно было успеть сделать одну или две задачи;
|
|
||||||
- ввести ежедневные совещания, чтобы проверять движение задач по статусу;
|
|
||||||
- устроить сеансы парного программирования, чтобы убедиться, что разработчик может работать быстрее;
|
|
||||||
|
|
||||||
§ recommendations.author.manager.title
|
|
||||||
Обозначьте дедлайны
|
|
||||||
|
|
||||||
§ recommendations.author.manager.description
|
|
||||||
У любой задачи должен быть чёткий дедлайн.
|
|
||||||
|
|
||||||
Это позволит не затягивать её выполнение на несколько дней или недель.
|
|
||||||
|
|
||||||
# Какие показатели стоит проверить:
|
|
||||||
- количество дней на одну задачу, которое тратит работник;
|
|
||||||
- количество дней ожидания влития PR (страница статистики по PR);
|
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.title
|
|
||||||
Проводите ежедневные совещания
|
|
||||||
|
|
||||||
§ recommendations.author.shorTalk.description
|
|
||||||
они помогают быть в курсе проекта.
|
|
||||||
|
|
||||||
Не растягивайте их отвлекаясь на постороние темы.
|
|
||||||
|
|
||||||
# На какие вопросы должен ответить сотрудник:
|
|
||||||
- что было сделано;
|
|
||||||
- что будет сделано;
|
|
||||||
- есть ли какие-либо проблемы;
|
|
||||||
|
|
||||||
# Следует обрывать монолог, если:
|
|
||||||
- начинают подробно описывать мелкие детали, которые не важны;
|
|
||||||
- уводят диалог в сторону, от первоначального плана;
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
Часто сотрудник, который ничего не делает, старается уйти от ответа. Для этого он рассказывает кучу ненужных подробностей свой работы. Это позволяет усыпить внимание участников и растянуть время ответа. Создается ощущение что он чем-то занят, хотя по факту работы не было.
|
|
||||||
|
|
||||||
§ recommendations.author.ipr.title
|
|
||||||
Составьте план обучения
|
|
||||||
|
|
||||||
§ recommendations.author.ipr.description
|
|
||||||
на каждого сотрудника.
|
|
||||||
|
|
||||||
*Индивидуальный план обучения* — это список целей и задач, которые помогают человеку развиваться в определенной области.
|
|
||||||
|
|
||||||
# Как составить план:
|
|
||||||
- составить матрицу компетенций;
|
|
||||||
- определить по каким компетенциям меньше всего знаний и опыта;
|
|
||||||
- узнать какие из этих компетенций интересны сотруднику;
|
|
||||||
- придумать 3..5 целей в рамках каждой такой компетенции на пол-года или год;
|
|
||||||
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
|
||||||
- каждый месяц напоминать об общем плане достижения этих целей;
|
|
||||||
|
|
||||||
# Нужен ли план руководителю?
|
|
||||||
Да, руководитель так же должен составить план на себя. Если нет вышестоящего руководителя, то он должен проверять сам себя.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- сотрудники становятся более лояльны к компании;
|
|
||||||
- за теже деньги вы получаете более квалифицированные кадры;
|
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.title
|
|
||||||
Проводите 1-1 каждый месяц
|
|
||||||
|
|
||||||
§ recommendations.author.oneToOne.description
|
|
||||||
это поможет выявить проблемы на ранней стадии.
|
|
||||||
|
|
||||||
*One-to-one* — это регулярные личные встречи руководителя с подчиненным. На таких встречах обычно обсуждают всё, что важно для сотрудника, что его волнует, и то, чем он может поделиться с руководителем только наедине.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- легко выяснить, кто из сотрудников перегружен, а у кого есть свободное время;
|
|
||||||
- можно предотвратить выгорание сотрудника;
|
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
|
||||||
- повышается мотивация и вовлеченность сотрудников;
|
|
||||||
|
|
||||||
§ recommendations.author.club.title
|
|
||||||
Ходите в бар
|
|
||||||
|
|
||||||
§ recommendations.author.club.description
|
|
||||||
один раз в месяц или два.
|
|
||||||
|
|
||||||
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
|
|
||||||
|
|
||||||
# Почему это важно:
|
|
||||||
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
|
||||||
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
|
||||||
- повышается вовлеченность сотрудников;
|
|
||||||
|
|
||||||
§ recommendations.hour.onlyWork.title: Выходных тут нет
|
|
||||||
§ recommendations.hour.onlyWork.description: Вероятно, стоит уволить менеджера проекта.
|
|
||||||
§ recommendations.hour.weekends.title: Работа на выходных
|
|
||||||
§ recommendations.hour.weekends.description: Вероятно, стоит проверить менеджера проекта.
|
|
||||||
§ recommendations.hour.easy.title: Бывают проблемы
|
|
||||||
§ recommendations.hour.easy.description: Вероятно, бывают завалы и приходится работать на выходных.
|
|
||||||
§ recommendations.week.lazyDays.down.title: Стало меньше прогулов
|
|
||||||
§ recommendations.week.lazyDays.down.description: за последние три недели этот показатель упал
|
|
||||||
§ recommendations.week.lazyDays.up.title: Стало больше прогулов
|
|
||||||
§ recommendations.week.lazyDays.up.description: нет задач или нужен более жесткий контроль
|
|
||||||
§ recommendations.week.notWork.title: Стабильно не дорабатывает
|
|
||||||
§ recommendations.week.notWork.description: т.к. каждую неделю пишет код не 100% времени
|
|
||||||
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
|
||||||
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
|
||||||
§ recommendations.week.task.up.title: Растёт производительность
|
|
||||||
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
|
||||||
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
|
||||||
§ recommendations.week.task.down.title: Падает производительность
|
|
||||||
§ recommendations.week.task.down.description
|
|
||||||
или задачи хуже разбивают. Нужно проверить. Если гранулярность та же - взять на контроль.
|
|
||||||
|
|
||||||
# Метод оценки:
|
|
||||||
- количество задач в день, над которыми работают, на протяжении последних трех недель стабильно падает.
|
|
||||||
|
|
||||||
# Возможные ошибки:
|
|
||||||
- задачи могли быть сложнее, чем казались;
|
|
||||||
- задачи могли иметь большой объём работы (нужно проверить количество изменений, падают они или нет за этот же период)
|
|
||||||
|
|
||||||
§ recommendations.type.everyHasOne.title: Не подписывают тип задачи
|
|
||||||
§ recommendations.type.everyHasOne.description: большинство типов задач делает один человек.
|
|
||||||
§ recommendations.type.oneMaintainer.title: Узкая специализация
|
|
||||||
§ recommendations.type.oneMaintainer.description
|
|
||||||
большинство задач одного типа делают одни и те же люди.
|
|
||||||
|
|
||||||
# Типы задач:
|
|
||||||
|
|
||||||
§ recommendations.type.common
|
|
||||||
# Возможно, это не так
|
|
||||||
|
|
||||||
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
|
||||||
|
|
||||||
Шаги, которые помогут это сделать:
|
|
||||||
- настроить пре-коммит проверку для commit message;
|
|
||||||
- объяснить команде, что нужно указывать тип;
|
|
||||||
- проверить в новых ветках, что сотрудники следуют правилу;
|
|
||||||
|
|
||||||
# Если это действительно так
|
|
||||||
|
|
||||||
Вы настроили проверки и убедились что один и тот же сотрудник, делает задачи одного и того же типа.
|
|
||||||
|
|
||||||
Почему это плохо:
|
|
||||||
- его увольнение остановит целую пачку процессов;
|
|
||||||
- уменьшается компетенция остальных членов команды;
|
|
||||||
- трудно верхнеуровнево понять его правки;
|
|
||||||
|
|
||||||
Как это исправить:
|
|
||||||
- распределять разные типы задач равномерно;
|
|
||||||
- менять область работы (тесты, документация, ошибки) между сотрудниками через спринт;
|
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.title
|
|
||||||
Это локальный продукт
|
|
||||||
|
|
||||||
§ recommendations.type.fewTypes.description
|
|
||||||
для конкретного заказчика или проблемы.
|
|
||||||
|
|
||||||
# Какие признаки есть у «глобального» продукта:
|
|
||||||
- локализация;
|
|
||||||
- документация;
|
|
||||||
- большой обьем тестов;
|
|
||||||
- визуальная кастомизация;
|
|
||||||
- рефакторинг узких мест;
|
|
||||||
- и т.п.
|
|
||||||
|
|
||||||
# Почему этот продукт выглядит как «локальный»:
|
|
||||||
- у каждого «глобального» признака будет перевес по своему типу задач;
|
|
||||||
- чем больше «глобальных» признаков, тем больше вероятность «глобального» продукта;
|
|
||||||
|
|
||||||
В данном случае мы видим небольшое число типов, а следовательно, скорее всего есть недоработки, мешающие легко масштабировать продукт на мировой рынок и продавать его в других странах.
|
|
||||||
|
|
||||||
# Возможно, это не так
|
|
||||||
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
|
||||||
|
|
||||||
§ recommendations.type.diff.title
|
|
||||||
Разбейте лидирующий тип на подтипы
|
|
||||||
|
|
||||||
§ recommendations.type.diff.description
|
|
||||||
для детализации ошибок.
|
|
||||||
|
|
||||||
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
|
|
||||||
|
|
||||||
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
|
|
||||||
|
|
||||||
Рассмотрим несколько вариантов подтипов:
|
|
||||||
- fix_dev (ошибка выявленная в процессе разработки);
|
|
||||||
- fix_test (ошибка выявленная в процессе тестирования);
|
|
||||||
- fix (ошибка выявленная в проде);
|
|
||||||
|
|
||||||
§ recommendations.type.buddy.title
|
|
||||||
Копите мелкие задачи
|
|
||||||
|
|
||||||
§ recommendations.type.buddy.description
|
|
||||||
для новых сотрудников.
|
|
||||||
|
|
||||||
# Если задача:
|
|
||||||
- не важная;
|
|
||||||
- не большая;
|
|
||||||
- не требует сильного погружения в контекст;
|
|
||||||
- больше про рефакторинг, чем про новый код;
|
|
||||||
|
|
||||||
# Положите её в backlog с меткой «для новичков».
|
|
||||||
|
|
||||||
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
|
|
||||||
|
|
||||||
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
|
|
||||||
`);
|
|
||||||
|
|
||||||
export default {};
|
|
82
src/ts/helpers/File.ts
Normal file
82
src/ts/helpers/File.ts
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { ColumnTypesEnum, IColumn } from '../components/Table/interfaces/Column';
|
||||||
|
// import localization from './Localization';
|
||||||
|
|
||||||
|
export function downloadFile(file: Blob, fileName: string) {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = URL.createObjectURL(file);
|
||||||
|
link.download = fileName;
|
||||||
|
document.body.append(link);
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
setTimeout(() => URL.revokeObjectURL(link.href), 7000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumnsFromChildren(children: React.ReactNode) {
|
||||||
|
const columns = React.Children.map(children, (child: React.ReactNode) => {
|
||||||
|
if (!React.isValidElement(child)) return null;
|
||||||
|
const template = child?.props?.template || ColumnTypesEnum.STRING;
|
||||||
|
return {
|
||||||
|
...child.props as object,
|
||||||
|
template,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const correctColumns = Array.from(columns)
|
||||||
|
.filter((column: IColumn) => column?.title);
|
||||||
|
|
||||||
|
return correctColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTitles(columns: IColumn[]) {
|
||||||
|
return columns.map((column: IColumn) => (column.title || '').split('.').pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFormatter(columns: IColumn[]) {
|
||||||
|
return (item: any) => {
|
||||||
|
return columns.map((column: IColumn) => {
|
||||||
|
let value = column.properties
|
||||||
|
? item[column.properties]
|
||||||
|
: item;
|
||||||
|
|
||||||
|
if (column.formatter) {
|
||||||
|
value = column.formatter(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const type = typeof value;
|
||||||
|
if (type === 'object') {
|
||||||
|
return JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'string') {
|
||||||
|
return value.replace('.', ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function downloadCsv(
|
||||||
|
list: Array<any>,
|
||||||
|
children: React.ReactNode,
|
||||||
|
name?: string,
|
||||||
|
) {
|
||||||
|
const columns = getColumnsFromChildren(children);
|
||||||
|
console.dir(columns);
|
||||||
|
const formatter = getFormatter(columns);
|
||||||
|
const csvFile = [
|
||||||
|
getTitles(columns).join(';'),
|
||||||
|
...list.map((item: any) => formatter(item).join(';')),
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
const type = 'text/csv;charset=windows-1251;'; // utf-8;';
|
||||||
|
const file = new Blob([csvFile], { type });
|
||||||
|
const fileName = `${document.title} - ${name || ''}.csv`;
|
||||||
|
return downloadFile(file, fileName);
|
||||||
|
}
|
|
@ -6,7 +6,6 @@ class Localization {
|
||||||
insertArguments(message: string, args?: any) {
|
insertArguments(message: string, args?: any) {
|
||||||
if (!args) return message;
|
if (!args) return message;
|
||||||
const list = Array.isArray(args) ? args : [args];
|
const list = Array.isArray(args) ? args : [args];
|
||||||
console.log(list);
|
|
||||||
list.forEach((text: any, index: number) => {
|
list.forEach((text: any, index: number) => {
|
||||||
message = message.replace(`$${index + 1}`, text || '_');
|
message = message.replace(`$${index + 1}`, text || '_');
|
||||||
});
|
});
|
||||||
|
|
59
src/ts/helpers/RPC.ts
Normal file
59
src/ts/helpers/RPC.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import IHashMap from 'ts/interfaces/HashMap';
|
||||||
|
|
||||||
|
function getParametersFromString(text: string): IHashMap<string> {
|
||||||
|
return Object.fromEntries((text || '')
|
||||||
|
.substring(1, Infinity)
|
||||||
|
.split('&')
|
||||||
|
.map((token: string) => token.split('=')));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParametersFromURL(): IHashMap<string> {
|
||||||
|
return {
|
||||||
|
...getParametersFromString(location.search),
|
||||||
|
...getParametersFromString(location.hash),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadJsDump(url: string, callback: Function) {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = url;
|
||||||
|
script.async = true; // @ts-ignore
|
||||||
|
script.onload = callback; // @ts-ignore
|
||||||
|
script.onerror = callback;
|
||||||
|
document.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCssFile(url: string) {
|
||||||
|
const node = document.createElement('link');
|
||||||
|
node.setAttribute('rel', 'stylesheet');
|
||||||
|
node.setAttribute('href', url);
|
||||||
|
document.body.appendChild(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
export let applicationHasCustom = {
|
||||||
|
theme: false,
|
||||||
|
title: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function applyUrlCommands(callback: Function) {
|
||||||
|
const parameters: IHashMap<string> = getParametersFromURL();
|
||||||
|
|
||||||
|
const cssUrl = parameters.style || parameters.theme;
|
||||||
|
if (cssUrl) {
|
||||||
|
loadCssFile(cssUrl);
|
||||||
|
applicationHasCustom.theme = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = parameters.title;
|
||||||
|
if (title) {
|
||||||
|
document.title = decodeURIComponent(title);
|
||||||
|
applicationHasCustom.title = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsUrl = parameters.dump || parameters.log;
|
||||||
|
if (jsUrl) {
|
||||||
|
loadJsDump(jsUrl, callback);
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,5 @@ export default function getTitle(dataGrip: any, commits: any) {
|
||||||
const formattedTask = task.split('-').shift().toUpperCase() || '';
|
const formattedTask = task.split('-').shift().toUpperCase() || '';
|
||||||
const formattedAuthor = author.split(' ').shift() || '';
|
const formattedAuthor = author.split(' ').shift() || '';
|
||||||
|
|
||||||
const title = `${type} ${formattedTask} (${year}, ${formattedAuthor})`;
|
return `${type} ${formattedTask} (${year}, ${formattedAuthor})`;
|
||||||
return `${title}. Git статистика`;
|
|
||||||
}
|
}
|
|
@ -59,7 +59,7 @@ export default function getAchievementByAuthor(author: string) {
|
||||||
if (getList?.some((commit: ICommit) => commit.taskNumber === '300')) list.push('taskNumber300');
|
if (getList?.some((commit: ICommit) => commit.taskNumber === '300')) list.push('taskNumber300');
|
||||||
|
|
||||||
return list.reduce((acc: any, type: string) => {
|
return list.reduce((acc: any, type: string) => {
|
||||||
const index = ALL_ACHIEVEMENTS[type][2];
|
const index = ALL_ACHIEVEMENTS[type] - 1;
|
||||||
acc[index].push(type);
|
acc[index].push(type);
|
||||||
return acc;
|
return acc;
|
||||||
}, [[], [], []]);
|
}, [[], [], []]);
|
||||||
|
|
|
@ -11,20 +11,21 @@ interface ITableOfContents {
|
||||||
|
|
||||||
function TableOfContents({ titles }: ITableOfContents) {
|
function TableOfContents({ titles }: ITableOfContents) {
|
||||||
const items = (titles || []).map((title) => (
|
const items = (titles || []).map((title) => (
|
||||||
<li
|
<a
|
||||||
key={title}
|
key={title}
|
||||||
className={style.table_of_contents_item}
|
className={style.table_of_contents_item}
|
||||||
|
href={`#${title}`}
|
||||||
>
|
>
|
||||||
{localization.get(title || '')}
|
{localization.get(title || '')}
|
||||||
</li>
|
</a>
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title="page.print.tableOfContents" />
|
<Title title="page.print.tableOfContents" />
|
||||||
<ul className={style.table_of_contents}>
|
<nav className={style.table_of_contents}>
|
||||||
{items}
|
{items}
|
||||||
</ul>
|
</nav>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
@import '../../../../styles/variables';
|
@import '../../../../styles/variables';
|
||||||
|
|
||||||
.table_of_contents {
|
.table_of_contents {
|
||||||
|
display: block;
|
||||||
margin-bottom: var(--space-xxl);
|
margin-bottom: var(--space-xxl);
|
||||||
|
|
||||||
&_item {
|
&_item {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: block;
|
||||||
padding: 0 0 0 22px;
|
padding: 0 0 0 22px;
|
||||||
margin: var(--space-m) 0;
|
margin: var(--space-m) 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--color-black);
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface IAchievementBlockProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
||||||
if (!achievements.length) return null;
|
if (!achievements?.length) return null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Description text={`# ${localization.get(title)}`}/>
|
<Description text={`# ${localization.get(title)}`}/>
|
||||||
|
|
|
@ -21,7 +21,7 @@ interface IAchievementBlockProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
function AchievementBlock({ title, achievements }: IAchievementBlockProps) {
|
||||||
if (!achievements.length) return null;
|
if (!achievements?.length) return null;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Description text={`# ${title}`}/>
|
<Description text={`# ${title}`}/>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Select from 'ts/components/UiKit/components/Select';
|
||||||
import PageBox from 'ts/components/Page/Box';
|
import PageBox from 'ts/components/Page/Box';
|
||||||
import Title from 'ts/components/Title';
|
import Title from 'ts/components/Title';
|
||||||
import localization from 'ts/helpers/Localization';
|
import localization from 'ts/helpers/Localization';
|
||||||
|
import { applicationHasCustom } from 'ts/helpers/RPC';
|
||||||
|
|
||||||
const Common = observer((): React.ReactElement | null => {
|
const Common = observer((): React.ReactElement | null => {
|
||||||
const [title, setTitle] = useState<string>(document.title);
|
const [title, setTitle] = useState<string>(document.title);
|
||||||
|
@ -22,6 +23,7 @@ const Common = observer((): React.ReactElement | null => {
|
||||||
onChange={(value: string) => {
|
onChange={(value: string) => {
|
||||||
setTitle(value);
|
setTitle(value);
|
||||||
document.title = value || 'Git статистика';
|
document.title = value || 'Git статистика';
|
||||||
|
applicationHasCustom.title = true;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -29,9 +29,10 @@ import Description from 'ts/components/Description';
|
||||||
interface IAuthorViewProps {
|
interface IAuthorViewProps {
|
||||||
response?: IPagination<any>;
|
response?: IPagination<any>;
|
||||||
updateSort?: Function;
|
updateSort?: Function;
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AuthorView({ response, updateSort }: IAuthorViewProps) {
|
function AuthorView({ response, updateSort, mode }: IAuthorViewProps) {
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
const textWork = localization.get('page.team.author.worked');
|
const textWork = localization.get('page.team.author.worked');
|
||||||
|
@ -46,6 +47,8 @@ function AuthorView({ response, updateSort }: IAuthorViewProps) {
|
||||||
rows={response.content}
|
rows={response.content}
|
||||||
sort={response.sort}
|
sort={response.sort}
|
||||||
updateSort={updateSort}
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 3 : undefined}
|
||||||
>
|
>
|
||||||
<Column
|
<Column
|
||||||
isFixed
|
isFixed
|
||||||
|
@ -163,17 +166,15 @@ const Author = observer(({
|
||||||
<RecommendationsWrapper recommendations={recommendations} />
|
<RecommendationsWrapper recommendations={recommendations} />
|
||||||
)}
|
)}
|
||||||
<Title title="page.team.author.title"/>
|
<Title title="page.team.author.title"/>
|
||||||
<PageWrapper template="table">
|
<DataLoader
|
||||||
<DataLoader
|
to="response"
|
||||||
to="response"
|
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
content: rows, pagination, sort, mode,
|
||||||
content: rows, pagination, sort, mode,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<AuthorView mode={mode} />
|
||||||
<AuthorView />
|
<Pagination />
|
||||||
<Pagination />
|
</DataLoader>
|
||||||
</DataLoader>
|
|
||||||
</PageWrapper>
|
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<PageColumn>
|
<PageColumn>
|
||||||
<Description
|
<Description
|
||||||
|
|
|
@ -39,6 +39,8 @@ function AllPR({
|
||||||
rows={response.content}
|
rows={response.content}
|
||||||
sort={response.sort}
|
sort={response.sort}
|
||||||
updateSort={updateSort}
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 2 : undefined}
|
||||||
>
|
>
|
||||||
{mode === 'print' ? (
|
{mode === 'print' ? (
|
||||||
<Column
|
<Column
|
||||||
|
|
|
@ -22,9 +22,10 @@ const order = Object.values(TITLES);
|
||||||
interface IAuthorsProps {
|
interface IAuthorsProps {
|
||||||
response?: IPagination<any>;
|
response?: IPagination<any>;
|
||||||
updateSort?: Function;
|
updateSort?: Function;
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Authors({ response, updateSort }: IAuthorsProps) {
|
function Authors({ response, updateSort, mode }: IAuthorsProps) {
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
const timeChart = getOptions({ order, limit: 3 });
|
const timeChart = getOptions({ order, limit: 3 });
|
||||||
|
@ -42,6 +43,8 @@ function Authors({ response, updateSort }: IAuthorsProps) {
|
||||||
rows={response.content}
|
rows={response.content}
|
||||||
sort={response.sort}
|
sort={response.sort}
|
||||||
updateSort={updateSort}
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 3 : undefined}
|
||||||
>
|
>
|
||||||
<Column
|
<Column
|
||||||
isSortable
|
isSortable
|
||||||
|
|
|
@ -34,9 +34,7 @@ const PR = observer(({
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title title="page.team.pr.oneTaskDays"/>
|
<Title title="page.team.pr.oneTaskDays"/>
|
||||||
<PageWrapper template="table">
|
<Total/>
|
||||||
<Total/>
|
|
||||||
</PageWrapper>
|
|
||||||
|
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<PageColumn>
|
<PageColumn>
|
||||||
|
@ -57,17 +55,15 @@ const PR = observer(({
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<Title title="page.team.pr.statByAuthors"/>
|
<Title title="page.team.pr.statByAuthors"/>
|
||||||
<PageWrapper template="table">
|
<DataLoader
|
||||||
<DataLoader
|
to="response"
|
||||||
to="response"
|
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
content: authorsStat, pagination, sort, mode,
|
||||||
content: authorsStat, pagination, sort, mode,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<Authors mode={mode}/>
|
||||||
<Authors/>
|
<Pagination/>
|
||||||
<Pagination/>
|
</DataLoader>
|
||||||
</DataLoader>
|
|
||||||
</PageWrapper>
|
|
||||||
|
|
||||||
<PageBreak/>
|
<PageBreak/>
|
||||||
<Title title="page.team.pr.longDelay"/>
|
<Title title="page.team.pr.longDelay"/>
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { getMoney } from 'ts/helpers/formatter';
|
||||||
import dataGripStore from 'ts/store/DataGrip';
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||||
import PageWrapper from 'ts/components/Page/wrapper';
|
|
||||||
import DataLoader from 'ts/components/DataLoader';
|
import DataLoader from 'ts/components/DataLoader';
|
||||||
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
||||||
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
||||||
|
@ -22,15 +21,24 @@ import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||||
|
|
||||||
interface IScopeViewProps {
|
interface IScopeViewProps {
|
||||||
response?: IPagination<any>;
|
response?: IPagination<any>;
|
||||||
|
updateSort?: Function;
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ScopeView({ response }: IScopeViewProps) {
|
function ScopeView({ response, updateSort, mode }: IScopeViewProps) {
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
const typeChart = getOptions({ order: dataGripStore.dataGrip.type.list });
|
const typeChart = getOptions({ order: dataGripStore.dataGrip.type.list });
|
||||||
const authorChart = getOptions({ order: dataGripStore.dataGrip.author.list });
|
const authorChart = getOptions({ order: dataGripStore.dataGrip.author.list });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DataView rows={response.content}>
|
<DataView
|
||||||
|
rows={response.content}
|
||||||
|
sort={response.sort}
|
||||||
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 3 : undefined}
|
||||||
|
>
|
||||||
<Column
|
<Column
|
||||||
isFixed
|
isFixed
|
||||||
template={ColumnTypesEnum.STRING}
|
template={ColumnTypesEnum.STRING}
|
||||||
|
@ -118,17 +126,15 @@ const Scope = observer(({
|
||||||
<RecommendationsWrapper recommendations={recommendations} />
|
<RecommendationsWrapper recommendations={recommendations} />
|
||||||
)}
|
)}
|
||||||
<Title title="page.team.scope.title"/>
|
<Title title="page.team.scope.title"/>
|
||||||
<PageWrapper template="table">
|
<DataLoader
|
||||||
<DataLoader
|
to="response"
|
||||||
to="response"
|
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
||||||
loader={(pagination?: IPaginationRequest) => getFakeLoader({
|
content: rows, pagination, mode,
|
||||||
content: rows, pagination, mode,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<ScopeView mode={mode} />
|
||||||
<ScopeView />
|
<Pagination />
|
||||||
<Pagination />
|
</DataLoader>
|
||||||
</DataLoader>
|
|
||||||
</PageWrapper>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Races from 'ts/components/Races';
|
||||||
|
|
||||||
import Tv100And1 from 'ts/components/Tv100And1';
|
import Tv100And1 from 'ts/components/Tv100And1';
|
||||||
|
|
||||||
import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
|
// import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
|
||||||
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
||||||
import Description from 'ts/components/Description';
|
import Description from 'ts/components/Description';
|
||||||
import DataView from 'ts/components/DataView';
|
import DataView from 'ts/components/DataView';
|
||||||
|
@ -51,16 +51,17 @@ const Top = observer((): React.ReactElement => {
|
||||||
|
|
||||||
const authors = dataGripStore.dataGrip.author.statistic.map((statistic: any) => {
|
const authors = dataGripStore.dataGrip.author.statistic.map((statistic: any) => {
|
||||||
const achievements = getAchievementByAuthor(statistic.author);
|
const achievements = getAchievementByAuthor(statistic.author);
|
||||||
|
console.dir(achievements);
|
||||||
const from = getDate(statistic.firstCommit.date);
|
const from = getDate(statistic.firstCommit.date);
|
||||||
const to = getDate(statistic.lastCommit.date);
|
const to = getDate(statistic.lastCommit.date);
|
||||||
const achievementsList = [
|
const achievementsList = [
|
||||||
...achievements[ACHIEVEMENT_TYPE.GOOD],
|
// ...achievements[ACHIEVEMENT_TYPE.GOOD],
|
||||||
...achievements[ACHIEVEMENT_TYPE.NORMAL],
|
// ...achievements[ACHIEVEMENT_TYPE.NORMAL],
|
||||||
...achievements[ACHIEVEMENT_TYPE.BAD],
|
// ...achievements[ACHIEVEMENT_TYPE.BAD],
|
||||||
].map((type: string) => (
|
].map((code: string) => (
|
||||||
<Achievement
|
<Achievement
|
||||||
key={type}
|
key={code}
|
||||||
type={type}
|
code={code}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,10 @@ import localization from 'ts/helpers/Localization';
|
||||||
interface ITypeViewProps {
|
interface ITypeViewProps {
|
||||||
response?: IPagination<any>;
|
response?: IPagination<any>;
|
||||||
updateSort?: Function;
|
updateSort?: Function;
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function TypeView({ response, updateSort }: ITypeViewProps) {
|
function TypeView({ response, updateSort, mode }: ITypeViewProps) {
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
const taskChart = getOptions({ max: getMax(response, 'tasks'), suffix: 'page.team.type.tasksSmall' });
|
const taskChart = getOptions({ max: getMax(response, 'tasks'), suffix: 'page.team.type.tasksSmall' });
|
||||||
|
@ -41,6 +42,8 @@ function TypeView({ response, updateSort }: ITypeViewProps) {
|
||||||
rows={response.content}
|
rows={response.content}
|
||||||
sort={response.sort}
|
sort={response.sort}
|
||||||
updateSort={updateSort}
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 3 : undefined}
|
||||||
>
|
>
|
||||||
<Column
|
<Column
|
||||||
isFixed
|
isFixed
|
||||||
|
@ -123,17 +126,15 @@ const Type = observer(({
|
||||||
<RecommendationsWrapper recommendations={recommendations} />
|
<RecommendationsWrapper recommendations={recommendations} />
|
||||||
)}
|
)}
|
||||||
<Title title="page.team.type.title"/>
|
<Title title="page.team.type.title"/>
|
||||||
<PageWrapper template="table">
|
<DataLoader
|
||||||
<DataLoader
|
to="response"
|
||||||
to="response"
|
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
content: rows, pagination, sort, mode,
|
||||||
content: rows, pagination, sort, mode,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<TypeView mode={mode} />
|
||||||
<TypeView />
|
<Pagination />
|
||||||
<Pagination />
|
</DataLoader>
|
||||||
</DataLoader>
|
|
||||||
</PageWrapper>
|
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<Description
|
<Description
|
||||||
text={localization.get('page.team.type.description')}
|
text={localization.get('page.team.type.description')}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { getShortDateRange } from 'ts/helpers/formatter';
|
||||||
import dataGripStore from 'ts/store/DataGrip';
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||||
import PageWrapper from 'ts/components/Page/wrapper';
|
import Title from 'ts/components/Title';
|
||||||
import DataLoader from 'ts/components/DataLoader';
|
import DataLoader from 'ts/components/DataLoader';
|
||||||
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
import Pagination from 'ts/components/DataLoader/components/Pagination';
|
||||||
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
import getFakeLoader from 'ts/components/DataLoader/helpers/formatter';
|
||||||
|
@ -25,9 +25,10 @@ import { getMax } from 'ts/pages/Common/helpers/getMax';
|
||||||
interface IWeekViewProps {
|
interface IWeekViewProps {
|
||||||
response?: IPagination<any>;
|
response?: IPagination<any>;
|
||||||
updateSort?: Function;
|
updateSort?: Function;
|
||||||
|
mode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function WeekView({ response, updateSort }: IWeekViewProps) {
|
function WeekView({ response, updateSort, mode }: IWeekViewProps) {
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
const tasksChart = getOptions({ max: getMax(response, 'tasks'), order: dataGripStore.dataGrip.type.list, suffix: 'page.team.week.tasks' });
|
const tasksChart = getOptions({ max: getMax(response, 'tasks'), order: dataGripStore.dataGrip.type.list, suffix: 'page.team.week.tasks' });
|
||||||
|
@ -48,6 +49,8 @@ function WeekView({ response, updateSort }: IWeekViewProps) {
|
||||||
rows={response.content}
|
rows={response.content}
|
||||||
sort={response.sort}
|
sort={response.sort}
|
||||||
updateSort={updateSort}
|
updateSort={updateSort}
|
||||||
|
type={mode === 'print' ? 'cards' : undefined}
|
||||||
|
columnCount={mode === 'print' ? 3 : undefined}
|
||||||
>
|
>
|
||||||
<Column
|
<Column
|
||||||
isFixed
|
isFixed
|
||||||
|
@ -161,17 +164,18 @@ const Week = observer(({
|
||||||
{mode !== 'print' && (
|
{mode !== 'print' && (
|
||||||
<RecommendationsWrapper recommendations={recommendations} />
|
<RecommendationsWrapper recommendations={recommendations} />
|
||||||
)}
|
)}
|
||||||
<PageWrapper template="table">
|
{mode === 'print' && (
|
||||||
<DataLoader
|
<Title title="page.team.week.title"/>
|
||||||
to="response"
|
)}
|
||||||
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
<DataLoader
|
||||||
content: rows, pagination, sort,
|
to="response"
|
||||||
})}
|
loader={(pagination?: IPaginationRequest, sort?: ISort[]) => getFakeLoader({
|
||||||
>
|
content: rows, pagination, sort,
|
||||||
<WeekView />
|
})}
|
||||||
{mode !== 'print' && <Pagination />}
|
>
|
||||||
</DataLoader>
|
<WeekView mode={mode} />
|
||||||
</PageWrapper>
|
{mode !== 'print' && <Pagination />}
|
||||||
|
</DataLoader>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,7 @@ import getFileTreeWithStatistic from 'ts/helpers/DataGrip/helpers/tree';
|
||||||
import Parser from 'ts/helpers/Parser';
|
import Parser from 'ts/helpers/Parser';
|
||||||
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
|
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
|
||||||
import getTitle from 'ts/helpers/Title';
|
import getTitle from 'ts/helpers/Title';
|
||||||
|
import { applicationHasCustom } from 'ts/helpers/RPC';
|
||||||
|
|
||||||
import settingsStore from './Settings';
|
import settingsStore from './Settings';
|
||||||
|
|
||||||
|
@ -70,7 +71,10 @@ class DataGripStore implements IDataGripStore {
|
||||||
this.dataGrip = dataGrip;
|
this.dataGrip = dataGrip;
|
||||||
|
|
||||||
console.dir(this.dataGrip);
|
console.dir(this.dataGrip);
|
||||||
document.title = getTitle(this.dataGrip, this.commits);
|
console.dir(getTitle(this.dataGrip, this.commits));
|
||||||
|
if (!applicationHasCustom.title) {
|
||||||
|
document.title = getTitle(this.dataGrip, this.commits);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChars() { // todo: remove, never use
|
updateChars() { // todo: remove, never use
|
||||||
|
|
94
src/ts/translations/en/achievements.ts
Normal file
94
src/ts/translations/en/achievements.ts
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
export default `
|
||||||
|
§ achievements.commitsAfter1500.title: Сова
|
||||||
|
§ achievements.commitsAfter1500.description: 70% коммитов после 15:00
|
||||||
|
§ achievements.commitsBefore1500.title: Ранняя пташка
|
||||||
|
§ achievements.commitsBefore1500.description: 70% коммитов до обеда
|
||||||
|
§ achievements.workEveryTime.title: Раб божий
|
||||||
|
§ achievements.workEveryTime.description: есть коммит на каждый час суток
|
||||||
|
§ achievements.workNotWork.title: Стрельба холостыми
|
||||||
|
§ achievements.workNotWork.description: коммиты есть, а закрытых задач нет
|
||||||
|
§ achievements.userNotWork.title: Залётный
|
||||||
|
§ achievements.userNotWork.description: это не его основной проект
|
||||||
|
§ achievements.userIsDied.title: Мёртвая душа
|
||||||
|
§ achievements.userIsDied.description: работал, но уволился
|
||||||
|
§ achievements.lessTasks.title: Зашел и вышел
|
||||||
|
§ achievements.lessTasks.description: меньше всего закрытых задач
|
||||||
|
§ achievements.moreTasks.title: Батя грит малаца
|
||||||
|
§ achievements.moreTasks.description: больше всего закрытых задач
|
||||||
|
§ achievements.everyMessageLong.title: Мастер красноречия
|
||||||
|
§ achievements.everyMessageLong.description: стабильно самые длинные подписи коммитов
|
||||||
|
§ achievements.everyMessageShort.title: Болтун находка для шпиона
|
||||||
|
§ achievements.everyMessageShort.description: стабильно, самые короткие подписи коммитов
|
||||||
|
§ achievements.shortestName.title: Размер не главное
|
||||||
|
§ achievements.shortestName.description: самое короткое имя
|
||||||
|
§ achievements.longestName.title: Азим Азиз Иль Ам Кадир Имран II
|
||||||
|
§ achievements.longestName.description: самое длинное имя
|
||||||
|
§ achievements.moreCommits.title: Мастер бекапов
|
||||||
|
§ achievements.moreCommits.description: больше всего коммитов
|
||||||
|
§ achievements.lessCommits.title: Редко но метко
|
||||||
|
§ achievements.lessCommits.description: меньше всего коммитов
|
||||||
|
§ achievements.oneCommitOneTask.title: Точно в цель
|
||||||
|
§ achievements.oneCommitOneTask.description: в среднем один коммит на задачу
|
||||||
|
§ achievements.moreLazyDays.title: Мысленно я с вами
|
||||||
|
§ achievements.moreLazyDays.description: больше всего дней без коммитов
|
||||||
|
§ achievements.lessLazyDays.title: Папа Карло
|
||||||
|
§ achievements.lessLazyDays.description: меньше всего дней без коммитов
|
||||||
|
§ achievements.zeroLazyDays.title: Ни единого разрыва
|
||||||
|
§ achievements.zeroLazyDays.description: ни одного дня без коммитов
|
||||||
|
§ achievements.moreWorkDays.title: Ценный работник
|
||||||
|
§ achievements.moreWorkDays.description: больше всего рабочих дней
|
||||||
|
§ achievements.moreScopes.title: Стартапер
|
||||||
|
§ achievements.moreScopes.description: сделал больше всего фичей
|
||||||
|
§ achievements.lessScopes.title: Щегол
|
||||||
|
§ achievements.lessScopes.description: сделал меньше всего фичей
|
||||||
|
§ achievements.moreDaysForTask.title: Улитка на склоне
|
||||||
|
§ achievements.moreDaysForTask.description: работа по задачам идёт медленнее чем у остальных
|
||||||
|
§ achievements.more2DaysForTask.title: Cо слоу
|
||||||
|
§ achievements.more2DaysForTask.description: больше двух дней на задачу
|
||||||
|
§ achievements.moreDaysInProject.title: Старожил
|
||||||
|
§ achievements.moreDaysInProject.description: больше всего дней на проекте
|
||||||
|
§ achievements.lessDaysInProject.title: А это кто?
|
||||||
|
§ achievements.lessDaysInProject.description: меньше всего дней на проекте
|
||||||
|
§ achievements.more90DaysInProject.title: Добро пожаловать
|
||||||
|
§ achievements.more90DaysInProject.description: не уволили на испытательном
|
||||||
|
§ achievements.lessDaysForTask.title: Скорострел
|
||||||
|
§ achievements.lessDaysForTask.description: одна задача занимает меньше дня
|
||||||
|
§ achievements.adam.title: Адам
|
||||||
|
§ achievements.adam.description: первый стабильный сотрудник на проекте
|
||||||
|
§ achievements.more666DaysInProject.title: Чёрт
|
||||||
|
§ achievements.more666DaysInProject.description: отработал 666 дней на проекте
|
||||||
|
§ achievements.more777DaysInProject.title: Азино 3 топора
|
||||||
|
§ achievements.more777DaysInProject.description: отработал 777 дней на проекте
|
||||||
|
§ achievements.moreRefactoring.title: Выпускающий редактор
|
||||||
|
§ achievements.moreRefactoring.description: сделал больше всех меток «рефакторинг»
|
||||||
|
§ achievements.longestMessage.title: А разговоров то было...
|
||||||
|
§ achievements.longestMessage.description: самая длинная подпись коммита за все время
|
||||||
|
§ achievements.moreTasksInDay.title: Спиди-гонщик
|
||||||
|
§ achievements.moreTasksInDay.description: рекорд по количеству закрытых задач в день
|
||||||
|
§ achievements.hasCommitFrom0to7.title: Ночной дозор
|
||||||
|
§ achievements.hasCommitFrom0to7.description: есть коммит на каждый час ночи
|
||||||
|
§ achievements.noCommitOnDay.title: Технический перерыв
|
||||||
|
§ achievements.noCommitOnDay.description: есть определенный час и день в рабочее время в который никогда не комитит
|
||||||
|
§ achievements.hasCommitEveryTime.title: Умер на работе
|
||||||
|
§ achievements.hasCommitEveryTime.description: есть коммит на час каждого дня (включая выходные)
|
||||||
|
§ achievements.commitsAfter1800.title: Делу время
|
||||||
|
§ achievements.commitsAfter1800.description: нет ни одного коммита после 18:00
|
||||||
|
§ achievements.more1488DaysInProject.title: им. Максима Марцинкевича
|
||||||
|
§ achievements.more1488DaysInProject.description: отработал 1488 дней на проекте
|
||||||
|
§ achievements.taskNumber300.title: Знаком с трактористом
|
||||||
|
§ achievements.taskNumber300.description: первый взял в работу задачу с номером 300
|
||||||
|
§ achievements.moreFix.title: Bug hunter
|
||||||
|
§ achievements.moreFix.description: больше всего закрытых багов
|
||||||
|
§ achievements.lessWorkDays.title: Дальше без меня
|
||||||
|
§ achievements.lessWorkDays.description: меньше всего рабочих дней
|
||||||
|
§ achievements.moreCreateCode.title: Созидатель
|
||||||
|
§ achievements.moreCreateCode.description: склонен больше остальных добавлять код
|
||||||
|
§ achievements.moreRemoveCode.title: Разрушитель
|
||||||
|
§ achievements.moreRemoveCode.description: склонен больше остальных удалять код
|
||||||
|
§ achievements.moreChangeCode.title: Реформатор
|
||||||
|
§ achievements.moreChangeCode.description: склонен больше остальных изменять код
|
||||||
|
§ achievements.moreStyle.title: Полиция моды
|
||||||
|
§ achievements.moreStyle.description: склонен больше остальных изменять CSS
|
||||||
|
§ achievements.moreOnHoliday.title: Нет жизни
|
||||||
|
§ achievements.moreOnHoliday.description: относительно много коммитов в нерабочее время
|
||||||
|
`;
|
28
src/ts/translations/en/common.ts
Normal file
28
src/ts/translations/en/common.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
export default `
|
||||||
|
§ uiKit.console: Копировать
|
||||||
|
§ uiKit.dataLoader.page: Страница
|
||||||
|
§ uiKit.dataLoader.size: Отображается по
|
||||||
|
§ uiKit.dataLoader.from: из
|
||||||
|
§ uiKit.dataLoader.all: Показать все
|
||||||
|
§ uiKit.hoursChart.work: стандартное рабочее время (будни, с 07:00 до 20:00)
|
||||||
|
§ uiKit.hoursChart.weekend: выходные дни или время до/после рабочего дня
|
||||||
|
§ uiKit.hoursChart.days: суммарное количество коммитов за все время в конкретный день и час
|
||||||
|
§ uiKit.page.remove: Удалить
|
||||||
|
§ uiKit.races.go: Поехали
|
||||||
|
§ uiKit.nothingFound.common.title: Нет или недостаточно данных для отображения
|
||||||
|
§ uiKit.nothingFound.common.description: Система обработает больше данных, если коммиты будут подписаны в формате [Git commit message convention|https://www.conventionalcommits.org/en/v1.0.0/]. Шаблон:
|
||||||
|
§ uiKit.nothingFound.common.console: Номер_задачи тип(фича): пояснение
|
||||||
|
§ uiKit.nothingFound.common.example: Например:
|
||||||
|
§ uiKit.nothingFound.staff.title: Нет данных для этого сотрудника
|
||||||
|
§ uiKit.nothingFound.staff.description1:
|
||||||
|
Он вносил правки не каждый рабочий день и получил статус «Помошник».
|
||||||
|
Работой сотрудников с таким статусом по данному проекту можно пренебречь, т.к. его влад на общем фоне незначителен.
|
||||||
|
|
||||||
|
§ uiKit.nothingFound.staff.description2:
|
||||||
|
Поэтому система не рассчитывает для него ряд показателей.
|
||||||
|
Если это ошибка и данного сотрудника нужно рассчитать как обычного, перейдите в раздел «Настройки» и измените его тип.
|
||||||
|
|
||||||
|
§ common.filters: Фильтры
|
||||||
|
§ common.notifications.save: Изменения сохранены
|
||||||
|
§ common.notifications.setting: Настройки сохранены
|
||||||
|
`;
|
15
src/ts/translations/en/index.ts
Normal file
15
src/ts/translations/en/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import achievements from './achievements';
|
||||||
|
import common from './common';
|
||||||
|
import navigation from './navigation';
|
||||||
|
import recommendations from './recommendations';
|
||||||
|
import settings from './settings';
|
||||||
|
import pages from './pages';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
achievements,
|
||||||
|
common,
|
||||||
|
navigation,
|
||||||
|
recommendations,
|
||||||
|
settings,
|
||||||
|
pages,
|
||||||
|
].join('');
|
37
src/ts/translations/en/navigation.ts
Normal file
37
src/ts/translations/en/navigation.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
export default `
|
||||||
|
§ sidebar.switch.team: Team
|
||||||
|
§ sidebar.switch.person: Employee
|
||||||
|
§ sidebar.buttons.settings: Settings
|
||||||
|
§ sidebar.buttons.print: Print
|
||||||
|
§ sidebar.filters.all: all time
|
||||||
|
§ sidebar.filters.year: year
|
||||||
|
§ sidebar.filters.halfYear: half year
|
||||||
|
§ sidebar.filters.month: month
|
||||||
|
§ sidebar.filters.week: week
|
||||||
|
§ sidebar.team.total: Common info
|
||||||
|
§ sidebar.team.scope: Features
|
||||||
|
§ sidebar.team.author: Employees
|
||||||
|
§ sidebar.team.type: Task types
|
||||||
|
§ sidebar.team.pr: Pull requests
|
||||||
|
§ sidebar.team.day: By day
|
||||||
|
§ sidebar.team.week: By week
|
||||||
|
§ sidebar.team.month: By month
|
||||||
|
§ sidebar.team.tree: Files
|
||||||
|
§ sidebar.team.hours: Расписание
|
||||||
|
§ sidebar.team.commits: All commits
|
||||||
|
§ sidebar.team.changes: All changes
|
||||||
|
§ sidebar.team.words: Popular words
|
||||||
|
§ sidebar.team.top: Викторина
|
||||||
|
§ sidebar.team.settings: Settings
|
||||||
|
§ sidebar.person.total: Common info
|
||||||
|
§ sidebar.person.money: Work cost
|
||||||
|
§ sidebar.person.speed: Speed
|
||||||
|
§ sidebar.person.day: By day
|
||||||
|
§ sidebar.person.week: By week
|
||||||
|
§ sidebar.person.month: By month
|
||||||
|
§ sidebar.person.hours: Расписание
|
||||||
|
§ sidebar.person.commits: All commits
|
||||||
|
§ sidebar.person.changes: All changes
|
||||||
|
§ sidebar.person.words: Popular words
|
||||||
|
§ sidebar.person.settings: Settings
|
||||||
|
`;
|
203
src/ts/translations/en/pages.ts
Normal file
203
src/ts/translations/en/pages.ts
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
export default `
|
||||||
|
§ page.welcome.step1: Выполните команду в корне вашего проекта
|
||||||
|
§ page.welcome.step3: Перетащите
|
||||||
|
§ page.welcome.step4: файл log.txt на эту страницу
|
||||||
|
§ page.welcome.description1: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл
|
||||||
|
§ page.welcome.description2: [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
|
||||||
|
§ page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
|
||||||
|
§ page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
|
||||||
|
§ page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].
|
||||||
|
§ page.common.words.title: Статистика по словам
|
||||||
|
§ page.common.words.description: самое популярное слово. Встречается $1 раза.
|
||||||
|
§ page.common.commits.title: Количество коммитов по дням
|
||||||
|
§ page.common.commits.description: ($1) самый продуктивный день по числу коммитов.
|
||||||
|
§ page.common.commits.title2: $1 сделано коммитов: $2
|
||||||
|
§ page.common.filter.allUsers: Не имеет значения
|
||||||
|
§ page.print.modal.title: Что распечатываем?
|
||||||
|
§ page.print.modal.page: Текущую страницу
|
||||||
|
§ page.print.modal.type: Текущий раздел
|
||||||
|
§ page.print.modal.all: Всю статистику
|
||||||
|
§ page.print.modal.cancel: Отмена
|
||||||
|
§ page.print.tableOfContents: Оглавление
|
||||||
|
§ page.print.title: Отчёт по git-репозиторию «$1»
|
||||||
|
§ page.print.description: Данные для отчёта были получены из истории коммитов.
|
||||||
|
§ page.team.author.title: Статистика по сотрудникам
|
||||||
|
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||||
|
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
||||||
|
§ page.team.author.types: Тип работ
|
||||||
|
§ page.team.author.commits: Коммитов
|
||||||
|
§ page.team.author.commitsSmall: коммитов
|
||||||
|
§ page.team.author.tasks: Задач
|
||||||
|
§ page.team.author.tasksSmall: задач
|
||||||
|
§ page.team.author.workedLosses: Дни с коммитами и без
|
||||||
|
§ page.team.author.worked: работа
|
||||||
|
§ page.team.author.losses: дни без коммитов
|
||||||
|
§ page.team.author.days: дней
|
||||||
|
§ page.team.author.daysForTask: Дней на задачу
|
||||||
|
§ page.team.author.scopes: Фич
|
||||||
|
§ page.team.author.moneyAll: Получил
|
||||||
|
§ page.team.author.moneyWorked: Отработал
|
||||||
|
§ page.team.author.moneyLosses: Переплата
|
||||||
|
§ page.team.hours.title: Распределение коммитов в течении каждого дня недели
|
||||||
|
§ page.team.month.title: Календарь работы по проекту
|
||||||
|
§ page.team.scope.title: Статистика по фичам
|
||||||
|
§ page.team.scope.scope: Фича
|
||||||
|
§ page.team.scope.days: Раб. дней
|
||||||
|
§ page.team.scope.authorsDays: Человеко-дней
|
||||||
|
§ page.team.scope.tasks: Задач
|
||||||
|
§ page.team.scope.commits: Коммитов
|
||||||
|
§ page.team.scope.commitsSmall: коммитов
|
||||||
|
§ page.team.scope.types: Тип работ
|
||||||
|
§ page.team.scope.authors: Персональный вклад
|
||||||
|
§ page.team.scope.cost: Стоимость
|
||||||
|
§ page.team.type.title: Статистика по типам задач
|
||||||
|
§ page.team.type.description: *Персональный вклад* считается по количеству коммитов, а не объему измененных строк или файлов. Поэтому следует так же смотреть раздел «Анализ файлов», чтобы оценить масштаб изменений.
|
||||||
|
§ page.team.type.type: Тип работы
|
||||||
|
§ page.team.type.tasks: Задач
|
||||||
|
§ page.team.type.tasksSmall: задач
|
||||||
|
§ page.team.type.days: Дней
|
||||||
|
§ page.team.type.daysSmall: дней
|
||||||
|
§ page.team.type.authorsDays: Человеко-дней
|
||||||
|
§ page.team.type.commits: Коммитов
|
||||||
|
§ page.team.type.authors: Персональный вклад
|
||||||
|
§ page.team.total.titleA: Объём работ
|
||||||
|
§ page.team.total.titleB: Стоимость
|
||||||
|
§ page.team.total.daysWorked.title: человеко-дней
|
||||||
|
§ page.team.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.team.total.commits.title: коммитов
|
||||||
|
§ page.team.total.commits.description: Удалённые ветки не считаются
|
||||||
|
§ page.team.total.daysLosses.title: дней без коммитов
|
||||||
|
§ page.team.total.daysLosses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
||||||
|
§ page.team.total.employment.title: работает / уволилось
|
||||||
|
§ page.team.total.employment.description: Если сотрудник в течении месяца не сделал ни одного коммита, он считается уволенным
|
||||||
|
§ page.team.total.moneyAll.title: общая
|
||||||
|
§ page.team.total.moneyAll.description: Суммарные затраты на зп
|
||||||
|
§ page.team.total.moneyWorked.title: фактическая
|
||||||
|
§ page.team.total.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
||||||
|
§ page.team.total.moneyLosses.title: возможная переплата
|
||||||
|
§ page.team.total.moneyLosses.description: Оплаченные рабочие дни, когда коммитов не было
|
||||||
|
§ page.team.total.weekendPayment.title: работа на выходных
|
||||||
|
§ page.team.total.weekendPayment.description: Суммарная переплата за работу в выходные дни
|
||||||
|
§ page.team.total.workSpeed.title: задач в день
|
||||||
|
§ page.team.total.workSpeed.description: Средняя скорость работы команды при текущем составе сотрудников
|
||||||
|
§ page.team.total.moneySpeed.title: в месяц
|
||||||
|
§ page.team.total.moneySpeed.description: Прогнозируемая сумма выплаты на зп при текущем составе сотрудников без учета налогов и сопутствующих затрат
|
||||||
|
§ page.team.total.description1: *Человеко-дни* — это работа одного сотрудника в течение одного рабочего дня. Например, за один календарный день, команда из трех сотрудников выдает объем работы в три человеко-дня.
|
||||||
|
§ page.team.total.description2: *Днями прогулов* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют.
|
||||||
|
§ page.team.total.description3: Карточка *работает и уволилось* показывает фактический состав сотрудников, которые постоянно участвуют в работе. Кроме этого, есть «помощники» — это сотрудники, как правило другой специализации, которые могут иногда делать коммиты в проект.
|
||||||
|
§ page.team.total.description4: *Переплатой* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют. Именно поэтому переплата + фактическая стоимость != общей. В общей стоимости заложена оплата выходных, государственных праздников и отпусков.
|
||||||
|
§ page.team.total.description5: *Работой на выходных* считается по коэффициенту х2 от оплаты обычного дня. Выше отображена именно переплата (х1), т.к. сам факт переработки в данном контексте не интересен. Мы не смотрим скорость сжигания бюджета. Мы смотрим переплату при увеличении скорости работы.
|
||||||
|
§ page.team.tree.title: Дерево проекта с учётом выбранных фильтров
|
||||||
|
§ page.team.tree.filters.author: Сотрудник
|
||||||
|
§ page.team.tree.filters.commits: Количество коммитов
|
||||||
|
§ page.team.tree.filters.help: Минимальное количество коммитов, которое сделал сотрудник в файле
|
||||||
|
§ page.team.tree.filters.all: Все сотрудники
|
||||||
|
§ page.team.tree.add: Кто добавлял
|
||||||
|
§ page.team.tree.change: Кто менял
|
||||||
|
§ page.team.tree.remove: Кто удалял
|
||||||
|
§ page.team.tree.line: строк
|
||||||
|
§ page.team.tree.lineAdd: добавили
|
||||||
|
§ page.team.tree.lineRemove: изменили
|
||||||
|
§ page.team.week.title: Статистика по неделям
|
||||||
|
§ page.team.week.date: Дата
|
||||||
|
§ page.team.week.numberTasks: Количество задач
|
||||||
|
§ page.team.week.people: Количество человек
|
||||||
|
§ page.team.week.line: Изменение строк
|
||||||
|
§ page.team.week.days: Дни с коммитами и без
|
||||||
|
§ page.team.week.lossesDetails: Кто не коммитил
|
||||||
|
§ page.team.week.add: добавили
|
||||||
|
§ page.team.week.change: изменили
|
||||||
|
§ page.team.week.remove: удалили
|
||||||
|
§ page.team.week.hasCommits: были коммиты
|
||||||
|
§ page.team.week.hasNotCommits: небыло коммитов
|
||||||
|
§ page.team.week.days: дней
|
||||||
|
§ page.team.week.tasks: задач
|
||||||
|
§ page.team.pr.task: Задача
|
||||||
|
§ page.team.pr.tasks: задач
|
||||||
|
§ page.team.pr.firstCommitTime: Первый коммит
|
||||||
|
§ page.team.pr.lastCommitTime: Последний
|
||||||
|
§ page.team.pr.workDays: Дней разработки
|
||||||
|
§ page.team.pr.delayDays: Дней ожидания влития
|
||||||
|
§ page.team.pr.commits: Коммиты
|
||||||
|
§ page.team.pr.date: Дата влития
|
||||||
|
§ page.team.pr.mergeAuthor: Влил
|
||||||
|
§ page.team.pr.author: Сотрудник
|
||||||
|
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
||||||
|
§ page.team.pr.work: разработка
|
||||||
|
§ page.team.pr.delay: ожидание
|
||||||
|
§ page.team.pr.days: дней
|
||||||
|
§ page.team.pr.oneTaskDays: Время потраченное на одну задачу
|
||||||
|
§ page.team.pr.description1: *Время разработки* это разница времени от первого до последнего коммита по задаче. Не важно были перерывы в несколько дней между коммитами или нет. Сам факт какого-либо коммита увеличивает время.
|
||||||
|
§ page.team.pr.description2: *Время ожидания* это время между последним коммитом и влитием кода. Оно показывает фактический простой в ожидании чего-либо.
|
||||||
|
§ page.team.pr.description3: *Зачем отображать время разработки* без разбивки на кодинг и код-ревью? Затем, чтобы показать бизнесу фактическое время поставки кода. Ожидание тестирования, замечания на ревью, проблемы DevOps и прочие несовершенства процесса, как раз уже заложены в этот срок.
|
||||||
|
§ page.team.pr.statByAuthors: Статистика по сотрудникам
|
||||||
|
§ page.team.pr.longDelay: Длительное ожидание влития
|
||||||
|
§ page.person.print.photo.title: Фотография
|
||||||
|
§ page.person.print.photo.description: место для фотографии
|
||||||
|
§ page.person.total.title: Основные характеристики
|
||||||
|
§ page.person.total.daysWorked.title: дней работы
|
||||||
|
§ page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.person.total.tasks.title: задач
|
||||||
|
§ page.person.total.tasks.description: Если коммиты правильно подписаны
|
||||||
|
§ page.person.character.title: Персонаж
|
||||||
|
§ page.person.achievement.title: Достижения
|
||||||
|
§ page.person.achievement.positive: Позитивные
|
||||||
|
§ page.person.achievement.normal: Нейтральные
|
||||||
|
§ page.person.achievement.negative: Негативные
|
||||||
|
§ page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
|
||||||
|
§ page.person.gets.title: Взятые геты:
|
||||||
|
§ page.person.gets.description: «Взять гет» в данном случае означает первым оставить коммит к задаче с «красивым» номером.
|
||||||
|
§ page.person.business.days.title: дней работы
|
||||||
|
§ page.person.business.days.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.person.business.tasks.title: задач
|
||||||
|
§ page.person.business.tasks.description: Если коммиты правильно подписаны
|
||||||
|
§ page.person.business.losses.title: дней без коммитов
|
||||||
|
§ page.person.business.losses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
||||||
|
§ page.person.business.commits.title: коммитов
|
||||||
|
§ page.person.business.commits.description: Удалённые ветки не считаются
|
||||||
|
§ page.person.business.time.description: Время от первого, до последнего коммита (в том числе, нерабочие дни)
|
||||||
|
§ page.person.business.time.title: Дней на проекте:
|
||||||
|
§ page.person.business.time.dismissed: (уволен)
|
||||||
|
§ page.person.business.time.staff: (не в команде)
|
||||||
|
§ page.person.business.achievements: Достижения
|
||||||
|
§ page.person.changes.title: Достижения
|
||||||
|
§ page.person.changes.description:
|
||||||
|
При некоторых видах форматирования git отмечает строки как «удалённые» и «добавленные»,
|
||||||
|
хотя на самом деле они были «изменены». Поэтому, если вы провели большой рефакторинг,
|
||||||
|
git может показать малое количество изменений в статистике, а фактический результат
|
||||||
|
будет отмечен, как скачок «удаленных» и «добавленных» строк.
|
||||||
|
§ page.person.changes.description: Список коммитов и количество изменений в них за этот день:
|
||||||
|
§ page.person.commits.title: Список коммитов:
|
||||||
|
§ page.person.money.title.total: За всё время
|
||||||
|
§ page.person.money.title.middle: Средняя стоимость
|
||||||
|
§ page.person.money.moneyAll.title: получил
|
||||||
|
§ page.person.money.moneyAll.description: Предполагаемая сумма зп с проекта (см. настройки)
|
||||||
|
§ page.person.money.moneyWorked.title: отработал
|
||||||
|
§ page.person.money.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
||||||
|
§ page.person.money.moneyLosses.title: возможная переплата
|
||||||
|
§ page.person.money.moneyLosses.description: Дни без коммитов умноженные на среднюю зп
|
||||||
|
§ page.person.money.tasks.title: задача
|
||||||
|
§ page.person.money.tasks.description: Количество закрытых задач к стоимости дня
|
||||||
|
§ page.person.money.commits.title: коммит
|
||||||
|
§ page.person.money.commits.description: Количество коммитов к стоимости рабочего дня
|
||||||
|
§ page.person.speed.task: Одна задача в среднем это
|
||||||
|
§ page.person.speed.max: Максимальная скорость в день
|
||||||
|
§ page.person.speed.days.title: дней
|
||||||
|
§ page.person.speed.days.description: Имеются ввиду рабочие дни, если коммиты правильно подписаны
|
||||||
|
§ page.person.speed.commits.title: коммитов
|
||||||
|
§ page.person.speed.commits.description: Отрезаны 10% максимальных и минимальных значений
|
||||||
|
§ page.person.speed.line.title: строк кода
|
||||||
|
§ page.person.speed.line.description: Отрезаны 10% максимальных и минимальных значений
|
||||||
|
§ 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: выходные
|
||||||
|
`;
|
506
src/ts/translations/en/recommendations.ts
Normal file
506
src/ts/translations/en/recommendations.ts
Normal file
|
@ -0,0 +1,506 @@
|
||||||
|
export default `
|
||||||
|
§ recommendations.title
|
||||||
|
Рекомендации и факты
|
||||||
|
|
||||||
|
§ recommendations.timestamp.firstCommit.description
|
||||||
|
сделал первый коммит
|
||||||
|
|
||||||
|
День недели: $1
|
||||||
|
|
||||||
|
§ recommendations.timestamp.lastCommit.description
|
||||||
|
сделал последний коммит
|
||||||
|
|
||||||
|
День недели: $1
|
||||||
|
|
||||||
|
§ recommendations.timestamp.common.title: $1 дней
|
||||||
|
§ recommendations.timestamp.allDays.description: от первого до последнего коммита (включая выходные и праздники).
|
||||||
|
§ recommendations.timestamp.lossesDays.description: без коммитов, даже с учётом выходных, отпуска и государственных праздников.
|
||||||
|
§ recommendations.timestamp.weekendDays.description
|
||||||
|
работы на выходных
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- сотрудники быстрее выгорают;
|
||||||
|
|
||||||
|
§ recommendations.timestamp.regularWeekendWord.title: Регулярные переработки
|
||||||
|
§ recommendations.timestamp.sometimeWeekendWord.title: Бывают переработки
|
||||||
|
§ recommendations.timestamp.weekendWord.description
|
||||||
|
Вероятно, стоит сменить менеджера проекта, аналитика и архитектора.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- качество продукта, как правило, получается низкое;
|
||||||
|
- часть сотрудников увольняется;
|
||||||
|
- из-за спешки появляются новые ошибки;
|
||||||
|
|
||||||
|
# Скорее всего:
|
||||||
|
- неверно оценили сроки в самом начале;
|
||||||
|
- тех. задание отсутствует;
|
||||||
|
- слабая аналитика;
|
||||||
|
- слабая архитектура (архитектора не нанимали, а команда состоит из мидл разработчиков);
|
||||||
|
- сначала начали писать код, потом проектировать;
|
||||||
|
- нет нормальных процессов, чтобы понять ошибки;
|
||||||
|
|
||||||
|
§ recommendations.timestamp.neverWeekendWord.title: Обычно без переработок
|
||||||
|
§ recommendations.timestamp.neverWeekendWord.description
|
||||||
|
Но иногда бывают.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- сотрудники быстрее выгорают;
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.not.title
|
||||||
|
Нет параллельных работ
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.not.description
|
||||||
|
любую фичу в один момент времени делает один человек.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат меньше 1.3 считаем, что параллельных работ в рамках большинства фичей обычно нет;
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- повышается bus factor;
|
||||||
|
- сотрудники медленнее развиваются;
|
||||||
|
- трудно качественно проверить работу сотрудника;
|
||||||
|
|
||||||
|
# Почему это хорошо:
|
||||||
|
- появляются эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
||||||
|
- скорее всего не бывает merge конфликтов;
|
||||||
|
- проект может очень быстро параллельно развиваться в разные стороны;
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.has.title
|
||||||
|
Часть работ параллельно
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.has.description
|
||||||
|
Иногда фичу делают одновременно несколько человек.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делается параллельно;
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.every.title
|
||||||
|
Параллельные работы
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.every.description
|
||||||
|
любую фичу в один момент времени делают несколько человек
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат больше двух считаем, что большая часть работ в рамках разных фичей обычно делается параллельно;
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.scope.money
|
||||||
|
в такую сумму можно оценить работу по данному проекту.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни затраченные на разработку умножаются на индивидуальную зарплату разработчиков;
|
||||||
|
|
||||||
|
Изменить зарплату каждого разработчика, для более точной суммы, можно в разделе «Настройки»
|
||||||
|
|
||||||
|
# Это много или мало?
|
||||||
|
Для ответа на этот вопрос, нужно ответить на следующие:
|
||||||
|
- Можно ли за эти деньги было купить готовое решение?
|
||||||
|
- Можно ли за эти деньги сделать более хороший продукт?
|
||||||
|
|
||||||
|
Если ответ на оба вопроса «да», то возможно, разработка с нуля не стоила потраченных на неё денег.
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.everyHasOne.title
|
||||||
|
Bus factor = 1
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.everyHasOne.description
|
||||||
|
В большинство фич погружен один человек.
|
||||||
|
Надо переключать людей.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- если сотрудники будут увольняться, будет трудно продолжить их работу;
|
||||||
|
- невозможно контролировать качество его кода;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- более 80% коммитов в фичу делает один человек;
|
||||||
|
- проект имеет более 60% таких фичей;
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.oneMaintainer
|
||||||
|
в фичи погружен один человек.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- если он уволится, будет трудно продолжить разработку;
|
||||||
|
- снижается качество code-review;
|
||||||
|
- трудно запараллелить разработку при необходимости;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- более 80% коммитов в фичу сделал один человек;
|
||||||
|
|
||||||
|
§ recommendations.scope.types.process.title
|
||||||
|
Плохие процессы
|
||||||
|
|
||||||
|
§ recommendations.scope.types.process.description
|
||||||
|
Большинство фич содержат один тип задач.
|
||||||
|
|
||||||
|
§ recommendations.scope.types.one
|
||||||
|
фичи содержат один тип задач.
|
||||||
|
|
||||||
|
§ recommendations.scope.types.common
|
||||||
|
Возможно, разработчики неправильно подписывают коммиты или менеджер заводит один и тот же тип задач.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- невозможно передать поддержку другой команде;
|
||||||
|
- невозможно выпустить "коробочную" версию;
|
||||||
|
- сильная зависимость от конкретных разработчиков;
|
||||||
|
- большое количество ошибок и низкое качество кода;
|
||||||
|
- вероятное замедление разработки в будущем;
|
||||||
|
|
||||||
|
# В чём ошибка менеджера:
|
||||||
|
- взгляд на продукт, только с позиции «работающей демки»;
|
||||||
|
|
||||||
|
# Что должно быть:
|
||||||
|
- тесты;
|
||||||
|
- ошибки (выявленные по результатам тестов);
|
||||||
|
- рефакторинг (т.к. архитектура может измениться);
|
||||||
|
- документация;
|
||||||
|
- правки стиля (как результат опроса фокус-группы);
|
||||||
|
|
||||||
|
§ recommendations.scope.plan.title
|
||||||
|
Постройте долгосрочный план
|
||||||
|
|
||||||
|
§ recommendations.scope.plan.description
|
||||||
|
с учетом архитектуры.
|
||||||
|
|
||||||
|
При том опираться этот план должен сразу на самые трудные задачи.
|
||||||
|
|
||||||
|
# Почему отсутствие плана плохо:
|
||||||
|
- сотрудники делают минимально работающую версию, не закладывая точки расширения. После этого пишется не масштабируемый код, который тормозит следующие фичи;
|
||||||
|
|
||||||
|
# В чём ошибка менеджера:
|
||||||
|
- он не показал, как продукт будет развиваться далее и в каких точках будет рост;
|
||||||
|
|
||||||
|
# Как должно быть:
|
||||||
|
- составляется глобальный план развития продукта;
|
||||||
|
- составляется глобальный план развития архитектуры (с разработчиками и DBA);
|
||||||
|
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
||||||
|
|
||||||
|
§ recommendations.scope.cost.title
|
||||||
|
Оцените инвестиции в фичу
|
||||||
|
|
||||||
|
§ recommendations.scope.cost.description
|
||||||
|
с количеством потенциальной прибыли.
|
||||||
|
|
||||||
|
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более коммерчески успешным.
|
||||||
|
|
||||||
|
§ recommendations.author.lotOfLazy
|
||||||
|
пишет слишком мало кода.
|
||||||
|
|
||||||
|
# Может уволить?
|
||||||
|
- он тимлид, архитектор, аналитик?
|
||||||
|
- это его основной проект?
|
||||||
|
- есть какие-то зависимости от него?
|
||||||
|
|
||||||
|
# Почему нет смысла исправлять
|
||||||
|
Суммарные затраты на разработчика уже больше чем прибыль от его работы.
|
||||||
|
Если мы считаем, что объективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
||||||
|
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
||||||
|
|
||||||
|
§ recommendations.author.manyLazy
|
||||||
|
пишет мало кода. Нужно взять на контроль.
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
||||||
|
- в данном случае показатель от 60% до 80%;
|
||||||
|
|
||||||
|
# Как контролировать:
|
||||||
|
- дробить задачи на 1..2 дня;
|
||||||
|
- каждый день спрашивать статус;
|
||||||
|
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
||||||
|
- устроить парное программирование, чтобы проверить фактическую скорость;
|
||||||
|
|
||||||
|
§ recommendations.author.oneTypeMans
|
||||||
|
получает слишком однообразные задачи по типу. Может выгореть.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- если сотрудник выгорит, его скорость работы снизится;
|
||||||
|
- замедляется профессиональный рост;
|
||||||
|
- повышается вероятность увольнения;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- для каждого коммита определятся тип задачи;
|
||||||
|
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
||||||
|
|
||||||
|
§ recommendations.author.workToday.title: Работает $1
|
||||||
|
§ recommendations.author.workToday.description
|
||||||
|
над проектом в данный момент.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- рабочих дней более 50%;
|
||||||
|
- работали в течении последних 30 дней;
|
||||||
|
|
||||||
|
§ recommendations.author.dismissed.title: Уволилось $1
|
||||||
|
§ recommendations.author.dismissed.description
|
||||||
|
или работало короткий промежуток времени.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- работали в нормальном ритме (видимо, это их основной репозиторий);
|
||||||
|
- за последний месяц не было ни одного коммита;
|
||||||
|
- отпуск обычно 14 дней (их отсутствие не похоже на отпуск);
|
||||||
|
|
||||||
|
§ recommendations.author.staff.title: Помогают $1
|
||||||
|
§ recommendations.author.staff.description
|
||||||
|
Люди другой специализации, которые что-либо коммитили.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- это не open-source проект;
|
||||||
|
- рабочих дней менее 15% от общего числа;
|
||||||
|
- изменяют примерно одни и те же файлы;
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.openSource.title
|
||||||
|
Открытый проект
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.openSource.description
|
||||||
|
пять дней в неделю тут не работают.
|
||||||
|
|
||||||
|
Проект может быть и закрытым, просто такой темп работы обычно у открытых библиотек на GitHub.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- берется статистика по всем активным разработчикам;
|
||||||
|
- подсчитывается среднее число дней работы и без коммитов;
|
||||||
|
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
||||||
|
|
||||||
|
# Последствия
|
||||||
|
Для проектов, где работа не постоянна, нет смысла во многих показателях. Поэтому показатели без коммитов, скорости и т.п. будут скрыты.
|
||||||
|
|
||||||
|
Как правило, оценку таких проектов делают перед началом разработки своей закрытой версии. Самые интересные показатели в этом случае вероятная стоимость и суммарное время на разработку.
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.easy.title
|
||||||
|
Слабая загрузка
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.easy.description
|
||||||
|
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- берется статистика по всем активным разработчикам;
|
||||||
|
- подсчитывается среднее число дней работы и без коммитов;
|
||||||
|
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
||||||
|
|
||||||
|
# Возможные причины:
|
||||||
|
- фактически нет задач;
|
||||||
|
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
||||||
|
- разработчиков отвлекают совещаниями;
|
||||||
|
- команда не работает;
|
||||||
|
|
||||||
|
# Варианты решения:
|
||||||
|
- обсудить проблему с командой;
|
||||||
|
- уменьшить гранулярность задач, чтобы за день можно было успеть сделать одну или две задачи;
|
||||||
|
- ввести ежедневные совещания, чтобы проверять движение задач по статусу;
|
||||||
|
- устроить сеансы парного программирования, чтобы убедиться, что разработчик может работать быстрее;
|
||||||
|
|
||||||
|
§ recommendations.author.manager.title
|
||||||
|
Обозначьте дедлайны
|
||||||
|
|
||||||
|
§ recommendations.author.manager.description
|
||||||
|
У любой задачи должен быть чёткий дедлайн.
|
||||||
|
|
||||||
|
Это позволит не затягивать её выполнение на несколько дней или недель.
|
||||||
|
|
||||||
|
# Какие показатели стоит проверить:
|
||||||
|
- количество дней на одну задачу, которое тратит работник;
|
||||||
|
- количество дней ожидания влития PR (страница статистики по PR);
|
||||||
|
|
||||||
|
§ recommendations.author.shorTalk.title
|
||||||
|
Проводите ежедневные совещания
|
||||||
|
|
||||||
|
§ recommendations.author.shorTalk.description
|
||||||
|
они помогают быть в курсе проекта.
|
||||||
|
|
||||||
|
Не растягивайте их отвлекаясь на посторонние темы.
|
||||||
|
|
||||||
|
# На какие вопросы должен ответить сотрудник:
|
||||||
|
- что было сделано;
|
||||||
|
- что будет сделано;
|
||||||
|
- есть ли какие-либо проблемы;
|
||||||
|
|
||||||
|
# Следует обрывать монолог, если:
|
||||||
|
- начинают подробно описывать мелкие детали, которые не важны;
|
||||||
|
- уводят диалог в сторону, от первоначального плана;
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
Часто сотрудник, который ничего не делает, старается уйти от ответа. Для этого он рассказывает кучу ненужных подробностей свой работы. Это позволяет усыпить внимание участников и растянуть время ответа. Создается ощущение что он чем-то занят, хотя по факту работы не было.
|
||||||
|
|
||||||
|
§ recommendations.author.ipr.title
|
||||||
|
Составьте план обучения
|
||||||
|
|
||||||
|
§ recommendations.author.ipr.description
|
||||||
|
на каждого сотрудника.
|
||||||
|
|
||||||
|
*Индивидуальный план обучения* — это список целей и задач, которые помогают человеку развиваться в определенной области.
|
||||||
|
|
||||||
|
# Как составить план:
|
||||||
|
- составить матрицу компетенций;
|
||||||
|
- определить по каким компетенциям меньше всего знаний и опыта;
|
||||||
|
- узнать какие из этих компетенций интересны сотруднику;
|
||||||
|
- придумать 3..5 целей в рамках каждой такой компетенции на полпостороние года или год;
|
||||||
|
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
||||||
|
- каждый месяц напоминать об общем плане достижения этих целей;
|
||||||
|
|
||||||
|
# Нужен ли план руководителю?
|
||||||
|
Да, руководитель так же должен составить план на себя. Если нет вышестоящего руководителя, то он должен проверять сам себя.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- сотрудники становятся более лояльны к компании;
|
||||||
|
- за теже деньги вы получаете более квалифицированные кадры;
|
||||||
|
|
||||||
|
§ recommendations.author.oneToOne.title
|
||||||
|
Проводите 1-1 каждый месяц
|
||||||
|
|
||||||
|
§ recommendations.author.oneToOne.description
|
||||||
|
это поможет выявить проблемы на ранней стадии.
|
||||||
|
|
||||||
|
*One-to-one* — это регулярные личные встречи руководителя с подчиненным. На таких встречах обычно обсуждают всё, что важно для сотрудника, что его волнует, и то, чем он может поделиться с руководителем только наедине.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- легко выяснить, кто из сотрудников перегружен, а у кого есть свободное время;
|
||||||
|
- можно предотвратить выгорание сотрудника;
|
||||||
|
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
||||||
|
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
||||||
|
- повышается мотивация и вовлеченность сотрудников;
|
||||||
|
|
||||||
|
§ recommendations.author.club.title
|
||||||
|
Ходите в бар
|
||||||
|
|
||||||
|
§ recommendations.author.club.description
|
||||||
|
один раз в месяц или два.
|
||||||
|
|
||||||
|
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
||||||
|
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
||||||
|
- повышается вовлеченность сотрудников;
|
||||||
|
|
||||||
|
§ recommendations.hour.onlyWork.title: Выходных тут нет
|
||||||
|
§ recommendations.hour.onlyWork.description: Вероятно, стоит уволить менеджера проекта.
|
||||||
|
§ recommendations.hour.weekends.title: Работа на выходных
|
||||||
|
§ recommendations.hour.weekends.description: Вероятно, стоит проверить менеджера проекта.
|
||||||
|
§ recommendations.hour.easy.title: Бывают проблемы
|
||||||
|
§ recommendations.hour.easy.description: Вероятно, бывают завалы и приходится работать на выходных.
|
||||||
|
§ recommendations.week.lazyDays.down.title: Стало меньше прогулов
|
||||||
|
§ recommendations.week.lazyDays.down.description: за последние три недели этот показатель упал
|
||||||
|
§ recommendations.week.lazyDays.up.title: Стало больше прогулов
|
||||||
|
§ recommendations.week.lazyDays.up.description: нет задач или нужен более жесткий контроль
|
||||||
|
§ recommendations.week.notWork.title: Стабильно не дорабатывает
|
||||||
|
§ recommendations.week.notWork.description: т.к. каждую неделю пишет код не 100% времени
|
||||||
|
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
||||||
|
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
||||||
|
§ recommendations.week.task.up.title: Растёт производительность
|
||||||
|
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||||
|
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
||||||
|
§ recommendations.week.task.down.title: Падает производительность
|
||||||
|
§ recommendations.week.task.down.description
|
||||||
|
или задачи хуже разбивают. Нужно проверить. Если гранулярность та же - взять на контроль.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- количество задач в день, над которыми работают, на протяжении последних трех недель стабильно падает.
|
||||||
|
|
||||||
|
# Возможные ошибки:
|
||||||
|
- задачи могли быть сложнее, чем казались;
|
||||||
|
- задачи могли иметь большой объём работы (нужно проверить количество изменений, падают они или нет за этот же период)
|
||||||
|
|
||||||
|
§ recommendations.type.everyHasOne.title: Не подписывают тип задачи
|
||||||
|
§ recommendations.type.everyHasOne.description: большинство типов задач делает один человек.
|
||||||
|
§ recommendations.type.oneMaintainer.title: Узкая специализация
|
||||||
|
§ recommendations.type.oneMaintainer.description
|
||||||
|
большинство задач одного типа делают одни и те же люди.
|
||||||
|
|
||||||
|
# Типы задач:
|
||||||
|
|
||||||
|
§ recommendations.type.common
|
||||||
|
# Возможно, это не так
|
||||||
|
|
||||||
|
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
||||||
|
|
||||||
|
Шаги, которые помогут это сделать:
|
||||||
|
- настроить пре-коммит проверку для commit message;
|
||||||
|
- объяснить команде, что нужно указывать тип;
|
||||||
|
- проверить в новых ветках, что сотрудники следуют правилу;
|
||||||
|
|
||||||
|
# Если это действительно так
|
||||||
|
|
||||||
|
Вы настроили проверки и убедились что один и тот же сотрудник, делает задачи одного и того же типа.
|
||||||
|
|
||||||
|
Почему это плохо:
|
||||||
|
- его увольнение остановит целую пачку процессов;
|
||||||
|
- уменьшается компетенция остальных членов команды;
|
||||||
|
- трудно верхнеуровнево понять его правки;
|
||||||
|
|
||||||
|
Как это исправить:
|
||||||
|
- распределять разные типы задач равномерно;
|
||||||
|
- менять область работы (тесты, документация, ошибки) между сотрудниками через спринт;
|
||||||
|
|
||||||
|
§ recommendations.type.fewTypes.title
|
||||||
|
Это локальный продукт
|
||||||
|
|
||||||
|
§ recommendations.type.fewTypes.description
|
||||||
|
для конкретного заказчика или проблемы.
|
||||||
|
|
||||||
|
# Какие признаки есть у «глобального» продукта:
|
||||||
|
- локализация;
|
||||||
|
- документация;
|
||||||
|
- большой объём тестов;
|
||||||
|
- визуальная кастомизация;
|
||||||
|
- рефакторинг узких мест;
|
||||||
|
- и т.п.
|
||||||
|
|
||||||
|
# Почему этот продукт выглядит как «локальный»:
|
||||||
|
- у каждого «глобального» признака будет перевес по своему типу задач;
|
||||||
|
- чем больше «глобальных» признаков, тем больше вероятность «глобального» продукта;
|
||||||
|
|
||||||
|
В данном случае мы видим небольшое число типов, а следовательно, скорее всего есть недоработки, мешающие легко масштабировать продукт на мировой рынок и продавать его в других странах.
|
||||||
|
|
||||||
|
# Возможно, это не так
|
||||||
|
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
||||||
|
|
||||||
|
§ recommendations.type.diff.title
|
||||||
|
Разбейте лидирующий тип на подтипы
|
||||||
|
|
||||||
|
§ recommendations.type.diff.description
|
||||||
|
для детализации ошибок.
|
||||||
|
|
||||||
|
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
|
||||||
|
|
||||||
|
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
|
||||||
|
|
||||||
|
Рассмотрим несколько вариантов подтипов:
|
||||||
|
- fix_dev (ошибка выявленная в процессе разработки);
|
||||||
|
- fix_test (ошибка выявленная в процессе тестирования);
|
||||||
|
- fix (ошибка выявленная в проде);
|
||||||
|
|
||||||
|
§ recommendations.type.buddy.title
|
||||||
|
Копите мелкие задачи
|
||||||
|
|
||||||
|
§ recommendations.type.buddy.description
|
||||||
|
для новых сотрудников.
|
||||||
|
|
||||||
|
# Если задача:
|
||||||
|
- не важная;
|
||||||
|
- не большая;
|
||||||
|
- не требует сильного погружения в контекст;
|
||||||
|
- больше про рефакторинг, чем про новый код;
|
||||||
|
|
||||||
|
# Положите её в backlog с меткой «для новичков».
|
||||||
|
|
||||||
|
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
|
||||||
|
|
||||||
|
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
|
||||||
|
`;
|
27
src/ts/translations/en/settings.ts
Normal file
27
src/ts/translations/en/settings.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
export default `
|
||||||
|
§ page.settings.document.title: Настройки отображения
|
||||||
|
§ page.settings.document.name: Заголовок страницы
|
||||||
|
§ page.settings.document.language: Язык интерфейса
|
||||||
|
§ page.settings.links.title: Префиксы ссылок
|
||||||
|
§ page.settings.links.task: Для номеров задач
|
||||||
|
§ page.settings.links.pr: Для PR
|
||||||
|
§ page.settings.user.title: Индивидуальные настройки
|
||||||
|
§ page.settings.user.notFound: Индивидуальных настроек нет. Данные по всем сотрудникам вычисляются по общим параметрам.
|
||||||
|
§ page.settings.user.subTitle: Дополнение к трудовому договору №$1
|
||||||
|
§ page.settings.user.from: Дата начала действия
|
||||||
|
§ page.settings.mailmap: Настройки .mailmap
|
||||||
|
§ page.settings.common.title: Общие данные по зарплате
|
||||||
|
§ page.settings.common.type.title: Тип работы над проектом
|
||||||
|
§ page.settings.common.type.full: Полная занятость
|
||||||
|
§ page.settings.common.type.part: Проектная работа
|
||||||
|
§ page.settings.common.salary: Зарплата в месяц
|
||||||
|
§ page.settings.common.currency: Currency
|
||||||
|
§ page.settings.common.workDaysInYear: Количество рабочих дней в году
|
||||||
|
§ page.settings.common.vacationDaysInYear: Количество дней отпуска в год
|
||||||
|
§ page.settings.common.workDaysInWeek: Рабочие дни
|
||||||
|
§ page.settings.form.save: Save
|
||||||
|
§ page.settings.form.cancel: Cancel
|
||||||
|
§ page.settings.form.remove: Remove
|
||||||
|
§ page.settings.form.addEmployee: Добавить сотрудника
|
||||||
|
§ page.settings.form.addContract: Добавить трудовой договор
|
||||||
|
`;
|
94
src/ts/translations/ru/achievements.ts
Normal file
94
src/ts/translations/ru/achievements.ts
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
export default `
|
||||||
|
§ achievements.commitsAfter1500.title: Сова
|
||||||
|
§ achievements.commitsAfter1500.description: 70% коммитов после 15:00
|
||||||
|
§ achievements.commitsBefore1500.title: Ранняя пташка
|
||||||
|
§ achievements.commitsBefore1500.description: 70% коммитов до обеда
|
||||||
|
§ achievements.workEveryTime.title: Раб божий
|
||||||
|
§ achievements.workEveryTime.description: есть коммит на каждый час суток
|
||||||
|
§ achievements.workNotWork.title: Стрельба холостыми
|
||||||
|
§ achievements.workNotWork.description: коммиты есть, а закрытых задач нет
|
||||||
|
§ achievements.userNotWork.title: Залётный
|
||||||
|
§ achievements.userNotWork.description: это не его основной проект
|
||||||
|
§ achievements.userIsDied.title: Мёртвая душа
|
||||||
|
§ achievements.userIsDied.description: работал, но уволился
|
||||||
|
§ achievements.lessTasks.title: Зашел и вышел
|
||||||
|
§ achievements.lessTasks.description: меньше всего закрытых задач
|
||||||
|
§ achievements.moreTasks.title: Батя грит малаца
|
||||||
|
§ achievements.moreTasks.description: больше всего закрытых задач
|
||||||
|
§ achievements.everyMessageLong.title: Мастер красноречия
|
||||||
|
§ achievements.everyMessageLong.description: стабильно самые длинные подписи коммитов
|
||||||
|
§ achievements.everyMessageShort.title: Болтун находка для шпиона
|
||||||
|
§ achievements.everyMessageShort.description: стабильно, самые короткие подписи коммитов
|
||||||
|
§ achievements.shortestName.title: Размер не главное
|
||||||
|
§ achievements.shortestName.description: самое короткое имя
|
||||||
|
§ achievements.longestName.title: Азим Азиз Иль Ам Кадир Имран II
|
||||||
|
§ achievements.longestName.description: самое длинное имя
|
||||||
|
§ achievements.moreCommits.title: Мастер бекапов
|
||||||
|
§ achievements.moreCommits.description: больше всего коммитов
|
||||||
|
§ achievements.lessCommits.title: Редко но метко
|
||||||
|
§ achievements.lessCommits.description: меньше всего коммитов
|
||||||
|
§ achievements.oneCommitOneTask.title: Точно в цель
|
||||||
|
§ achievements.oneCommitOneTask.description: в среднем один коммит на задачу
|
||||||
|
§ achievements.moreLazyDays.title: Мысленно я с вами
|
||||||
|
§ achievements.moreLazyDays.description: больше всего дней без коммитов
|
||||||
|
§ achievements.lessLazyDays.title: Папа Карло
|
||||||
|
§ achievements.lessLazyDays.description: меньше всего дней без коммитов
|
||||||
|
§ achievements.zeroLazyDays.title: Ни единого разрыва
|
||||||
|
§ achievements.zeroLazyDays.description: ни одного дня без коммитов
|
||||||
|
§ achievements.moreWorkDays.title: Ценный работник
|
||||||
|
§ achievements.moreWorkDays.description: больше всего рабочих дней
|
||||||
|
§ achievements.moreScopes.title: Стартапер
|
||||||
|
§ achievements.moreScopes.description: сделал больше всего фичей
|
||||||
|
§ achievements.lessScopes.title: Щегол
|
||||||
|
§ achievements.lessScopes.description: сделал меньше всего фичей
|
||||||
|
§ achievements.moreDaysForTask.title: Улитка на склоне
|
||||||
|
§ achievements.moreDaysForTask.description: работа по задачам идёт медленнее чем у остальных
|
||||||
|
§ achievements.more2DaysForTask.title: Cо слоу
|
||||||
|
§ achievements.more2DaysForTask.description: больше двух дней на задачу
|
||||||
|
§ achievements.moreDaysInProject.title: Старожил
|
||||||
|
§ achievements.moreDaysInProject.description: больше всего дней на проекте
|
||||||
|
§ achievements.lessDaysInProject.title: А это кто?
|
||||||
|
§ achievements.lessDaysInProject.description: меньше всего дней на проекте
|
||||||
|
§ achievements.more90DaysInProject.title: Добро пожаловать
|
||||||
|
§ achievements.more90DaysInProject.description: не уволили на испытательном
|
||||||
|
§ achievements.lessDaysForTask.title: Скорострел
|
||||||
|
§ achievements.lessDaysForTask.description: одна задача занимает меньше дня
|
||||||
|
§ achievements.adam.title: Адам
|
||||||
|
§ achievements.adam.description: первый стабильный сотрудник на проекте
|
||||||
|
§ achievements.more666DaysInProject.title: Чёрт
|
||||||
|
§ achievements.more666DaysInProject.description: отработал 666 дней на проекте
|
||||||
|
§ achievements.more777DaysInProject.title: Азино 3 топора
|
||||||
|
§ achievements.more777DaysInProject.description: отработал 777 дней на проекте
|
||||||
|
§ achievements.moreRefactoring.title: Выпускающий редактор
|
||||||
|
§ achievements.moreRefactoring.description: сделал больше всех меток «рефакторинг»
|
||||||
|
§ achievements.longestMessage.title: А разговоров то было...
|
||||||
|
§ achievements.longestMessage.description: самая длинная подпись коммита за все время
|
||||||
|
§ achievements.moreTasksInDay.title: Спиди-гонщик
|
||||||
|
§ achievements.moreTasksInDay.description: рекорд по количеству закрытых задач в день
|
||||||
|
§ achievements.hasCommitFrom0to7.title: Ночной дозор
|
||||||
|
§ achievements.hasCommitFrom0to7.description: есть коммит на каждый час ночи
|
||||||
|
§ achievements.noCommitOnDay.title: Технический перерыв
|
||||||
|
§ achievements.noCommitOnDay.description: есть определенный час и день в рабочее время в который никогда не комитит
|
||||||
|
§ achievements.hasCommitEveryTime.title: Умер на работе
|
||||||
|
§ achievements.hasCommitEveryTime.description: есть коммит на час каждого дня (включая выходные)
|
||||||
|
§ achievements.commitsAfter1800.title: Делу время
|
||||||
|
§ achievements.commitsAfter1800.description: нет ни одного коммита после 18:00
|
||||||
|
§ achievements.more1488DaysInProject.title: им. Максима Марцинкевича
|
||||||
|
§ achievements.more1488DaysInProject.description: отработал 1488 дней на проекте
|
||||||
|
§ achievements.taskNumber300.title: Знаком с трактористом
|
||||||
|
§ achievements.taskNumber300.description: первый взял в работу задачу с номером 300
|
||||||
|
§ achievements.moreFix.title: Bug hunter
|
||||||
|
§ achievements.moreFix.description: больше всего закрытых багов
|
||||||
|
§ achievements.lessWorkDays.title: Дальше без меня
|
||||||
|
§ achievements.lessWorkDays.description: меньше всего рабочих дней
|
||||||
|
§ achievements.moreCreateCode.title: Созидатель
|
||||||
|
§ achievements.moreCreateCode.description: склонен больше остальных добавлять код
|
||||||
|
§ achievements.moreRemoveCode.title: Разрушитель
|
||||||
|
§ achievements.moreRemoveCode.description: склонен больше остальных удалять код
|
||||||
|
§ achievements.moreChangeCode.title: Реформатор
|
||||||
|
§ achievements.moreChangeCode.description: склонен больше остальных изменять код
|
||||||
|
§ achievements.moreStyle.title: Полиция моды
|
||||||
|
§ achievements.moreStyle.description: склонен больше остальных изменять CSS
|
||||||
|
§ achievements.moreOnHoliday.title: Нет жизни
|
||||||
|
§ achievements.moreOnHoliday.description: относительно много коммитов в нерабочее время
|
||||||
|
`;
|
28
src/ts/translations/ru/common.ts
Normal file
28
src/ts/translations/ru/common.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
export default `
|
||||||
|
§ uiKit.console: Копировать
|
||||||
|
§ uiKit.dataLoader.page: Страница
|
||||||
|
§ uiKit.dataLoader.size: Отображается по
|
||||||
|
§ uiKit.dataLoader.from: из
|
||||||
|
§ uiKit.dataLoader.all: Показать все
|
||||||
|
§ uiKit.hoursChart.work: стандартное рабочее время (будни, с 07:00 до 20:00)
|
||||||
|
§ uiKit.hoursChart.weekend: выходные дни или время до/после рабочего дня
|
||||||
|
§ uiKit.hoursChart.days: суммарное количество коммитов за все время в конкретный день и час
|
||||||
|
§ uiKit.page.remove: Удалить
|
||||||
|
§ uiKit.races.go: Поехали
|
||||||
|
§ uiKit.nothingFound.common.title: Нет или недостаточно данных для отображения
|
||||||
|
§ uiKit.nothingFound.common.description: Система обработает больше данных, если коммиты будут подписаны в формате [Git commit message convention|https://www.conventionalcommits.org/en/v1.0.0/]. Шаблон:
|
||||||
|
§ uiKit.nothingFound.common.console: Номер_задачи тип(фича): пояснение
|
||||||
|
§ uiKit.nothingFound.common.example: Например:
|
||||||
|
§ uiKit.nothingFound.staff.title: Нет данных для этого сотрудника
|
||||||
|
§ uiKit.nothingFound.staff.description1:
|
||||||
|
Он вносил правки не каждый рабочий день и получил статус «Помошник».
|
||||||
|
Работой сотрудников с таким статусом по данному проекту можно пренебречь, т.к. его влад на общем фоне незначителен.
|
||||||
|
|
||||||
|
§ uiKit.nothingFound.staff.description2:
|
||||||
|
Поэтому система не рассчитывает для него ряд показателей.
|
||||||
|
Если это ошибка и данного сотрудника нужно рассчитать как обычного, перейдите в раздел «Настройки» и измените его тип.
|
||||||
|
|
||||||
|
§ common.filters: Фильтры
|
||||||
|
§ common.notifications.save: Изменения сохранены
|
||||||
|
§ common.notifications.setting: Настройки сохранены
|
||||||
|
`;
|
15
src/ts/translations/ru/index.ts
Normal file
15
src/ts/translations/ru/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import achievements from './achievements';
|
||||||
|
import common from './common';
|
||||||
|
import navigation from './navigation';
|
||||||
|
import recommendations from './recommendations';
|
||||||
|
import settings from './settings';
|
||||||
|
import pages from './pages';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
achievements,
|
||||||
|
common,
|
||||||
|
navigation,
|
||||||
|
recommendations,
|
||||||
|
settings,
|
||||||
|
pages,
|
||||||
|
].join('');
|
37
src/ts/translations/ru/navigation.ts
Normal file
37
src/ts/translations/ru/navigation.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
export default `
|
||||||
|
§ sidebar.switch.team: Команда
|
||||||
|
§ sidebar.switch.person: Сотрудник
|
||||||
|
§ sidebar.buttons.settings: Настройки
|
||||||
|
§ sidebar.buttons.print: Печать
|
||||||
|
§ sidebar.filters.all: всё время
|
||||||
|
§ sidebar.filters.year: год
|
||||||
|
§ sidebar.filters.halfYear: пол года
|
||||||
|
§ sidebar.filters.month: месяц
|
||||||
|
§ sidebar.filters.week: неделя
|
||||||
|
§ sidebar.team.total: Общая информация
|
||||||
|
§ sidebar.team.scope: Фичи
|
||||||
|
§ sidebar.team.author: Сотрудники
|
||||||
|
§ sidebar.team.type: Типы задач
|
||||||
|
§ sidebar.team.pr: Влитие кода
|
||||||
|
§ sidebar.team.day: По дням
|
||||||
|
§ sidebar.team.week: По неделям
|
||||||
|
§ sidebar.team.month: По месяцам
|
||||||
|
§ sidebar.team.tree: Анализ файлов
|
||||||
|
§ sidebar.team.hours: Расписание
|
||||||
|
§ sidebar.team.commits: Все коммиты
|
||||||
|
§ sidebar.team.changes: Все изменения
|
||||||
|
§ sidebar.team.words: Популярные слова
|
||||||
|
§ sidebar.team.top: Викторина
|
||||||
|
§ sidebar.team.settings: Настройки
|
||||||
|
§ sidebar.person.total: Общая информация
|
||||||
|
§ sidebar.person.money: Стоимость работы
|
||||||
|
§ sidebar.person.speed: Скорость
|
||||||
|
§ sidebar.person.day: По дням
|
||||||
|
§ sidebar.person.week: По неделям
|
||||||
|
§ sidebar.person.month: По месяцам
|
||||||
|
§ sidebar.person.hours: Расписание
|
||||||
|
§ sidebar.person.commits: Все коммиты
|
||||||
|
§ sidebar.person.changes: Все изменения
|
||||||
|
§ sidebar.person.words: Популярные слова
|
||||||
|
§ sidebar.person.settings: Настройки
|
||||||
|
`;
|
203
src/ts/translations/ru/pages.ts
Normal file
203
src/ts/translations/ru/pages.ts
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
export default `
|
||||||
|
§ page.welcome.step1: Выполните команду в корне вашего проекта
|
||||||
|
§ page.welcome.step3: Перетащите
|
||||||
|
§ page.welcome.step4: файл log.txt на эту страницу
|
||||||
|
§ page.welcome.description1: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл
|
||||||
|
§ page.welcome.description2: [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
|
||||||
|
§ page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
|
||||||
|
§ page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
|
||||||
|
§ page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].
|
||||||
|
§ page.common.words.title: Статистика по словам
|
||||||
|
§ page.common.words.description: самое популярное слово. Встречается $1 раза.
|
||||||
|
§ page.common.commits.title: Количество коммитов по дням
|
||||||
|
§ page.common.commits.description: ($1) самый продуктивный день по числу коммитов.
|
||||||
|
§ page.common.commits.title2: $1 сделано коммитов: $2
|
||||||
|
§ page.common.filter.allUsers: Не имеет значения
|
||||||
|
§ page.print.modal.title: Что распечатываем?
|
||||||
|
§ page.print.modal.page: Текущую страницу
|
||||||
|
§ page.print.modal.type: Текущий раздел
|
||||||
|
§ page.print.modal.all: Всю статистику
|
||||||
|
§ page.print.modal.cancel: Отмена
|
||||||
|
§ page.print.tableOfContents: Оглавление
|
||||||
|
§ page.print.title: Отчёт по git-репозиторию «$1»
|
||||||
|
§ page.print.description: Данные для отчёта были получены из истории коммитов.
|
||||||
|
§ page.team.author.title: Статистика по сотрудникам
|
||||||
|
§ page.team.author.description1: *Часть статистики* (скорость работы, затраченные деньги и т.п.) *по сотрудникам с типом «Помощник» не считается*, т.к. это эпизодическая роль в проекте. Предполагаем, что они не влияют на проект, а их правками можно пренебречь на фоне общего объема работы.
|
||||||
|
§ page.team.author.description2: *Сортировка по умолчанию* — это сортировка по количеству задач и группам (текущие, уволенные, помогающие сотрудники).
|
||||||
|
§ page.team.author.types: Тип работ
|
||||||
|
§ page.team.author.commits: Коммитов
|
||||||
|
§ page.team.author.commitsSmall: коммитов
|
||||||
|
§ page.team.author.tasks: Задач
|
||||||
|
§ page.team.author.tasksSmall: задач
|
||||||
|
§ page.team.author.workedLosses: Дни с коммитами и без
|
||||||
|
§ page.team.author.worked: работа
|
||||||
|
§ page.team.author.losses: дни без коммитов
|
||||||
|
§ page.team.author.days: дней
|
||||||
|
§ page.team.author.daysForTask: Дней на задачу
|
||||||
|
§ page.team.author.scopes: Фич
|
||||||
|
§ page.team.author.moneyAll: Получил
|
||||||
|
§ page.team.author.moneyWorked: Отработал
|
||||||
|
§ page.team.author.moneyLosses: Переплата
|
||||||
|
§ page.team.hours.title: Распределение коммитов в течении каждого дня недели
|
||||||
|
§ page.team.month.title: Календарь работы по проекту
|
||||||
|
§ page.team.scope.title: Статистика по фичам
|
||||||
|
§ page.team.scope.scope: Фича
|
||||||
|
§ page.team.scope.days: Раб. дней
|
||||||
|
§ page.team.scope.authorsDays: Человеко-дней
|
||||||
|
§ page.team.scope.tasks: Задач
|
||||||
|
§ page.team.scope.commits: Коммитов
|
||||||
|
§ page.team.scope.commitsSmall: коммитов
|
||||||
|
§ page.team.scope.types: Тип работ
|
||||||
|
§ page.team.scope.authors: Персональный вклад
|
||||||
|
§ page.team.scope.cost: Стоимость
|
||||||
|
§ page.team.type.title: Статистика по типам задач
|
||||||
|
§ page.team.type.description: *Персональный вклад* считается по количеству коммитов, а не объему измененных строк или файлов. Поэтому следует так же смотреть раздел «Анализ файлов», чтобы оценить масштаб изменений.
|
||||||
|
§ page.team.type.type: Тип работы
|
||||||
|
§ page.team.type.tasks: Задач
|
||||||
|
§ page.team.type.tasksSmall: задач
|
||||||
|
§ page.team.type.days: Дней
|
||||||
|
§ page.team.type.daysSmall: дней
|
||||||
|
§ page.team.type.authorsDays: Человеко-дней
|
||||||
|
§ page.team.type.commits: Коммитов
|
||||||
|
§ page.team.type.authors: Персональный вклад
|
||||||
|
§ page.team.total.titleA: Объём работ
|
||||||
|
§ page.team.total.titleB: Стоимость
|
||||||
|
§ page.team.total.daysWorked.title: человеко-дней
|
||||||
|
§ page.team.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.team.total.commits.title: коммитов
|
||||||
|
§ page.team.total.commits.description: Удалённые ветки не считаются
|
||||||
|
§ page.team.total.daysLosses.title: дней без коммитов
|
||||||
|
§ page.team.total.daysLosses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
||||||
|
§ page.team.total.employment.title: работает / уволилось
|
||||||
|
§ page.team.total.employment.description: Если сотрудник в течении месяца не сделал ни одного коммита, он считается уволенным
|
||||||
|
§ page.team.total.moneyAll.title: общая
|
||||||
|
§ page.team.total.moneyAll.description: Суммарные затраты на зп
|
||||||
|
§ page.team.total.moneyWorked.title: фактическая
|
||||||
|
§ page.team.total.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
||||||
|
§ page.team.total.moneyLosses.title: возможная переплата
|
||||||
|
§ page.team.total.moneyLosses.description: Оплаченные рабочие дни, когда коммитов не было
|
||||||
|
§ page.team.total.weekendPayment.title: работа на выходных
|
||||||
|
§ page.team.total.weekendPayment.description: Суммарная переплата за работу в выходные дни
|
||||||
|
§ page.team.total.workSpeed.title: задач в день
|
||||||
|
§ page.team.total.workSpeed.description: Средняя скорость работы команды при текущем составе сотрудников
|
||||||
|
§ page.team.total.moneySpeed.title: в месяц
|
||||||
|
§ page.team.total.moneySpeed.description: Прогнозируемая сумма выплаты на зп при текущем составе сотрудников без учета налогов и сопутствующих затрат
|
||||||
|
§ page.team.total.description1: *Человеко-дни* — это работа одного сотрудника в течение одного рабочего дня. Например, за один календарный день, команда из трех сотрудников выдает объем работы в три человеко-дня.
|
||||||
|
§ page.team.total.description2: *Днями прогулов* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют.
|
||||||
|
§ page.team.total.description3: Карточка *работает и уволилось* показывает фактический состав сотрудников, которые постоянно участвуют в работе. Кроме этого, есть «помощники» — это сотрудники, как правило другой специализации, которые могут иногда делать коммиты в проект.
|
||||||
|
§ page.team.total.description4: *Переплатой* считаются только рабочие дни, когда коммиты могли бы быть сделаны. Выходные, государственные праздники и отпуска в расчёте не участвуют. Именно поэтому переплата + фактическая стоимость != общей. В общей стоимости заложена оплата выходных, государственных праздников и отпусков.
|
||||||
|
§ page.team.total.description5: *Работой на выходных* считается по коэффициенту х2 от оплаты обычного дня. Выше отображена именно переплата (х1), т.к. сам факт переработки в данном контексте не интересен. Мы не смотрим скорость сжигания бюджета. Мы смотрим переплату при увеличении скорости работы.
|
||||||
|
§ page.team.tree.title: Дерево проекта с учётом выбранных фильтров
|
||||||
|
§ page.team.tree.filters.author: Сотрудник
|
||||||
|
§ page.team.tree.filters.commits: Количество коммитов
|
||||||
|
§ page.team.tree.filters.help: Минимальное количество коммитов, которое сделал сотрудник в файле
|
||||||
|
§ page.team.tree.filters.all: Все сотрудники
|
||||||
|
§ page.team.tree.add: Кто добавлял
|
||||||
|
§ page.team.tree.change: Кто менял
|
||||||
|
§ page.team.tree.remove: Кто удалял
|
||||||
|
§ page.team.tree.line: строк
|
||||||
|
§ page.team.tree.lineAdd: добавили
|
||||||
|
§ page.team.tree.lineRemove: изменили
|
||||||
|
§ page.team.week.title: Статистика по неделям
|
||||||
|
§ page.team.week.date: Дата
|
||||||
|
§ page.team.week.numberTasks: Количество задач
|
||||||
|
§ page.team.week.people: Количество человек
|
||||||
|
§ page.team.week.line: Изменение строк
|
||||||
|
§ page.team.week.days: Дни с коммитами и без
|
||||||
|
§ page.team.week.lossesDetails: Кто не коммитил
|
||||||
|
§ page.team.week.add: добавили
|
||||||
|
§ page.team.week.change: изменили
|
||||||
|
§ page.team.week.remove: удалили
|
||||||
|
§ page.team.week.hasCommits: были коммиты
|
||||||
|
§ page.team.week.hasNotCommits: небыло коммитов
|
||||||
|
§ page.team.week.days: дней
|
||||||
|
§ page.team.week.tasks: задач
|
||||||
|
§ page.team.pr.task: Задача
|
||||||
|
§ page.team.pr.tasks: задач
|
||||||
|
§ page.team.pr.firstCommitTime: Первый коммит
|
||||||
|
§ page.team.pr.lastCommitTime: Последний
|
||||||
|
§ page.team.pr.workDays: Дней разработки
|
||||||
|
§ page.team.pr.delayDays: Дней ожидания влития
|
||||||
|
§ page.team.pr.commits: Коммиты
|
||||||
|
§ page.team.pr.date: Дата влития
|
||||||
|
§ page.team.pr.mergeAuthor: Влил
|
||||||
|
§ page.team.pr.author: Сотрудник
|
||||||
|
§ page.team.pr.middleTimeRelease: Среднее время поставки (дни)
|
||||||
|
§ page.team.pr.work: разработка
|
||||||
|
§ page.team.pr.delay: ожидание
|
||||||
|
§ page.team.pr.days: дней
|
||||||
|
§ page.team.pr.oneTaskDays: Время потраченное на одну задачу
|
||||||
|
§ page.team.pr.description1: *Время разработки* это разница времени от первого до последнего коммита по задаче. Не важно были перерывы в несколько дней между коммитами или нет. Сам факт какого-либо коммита увеличивает время.
|
||||||
|
§ page.team.pr.description2: *Время ожидания* это время между последним коммитом и влитием кода. Оно показывает фактический простой в ожидании чего-либо.
|
||||||
|
§ page.team.pr.description3: *Зачем отображать время разработки* без разбивки на кодинг и код-ревью? Затем, чтобы показать бизнесу фактическое время поставки кода. Ожидание тестирования, замечания на ревью, проблемы DevOps и прочие несовершенства процесса, как раз уже заложены в этот срок.
|
||||||
|
§ page.team.pr.statByAuthors: Статистика по сотрудникам
|
||||||
|
§ page.team.pr.longDelay: Длительное ожидание влития
|
||||||
|
§ page.person.print.photo.title: Фотография
|
||||||
|
§ page.person.print.photo.description: место для фотографии
|
||||||
|
§ page.person.total.title: Основные характеристики
|
||||||
|
§ page.person.total.daysWorked.title: дней работы
|
||||||
|
§ page.person.total.daysWorked.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.person.total.tasks.title: задач
|
||||||
|
§ page.person.total.tasks.description: Если коммиты правильно подписаны
|
||||||
|
§ page.person.character.title: Персонаж
|
||||||
|
§ page.person.achievement.title: Достижения
|
||||||
|
§ page.person.achievement.positive: Позитивные
|
||||||
|
§ page.person.achievement.normal: Нейтральные
|
||||||
|
§ page.person.achievement.negative: Негативные
|
||||||
|
§ page.person.achievement.description: Чем больше сотрудник набрал отрицательных достижений, тем больше вероятность, что ситуация нестандартная. Возможно, стоит изменить режим его работы, задачи или отчётность. Следует поговорить с ним и узнать, какие проблемы мешают его работе.
|
||||||
|
§ page.person.gets.title: Взятые геты:
|
||||||
|
§ page.person.gets.description: «Взять гет» в данном случае означает первым оставить коммит к задаче с «красивым» номером.
|
||||||
|
§ page.person.business.days.title: дней работы
|
||||||
|
§ page.person.business.days.description: Учтены только дни, в которые делались коммиты
|
||||||
|
§ page.person.business.tasks.title: задач
|
||||||
|
§ page.person.business.tasks.description: Если коммиты правильно подписаны
|
||||||
|
§ page.person.business.losses.title: дней без коммитов
|
||||||
|
§ page.person.business.losses.description: Все дни минус: праздники, выходные, отпуск, дни с коммитами
|
||||||
|
§ page.person.business.commits.title: коммитов
|
||||||
|
§ page.person.business.commits.description: Удалённые ветки не считаются
|
||||||
|
§ page.person.business.time.description: Время от первого, до последнего коммита (в том числе, нерабочие дни)
|
||||||
|
§ page.person.business.time.title: Дней на проекте:
|
||||||
|
§ page.person.business.time.dismissed: (уволен)
|
||||||
|
§ page.person.business.time.staff: (не в команде)
|
||||||
|
§ page.person.business.achievements: Достижения
|
||||||
|
§ page.person.changes.title: Достижения
|
||||||
|
§ page.person.changes.description:
|
||||||
|
При некоторых видах форматирования git отмечает строки как «удалённые» и «добавленные»,
|
||||||
|
хотя на самом деле они были «изменены». Поэтому, если вы провели большой рефакторинг,
|
||||||
|
git может показать малое количество изменений в статистике, а фактический результат
|
||||||
|
будет отмечен, как скачок «удаленных» и «добавленных» строк.
|
||||||
|
§ page.person.changes.description: Список коммитов и количество изменений в них за этот день:
|
||||||
|
§ page.person.commits.title: Список коммитов:
|
||||||
|
§ page.person.money.title.total: За всё время
|
||||||
|
§ page.person.money.title.middle: Средняя стоимость
|
||||||
|
§ page.person.money.moneyAll.title: получил
|
||||||
|
§ page.person.money.moneyAll.description: Предполагаемая сумма зп с проекта (см. настройки)
|
||||||
|
§ page.person.money.moneyWorked.title: отработал
|
||||||
|
§ page.person.money.moneyWorked.description: Фактически отработанные дни умноженные на среднюю зп
|
||||||
|
§ page.person.money.moneyLosses.title: возможная переплата
|
||||||
|
§ page.person.money.moneyLosses.description: Дни без коммитов умноженные на среднюю зп
|
||||||
|
§ page.person.money.tasks.title: задача
|
||||||
|
§ page.person.money.tasks.description: Количество закрытых задач к стоимости дня
|
||||||
|
§ page.person.money.commits.title: коммит
|
||||||
|
§ page.person.money.commits.description: Количество коммитов к стоимости рабочего дня
|
||||||
|
§ page.person.speed.task: Одна задача в среднем это
|
||||||
|
§ page.person.speed.max: Максимальная скорость в день
|
||||||
|
§ page.person.speed.days.title: дней
|
||||||
|
§ page.person.speed.days.description: Имеются ввиду рабочие дни, если коммиты правильно подписаны
|
||||||
|
§ page.person.speed.commits.title: коммитов
|
||||||
|
§ page.person.speed.commits.description: Отрезаны 10% максимальных и минимальных значений
|
||||||
|
§ page.person.speed.line.title: строк кода
|
||||||
|
§ page.person.speed.line.description: Отрезаны 10% максимальных и минимальных значений
|
||||||
|
§ 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: выходные
|
||||||
|
`;
|
506
src/ts/translations/ru/recommendations.ts
Normal file
506
src/ts/translations/ru/recommendations.ts
Normal file
|
@ -0,0 +1,506 @@
|
||||||
|
export default `
|
||||||
|
§ recommendations.title
|
||||||
|
Рекомендации и факты
|
||||||
|
|
||||||
|
§ recommendations.timestamp.firstCommit.description
|
||||||
|
сделал первый коммит
|
||||||
|
|
||||||
|
День недели: $1
|
||||||
|
|
||||||
|
§ recommendations.timestamp.lastCommit.description
|
||||||
|
сделал последний коммит
|
||||||
|
|
||||||
|
День недели: $1
|
||||||
|
|
||||||
|
§ recommendations.timestamp.common.title: $1 дней
|
||||||
|
§ recommendations.timestamp.allDays.description: от первого до последнего коммита (включая выходные и праздники).
|
||||||
|
§ recommendations.timestamp.lossesDays.description: без коммитов, даже с учётом выходных, отпуска и государственных праздников.
|
||||||
|
§ recommendations.timestamp.weekendDays.description
|
||||||
|
работы на выходных
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- сотрудники быстрее выгорают;
|
||||||
|
|
||||||
|
§ recommendations.timestamp.regularWeekendWord.title: Регулярные переработки
|
||||||
|
§ recommendations.timestamp.sometimeWeekendWord.title: Бывают переработки
|
||||||
|
§ recommendations.timestamp.weekendWord.description
|
||||||
|
Вероятно, стоит сменить менеджера проекта, аналитика и архитектора.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- качество продукта, как правило, получается низкое;
|
||||||
|
- часть сотрудников увольняется;
|
||||||
|
- из-за спешки появляются новые ошибки;
|
||||||
|
|
||||||
|
# Скорее всего:
|
||||||
|
- неверно оценили сроки в самом начале;
|
||||||
|
- тех. задание отсутствует;
|
||||||
|
- слабая аналитика;
|
||||||
|
- слабая архитектура (архитектора не нанимали, а команда состоит из мидл разработчиков);
|
||||||
|
- сначала начали писать код, потом проектировать;
|
||||||
|
- нет нормальных процессов, чтобы понять ошибки;
|
||||||
|
|
||||||
|
§ recommendations.timestamp.neverWeekendWord.title: Обычно без переработок
|
||||||
|
§ recommendations.timestamp.neverWeekendWord.description
|
||||||
|
Но иногда бывают.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- заказчик платит двойную цену за работу в выходной день;
|
||||||
|
- сотрудники быстрее выгорают;
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.not.title
|
||||||
|
Нет параллельных работ
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.not.description
|
||||||
|
любую фичу в один момент времени делает один человек.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат меньше 1.3 считаем, что параллельных работ в рамках большинства фичей обычно нет;
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- повышается bus factor;
|
||||||
|
- сотрудники медленнее развиваются;
|
||||||
|
- трудно качественно проверить работу сотрудника;
|
||||||
|
|
||||||
|
# Почему это хорошо:
|
||||||
|
- появляются эксперты, которые очень глубоко погружены в предметную область и могут предложить более качественные решения;
|
||||||
|
- скорее всего не бывает merge конфликтов;
|
||||||
|
- проект может очень быстро параллельно развиваться в разные стороны;
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.has.title
|
||||||
|
Часть работ параллельно
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.has.description
|
||||||
|
Иногда фичу делают одновременно несколько человек.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат от 1.3 до 2.0 считаем, что часть работ в рамках разных фичей иногда делается параллельно;
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.every.title
|
||||||
|
Параллельные работы
|
||||||
|
|
||||||
|
§ recommendations.scope.parallelism.every.description
|
||||||
|
любую фичу в один момент времени делают несколько человек
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни делятся на фактические дни для каждой фичи;
|
||||||
|
- находим среднее арифметическое;
|
||||||
|
- если результат больше двух считаем, что большая часть работ в рамках разных фичей обычно делается параллельно;
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.scope.money
|
||||||
|
в такую сумму можно оценить работу по данному проекту.
|
||||||
|
|
||||||
|
# Метод расчёта:
|
||||||
|
- человеко-дни затраченные на разработку умножаются на индивидуальную зарплату разработчиков;
|
||||||
|
|
||||||
|
Изменить зарплату каждого разработчика, для более точной суммы, можно в разделе «Настройки»
|
||||||
|
|
||||||
|
# Это много или мало?
|
||||||
|
Для ответа на этот вопрос, нужно ответить на следующие:
|
||||||
|
- Можно ли за эти деньги было купить готовое решение?
|
||||||
|
- Можно ли за эти деньги сделать более хороший продукт?
|
||||||
|
|
||||||
|
Если ответ на оба вопроса «да», то возможно, разработка с нуля не стоила потраченных на неё денег.
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.everyHasOne.title
|
||||||
|
Bus factor = 1
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.everyHasOne.description
|
||||||
|
В большинство фич погружен один человек.
|
||||||
|
Надо переключать людей.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- если сотрудники будут увольняться, будет трудно продолжить их работу;
|
||||||
|
- невозможно контролировать качество его кода;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- более 80% коммитов в фичу делает один человек;
|
||||||
|
- проект имеет более 60% таких фичей;
|
||||||
|
|
||||||
|
§ recommendations.scope.bus.oneMaintainer
|
||||||
|
в фичи погружен один человек.
|
||||||
|
|
||||||
|
# Почему это плохо:
|
||||||
|
- если он уволится, будет трудно продолжить разработку;
|
||||||
|
- снижается качество code-review;
|
||||||
|
- трудно запараллелить разработку при необходимости;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- более 80% коммитов в фичу сделал один человек;
|
||||||
|
|
||||||
|
§ recommendations.scope.types.process.title
|
||||||
|
Плохие процессы
|
||||||
|
|
||||||
|
§ recommendations.scope.types.process.description
|
||||||
|
Большинство фич содержат один тип задач.
|
||||||
|
|
||||||
|
§ recommendations.scope.types.one
|
||||||
|
фичи содержат один тип задач.
|
||||||
|
|
||||||
|
§ recommendations.scope.types.common
|
||||||
|
Возможно, разработчики неправильно подписывают коммиты или менеджер заводит один и тот же тип задач.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- невозможно передать поддержку другой команде;
|
||||||
|
- невозможно выпустить "коробочную" версию;
|
||||||
|
- сильная зависимость от конкретных разработчиков;
|
||||||
|
- большое количество ошибок и низкое качество кода;
|
||||||
|
- вероятное замедление разработки в будущем;
|
||||||
|
|
||||||
|
# В чём ошибка менеджера:
|
||||||
|
- взгляд на продукт, только с позиции «работающей демки»;
|
||||||
|
|
||||||
|
# Что должно быть:
|
||||||
|
- тесты;
|
||||||
|
- ошибки (выявленные по результатам тестов);
|
||||||
|
- рефакторинг (т.к. архитектура может измениться);
|
||||||
|
- документация;
|
||||||
|
- правки стиля (как результат опроса фокус-группы);
|
||||||
|
|
||||||
|
§ recommendations.scope.plan.title
|
||||||
|
Постройте долгосрочный план
|
||||||
|
|
||||||
|
§ recommendations.scope.plan.description
|
||||||
|
с учетом архитектуры.
|
||||||
|
|
||||||
|
При том опираться этот план должен сразу на самые трудные задачи.
|
||||||
|
|
||||||
|
# Почему отсутствие плана плохо:
|
||||||
|
- сотрудники делают минимально работающую версию, не закладывая точки расширения. После этого пишется не масштабируемый код, который тормозит следующие фичи;
|
||||||
|
|
||||||
|
# В чём ошибка менеджера:
|
||||||
|
- он не показал, как продукт будет развиваться далее и в каких точках будет рост;
|
||||||
|
|
||||||
|
# Как должно быть:
|
||||||
|
- составляется глобальный план развития продукта;
|
||||||
|
- составляется глобальный план развития архитектуры (с разработчиками и DBA);
|
||||||
|
- на уровне схем сразу проговариваются моменты, которые могут сильно измениться;
|
||||||
|
|
||||||
|
§ recommendations.scope.cost.title
|
||||||
|
Оцените инвестиции в фичу
|
||||||
|
|
||||||
|
§ recommendations.scope.cost.description
|
||||||
|
с количеством потенциальной прибыли.
|
||||||
|
|
||||||
|
Фичи которые дорого стоят в разработке, но приносят мало прибыли, возможно, стоит отложить или вообще отменить. Это сделает проект более коммерчески успешным.
|
||||||
|
|
||||||
|
§ recommendations.author.lotOfLazy
|
||||||
|
пишет слишком мало кода.
|
||||||
|
|
||||||
|
# Может уволить?
|
||||||
|
- он тимлид, архитектор, аналитик?
|
||||||
|
- это его основной проект?
|
||||||
|
- есть какие-то зависимости от него?
|
||||||
|
|
||||||
|
# Почему нет смысла исправлять
|
||||||
|
Суммарные затраты на разработчика уже больше чем прибыль от его работы.
|
||||||
|
Если мы считаем, что объективных помех его работе не было, то человек либо не хочет работать вообще, либо работает на двух проектах одновременно.
|
||||||
|
Увольнение и замена новым сотрудником выглядит оправданным с точки зрения общей статистики.
|
||||||
|
|
||||||
|
§ recommendations.author.manyLazy
|
||||||
|
пишет мало кода. Нужно взять на контроль.
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- на тестовых выборках хороший программист пишет код больше 80% времени;
|
||||||
|
- в данном случае показатель от 60% до 80%;
|
||||||
|
|
||||||
|
# Как контролировать:
|
||||||
|
- дробить задачи на 1..2 дня;
|
||||||
|
- каждый день спрашивать статус;
|
||||||
|
- убедиться, что задачи хорошо расписаны и готовы к началу разработки;
|
||||||
|
- устроить парное программирование, чтобы проверить фактическую скорость;
|
||||||
|
|
||||||
|
§ recommendations.author.oneTypeMans
|
||||||
|
получает слишком однообразные задачи по типу. Может выгореть.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- если сотрудник выгорит, его скорость работы снизится;
|
||||||
|
- замедляется профессиональный рост;
|
||||||
|
- повышается вероятность увольнения;
|
||||||
|
|
||||||
|
# Как делается выборка:
|
||||||
|
- для каждого коммита определятся тип задачи;
|
||||||
|
- если больше 70% задач одного типа, значит человек делает одно и тоже;
|
||||||
|
|
||||||
|
§ recommendations.author.workToday.title: Работает $1
|
||||||
|
§ recommendations.author.workToday.description
|
||||||
|
над проектом в данный момент.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- рабочих дней более 50%;
|
||||||
|
- работали в течении последних 30 дней;
|
||||||
|
|
||||||
|
§ recommendations.author.dismissed.title: Уволилось $1
|
||||||
|
§ recommendations.author.dismissed.description
|
||||||
|
или работало короткий промежуток времени.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- работали в нормальном ритме (видимо, это их основной репозиторий);
|
||||||
|
- за последний месяц не было ни одного коммита;
|
||||||
|
- отпуск обычно 14 дней (их отсутствие не похоже на отпуск);
|
||||||
|
|
||||||
|
§ recommendations.author.staff.title: Помогают $1
|
||||||
|
§ recommendations.author.staff.description
|
||||||
|
Люди другой специализации, которые что-либо коммитили.
|
||||||
|
|
||||||
|
# Состав:
|
||||||
|
- $1;
|
||||||
|
|
||||||
|
# Почему именно они:
|
||||||
|
- это не open-source проект;
|
||||||
|
- рабочих дней менее 15% от общего числа;
|
||||||
|
- изменяют примерно одни и те же файлы;
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.openSource.title
|
||||||
|
Открытый проект
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.openSource.description
|
||||||
|
пять дней в неделю тут не работают.
|
||||||
|
|
||||||
|
Проект может быть и закрытым, просто такой темп работы обычно у открытых библиотек на GitHub.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- берется статистика по всем активным разработчикам;
|
||||||
|
- подсчитывается среднее число дней работы и без коммитов;
|
||||||
|
- у open-source библиотек рабочих дней обычно максимум 15..20%;
|
||||||
|
|
||||||
|
# Последствия
|
||||||
|
Для проектов, где работа не постоянна, нет смысла во многих показателях. Поэтому показатели без коммитов, скорости и т.п. будут скрыты.
|
||||||
|
|
||||||
|
Как правило, оценку таких проектов делают перед началом разработки своей закрытой версии. Самые интересные показатели в этом случае вероятная стоимость и суммарное время на разработку.
|
||||||
|
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.easy.title
|
||||||
|
Слабая загрузка
|
||||||
|
|
||||||
|
§ recommendations.author.projectType.easy.description
|
||||||
|
слишком много дней без коммитов. Нужно понять почему команда не пишет код.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- берется статистика по всем активным разработчикам;
|
||||||
|
- подсчитывается среднее число дней работы и без коммитов;
|
||||||
|
- загрузка считается слабой, если процент без коммитов от 5% до 20%;
|
||||||
|
|
||||||
|
# Возможные причины:
|
||||||
|
- фактически нет задач;
|
||||||
|
- задачи есть, но хорошо ложатся на текущую архитектуру;
|
||||||
|
- разработчиков отвлекают совещаниями;
|
||||||
|
- команда не работает;
|
||||||
|
|
||||||
|
# Варианты решения:
|
||||||
|
- обсудить проблему с командой;
|
||||||
|
- уменьшить гранулярность задач, чтобы за день можно было успеть сделать одну или две задачи;
|
||||||
|
- ввести ежедневные совещания, чтобы проверять движение задач по статусу;
|
||||||
|
- устроить сеансы парного программирования, чтобы убедиться, что разработчик может работать быстрее;
|
||||||
|
|
||||||
|
§ recommendations.author.manager.title
|
||||||
|
Обозначьте дедлайны
|
||||||
|
|
||||||
|
§ recommendations.author.manager.description
|
||||||
|
У любой задачи должен быть чёткий дедлайн.
|
||||||
|
|
||||||
|
Это позволит не затягивать её выполнение на несколько дней или недель.
|
||||||
|
|
||||||
|
# Какие показатели стоит проверить:
|
||||||
|
- количество дней на одну задачу, которое тратит работник;
|
||||||
|
- количество дней ожидания влития PR (страница статистики по PR);
|
||||||
|
|
||||||
|
§ recommendations.author.shorTalk.title
|
||||||
|
Проводите ежедневные совещания
|
||||||
|
|
||||||
|
§ recommendations.author.shorTalk.description
|
||||||
|
они помогают быть в курсе проекта.
|
||||||
|
|
||||||
|
Не растягивайте их отвлекаясь на посторонние темы.
|
||||||
|
|
||||||
|
# На какие вопросы должен ответить сотрудник:
|
||||||
|
- что было сделано;
|
||||||
|
- что будет сделано;
|
||||||
|
- есть ли какие-либо проблемы;
|
||||||
|
|
||||||
|
# Следует обрывать монолог, если:
|
||||||
|
- начинают подробно описывать мелкие детали, которые не важны;
|
||||||
|
- уводят диалог в сторону, от первоначального плана;
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
Часто сотрудник, который ничего не делает, старается уйти от ответа. Для этого он рассказывает кучу ненужных подробностей свой работы. Это позволяет усыпить внимание участников и растянуть время ответа. Создается ощущение что он чем-то занят, хотя по факту работы не было.
|
||||||
|
|
||||||
|
§ recommendations.author.ipr.title
|
||||||
|
Составьте план обучения
|
||||||
|
|
||||||
|
§ recommendations.author.ipr.description
|
||||||
|
на каждого сотрудника.
|
||||||
|
|
||||||
|
*Индивидуальный план обучения* — это список целей и задач, которые помогают человеку развиваться в определенной области.
|
||||||
|
|
||||||
|
# Как составить план:
|
||||||
|
- составить матрицу компетенций;
|
||||||
|
- определить по каким компетенциям меньше всего знаний и опыта;
|
||||||
|
- узнать какие из этих компетенций интересны сотруднику;
|
||||||
|
- придумать 3..5 целей в рамках каждой такой компетенции на полпостороние года или год;
|
||||||
|
- каждый месяц пытаться сделать что-либо для достижения одной цели;
|
||||||
|
- каждый месяц напоминать об общем плане достижения этих целей;
|
||||||
|
|
||||||
|
# Нужен ли план руководителю?
|
||||||
|
Да, руководитель так же должен составить план на себя. Если нет вышестоящего руководителя, то он должен проверять сам себя.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- сотрудники становятся более лояльны к компании;
|
||||||
|
- за теже деньги вы получаете более квалифицированные кадры;
|
||||||
|
|
||||||
|
§ recommendations.author.oneToOne.title
|
||||||
|
Проводите 1-1 каждый месяц
|
||||||
|
|
||||||
|
§ recommendations.author.oneToOne.description
|
||||||
|
это поможет выявить проблемы на ранней стадии.
|
||||||
|
|
||||||
|
*One-to-one* — это регулярные личные встречи руководителя с подчиненным. На таких встречах обычно обсуждают всё, что важно для сотрудника, что его волнует, и то, чем он может поделиться с руководителем только наедине.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- легко выяснить, кто из сотрудников перегружен, а у кого есть свободное время;
|
||||||
|
- можно предотвратить выгорание сотрудника;
|
||||||
|
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
||||||
|
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
||||||
|
- повышается мотивация и вовлеченность сотрудников;
|
||||||
|
|
||||||
|
§ recommendations.author.club.title
|
||||||
|
Ходите в бар
|
||||||
|
|
||||||
|
§ recommendations.author.club.description
|
||||||
|
один раз в месяц или два.
|
||||||
|
|
||||||
|
Это поможет выстроить неформальную коммуникацию в коллективе и сплотить команду, даже если общение будет сжатым.
|
||||||
|
|
||||||
|
# Почему это важно:
|
||||||
|
- можно получить быструю обратную связь о процессах, которые вы можете не замечать;
|
||||||
|
- формируется доверительное отношение, сотрудники становятся более лояльны к компании;
|
||||||
|
- повышается вовлеченность сотрудников;
|
||||||
|
|
||||||
|
§ recommendations.hour.onlyWork.title: Выходных тут нет
|
||||||
|
§ recommendations.hour.onlyWork.description: Вероятно, стоит уволить менеджера проекта.
|
||||||
|
§ recommendations.hour.weekends.title: Работа на выходных
|
||||||
|
§ recommendations.hour.weekends.description: Вероятно, стоит проверить менеджера проекта.
|
||||||
|
§ recommendations.hour.easy.title: Бывают проблемы
|
||||||
|
§ recommendations.hour.easy.description: Вероятно, бывают завалы и приходится работать на выходных.
|
||||||
|
§ recommendations.week.lazyDays.down.title: Стало меньше прогулов
|
||||||
|
§ recommendations.week.lazyDays.down.description: за последние три недели этот показатель упал
|
||||||
|
§ recommendations.week.lazyDays.up.title: Стало больше прогулов
|
||||||
|
§ recommendations.week.lazyDays.up.description: нет задач или нужен более жесткий контроль
|
||||||
|
§ recommendations.week.notWork.title: Стабильно не дорабатывает
|
||||||
|
§ recommendations.week.notWork.description: т.к. каждую неделю пишет код не 100% времени
|
||||||
|
§ recommendations.week.upWork.title: Стабильно перерабатывает
|
||||||
|
§ recommendations.week.upWork.description: т.к. каждую неделю пишет код в выходные дни
|
||||||
|
§ recommendations.week.task.up.title: Растёт производительность
|
||||||
|
§ recommendations.week.task.up.description: или задачи стали слишком мелкие. Нужно проверить. Если гранулярность та же - закрепить результат.
|
||||||
|
§ recommendations.week.task.lazyMaintainer.description: стабильный лидер по прогулам. Уволить?
|
||||||
|
§ recommendations.week.task.down.title: Падает производительность
|
||||||
|
§ recommendations.week.task.down.description
|
||||||
|
или задачи хуже разбивают. Нужно проверить. Если гранулярность та же - взять на контроль.
|
||||||
|
|
||||||
|
# Метод оценки:
|
||||||
|
- количество задач в день, над которыми работают, на протяжении последних трех недель стабильно падает.
|
||||||
|
|
||||||
|
# Возможные ошибки:
|
||||||
|
- задачи могли быть сложнее, чем казались;
|
||||||
|
- задачи могли иметь большой объём работы (нужно проверить количество изменений, падают они или нет за этот же период)
|
||||||
|
|
||||||
|
§ recommendations.type.everyHasOne.title: Не подписывают тип задачи
|
||||||
|
§ recommendations.type.everyHasOne.description: большинство типов задач делает один человек.
|
||||||
|
§ recommendations.type.oneMaintainer.title: Узкая специализация
|
||||||
|
§ recommendations.type.oneMaintainer.description
|
||||||
|
большинство задач одного типа делают одни и те же люди.
|
||||||
|
|
||||||
|
# Типы задач:
|
||||||
|
|
||||||
|
§ recommendations.type.common
|
||||||
|
# Возможно, это не так
|
||||||
|
|
||||||
|
Нужно убедиться, что остальные сотрудники верно подписывают коммиты.
|
||||||
|
|
||||||
|
Шаги, которые помогут это сделать:
|
||||||
|
- настроить пре-коммит проверку для commit message;
|
||||||
|
- объяснить команде, что нужно указывать тип;
|
||||||
|
- проверить в новых ветках, что сотрудники следуют правилу;
|
||||||
|
|
||||||
|
# Если это действительно так
|
||||||
|
|
||||||
|
Вы настроили проверки и убедились что один и тот же сотрудник, делает задачи одного и того же типа.
|
||||||
|
|
||||||
|
Почему это плохо:
|
||||||
|
- его увольнение остановит целую пачку процессов;
|
||||||
|
- уменьшается компетенция остальных членов команды;
|
||||||
|
- трудно верхнеуровнево понять его правки;
|
||||||
|
|
||||||
|
Как это исправить:
|
||||||
|
- распределять разные типы задач равномерно;
|
||||||
|
- менять область работы (тесты, документация, ошибки) между сотрудниками через спринт;
|
||||||
|
|
||||||
|
§ recommendations.type.fewTypes.title
|
||||||
|
Это локальный продукт
|
||||||
|
|
||||||
|
§ recommendations.type.fewTypes.description
|
||||||
|
для конкретного заказчика или проблемы.
|
||||||
|
|
||||||
|
# Какие признаки есть у «глобального» продукта:
|
||||||
|
- локализация;
|
||||||
|
- документация;
|
||||||
|
- большой объём тестов;
|
||||||
|
- визуальная кастомизация;
|
||||||
|
- рефакторинг узких мест;
|
||||||
|
- и т.п.
|
||||||
|
|
||||||
|
# Почему этот продукт выглядит как «локальный»:
|
||||||
|
- у каждого «глобального» признака будет перевес по своему типу задач;
|
||||||
|
- чем больше «глобальных» признаков, тем больше вероятность «глобального» продукта;
|
||||||
|
|
||||||
|
В данном случае мы видим небольшое число типов, а следовательно, скорее всего есть недоработки, мешающие легко масштабировать продукт на мировой рынок и продавать его в других странах.
|
||||||
|
|
||||||
|
# Возможно, это не так
|
||||||
|
По типам файлов мы можем предположить тип программы (сайт, серверное приложение, DevOps скрипты и т.д.). Для frontend приложения наша гипотеза будет более верной, чем для DevOps-скриптов, которые могут быть лишь микро-модулем инициализации.
|
||||||
|
|
||||||
|
§ recommendations.type.diff.title
|
||||||
|
Разбейте лидирующий тип на подтипы
|
||||||
|
|
||||||
|
§ recommendations.type.diff.description
|
||||||
|
для детализации ошибок.
|
||||||
|
|
||||||
|
Как правило, тип задач с меткой «исправление ошибок» является лидирующим. Это делает статистику слабо-детализированной.
|
||||||
|
|
||||||
|
*Если у вас произошла такая ситуация*, вы можете разбить этот тип на подтипы (например, по месту обнаружения).
|
||||||
|
|
||||||
|
Рассмотрим несколько вариантов подтипов:
|
||||||
|
- fix_dev (ошибка выявленная в процессе разработки);
|
||||||
|
- fix_test (ошибка выявленная в процессе тестирования);
|
||||||
|
- fix (ошибка выявленная в проде);
|
||||||
|
|
||||||
|
§ recommendations.type.buddy.title
|
||||||
|
Копите мелкие задачи
|
||||||
|
|
||||||
|
§ recommendations.type.buddy.description
|
||||||
|
для новых сотрудников.
|
||||||
|
|
||||||
|
# Если задача:
|
||||||
|
- не важная;
|
||||||
|
- не большая;
|
||||||
|
- не требует сильного погружения в контекст;
|
||||||
|
- больше про рефакторинг, чем про новый код;
|
||||||
|
|
||||||
|
# Положите её в backlog с меткой «для новичков».
|
||||||
|
|
||||||
|
Когда придёт новый сотрудник, вы сможете моментально достать ему пачку небольших и разнообразных по типу задач, для ознакомления с проектом.
|
||||||
|
|
||||||
|
Также, если у вас будет застой в работе, вы сможете доставать по одной такой мелкой задаче из backlog-а.
|
||||||
|
`;
|
27
src/ts/translations/ru/settings.ts
Normal file
27
src/ts/translations/ru/settings.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
export default `
|
||||||
|
§ page.settings.document.title: Настройки отображения
|
||||||
|
§ page.settings.document.name: Заголовок страницы
|
||||||
|
§ page.settings.document.language: Язык интерфейса
|
||||||
|
§ page.settings.links.title: Префиксы ссылок
|
||||||
|
§ page.settings.links.task: Для номеров задач
|
||||||
|
§ page.settings.links.pr: Для PR
|
||||||
|
§ page.settings.user.title: Индивидуальные настройки
|
||||||
|
§ page.settings.user.notFound: Индивидуальных настроек нет. Данные по всем сотрудникам вычисляются по общим параметрам.
|
||||||
|
§ page.settings.user.subTitle: Дополнение к трудовому договору №$1
|
||||||
|
§ page.settings.user.from: Дата начала действия
|
||||||
|
§ page.settings.mailmap: Настройки .mailmap
|
||||||
|
§ page.settings.common.title: Общие данные по зарплате
|
||||||
|
§ page.settings.common.type.title: Тип работы над проектом
|
||||||
|
§ page.settings.common.type.full: Полная занятость
|
||||||
|
§ page.settings.common.type.part: Проектная работа
|
||||||
|
§ page.settings.common.salary: Зарплата в месяц
|
||||||
|
§ page.settings.common.currency: Валюта
|
||||||
|
§ page.settings.common.workDaysInYear: Количество рабочих дней в году
|
||||||
|
§ page.settings.common.vacationDaysInYear: Количество дней отпуска в год
|
||||||
|
§ page.settings.common.workDaysInWeek: Рабочие дни
|
||||||
|
§ page.settings.form.save: Сохранить
|
||||||
|
§ page.settings.form.cancel: Отмена
|
||||||
|
§ page.settings.form.remove: Удалить
|
||||||
|
§ page.settings.form.addEmployee: Добавить сотрудника
|
||||||
|
§ page.settings.form.addContract: Добавить трудовой договор
|
||||||
|
`;
|
Loading…
Reference in a new issue