This commit is contained in:
Бахирев 2024-02-28 23:17:21 +03:00
parent d8cf1d6efe
commit 68d3283497
182 changed files with 2694 additions and 1358 deletions

View file

@ -2,10 +2,16 @@
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=en)
# [Assayo](https://assayo.online/?ref=github&lang=en)
Visualization and analysis of your git repository data ([demo](https://assayo.jp/demo/?ref=github&lang=en&dump=./test.txt)).
Visualization and analysis of your git repository data ([demo](https://assayo.online/demo/?ref=github&lang=en&dump=./test.txt)).
##### Employee can evaluate new workplace
- work speed;
@ -63,8 +69,8 @@ This file contains data for show a report.
The difference between the online and offline format is the presence of a wrapper for strings. The offline format will be pulled up like a `js` file if you just opened `/build/index.html `
### How to view the report online?
- go to the [website](https://assayo.jp/);
- click the “[Demo](https://assayo.jp/demo)” button;
- go to the [website](https://assayo.online/);
- click the “[Demo](https://assayo.online/demo)” button;
- drag the `log.txt` file into the browser window;
### How to view the report offline?
@ -116,9 +122,9 @@ Every time you restart the computer, the script will update statistics on all th
### DevOps (CI/CD)
#### Public server
You can upload the data file for report construction to a public URL. And use the websites [assayo](https://assayo.jp/?ref=github&lang=en) to visualize it.
You can upload the data file for report construction to a public URL. And use the websites [assayo](https://assayo.online/?ref=github&lang=en) to visualize it.
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
https://assayo.online/demo/?dump=//you_site.com/some/log.txt
```
#### Private server
@ -157,5 +163,5 @@ You can add a new translation or correct an existing one in the ```ts/translatio
### Feedback, suggestions, comments
- telegramm [@bakhirev](https://t.me/bakhirev) (priority method of communication)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- website [https://assayo.jp/](https://assayo.jp/)
- website [https://assayo.online/](https://assayo.online/)

View file

@ -1,19 +1,17 @@
{
"files": {
"main.css": "./static/css/main.1c4d936b.css",
"main.js": "./static/js/main.13141a1e.js",
"main.css": "./static/css/main.0167aeb3.css",
"main.js": "./static/js/main.28c74018.js",
"static/media/car.png": "./static/media/car.b8dd8738e37fe866285f.png",
"index.html": "./index.html",
"static/media/warning.svg": "./static/media/warning.e39a87773603f3ab157f.svg",
"static/media/info.svg": "./static/media/info.954631f6b19e3fe9c495.svg",
"static/media/alert.svg": "./static/media/alert.41e2b99c481139c13074.svg",
"static/media/arrow_left.svg": "./static/media/arrow_left.d053cbdc58069cfc01de.svg",
"static/media/arrow_right.svg": "./static/media/arrow_right.7caaf9eb44d9210be019.svg",
"main.1c4d936b.css.map": "./static/css/main.1c4d936b.css.map",
"main.13141a1e.js.map": "./static/js/main.13141a1e.js.map"
"main.0167aeb3.css.map": "./static/css/main.0167aeb3.css.map",
"main.28c74018.js.map": "./static/js/main.28c74018.js.map"
},
"entrypoints": [
"static/css/main.1c4d936b.css",
"static/js/main.13141a1e.js"
"static/css/main.0167aeb3.css",
"static/js/main.28c74018.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html><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 Statistics</title><meta name="description" content="Simple and fast report on git commit history."><meta name="keywords" content="git, statistics, audit, history, log, monitoring, employee control"><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 statistics"><meta name="msapplication-tooltip" content="Simple and fast report on Git commit history."><meta property="og:title" content="Git Statistics"><meta property="og:description" content="Simple and fast report on Git commit history."><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 Statistics"><meta name="twitter:description" content="Simple and fast report on Git commit history."><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 Statistics"><meta itemprop="description" content="Simple and fast report on Git commit history."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.13141a1e.js"></script><link href="./static/css/main.1c4d936b.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><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 Statistics</title><meta name="description" content="Simple and fast report on git commit history."><meta name="keywords" content="git, statistics, audit, history, log, monitoring, employee control"><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 statistics"><meta name="msapplication-tooltip" content="Simple and fast report on Git commit history."><meta property="og:title" content="Git Statistics"><meta property="og:description" content="Simple and fast report on Git commit history."><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 Statistics"><meta name="twitter:description" content="Simple and fast report on Git commit history."><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 Statistics"><meta itemprop="description" content="Simple and fast report on Git commit history."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.28c74018.js"></script><link href="./static/css/main.0167aeb3.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

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

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

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,7 @@
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
/**
* @license React
* react-dom.production.min.js

File diff suppressed because one or more lines are too long

View file

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path stroke="#84858D" d="M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 198 B

View file

@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path stroke="#84858D" d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 188 B

View file

@ -1,161 +0,0 @@
> The [main documentation](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) is in russian. This is a translation. It may contain errors. If you a native speaker, you can help improve this translation. Thanks!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
# [Assayo](https://assayo.jp/?ref=github&lang=en)
Visualization and analysis of your git repository data ([demo](https://assayo.jp/demo/?ref=github&lang=en&dump=./test.txt)).
##### Employee can evaluate new workplace
- work speed;
- number of extra hours worked;
- areas of competence;
- volume of features and bugs;
- working style of colleagues;
##### Teamlead can evaluate employees
- identify slackers;
- estimate the amount of code;
- learn the work speed;
- notice behavioral anomalies;
- see the dynamics of work by week;
##### Founder can evaluate product
- product cost;
- cost of features;
- development time;
- forecast of rework time;
- forecast cost;
### How to quickly view the number of commits?
In the root directory of your project, run:
```
git shortlog -s -n -e
```
### How to concat authors?
In the root directory of your project, you need to create a `.mailmap` file.
Example of the contents of the file:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
Read more about the format of this file you can [here](https://git-scm.com/docs/gitmailmap).
### How to export data from git?
#### For online viewing
In the root directory of your project run:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### For offline viewing
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git will create a file `log.txt`.
This file contains data for show a report.
The difference between the online and offline format is the presence of a wrapper for strings. The offline format will be pulled up like a `js` file if you just opened `/build/index.html `
### How to view the report online?
- go to the [website](https://assayo.jp/);
- click the “[Demo](https://assayo.jp/demo)” button;
- drag the `log.txt` file into the browser window;
### How to view the report offline?
- download this repository;
- drag the `log.txt` file to the `/build` folder;
- run `/build/index.html`;
- or drag the `/build` folder to your repository (where the `log.txt` is located). You can change the name. For example, from `/build` to `/report`.
In this case, it is important that the `log.txt` file is generated by the command for offline viewing.
### How to rebuild the report build?
- download this repository
- run `npm install`
- run `npm run build`
- the new build will be in the `/build` folder
### How to view a report on a group of microservices?
- generate for each microservice file `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` and etc.)
- see “How to view an online report?”. At the last step, drag all the files at once into the browser window.
- see “How to see a report offline?”. At the second step, drag all microservice files (`log-1.txt`, `log-2.txt`, `log-3.txt` and etc.) to the report folder (`/build`).
### How to brand the interface?
You can create your own interface theme. Options:
- **Title**. You can set default document title in the URL parameter ```title```. Example: ```?title=You Company```
- **Visual theme**. To do this, you need to prepare a CSS file with new styles and specify its URL in the ```theme``` parameter. Example: ```?theme=//company.com/some.css```. You can use class names as selectors. Most of them do not change in new versions.
- **Language**. You can set language in the URL parameter ```lang```. Example: ```?lang=es```
### How to sign commits?
Follow the [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Example:
```
JIRA-1234 feat(profile): Added avatar for user
```
- task number in the task tracker `(JIRA-1234)`
- type of work `(feat, fix, style, refactor, test, doc и т.д.)`
- feature `(profile - new page on site or new function, use one (two) short wordor an abbreviation)`
- what problem were solved `(Added avatar for user)`
### How to automate data collection?
#### Without backend
- create a clone of the repository you need;
- copy the `build` folder to the root;
- open `build/index.html` in the browser and add it to bookmarks;
- add a shortcut to `build/assets/ci-cd.sh` to the startup folder (Windows);
Every time you restart the computer, the script will update statistics on all the data that automatically merged into the main branch.
### DevOps (CI/CD)
#### Public server
You can upload the data file for report construction to a public URL. And use the websites [assayo](https://assayo.jp/?ref=github&lang=en) to visualize it.
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
```
#### Private server
- download the [docker image](https://hub.docker.com/r/bakhirev/assayo);
- run it on your local network;
- use the web interface to view the reports, set the URL of the data in the URL parameter ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - URL of the assayo container, it listens on port 80;
you_url - URL of your container with git logs;
```
By default, the image will run at ```http://127.0.0.1:80/```. If it doesn't work, check if port 80 is free.
#### How to update the Docker image?
- remove metrics, alerts, old builds;
- run ```npm run build```
- run ```docker build -t assayo .```
- visually check the image ```docker run --name assayo -p 80:80 -d assayo```;
- add tag ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- push image to [Docker Hub](https://hub.docker.com/r/bakhirev/assayo);
### Releases are planned approximately once every six months. Whats next:
- more recommendations and achievements;
- annual/monthly summaries, report printing;
- localization and internationalization;
- file analysis;
- different roles for statistics (hiding finances);
- development of the backend, integration with other systems;
### How to add or edit a translation?
You can add a new translation or correct an existing one in the ```ts/translations/``` folder.
[Instruction](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### Feedback, suggestions, comments
- telegramm [@bakhirev](https://t.me/bakhirev) (priority method of communication)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- website [https://assayo.jp/](https://assayo.jp/)

View file

@ -1,162 +1,171 @@
> [Documentación básica](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) en ruso. Es una traducción. Puede contener errores. Si usted es un hablante nativo, puede ayudar a mejorar esta traducción. ¡Gracias!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=ru)
# [Assayo](https://assayo.online/?ref=github&lang=ru)
Visualización y análisis de los datos de su repositorio git ([demostración](https://assayo.jp/demo/?dump=./test.txt).
Visualización y análisis de los datos de su repositorio git. ([демо](https://assayo.online/demo/?dump=./test.txt)).
##### Сотрудник может оценить новое место работы
- темп работы;
- количество переработок;
- зоны ответственности;
- объем фичей и багов;
- стиль работы коллег;
##### El empleado puede evaluar el nuevo lugar de trabajo
- El ritmo de trabajo;
- El número de horas extras;
- Las áreas de responsabilidad;
- El volumen de características y errores;
- El estilo de trabajo de los colegas;
##### Руководитель может оценить сотрудников
- выявить бездельников;
- прикинуть объём кода;
- узнать скорость работы;
- заметить аномалии поведения;
- посмотреть динамику работы по неделям;
##### El jefe puede evaluar a los empleados
- Identificar a los ociosos;
- Calcular el volumen de código;
- Conocer la velocidad de trabajo;
- Se han notado anomalías de comportamiento;
- Ver el ritmo de trabajo por semanas;
##### Инвестор может оценить продукт
- стоимость продукта;
- стоимость фичей;
- время на разработку;
- прогноз времени доработок;
- прогноз стоимости;
##### El inversor puede evaluar el producto
- El costo del producto;
- El coste de las peculiaridades;
- El tiempo de desarrollo;
- La predicción del tiempo de mejoras;
- La predicción del costo;
### Как быстро посмотреть количество коммитов?
### Cómo puedo rápidamente ver el número de commits?
В корневой директории вашего проекта выполнить:
En la carpeta raíz de su proyecto, ejecute:
```
git shortlog -s -n -e
```
### Как объединить авторов?
В корневой директории вашего проекта нужно создать файл `.mailmap`.
Пример содержания файла:
### Cómo combinar a los autores?
En la carpeta raíz de su proyecto debe crear un archivo `.mailmap`.
Un ejemplo del contenido del archivo:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
Подробнее про формат этого файла можно прочитать [тут](https://git-scm.com/docs/gitmailmap).
Más información sobre el formato de este archivo se puede leer en [aquí](https://git-scm.com/docs/gitmailmap).
### Как выгрузить данные из git?
### Cómo descargar los datos desde git?
#### Для онлайн просмотра
В корневой директории вашего проекта выполнить:
#### Para la visualización en línea
En el directorio raíz de su proyecto ejecutar:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### Для офлайн просмотра
#### Para ver sin conexión
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git создаст файл `log.txt`.
Он содержит данные для построения отчёта.
Git creará un archivo `log.txt`.
contiene los datos para construir el informe.
Разница между онлайн и офлайн форматом в наличие обёртки для строк. Оффлайн формат будет подтягиваться, как `js` файл если вы просто открыли `/build/index.html`
La diferencia entre los formatos en línea y fuera de línea está en la existencia de una envoltura para las cadenas. El formato fuera de línea se cargará como un archivo`js` si usted simplemente lo abrió. `/build/index.html`
### Как посмотреть отчёт онлайн?
### ¿Cómo ver el informe en línea?
- Перейти на [сайт](https://assayo.jp/)
- Нажать кнопку «[Демо](https://assayo.jp/demo
- Перетащить файл `log.txt` в окно браузера
- Ir a [sitio web](https://assayo.online/)
- Pulse el botón [Demo](https://assayo.online/demo
- Arrastrar y soltar archivo `log.txt` en la ventana del navegador
### Как посмотреть отчёт офлайн?
- Скачать этот репозиторий
- Перетащить файл `log.txt` в папку `/build`
- Запустить `/build/index.html`
- Или перетащить папку `/build` к себе в репозиторий (туда, где лежит `log.txt`). Можно сменить название. Например с `/build` на `/report`
### ¿Cómo ver el informe sin conexión?
- Descargar este repositorio
- Arrastrar y soltar archivo `log.txt` en la carpeta `/build`
- Lanzar `/build/index.html`
- O arrastrar una carpeta `/build` a su repositorio (donde se encuentra ' log.txt`). Puede cambiar el nombre. Por ejemplo `/build` contra `/report`
В этом случае важно, чтобы файл `log.txt` был сгенерирован командой для офлайн просмотра.
En este caso, es importante que el archivo ' log.txt ' fue generado por el equipo para ver sin conexión.
### Как пересобрать билд отчёта?
- Скачать этот репозиторий
- Выполнить `npm install`
- Выполнить `npm run build`
- Свежая сборка будет в папке `/build`
### Como recompilar el build de un informe?
- Descargar este repositorio
- Ejecutar `npm install`
- Ejecutar `npm run build`
- La nueva compilación estará en el directorio `/build`
### Как посмотреть отчёт по группе микросервисов?
- Сгенерировать для каждого микросервиса файл `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.)
- См. «Как посмотреть отчёт онлайн?». На последнем шаге перетащить сразу все файлы в окно браузера.
- См. «Как посмотреть отчёт офлайн?». На втором шаге перетащить все файлы микросервисов (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.) в папку отчета (`/build`).
### Como mirar el reporte de un grupo de microservicios?
- Generar para cada microservicio el archivo `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.)
- Ver “Cómo ver el informe en línea?”. En el último paso, arrastrar todos los archivos al navegador.
- Ver “Cómo ver informe fuera de línea?”. En el segundo paso, arrastrar los archivos de todos los microservicios al navegador (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.) la carpeta informe (`/build`).
### Как брендировать интерфейс?
Вы можете написать свою тему для интерфейса. Можно менять:
- **Заголовок**. Вы можете указать его в URL-параметре ```title```. Например: ```?title=You Company```
- **Визуальную тему**. Для этого нужно подготовить CSS файл с новыми стилями и указать его адрес в URL-параметре ```theme```. Например: ```?theme=//company.com/some.css```. Вы можете использовать имена классов в качестве селекторов. Большинство из них не меняется в при выходе новой версий.
- **Язык**. Вы можете указать его в URL-параметре ```lang```. Например: ```?lang=es```
### ¿Cómo puedo personalizar la interfaz de usuario?
Puedes crear tu propio tema para la interfaz. Puedes cambiar:
- **El título**. Puedes especificarlo en el parámetro de la URL ```title```. Por ejemplo: ```?title=You Company```
- **El tema visual**. Para esto, debes preparar un archivo CSS con los nuevos estilos y especificar su dirección en el parámetro de URL ```theme```. Por ejemplo: ```?theme=//company.com/some.css```. Puedes usar los nombres de clases como selectores. La mayoría de ellos no cambia con el lanzamiento de nuevas versiones.
- **La lengua**. Puedes especificarla en el parámetro de la URL ```lang```. Por ejemplo: ```?lang=es```
### Как подписывать коммиты?
### ¿Cómo firmar los commits?
Следуйте практике [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Например:
Siga la práctica [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Por ejemplo:
```
JIRA-1234 feat(profile): Added avatar for user
```
- номер задачи в таск трекере `(JIRA-1234)`
- тип работы `(feat, fix, style, refactor, test, doc и т.д.)`
- фича `(profile - раздел сайта, страница или новый функционал, одним словом)`
- какую проблему решали `(Added avatar for user)`
- El número de la tarea en el gestor de tareas es `(JIRA-1234)`
- tipo de trabajo `(feat, fix, style, refactor, test, doc etc.)`
- ficha `(profile - La sección del sitio, la página o la nueva funcionalidad, en una palabra)`
- ¿qué problema resolvieron? `(Added avatar for user)`
### Как автоматизировать сбор данных?
### ¿Cómo automatizar el recolección de datos?
#### Без бекенда
- создайте клон нужного вам репозитория;
- скопируйте в корень папку `build`;
- откройте `build/index.html` в браузере и добавьте в закладки;
- добавьте ярлык на `build/assets/ci-cd.sh` в папку автозагрузки (Windows);
#### Sin backend
- clone del repositorio que desea;
- copiar a la carpeta raíz `build`;
- abridlo `build/index.html` añadir a favoritos;
- agregue un icono de `build/assets/ci-cd.sh` a su carpeta de inicio automático
(Windows);
Каждый раз, при перезагрузке компьютера, скрипт будет обновлять статистику по всем данным, которые автоматически влились в основную ветку.
Cada vez que reinicie su computadora, el script actualizará la estadística de todos los datos que se hayan incorporado automáticamente a la rama principal.
### DevOps (CI/CD)
#### Публичный сервер
#### Servidor público
Вы можете выкладывать файл с данными для построения отчёта на публичный URL. А для его визуализации использовать веб-интерфейс сайта [assayo](https://assayo.jp/). Просто укажите адресс, где лежат данные, в URL-параметре ```dump```:
Puede publicar el archivo con los datos para generar el informe en una URL pública. Para visualizarlo, puede usar la interfaz web del sitio [assayo](https://assayo.online/). Simplemente indique la dirección donde están los datos en el parámetro URL ```dump```:
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
https://assayo.online/demo/?dump=//you_site.com/some/log.txt
```
#### Приватный сервер
- скачайте [docker образ](https://hub.docker.com/r/bakhirev/assayo);
- поднимите его в локальной сети;
- для просмотра отчётов используйте веб-интерфейс указывая ему адресс, где лежат данные, в URL-параметре ```dump```:
#### Servidor privado
- descargar [docker образ](https://hub.docker.com/r/bakhirev/assayo);
- recogerlo en la red local;
- Para ver los informes, use la interfaz web indicándole la dirección de los datos en el parámetro URL ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - URL адресс контейнера assayo, он слушает 80 порт;
you_url - URL адресс вашего контейнера с логами git;
assayo_url - URL dirección del contenedor assayo, Él está escuchando el puerto 80;
you_url - URL la dirección de su contenedor con registros git;
```
По умолчанию образ запустится по адресу ```http://127.0.0.1:80/```. Если не получилось проверьте свободен ли у вас 80 порт.
#### Обновление Docker-образа
Por defecto, la imagen se ejecutará en la siguiente dirección ```http://127.0.0.1:80/```. Si no funciona, compruebe si tiene el puerto 80 disponible
#### Actualización de la imagen Docker
- удилить метрику, аллерты, старые билды;
- собрать билд ```npm run build```
- собрать образ ```docker build -t assayo .```
- визуально проверить образ ```docker run --name assayo -p 80:80 -d assayo```;
- поставить тег ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- запушить образ в Docker Hub
- eliminar métricas, alertas, compilaciones antiguas;
- construir ```npm run build```
- montar la imagen ```docker build -t assayo .```
- comprobar visualmente la imagen ```docker run --name assayo -p 80:80 -d assayo```;
- poner la etiqueta ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- poner la imagen en Docker Hub
### Релизы, примерно, раз в полгода. Что дальше:
### Los lanzamientos son aproximadamente una vez cada seis meses. Lo siguiente será:
- больше советов и достижений;
- итоги года / месяца, печать отчётов;
- локализация и интернационализация;
- анализ файлов;
- разные роли для статистики (скрытие финансов);
- разработка бекенда, интеграции с другими системами;
- más consejos y logros;
- resultados del año / mes, impresión de informes;
- localización e internacionalización;
- análisis de archivos;
- diferentes roles para estadísticas (ocultación de finanzas);
- desarrollo de la parte de atrás, integraciones con otros sistemas;
### Как добавить или отредактировать перевод?
### ¿Cómo añadir o editar una traducción?
Вы можете добавить новый перевод или поправить текущий в разделе ```ts/translations/```.
[Инструкция](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
Puede agregar una nueva traducción o corregir la actual en la sección ```ts/translations/```.
[Instrucciones](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### Пожелания, предложения, замечания
- telegramm [@bakhirev](https://t.me/bakhirev) (приоритетный способ связи)
### Deseos, sugerencias, comentarios
- telegramm [@bakhirev](https://t.me/bakhirev) (La forma preferencial de contacto)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- сайт [https://assayo.jp/](https://assayo.jp/)
- sitio web [https://assayo.online/](https://assayo.online/)

170
documents/FR.md Normal file
View file

@ -0,0 +1,170 @@
> La [documentation principale](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) est en russe. C'est une traduction. Il peut contenir des erreurs. Si vous êtes un locuteur natif, vous pouvez aider à améliorer cette traduction. Merci!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.online/?ref=github&lang=ru)
Visualisation et analyse des données de votre dépôt Git ([демо](https://assayo.online/demo/?dump=./test.txt)).
##### Un employé peut évaluer un nouveau lieu de travail
- le rythme du travail;
- le nombre de heures supplémentaires;
- les zones de responsabilité;
- la taille des fonctionnalités et bogues;
- le style de travail des collègues;
##### Un chef peut évaluer les employés
- détecter les fainéants;
- estimer la taille du code;
- connaître la vitesse de travail;
- remarquer les anomalies du comportement;
- remarquer les anomalies du comportement;
##### Linvestisseur peut évaluer le produit
- le coût du produit;
- le coût des fonctionnalités;
- la durée de développement;
- la projection de la durée des mises à niveau;
- la projection du coût;
### De combien de commits avez-vous besoin?
Dans le répertoire racine de votre projet, exécutez les commandes suivantes:
```
git shortlog -s -n -e
```
### Comment pouvez-vous combiner les auteurs ?
Dans le répertoire racine de votre projet, créez le fichier suivant: `.mailmap`.
Lexemple de la ligne de fichier est le suivant:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
Vous pouvez en savoir plus sur le format de ce fichier en lisant la documentation officielle. [ici](https://git-scm.com/docs/gitmailmap).
### Comment télécharger des données depuis git ?
#### Pour une visualisation en ligne
Dans le répertoire racine de votre projet, exécutez:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### Pour la navigation hors ligne
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git va créer le fichier `log.txt`.
Son contenu est destiné à la création de rapports.
La différence entre le format en ligne et le format hors ligne réside dans lenveloppe des lignes. Le format hors ligne sera chargé comme un fichier js si vous avez simplement ouvert `/build/index.html`
### Comment voir le rapport en ligne?
- Aller à [сайт](https://assayo.online/)
- Appuyer sur le bouton «[Démo](https://assayo.online/demo)»
- Faites glisser le fichier `log.txt` dans la fenêtre du navigateur
### Comment voir le rapport hors ligne?
- Télécharger ce dépôt
- Glisser le fichier `log.txt` dans le dossier `/build`
- Démarrer `/build/index.html`
- Ou coller le dossier `/build` Sur votre dépôt (là où se trouve `log.txt`). Vous pouvez changer le nom. Par exemple avec `/build` sur `/report`
Dans cette cas, il est important que le fichier log.txt ait été généré par le commande pour la visualisation hors ligne.
### Comment recompiler la build du rapport?
- Télécharger ce dépôt
- Exécuter `npm install`
- Exécuter `npm run build`
- La dernière build sera dans le dossier `/build`
### Comment voir le compte rendu pour un groupe de microservices?
- générer un fichier pour chaque microservice `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.)
- Voir «Comment voir le rapport en ligne?». Au dernier pas, glisser tous les fichiers dans la fenêtre du navigateur.
- Voir «Comment regarder le rapport hors-ligne?». Au deuxième pas, coller tous les fichier de microservices (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.) dans le dossier du rapport (`/build`).
### Comment apposer une marque sur linterface?
Vous pouvez écrire votre propre thème pour linterface. Vous pouvez changer :
- **En-tête**. Vous pouvez le spécifier dans le paramètre de lURL ```title```. Par exemple: ```?title=You Company```
- **Thème visuel**.Pour cela, vous devez préparer un fichier CSS avec de nouveaux styles et indiquer son adresse dans le paramètre de lURL ```theme```. Par exemple: ```?theme=//company.com/some.css```. Vous pouvez utiliser les noms de classes comme sélecteurs. La plupart dentre elles ne changent pas lors de la sortie de nouvelles versions.
- **Langue**. Vous pouvez lindiquer dans le paramètre dURL ```lang```. Par exemple: ```?lang=es```
### Comment signer les commits ?
Suivez la pratique [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Par exemple:
```
JIRA-1234 feat(profile): Added avatar for user
```
- numéro de tâche dans task Tracker `(JIRA-1234)`
- type de travail `(feat, fix, style, refactor, test, doc etc.)`
- ficha `(profile - la section du site, la page ou la nouvelle fonctionnalité, en un mot)`
- quel problème ont-ils résolu `(Added avatar for user)`
### Comment automatiser la collecte de données?
#### Sans back-end
- clonez le dépôt que vous voulez ;
- copiez le dossier `build`;
- Ouvrez `build/index.html` dans le navigateur et ajoutez-le aux favoris;
- ajoutez un raccourci sur `build/assets/ci-cd.sh` dans le dossier de démarrage automatique (Windows);
Chaque fois que votre ordinateur se recharge, le script mettra à jour les statistiques sur toutes les données qui se sont automatiquement insérées dans la branche principale.
### DevOps (CI/CD)
#### Serveur public
Vous pouvez mettre à disposition le fichier avec les données pour construire le rapport sur lURL publique. Et pour sa visualisation, utiliser linterface web du site. [assayo](https://assayo.online/). Tout simplement, indiquez ladresse où se trouvent les données dans le paramètre de lURL ```dump```:
```
https://assayo.online/demo/?dump=//you_site.com/some/log.txt
```
#### Serveur privé
- télécharger [docker образ](https://hub.docker.com/r/bakhirev/assayo);
- Soulevez-le sur le réseau local;
- Pour consulter les rapports, utilisez linterface web en lui indiquant ladresse où les données se trouvent, sous forme de paramètre dans lURL ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - URL Conteneur assayo, écoute le port 80;
you_url - URL адресс Adresse de votre conteneur de logs git;
```
Par défaut, l'image s'exécute à ```http://127.0.0.1:80/```. Si cela ne fonctionne pas, vérifiez si le port 80 est disponible.
#### Mise à jour de limage-Docker
- supprimer la métrique, les alertes, les vieilles builds;
- constuire la build ```npm run build```
- assembler l'image ```docker build -t assayo .```
- vérifier visuellement l'image ```docker run --name assayo -p 80:80 -d assayo```;
- mettre la balise ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- Envoyer le code au référentiel d'images dans Docker Hub
### Les versions sont publiées environ tous les six mois. Quoi de neuf:
- plus de conseils et de succès;
- résultats de lannée / du mois, impression des rapports;
- localisation et internationalisation;
- analyse des fichiers;
- différents rôles pour la statistique (cacher la finance);
- développement du backend, intégrations avec dautres systèmes;
### Comment ajouter ou modifier une traduction?
Vous pouvez ajouter une nouvelle traduction ou corriger la traduction existante dans le section ```ts/translations/```.
[Instruction](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### Souhaits, suggestions, commentaires
- telegramm [@bakhirev](https://t.me/bakhirev) (voie de communication prioritaire)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- site [https://assayo.online/](https://assayo.online/)

164
documents/JA.md Normal file
View file

@ -0,0 +1,164 @@
> [主な文書はロシア語です。](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) これは翻訳です。 エラーが含まれている可能性があります。 あなたがネイティブスピーカーであれば、この翻訳を改善するのに役立ちます。 ありがとう!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=ru)
データの可視化とGitレポジトリの分析 ([デモ](https://assayo.jp/demo/?dump=./test.txt&lang=ru)).
##### 従業員は新しい職場を評価することができます
- 働きのペース;
- 過労;
- 職務範囲;
- 新機能とバグの量;
- 同僚の仕事スタイル;
##### 管理者は従業員を評価できます
- 無職人の特定;
- コードの量を推定する;
- 作業速度を確認する;
- 行動の異常を発見する;
- 週次で作業状況を確認する;
##### アイベンターは製品を評価できます
- 製品の価格;
- 新機能の価格;
- 開発時間;
- 改善時間の予測;
- 予測価格;
### コミット数を素早く確認するにはどうすればよいでしょうか。
プロジェクトのルートディレクトリで以下のコマンドを実行します:
```
git shortlog -s -n -e
```
### 作者をまとめるにはどうすればいいですか?
プロジェクトのルートディレクトリ内に.mailmapファイルを作成する必要があります。
ファイルの内容の例:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
このファイルの形式について詳しく読むことができます [ここに](https://git-scm.com/docs/gitmailmap).
### Gitからデータをダウンロードするにはどうすればよろしいでしょうか。
#### Дオンラインで見るため
プロジェクトのルートディレクトリに次のコマンドを入力します:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### インターネットなしで見るために
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Gitはファイルを作成します `log.txt`.
このファイルには、レポートを構築するためのデータが含まれています。
インターネットのない形式とインターネットのある形式は、文字列が埋め込まれているという点で異なります。インターネットを持たない形式でファイルを開くと、単に「js」ファイルとして読み込まれます。 `/build/index.html`
### インターネットを使ってレポートを見るにはどうすれば良いでしょうか。
- に切り替える [ウェブサイト](https://assayo.jp/)
- ボタンを押す “[デモ](https://assayo.jp/demo?lang=ru)”
- ファイルをドラッグ&ドロップする `log.txt` ブラウザウィンドウで
### インターネットを使用せずレポートを見るにはどうしたらよいでしょうか
- このリポジトリをダウンロードする
- ファイルをドラッグ&ドロップする `log.txt` フォルダへ `/build`
- 実行するには `/build/index.html`
- フォルダをドラッグして下さい `/build` 自分のリポジトリーにフォルダを置いてください (それがある場所 `log.txt`). 名前を変更することができます。例えば名前 `/build``/report`
重要なのは、ファイル `log.txt` インターネットが利用できない環境で、レポートを表示するために作成されたコマンドである必要があります。
### レポートファイルを再構成する方法は?
- このリポジトリをダウンロードしてください
- 実行するには `npm install`
- 実行するには `npm run build`
- 最新のビルドは、フォルダに含まれるでしょう `/build`
### マイクロサービス群のレポートを表示するにはどうすればよいでしょうか。
- マイクロサービスごとにファイルを作成します。 `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` など。)
- "インターネット上でレポートを見る方法"を参照してください。最後の手順では、すべてのファイルをブラウザのウィンドウに一度にドラッグ&ドロップします。
- “インターネットなしでレポートを見る方法” を参照してください。第二段階では、マイクロサービスのすべてのファイルをドラッグしてドロップする必要があります。(`log-1.txt`, `log-2.txt`, `log-3.txt` など。) レポートフォルダへ (`/build`).
### 自社のブランドカラーでインターフェースをリニュアルカラーに変えるにはどうすればよろしいでしょうか。
インターフェースのテーマを独自に作成することができます。下記の項目は変更できます。
- **見出し**. それはURLパラメータで指定することができます ```title```. 例えば: ```?title=You Company```
- **CSS スタイル**. そのためにはCSSファイルを用意し、そのアドレスをURLパラメーターに指定する必要があります ```theme```. 例えば: ```?theme=//company.com/some.css```. クラス名をセレクターとして使用することができます。ほとんどの場合、新しいバージョンがリリースされると変更されません
- **言語**. URLパラメータに指定することができます ```lang```. 例えば: ```?lang=es```
### commit文の署名方法は
練習に従ってください [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). 例えば:
```
JIRA-1234 feat(profile): Added avatar for user
```
- 発行番号 `(JIRA-1234)`
- 仕事の種類 `(feat, fix, style, refactor, test, doc など。)`
- 仕事の分野 `(profile - サイトのセクション、ページ、新機能、簡単に)`
- ジョブの説明 `(Added avatar for user)`
### データの自動収集方法は?
#### バックエンドなし
- リポジトリのクローンを作成します。;
- フォルダをコピーする `build` 現在のリポジトリから;
- オープン `build/index.html` ブラウザでブックマークに追加します。;
- にショートカットを追加する `build/assets/ci-cd.sh` 自動起動フォルダーに (Windows);
コンピューターを再起動するとき、スクリプトはメインブランチに自動的に挿入されたすべてのデータについての統計を更新します。
### DevOps (CI/CD)
#### 公開サーバ
データをレポートビルド用に公開するファイルをURLで公開することができます。その視覚化は、サイト上で利用可能なツールを使用することで行うことができます。 [assayo](https://assayo.jp/). データがある場所のアドレスを、URLパラメータに入力してください。 ```dump```:
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
```
#### プライベートサーバー
- ダウンロード [dockerイメージ](https://hub.docker.com/r/bakhirev/assayo);
- ローカルネットワーク内で実行します。;
- レポートの表示には、データが置かれている場所のアドレスがURLパラメータに入っていることを指定したウェブインターフェイスを使用します。 ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - ポート80でリッスンしているassayoコンテナのURL;
you_url - gitのログのコンテナーのURLアドレス;
```
デフォルトではイメージは以下のアドレスで起動します ```http://127.0.0.1:80/```. 問題が解決しない場合は、ポート80が開いているか確認してみてください。
#### Dockerイメージの更新
- 次のコマンドを実行します ```npm run build```
- 次のコマンドを実行します ```docker build -t assayo .```
- 結果を確認する ```docker run --name assayo -p 80:80 -d assayo```;
- 次のコマンドを実行します ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- コンテナイメージをDocker Hubにアップロードする
### 半年ごとにリリースを行います。次は何でしょうか。
見て! [主なドキュメント](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
### 翻訳を追加または編集するにはどうすればいいでしょうか。
新しい翻訳を追加するか、現在の翻訳を修正するために、以下のセクションでそれを行うことができます: ```ts/translations/```.
[取扱説明書](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### 願い、提案、コメント
- telegramm [@bakhirev](https://t.me/bakhirev) (優先通信方式)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- ウェブサイト [https://assayo.jp/](https://assayo.jp/)

164
documents/PT.md Normal file
View file

@ -0,0 +1,164 @@
> [Documentação básica](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) em russo. É uma tradução. Pode conter erros. Se você é um falante nativo, você pode ajudar a melhorar esta tradução. Obrigado!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=ru)
Visualização e análise de dados do seu repositório git ([demonstração](https://assayo.jp/demo/?dump=./test.txt&lang=ru)).
##### Funcionario de avaliar o novo local de trabalho
- ritmo de trabalho;
- número de horas extras;
- áreas de responsabilidade;
- volume de novo funcionalidade e bugs;
- estilo de trabalho dos colegas;
##### O chefe pode avaliar os funcionários
- identificar os ociosos;
- estimar o volume do código;;
- descobrir a velocidade de trabalho;
- notar anomalias no comportamento;
- ver a dinâmica do trabalho por semanas;
##### O investidor pode avaliar o produto:
- o valor do produto;
- o custo do novo funcionalismo;
- tempo de desenvolvimento;
- Forecasting the time for improvements;
- previsão de custos;
### Como é rápido ver o número de commits?
No diretório raiz do seu projeto, execute o comando:
```
git shortlog -s -n -e
```
### Como combinar os autores?
É necessário criar um arquivo no diretório principal do seu projeto `.mailmap`.
Exemplo de conteúdo de arquivo:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
Pode ler mais sobre o formato deste arquivo em [aqui](https://git-scm.com/docs/gitmailmap).
### Como exportar dados do git?
#### Para visualização online
No diretório raiz do seu projeto executar:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### Para ver sem internet
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git criar um ficheiro `log.txt`.
Esse arquivo contém dados para construção de relatórios.
A diferença entre os formatos está na existência de uma envoltória para as linhas. O formato sem internet será puxado como `js` o arquivo se você o abriu simplesmente `/build/index.html`
### Como ver o relatório da Internet?
- Ir para [site](https://assayo.jp/)
- Pressione o botão “[Demonstração](https://assayo.jp/demo?lang=ru)”
- Arrastar e largar `log.txt` na janela do navegador
### Como visualizar o relatório sem internet?
- Baixar este repositório
- Arraste o arquivo `log.txt` para a pasta `/build`
- Lançar `/build/index.html`
- Ou arraste a pasta `/build` ir para o repositório (o lugar onde se encontra `log.txt`). Você pode mudar o nome. Por exemplo, do nome `/build` no título `/report`
É importante que o arquivo `log.txt` foi criado por uma equipe para navegar sem internet.
### Como recompilar o arquivo do relatório?
- Baixar este repositório
- Executar `npm install`
- Executar `npm run build`
- A compilação mais recente estará na pasta `/build`
### Como visualizar o relatório do grupo de microserviços?
- Gerar um arquivo para cada microserviço `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.)
- Veja “Como visualizar o relatório com a internet?”. No último passo, arraste todos os arquivos para a janela do navegador.
- Veja “Como visualizar o relatório sem a internet?”. No segundo passo, arraste todos os microserviços (`log-1.txt`, `log-2.txt`, `log-3.txt` etc.) na pasta relatório (`/build`).
### Como alterar as cores da interface para as cores da sua marca?
Você pode escrever seu próprio tema de interface. Pode mudar:
- **Cabeçalho**. Você pode especificar em um parâmetro da URL ```title```. Por exemplo: ```?title=You Company```
- **CSS стили**. Para fazer isso, você precisa preparar um arquivo CSS e especificar o seu endereço no parâmetro da URL ```theme```. Por exemplo: ```?theme=//company.com/some.css```. Você pode usar os nomes das classes como seletores. A maioria deles não muda na saída de uma nova versão.
- **Idioma**. Você pode incluir em um parâmetro de URL. ```lang```. Por exemplo: ```?lang=es```
### Como faço para assinar commits?
Siga a prática [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Por exemplo:
```
JIRA-1234 feat(profile): Added avatar for user
```
- número da tarefa `(JIRA-1234)`
- tipo de trabalho `(feat, fix, style, refactor, test, doc etc.)`
- área de trabalho `(profile - Página)`
- descrição do trabalho `(Added avatar for user)`
### Como automatizar a coleta de dados?
#### Sem backend
- criar um clone do seu repositório;
- copie a pasta `build` do repositório atual;
- abrir `build/index.html` no navegador e adicionar aos favoritos;
- adicionar um shortcut na `build/assets/ci-cd.sh` na pasta de inicialização (Windows);
A cada reinício do computador, o script atualiza a estatística com todos os dados que sejam automaticamente incorporados na branch principal.
### DevOps (CI/CD)
#### Servidor Público
Você pode disponibilizar o arquivo com os dados para construção do relatório em um URL público. Para visualizá-lo, você pode usar um site [assayo](https://assayo.jp/). Especifique o endereço onde os dados estão localizados no parâmetro de URL ```dump```:
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
```
#### Servidor Privado
- baixar [docker imagem](https://hub.docker.com/r/bakhirev/assayo);
- execute-o na rede local;
- Para visualizar os relatórios, utilize a interface web, indicando-lhe o endereço em que os dados se encontram localizados através do parâmetro URL ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - O URL do endereço do container Assay, ele está escutando na porta 80;
you_url - O URL do seu container com os logs do git;
```
Por padrão, a imagem será iniciada no endereço ```http://127.0.0.1:80/```. Se você não conseguiu, verifique se a porta 80 está disponível no seu computador.
#### Atualizar a imagem Docker
- executar um comando ```npm run build```
- executar um comando ```docker build -t assayo .```
- verificar o resultado ```docker run --name assayo -p 80:80 -d assayo```;
- executar um comando ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- enviar a imagem do container para o Docker Hub
### Liberações, aproximadamente, uma vez por semestre. O que vem a seguir:
Vide [documentação básica](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
### Como adicionar ou editar uma tradução?
Você pode adicionar uma nova tradução ou corrigir uma existente na seção ```ts/translations/```.
[Instrução](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### Sugestões, sugestões, comentários
- telegramm [@bakhirev](https://t.me/bakhirev) (método de comunicação prioritário)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- site [https://assayo.jp/](https://assayo.jp/)

View file

@ -1,9 +1,15 @@
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=ru)
# [Assayo](https://assayo.online/?ref=github&lang=ru)
Визуализация и анализ данных вашего git-репозитория ([демо](https://assayo.jp/demo/?dump=./test.txt)).
Визуализация и анализ данных вашего git-репозитория ([демо](https://assayo.online/demo/?dump=./test.txt)).
##### Сотрудник может оценить новое место работы
- темп работы;
@ -62,8 +68,8 @@ Git создаст файл `log.txt`.
### Как посмотреть отчёт онлайн?
- Перейти на [сайт](https://assayo.jp/)
- Нажать кнопку «[Демо](https://assayo.jp/demo)»
- Перейти на [сайт](https://assayo.online/)
- Нажать кнопку «[Демо](https://assayo.online/demo)»
- Перетащить файл `log.txt` в окно браузера
### Как посмотреть отчёт офлайн?
@ -116,9 +122,9 @@ JIRA-1234 feat(profile): Added avatar for user
#### Публичный сервер
Вы можете выкладывать файл с данными для построения отчёта на публичный URL. А для его визуализации использовать веб-интерфейс сайта [assayo](https://assayo.jp/). Просто укажите адресс, где лежат данные, в URL-параметре ```dump```:
Вы можете выкладывать файл с данными для построения отчёта на публичный URL. А для его визуализации использовать веб-интерфейс сайта [assayo](https://assayo.online/). Просто укажите адресс, где лежат данные, в URL-параметре ```dump```:
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
https://assayo.online/demo/?dump=//you_site.com/some/log.txt
```
#### Приватный сервер
@ -158,5 +164,5 @@ you_url - URL адресс вашего контейнера с логами
### Пожелания, предложения, замечания
- telegramm [@bakhirev](https://t.me/bakhirev) (приоритетный способ связи)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- сайт [https://assayo.jp/](https://assayo.jp/)
- сайт [https://assayo.online/](https://assayo.online/)

158
documents/SIMPLE_RU.md Normal file
View file

@ -0,0 +1,158 @@
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [Spanish](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [French](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
# [Assayo](https://assayo.online/?ref=github&lang=ru)
Визуализация и анализ данных вашего git-репозитория ([демонстрация](https://assayo.online/demo/?dump=./test.txt&lang=ru)).
##### Сотрудник может оценить новое место работы
- темп работы;
- количество переработок;
- зоны ответственности;
- объем нового функционала и багов;
- стиль работы коллег;
##### Руководитель может оценить сотрудников
- выявить бездельников;
- прикинуть объём кода;
- узнать скорость работы;
- заметить аномалии поведения;
- посмотреть динамику работы по неделям;
##### Инвестор может оценить продукт
- стоимость продукта;
- стоимость нового функционала;
- время на разработку;
- прогноз времени доработок;
- прогноз стоимости;
### Как быстро посмотреть количество коммитов?
В корневой директории вашего проекта выполнить команду:
```
git shortlog -s -n -e
```
### Как объединить авторов?
В корневой директории вашего проекта нужно создать файл `.mailmap`.
Пример содержания файла:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
Подробнее про формат этого файла можно прочитать [тут](https://git-scm.com/docs/gitmailmap).
### Как выгрузить данные из git?
#### Для онлайн просмотра
В корневой директории вашего проекта выполнить:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### Для просмотра без интернета
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git создаст файл `log.txt`.
Этот файл содержит данные для построения отчёта.
Разница между форматами в наличие обёртки для строк. Формат без интернета будет подтягиваться, как `js` файл если вы просто открыли `/build/index.html`
### Как посмотреть отчёт с интеретом?
- Перейти на [сайт](https://assayo.online/)
- Нажать кнопку “[Демонстрация](https://assayo.online/demo?lang=ru)”
- Перетащить файл `log.txt` в окно браузера
### Как посмотреть отчёт без интернета?
- Скачать этот репозиторий
- Перетащить файл `log.txt` в папку `/build`
- Запустить `/build/index.html`
- Или перетащить папку `/build` к себе в репозиторий (место, где лежит `log.txt`). Можно изменить название. Например с названия `/build` на название `/report`
Важно, чтобы файл `log.txt` был создан командой для просмотра без интернета.
### Как пересобрать файл отчёта?
- Скачать этот репозиторий
- Выполнить `npm install`
- Выполнить `npm run build`
- Свежая сборка будет в папке `/build`
### Как посмотреть отчёт по группе микросервисов?
- Сгенерировать для каждого микросервиса файл `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.)
- См. “Как посмотреть отчёт с интернетом?”. На последнем шаге перетащить сразу все файлы в окно браузера.
- См. “Как посмотреть отчёт без интернета?”. На втором шаге перетащить все файлы микросервисов (`log-1.txt`, `log-2.txt`, `log-3.txt` и т.д.) в папку отчета (`/build`).
### Как перекрасить интерфейс в свои фирменные цвета?
Вы можете написать свою тему оформления для интерфейса. Можно менять:
- **Заголовок**. Вы можете указать его в URL-параметре ```title```. Например: ```?title=You Company```
- **CSS стили**. Для этого нужно подготовить CSS файл и указать его адрес в URL-параметре ```theme```. Например: ```?theme=//company.com/some.css```. Вы можете использовать имена классов в качестве селекторов. Большинство из них не меняется в при выходе новой версий.
- **Язык**. Вы можете указать его в URL-параметре ```lang```. Например: ```?lang=es```
### Как подписывать коммиты?
Следуйте практике [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). Например:
```
JIRA-1234 feat(profile): Added avatar for user
```
- номер задачи `(JIRA-1234)`
- тип работы `(feat, fix, style, refactor, test, doc и т.д.)`
- область работы `(profile - раздел сайта, страница или новый функционал, одним словом)`
- описание работы `(Added avatar for user)`
### Как автоматизировать сбор данных?
#### Без бекенда
- создайте клон вашего репозитория;
- скопируйте папку `build` из текущего репозитория;
- откройте `build/index.html` в браузере и добавьте в закладки;
- добавьте ярлык на `build/assets/ci-cd.sh` в папку автозагрузки (Windows);
Каждый раз, при перезагрузке компьютера, скрипт будет обновлять статистику по всем данным, которые автоматически влились в основную ветку.
### DevOps (CI/CD)
#### Публичный сервер
Вы можете выкладывать файл с данными для построения отчёта на публичный URL. Для его визуализации можно использовать сайт [assayo](https://assayo.online/). Указывайте адресс, где лежат данные, в URL-параметре ```dump```:
```
https://assayo.online/demo/?dump=//you_site.com/some/log.txt
```
#### Приватный сервер
- скачайте [docker образ](https://hub.docker.com/r/bakhirev/assayo);
- запустите его в локальной сети;
- для просмотра отчётов используйте веб-интерфейс, указывая ему адресс, где лежат данные, в URL-параметре ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - URL адресс контейнера assayo, он слушает 80 порт;
you_url - URL адресс вашего контейнера с логами git;
```
По умолчанию образ запустится по адресу ```http://127.0.0.1:80/```. Если не получилось проверьте свободен ли у вас 80 порт.
#### Обновление Docker-образа
- выполнить команду ```npm run build```
- выполнить команду ```docker build -t assayo .```
- проверить результат ```docker run --name assayo -p 80:80 -d assayo```;
- выполнить команду ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- отправить образ контейнера в Docker Hub
### Релизы, примерно, раз в полгода. Что дальше:
Смотри [главную документацию](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
### Как добавить или отредактировать перевод?
Вы можете добавить новый перевод или поправить текущий в разделе ```ts/translations/```.
[Инструкция](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### Пожелания, предложения, замечания
- telegramm [@bakhirev](https://t.me/bakhirev) (приоритетный способ связи)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- сайт [https://assayo.online/](https://assayo.online/)

164
documents/ZH.md Normal file
View file

@ -0,0 +1,164 @@
> [主要文件是俄文。](https://github.com/bakhirev/assayo/blob/main/documents/RU.md) 这是一个翻译。 它可能包含错误。 如果您是母语人士,您可以帮助改进此翻译。 谢谢!
> - [Русский](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
> - [English](https://github.com/bakhirev/assayo)
> - [中文](https://github.com/bakhirev/assayo/blob/main/documents/ZH.md)
> - [Español](https://github.com/bakhirev/assayo/blob/main/documents/ES.md)
> - [Français](https://github.com/bakhirev/assayo/blob/main/documents/FR.md)
> - [Português](https://github.com/bakhirev/assayo/blob/main/documents/PT.md)
> - [Deutsch](https://github.com/bakhirev/assayo/blob/main/documents/DE.md)
> - [日本語](https://github.com/bakhirev/assayo/blob/main/documents/JA.md)
# [Assayo](https://assayo.jp/?ref=github&lang=ru)
对您的git仓库的数据进行可视化和分析 ([示范表现](https://assayo.jp/demo/?dump=./test.txt&lang=ru)).
##### 工作人员可以评估新工作场所
- 工作节奏;
- 加班数量;
- 责任范围;
- 新功能和错误量;
- 同事工作方式。;
##### 管理者可以评估员工
- 发现闲置工作者;
- 估算代码量;
- 了解工作速度;
- 注意行为异常;
- 查看工作周期动态。;
##### 投资者可以评估产品
- 产品的成本;
- 新功能的成本;
- 开发时间;
- 修改时间预测;
- 成本预测;
### 如何 quickly 查阅 commit 的 次数?
在项目的根目录中执行以下命令:
```
git shortlog -s -n -e
```
### 如何 combine 作者?
在项目的 根目录 创建一个文件 `.mailmap`.
文件内容示例:
```
Alex B <alex@mail.uk>
Alex B <alex@mail.uk> <alex@gov.tk>
Alex B <alex@mail.uk> <bakhirev@ya.kz>
Alex B <alex@mail.uk> <man64@yahoo.com>
```
关于这个文件格式的 详情 可以 参考 [这里](https://git-scm.com/docs/gitmailmap).
### 如何从 git 导出数据?
#### 供网上浏览
在项目的根目录执行:
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" > log.txt
```
#### 在没有互联网的情况下观看
```
git --no-pager log --numstat --oneline --all --reverse --date=iso-strict --pretty=format:"%ad>%cN>%cE>%s" | sed -e 's/\\/\\\\/g' | sed -e 's/`/"/g' | sed -e 's/^/report.push(\`/g' | sed 's/$/\`\);/g' | sed 's/\$/_/g' > log.txt
```
Git会创建一个文件 `log.txt`.
这个文件包含了构建报告的数据。
字符串格式的区别在于它们具有的包装。无网络格式将会像您只是简单地打开了js文件一样被加载。 `/build/index.html`
### 如何在线查看报告?
- 切换到 [网站](https://assayo.jp/)
- 按下按钮 “[示范](https://assayo.jp/demo?lang=ru)”
- 拖放文件 `log.txt` 在浏览器窗口中
### 如何在没有网络环境下查看报告?
- 下载这个存储库
- 拖放文件 `log.txt` 到文件夹 `/build`
- 要运行 `/build/index.html`
- 或是拖放文件夹 `/build` 到我的仓库 (它所在的地方 `log.txt`). 可以改变名称。比如,从名称 `/build` 到名称 `/report`
重要的事情是必须让log.txt这个文件是通过命令创建出来的这样它就可以在没有网的时候查看了。
### 如何重打包报告文件?
- 下载这个储存库
- 要执行 `npm install`
- 要执行 `npm run build`
- 最新的构建将在文件夹 `/build`
### 如何查看微服务组的报告?
- 为每个微服务生成文件 `log.txt` (`log-1.txt`, `log-2.txt`, `log-3.txt` 等等)
- 参见“如何在有网络环境下查看报告”。在最后一步,将所有文件同时拖入浏览器窗口。
- 参见“如何在没有网络环境下查看报告”。第二步将所有微服务文件拖动到 (`log-1.txt`, `log-2.txt`, `log-3.txt` 等等) 到报表文件夹 (`/build`).
### 如何将界面重新配色为公司专有颜色?
您可以为界面创建自己的主题。可以修改:
- **标题**. 你可以在网址参数中指定它 ```title```. 例如: ```?title=You Company```
- **CSS样式**. 为了做到这一点你需要准备一个CSS文件并在网址参数中指明其地址 ```theme```. 例如: ```?theme=//company.com/some.css```. 你可以使用类名作为选择器。大多数情况下,他们在新版本发布时不会发生变化。
- **语言**. 你可以把它放在网址的参数中。 ```lang```. 例如: ```?lang=es```
### 如何签署提交?
遵循实践 [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). 例如:
```
JIRA-1234 feat(profile): Added avatar for user
```
- 任务号 `(JIRA-1234)`
- 工作类别 `(feat, fix, style, refactor, test, doc 等等)`
- 工作领域 `(profile - 地盘组, 网页 或新功能, 一句话)`
- 职位描述 `(Added avatar for user)`
### 如何自动化数据采集?
#### 没有后端
- 克隆您的仓库;;
- 复制文件夹 `build` 从当前仓库;
- 打开 `build/index.html` 在浏览器中添加书签;
- 添加一个快捷方式 `build/assets/ci-cd.sh` 自动启动文件夹 (Windows);
每次重启计算机,该脚本将更新统计数据,这些数据自动添加到主分支中。
### DevOps (CI/CD)
#### 公共服务器
您可以将数据构建报告文件发布到公共URL可以使用网站来显示它。 [assayo](https://assayo.jp/). 指定数据所在的地址作为URL参数 ```dump```:
```
https://assayo.jp/demo/?dump=//you_site.com/some/log.txt
```
#### 专用服务器
- 下载 [docker镜像](https://hub.docker.com/r/bakhirev/assayo);
- 在本地网络中运行它;
- 使用web界面查看报告并指定数据所在地址作为URL参数 ```dump```:
```
http://assayo_url/?dump=//you_url/some/log.txt
assayo_url - assayo容器的URL地址它监听80端口;
you_url - git日志的容器的URL地址;
```
默认情况下,镜像会被启动在地址 ```http://127.0.0.1:80/```. 如果没有成功请检查你的80端口是否可用.
#### Docker 图像更新
- 运行命令 ```npm run build```
- 运行命令 ```docker build -t assayo .```
- 检查结果 ```docker run --name assayo -p 80:80 -d assayo```;
- 运行命令 ```docker tag IMAGE_ID bakhirev/assayo:latest```;
- 提交容器映像到 Docker Hub
### 释出版本大约每半年一次。接下来发生什么情况:
看 [主要文件](https://github.com/bakhirev/assayo/blob/main/documents/RU.md)
### 如何添加或编辑翻译?
您可以在“翻译”部分添加新翻译或更正当前翻译。 ```ts/translations/```.
[指示手册](https://docs.github.com/ru/get-started/exploring-projects-on-github/contributing-to-a-project)
### 愿望,建议,意见
- telegramm [@bakhirev](https://t.me/bakhirev) (优先通信方法)
- [alexey-bakhirev@yandex.ru](mailto:alexey-bakhirev@yandex.ru)
- 网站 [https://assayo.jp/](https://assayo.jp/)

277
package-lock.json generated
View file

@ -12,15 +12,18 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"http-proxy-middleware": "^2.0.6",
"i18next": "^23.9.0",
"mobx": "^6.7.0",
"mobx-react-lite": "^3.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
"sass": "^1.57.1",
"styled-components": "^5.3.6",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@types/file-saver": "^2.0.5",
@ -1818,16 +1821,21 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/runtime/node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/@babel/template": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
@ -4751,6 +4759,14 @@
"node": ">=8.9"
}
},
"node_modules/adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -5727,6 +5743,18 @@
"node": ">=4"
}
},
"node_modules/cfb": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
"dependencies": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@ -5877,6 +5905,14 @@
"node": ">= 4.0"
}
},
"node_modules/codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
@ -6095,6 +6131,17 @@
"node": ">=10"
}
},
"node_modules/crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
"bin": {
"crc32": "bin/crc32.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -8577,6 +8624,14 @@
"node": ">= 0.6"
}
},
"node_modules/frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@ -9124,6 +9179,14 @@
"node": ">=12"
}
},
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"dependencies": {
"void-elements": "3.1.0"
}
},
"node_modules/html-tags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz",
@ -9270,6 +9333,28 @@
"node": ">=10.17.0"
}
},
"node_modules/i18next": {
"version": "23.9.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.9.0.tgz",
"integrity": "sha512-f3MUciKqwzNV//mHG6EtdSlC65+nqH/3zK8sOSWqNV6FVu2tmHhF/rFOp9UF8S4m1odojtuipKaKJrP0Loh60g==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.23.2"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@ -14916,6 +15001,27 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-i18next": {
"version": "14.0.5",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.0.5.tgz",
"integrity": "sha512-5+bQSeEtgJrMBABBL5lO7jPdSNAbeAZ+MlFWDw//7FnVacuVu3l9EeWFzBQvZsKy+cihkbThWOAThEdH8YjGEw==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
"i18next": ">= 23.2.3",
"react": ">= 16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@ -16157,6 +16263,17 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"node_modules/ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"dependencies": {
"frac": "~1.1.2"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
@ -17321,6 +17438,14 @@
"node": ">= 0.8"
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@ -17815,6 +17940,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@ -18199,6 +18340,26 @@
}
}
},
"node_modules/xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
"dependencies": {
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
},
"bin": {
"xlsx": "bin/xlsx.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
@ -19463,11 +19624,18 @@
}
},
"@babel/runtime": {
"version": "7.20.13",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz",
"integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==",
"version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz",
"integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==",
"requires": {
"regenerator-runtime": "^0.13.11"
"regenerator-runtime": "^0.14.0"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
}
}
},
"@babel/template": {
@ -21601,6 +21769,11 @@
"regex-parser": "^2.2.11"
}
},
"adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
},
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -22312,6 +22485,15 @@
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
"integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw=="
},
"cfb": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
"requires": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@ -22418,6 +22600,11 @@
"q": "^1.1.2"
}
},
"codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
},
"collect-v8-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
@ -22594,6 +22781,11 @@
"yaml": "^1.10.0"
}
},
"crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -24397,6 +24589,11 @@
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
},
"frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
},
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@ -24803,6 +25000,14 @@
"terser": "^5.10.0"
}
},
"html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"requires": {
"void-elements": "3.1.0"
}
},
"html-tags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz",
@ -24900,6 +25105,14 @@
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
},
"i18next": {
"version": "23.9.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.9.0.tgz",
"integrity": "sha512-f3MUciKqwzNV//mHG6EtdSlC65+nqH/3zK8sOSWqNV6FVu2tmHhF/rFOp9UF8S4m1odojtuipKaKJrP0Loh60g==",
"requires": {
"@babel/runtime": "^7.23.2"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@ -28788,6 +29001,15 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"react-i18next": {
"version": "14.0.5",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.0.5.tgz",
"integrity": "sha512-5+bQSeEtgJrMBABBL5lO7jPdSNAbeAZ+MlFWDw//7FnVacuVu3l9EeWFzBQvZsKy+cihkbThWOAThEdH8YjGEw==",
"requires": {
"@babel/runtime": "^7.23.9",
"html-parse-stringify": "^3.0.1"
}
},
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@ -29709,6 +29931,14 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"requires": {
"frac": "~1.1.2"
}
},
"stable": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
@ -30581,6 +30811,11 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
},
"void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="
},
"w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@ -30939,6 +31174,16 @@
"is-typed-array": "^1.1.10"
}
},
"wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
},
"word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@ -31269,6 +31514,20 @@
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"requires": {}
},
"xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
"requires": {
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
}
},
"xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",

View file

@ -8,15 +8,18 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"http-proxy-middleware": "^2.0.6",
"i18next": "^23.9.0",
"mobx": "^6.7.0",
"mobx-react-lite": "^3.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.0.5",
"react-router-dom": "^6.8.0",
"react-scripts": "5.0.1",
"sass": "^1.57.1",
"styled-components": "^5.3.6",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"xlsx": "^0.18.5"
},
"scripts": {
"dev": "set PORT=3006 && react-app-rewired start",

View file

@ -5,6 +5,8 @@ import { render } from 'react-dom';
import localization from 'ts/helpers/Localization';
import ru from 'ts/translations/ru/index';
import en from 'ts/translations/en/index';
import './ts/helpers/i18n';
import Authorization from 'ts/pages/Authorization';
import userSettings from 'ts/store/UserSettings';
import Notifications from 'ts/components/Notifications';
@ -30,6 +32,7 @@ function renderReactApplication() {
window.onafterprint = () => {
printStore.endPrint();
};
render(
<React.StrictMode>
<HashRouter>

View file

@ -7,6 +7,7 @@ html {
*,
*:before,
*:after {
outline: none;
box-sizing: inherit;
}

View file

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import ALL_ACHIEVEMENTS from 'ts/helpers/achievement/constants/list';
import localization from 'ts/helpers/Localization';
import style from '../styles/index.module.scss';
@ -10,10 +10,11 @@ interface IAchievementProps {
}
function Achievement({ code }: IAchievementProps) {
const { t } = useTranslation();
if (!ALL_ACHIEVEMENTS[code]) return null;
const title = localization.get(`achievements.${code}.title`);
const description = localization.get(`achievements.${code}.description`);
const title = t(`achievements.${code}.title`);
const description = t(`achievements.${code}.description`);
const statusIndex = ALL_ACHIEVEMENTS[code];
const className = [

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.achievement_container {
margin: 12px 0 24px 0;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.vertical_bar {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.candy {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.card_with_icon,
.card_with_icon_long {

View file

@ -1,6 +1,6 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import localization from 'ts/helpers/Localization';
import style from './index.module.scss';
interface ICardWithIconProps {
@ -22,6 +22,7 @@ function CardWithIcon({
icon,
long = false,
}: ICardWithIconProps): React.ReactElement | null {
const { t } = useTranslation();
if (!value && value !== 0) return null;
return (
@ -42,10 +43,10 @@ function CardWithIcon({
{suffix || ''}
</p>
<h4 className={style.card_with_icon_title}>
{localization.get(title)}
{t(title || '')}
</h4>
<figcaption className={style.card_with_icon_description}>
{localization.get(description)}
{t(description || '')}
</figcaption>
</figure>
);

View file

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { IColumn } from 'ts/components/Table/interfaces/Column';
import localization from 'ts/helpers/Localization';
import style from '../styles/index.module.scss';
@ -18,6 +18,7 @@ function Line({
value,
className,
}: ILineProps): JSX.Element {
const { t } = useTranslation();
const columnClassName = typeof column.className === 'function'
? column.className('body', item)
: column.className;
@ -28,7 +29,7 @@ function Line({
className={`${style.card_line} ${className || ''} ${columnClassName || ''}`}
>
<div className={style.card_line_title}>
{localization.get(column.title)}
{t(column.title || '')}
</div>
<div className={style.card_line_value}>
{value}

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.card {
display: inline-block;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.character {
position: relative;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.console {
position: relative;

View file

@ -37,7 +37,7 @@ function Console({ className, textForCopy, children }: IConsoleProps) {
{children || textForCopy}
</div>
<Button
type="second"
mode="second"
className={`${style.console_copy}`}
onClick={() => {
copyInBuffer(textForCopy);

View file

@ -1,10 +1,10 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import type { IPagination, IPaginationRequest } from 'ts/interfaces/Pagination';
import UiKitInputString from 'ts/components/UiKit/components/InputString';
import UiKitButton from 'ts/components/UiKit/components/Button';
import Loading from 'ts/components/Loading';
import localization from 'ts/helpers/Localization';
import { DataLoaderState, IDataLoaderStore } from '../store';
import ErrorDescription from '../ErrorDescription';
@ -23,6 +23,7 @@ function SimplePagination({
pagination,
store,
}: ISimplePaginationProps) {
const { t } = useTranslation();
if (!response) return null;
const pageSizeCurrent = pagination?.size || 10;
@ -60,10 +61,10 @@ function SimplePagination({
return (
<nav className={style.paginator}>
<p className={style.paginator_text}>
{localization.get('uiKit.dataLoader.page')}
{t('uiKit.dataLoader.page')}
</p>
<UiKitButton
type="second"
mode="second"
disabled={!pageNumber}
onClick={() => {
if (store) store.goToPage(pageNumber - 1, pageSize || pageSizeCurrent);
@ -86,7 +87,7 @@ function SimplePagination({
}}
/>
<UiKitButton
type="second"
mode="second"
disabled={pageNumber === (totalPages - 1)}
onClick={() => {
if (store) store.goToPage(pageNumber + 1, pageSize || pageSizeCurrent);
@ -95,10 +96,10 @@ function SimplePagination({
»
</UiKitButton>
<p className={style.paginator_text}>
{localization.get('uiKit.dataLoader.from')}
{t('uiKit.dataLoader.from')}
</p>
<UiKitButton
type="second"
mode="second"
onClick={() => {
if (store) store.goToPage(totalPages - 1, pageSize || pageSizeCurrent);
}}
@ -106,7 +107,7 @@ function SimplePagination({
{totalPages}
</UiKitButton>
<p className={style.paginator_text}>
{localization.get('uiKit.dataLoader.size')}
{t('uiKit.dataLoader.size')}
</p>
<UiKitInputString
value={pageSize}
@ -127,12 +128,12 @@ function SimplePagination({
</p>
{canShowMore && (
<UiKitButton
type="slim"
mode="slim"
onClick={() => {
if (store) store.showAll();
}}
>
{localization.get('uiKit.dataLoader.all')}
{t('uiKit.dataLoader.all')}
</UiKitButton>
)}
</nav>

View file

@ -1,8 +1,8 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import type { IPagination } from 'ts/interfaces/Pagination';
import Loading from 'ts/components/Loading';
import localization from 'ts/helpers/Localization';
import { IDataLoaderStore, DataLoaderState } from '../store';
import ErrorDescription from '../ErrorDescription';
@ -22,6 +22,7 @@ function ShowAll({
store,
className,
}: IShowAllProps) {
const { t } = useTranslation();
if (!response) return null;
const {
number: pageNumber,
@ -49,7 +50,7 @@ function ShowAll({
className={`${style.show_all} ${className || ''}`}
onClick={() => { if (store) store.showAll(); }}
>
{localization.get('uiKit.dataLoader.all')}
{t('uiKit.dataLoader.all')}
</div>
);
}

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.load_more {
position: relative;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.paginator {
display: block;
@ -14,12 +14,12 @@
font-family: Arial, Verdana, sans-serif;
display: inline-block;
height: 36px;
height: 42px;
padding: 0;
margin: 0 var(--space-s);
text-align: left;
line-height: 36px;
line-height: 42px;
text-decoration: none;
vertical-align: bottom;
color: var(--color-black);
@ -31,7 +31,7 @@
input.paginator_page_number {
display: inline-block;
width: 36px;
width: 42px;
padding: 0;
margin: 0 var(--space-s);
text-align: center;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.infinite_scroll_border_top,
.infinite_scroll_border_bottom {

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.show_all {
position: relative;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.data_view {
&_buttons {

View file

@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import ISort from 'ts/interfaces/Sort';
import Table from 'ts/components/Table';
import Cards from 'ts/components/Cards';
import { downloadCsv } from 'ts/helpers/File';
import { downloadExcel } from 'ts/helpers/File';
import viewSettings from 'ts/store/ViewSettings';
import isMobile from 'ts/helpers/isMobile';
@ -33,6 +34,7 @@ function DataView({
updateSort,
children,
}: IDataViewProps): React.ReactElement | null {
const { t } = useTranslation();
const urlParams = useParams<any>();
const defaultType = viewSettings.getItem(urlParams, isMobile ? 'cards' : 'table');
const [localType, setType] = useState<string>(type || defaultType);
@ -53,14 +55,14 @@ function DataView({
<>
<div style={{ position: 'relative' }}>
<div className={style.data_view_buttons}>
{false && (
{!isMobile && (
<img
title={'Скачать CSV'}
title={'Скачать XLSX'}
src="./assets/icons/Download.svg"
className={style.data_view_icon}
onClick={() => {
const fileName = `${urlParams.type || ''} ${urlParams.page || ''}`;
downloadCsv(rows, children, fileName);
const fileName = t(`sidebar.${urlParams.type}.${urlParams.page}`);
downloadExcel(rows, children, fileName);
}}
/>
)}

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.day_info {
&_wrapper {

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.description {
white-space: normal;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.dropzone {
position: fixed;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.extension {
display: inline-block;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.external_link {
font-size: var(--font-s);

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.get_list_container {
margin: 12px 0 24px 0;

View file

@ -1,22 +1,22 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import style from '../styles/legend.module.scss';
function Legend(): React.ReactElement | null {
const { t } = useTranslation();
return (
<div className={style.legend}>
<div className={style.legend_item}>
<div className={style.legend_work}></div>
<div className={style.legend_title}>
{localization.get('uiKit.hoursChart.work')}
{t('uiKit.hoursChart.work')}
</div>
</div>
<div className={style.legend_item}>
<div className={style.legend_weekend}></div>
<div className={style.legend_title}>
{localization.get('uiKit.hoursChart.weekend')}
{t('uiKit.hoursChart.weekend')}
</div>
</div>
<div className={style.legend_item}>
@ -24,7 +24,7 @@ function Legend(): React.ReactElement | null {
42
</div>
<div className={style.legend_title}>
{localization.get('uiKit.hoursChart.days')}
{t('uiKit.hoursChart.days')}
</div>
</div>
</div>

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.user {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.legend {
display: block;

View file

@ -1,6 +1,5 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
interface ILineProps {
value?: number;
@ -23,14 +22,15 @@ function Line({
className,
formatter,
}: ILineProps): React.ReactElement | null {
const { t } = useTranslation();
if (!width || width <= 0) return null;
const formattedTitle = localization.get(title || '');
const localizationDescription = localization.get(description || '');
const formattedTitle = t(title || '');
const localizationDescription = t(description || '');
const fullDescription = localizationDescription || formattedTitle;
const formattedValue = formatter?.(value);
const formattedSuffix = suffix ? ` ${localization.get(suffix || '')}` : '';
const formattedSuffix = suffix ? ` ${t(suffix || '')}` : '';
const formattedDescription = value
? `${width}% (${formattedValue}${formattedSuffix}) ${fullDescription}`
: `${width}% ${fullDescription}`;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.line_chart {
--line_chart-height: 24px;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.loading {
display: block;

View file

@ -2,6 +2,7 @@ import React from 'react';
import { observer } from 'mobx-react-lite';
import UiKitButton from 'ts/components/UiKit/components/Button';
import isMobile from 'ts/helpers/isMobile';
import { Modal, Header, Footer } from './index';
import confirm from './store/Confirm';
@ -16,6 +17,7 @@ const Confirm = observer(() => {
</Header>
<Footer>
<UiKitButton
mode={isMobile ? ['primary', 'full_size'] : ['primary']}
onClick={() => {
confirm.cancel();
}}
@ -23,7 +25,7 @@ const Confirm = observer(() => {
{confirm.no}
</UiKitButton>
<UiKitButton
type="second"
mode={isMobile ? ['second', 'full_size'] : ['second']}
onClick={() => {
confirm.success();
}}

View file

@ -1,14 +1,14 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import style from '../index.module.scss';
function CommitFormat() {
const { t } = useTranslation();
return (
<>
<p className={style.nothing_found_title}>
{localization.get('uiKit.nothingFound.common.title')}
{t('uiKit.nothingFound.common.title')}
</p>
<p className={style.nothing_found_text}>
Система обработает больше данных, если коммиты будут подписаны в формате &quot;
@ -23,10 +23,10 @@ function CommitFormat() {
&quot;. Шаблон:
</p>
<p className={style.nothing_found_console}>
{localization.get('uiKit.nothingFound.common.console')}
{t('uiKit.nothingFound.common.console')}
</p>
<p className={style.nothing_found_text}>
{localization.get('uiKit.nothingFound.common.example')}
{t('uiKit.nothingFound.common.example')}
</p>
<p className={style.nothing_found_console}>
JIRA-0001 feat(profile): add user avatar<br/>

View file

@ -1,20 +1,20 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import style from '../index.module.scss';
function IsStaff() {
const { t } = useTranslation();
return (
<>
<p className={style.nothing_found_title}>
{localization.get('uiKit.nothingFound.staff.title')}
{t('uiKit.nothingFound.staff.title')}
</p>
<p className={style.nothing_found_text}>
{localization.get('uiKit.nothingFound.staff.description1')}
{t('uiKit.nothingFound.staff.description1')}
</p>
<p className={style.nothing_found_text}>
{localization.get('uiKit.nothingFound.staff.description2')}
{t('uiKit.nothingFound.staff.description2')}
</p>
</>
);

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.nothing_found {
display: block;

View file

@ -1,6 +1,5 @@
import React, { ReactNode } from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import CommitFormat from './components/CommitFormat';
import style from './index.module.scss';
@ -19,7 +18,8 @@ function NothingFound({
children,
className,
}: INothingFoundProps) {
const formattedMessage = localization.get(message || '');
const { t } = useTranslation();
const formattedMessage = t(message || '');
return (
<div className={`${style.nothing_found_wrapper} ${className}`}>
<div className={style.nothing_found}>

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.notifications {
position: fixed;

View file

@ -1,7 +1,7 @@
import React, { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import UiKitButton from 'ts/components/UiKit/components/Button';
import localization from 'ts/helpers/Localization';
import style from './index.module.scss';
@ -16,15 +16,16 @@ function PageBox({
onRemove,
children,
}: IPageColumnProps) {
const { t } = useTranslation();
return (
<div className={`${style.main_wrapper_white} ${className || ''}`}>
<div className={style.main_wrapper_icons}>
{onRemove && (
<UiKitButton
type="second"
mode="second"
onClick={() => onRemove()}
>
{localization.get('uiKit.page.remove')}
{t('uiKit.page.remove')}
</UiKitButton>
)}
</div>

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.main_wrapper {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.races {
position: relative;

View file

@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import UiKitButton from 'ts/components/UiKit/components/Button';
import localization from 'ts/helpers/Localization';
import Track from './Track';
import style from './index.module.scss';
@ -23,6 +23,7 @@ interface IRacesProps {
function Races({
tracks,
}: IRacesProps): React.ReactElement | null {
const { t } = useTranslation();
const [showAnimation, setShowAnimation] = useState<boolean>(false);
if (!tracks.length) return null;
@ -47,7 +48,7 @@ function Races({
setShowAnimation(true);
}}
>
{localization.get('uiKit.races.go')}
{t('uiKit.races.go')}
</UiKitButton>
)}
{lines}

View file

@ -51,7 +51,7 @@ function Card({
/>
{!isMobile && (
<UiKitButton
type="link"
mode="link"
className={style.recommendations_card_button}
onClick={onClick}
>

View file

@ -4,8 +4,9 @@ import { observer } from 'mobx-react-lite';
import UiKitButton from 'ts/components/UiKit/components/Button';
import { Modal, Header, Body, Footer } from 'ts/components/ModalWindow';
import Description from 'ts/components/Description';
import localization from 'ts/helpers/Localization';
import RECOMMENDATION_TYPES from 'ts/helpers/Recommendations/contstants';
import localization from 'ts/helpers/Localization';
import isMobile from 'ts/helpers/isMobile';
import { getFormattedTitle, getDescriptionText } from '../helpers';
import recommendationStore from '../store/index';
@ -55,7 +56,7 @@ const RecommendationDescription = observer(() => {
</Body>
<Footer className={style.recommendations_modal_footer}>
<UiKitButton
type="slim"
mode={[ isMobile ? 'primary' : 'slim', 'full_size']}
onClick={() => {
recommendationStore.close();
}}

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.recommendations_card {
position: relative;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.recommendations {
&_short,

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.recommendations_short,
.recommendations_full {

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.splash_screen {
position: fixed;
@ -24,19 +24,6 @@
animation: splash_screen_container 1s linear 4s forwards;
}
&_description {
font-size: 10px;
font-weight: 100;
display: block;
padding: 0;
margin: 8px 0 0 0;
overflow: hidden;
text-overflow: ellipsis;
text-transform: none;
color: #404148;
}
}
@keyframes splash_screen {

View file

@ -1,53 +1,17 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import Logo from 'ts/pages/PageWrapper/components/sidebar/Logo';
import style from './index.module.scss';
import progress from './progress.module.scss';
const TEXT: string[] = [
'обработка файлов',
'обработка коммитов',
'нормализация данных',
'анализ времени',
'анализ состава команды',
'оценка стоимости проекта',
'оценка затрат на разработку',
'расчёт общих рекомендаций',
'расчёт частных рекомендаций',
'аудит суммарных затрат',
'расчёт персональных ачивок',
'анализ эффективности',
].reverse();
function SplashScreen(): React.ReactElement | null {
const [timer, setTimer] = useState<any>(null);
const [index, setIndex] = useState<number>(0);
useEffect(() => {
if (timer) return;
let localIndex = 0;
setTimer(setInterval(() => {
localIndex = localIndex === 0
? TEXT.length - 1
: localIndex - 1;
setIndex(localIndex);
}, 200));
return () => {
clearInterval(timer);
};
}, []);
return (
<div className={style.splash_screen}>
<div className={style.splash_screen_container}>
<Logo />
<div className={progress.progress_bar}></div>
<p className={style.splash_screen_description}>
{TEXT[index] || ''}
</p>
</div>
</div>
);

View file

@ -1,6 +1,5 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import { IColumn } from '../interfaces/Column';
import headerStyle from '../styles/header.module.scss';
@ -17,10 +16,12 @@ function Header({
className,
updateSort,
}: ITitleProps) {
const { t } = useTranslation();
const cells = columns.map((column: IColumn, columnIndex: number) => {
const columnClassName = typeof column.className === 'function'
? column.className('header', columnIndex)
: column.className;
const formattedTitle = t(column.title || '');
return (
<div
@ -29,6 +30,7 @@ function Header({
style={{ width: column.width }}
>
<span
title={formattedTitle}
onClick={() => {
if (!column.isSortable || !updateSort) return;
updateSort([{
@ -37,7 +39,7 @@ function Header({
}]);
}}
>
{localization.get(column.title)}
{formattedTitle}
</span>
{column.title && column.sortDirection === -1 && (
<div className={headerStyle.sort_down} />

View file

@ -24,9 +24,14 @@ function DefaultCell({
? (() => { if (column.onClick) column.onClick(row); })
: undefined;
const cellTitle = typeof children === 'string' && children.length > 20
? children
: null;
return (
<div
key={column.title}
key={column.title} // @ts-ignore
title={cellTitle}
className={`${style.table_cell} ${className || ''} ${columnClassName || ''}`}
style={{
width: column.width,

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.title {
font-size: var(--font-l);

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.table_wrapper {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.tempo_chart {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.tempo {
display: block;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.tempo_task {
width: 100%;

View file

@ -1,4 +1,4 @@
@import '../../../styles/variables';
@import 'src/styles/variables';
.title {
font-size: var(--font-l);

View file

@ -1,6 +1,5 @@
import React from 'react';
import localization from 'ts/helpers/Localization';
import { useTranslation } from 'react-i18next';
import style from './index.module.scss';
@ -15,12 +14,13 @@ function Title({
addPadding,
className,
}: ITitleProps) {
const { t } = useTranslation();
return (
<>
<a // @ts-ignore
name={title}></a>
<h3 className={`${style.title} ${addPadding ? style.title_padding : ''} ${className || ''}`}>
{localization.get(title || '')}
{t(title || '')}
</h3>
</>
);

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.tv100and1 {
&_row {

View file

@ -1,36 +1,52 @@
import React from 'react';
import { IUiKitWrapperProps } from './Wrapper';
import style from '../styles/index.module.scss';
import style from '../styles/button.module.scss';
export function getCustomClassName(type?: string, disabled?: boolean) {
let customClassName = {
export type Mode = 'primary' | 'second' | 'link' | 'slim' | 'full_size';
export function getClassNameForMode(mode?: string) {
return {
link: style.ui_kit_button_link,
slim: style.ui_kit_button_slim,
second: style.ui_kit_button_second,
primary: style.ui_kit_button_primary,
}[type || 'primary'] || '';
full_size: style.ui_kit_button_full_size,
}[mode || ''] || '';
}
export function getCustomClassName(mode?: Mode | Mode[], disabled?: boolean) {
let customClassName = '';
if (Array.isArray(mode)) {
customClassName = mode.map(getClassNameForMode).join(' ');
} else if (mode) {
customClassName = getClassNameForMode(mode);
} else {
customClassName = getClassNameForMode('primary');
}
if (disabled) {
customClassName += ` ${style.disabled}`;
}
return customClassName;
}
interface IUiKitButtonProps extends IUiKitWrapperProps {
type?: 'primary' | 'second' | 'link' | 'slim',
mode?: Mode | Mode[]
onClick?: Function,
}
function UiKitButton({
title,
type,
mode,
disabled,
className,
onClick,
children,
}: IUiKitButtonProps) {
const customClassName = getCustomClassName(type, disabled);
const customClassName = getCustomClassName(mode, disabled);
return (
<button

View file

@ -1,19 +1,19 @@
import React, { useState } from 'react';
import { IUiKitWrapperProps } from './Wrapper';
import { getCustomClassName } from './Button';
import { getCustomClassName, Mode } from './Button';
import style from '../styles/index.module.scss';
import style from '../styles/button.module.scss';
interface IUiKitButtonMenuProps extends IUiKitWrapperProps {
type?: string,
mode?: Mode | Mode[],
options?: any[],
onClick: Function,
}
function UiKitButtonMenu({
title,
type,
mode,
disabled,
className,
@ -24,7 +24,7 @@ function UiKitButtonMenu({
if (!options?.length) return null;
const [isOpen, setOpen] = useState<boolean>(false);
const customClassName = getCustomClassName(type, disabled);
const customClassName = getCustomClassName(mode, disabled);
const buttons = options?.map((option: any) => {
const buttonTitle = option?.title ?? option?.id ?? option ?? '';
return (

View file

@ -22,7 +22,7 @@ function UiKitSelectWithButtons({
return (
<>
<UiKitButton
type="second"
mode="second"
disabled={index <= 0}
onClick={() => {
onChange(options[index - 1]?.id);
@ -37,7 +37,7 @@ function UiKitSelectWithButtons({
onChange={onChange}
/>
<UiKitButton
type="second"
mode="second"
disabled={index >= (options.length - 1)}
onClick={() => {
onChange(options[index + 1]?.id);

View file

@ -1,5 +1,5 @@
import React, { useRef } from 'react';
import localization from 'ts/helpers/Localization';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { IUiKitWrapperProps } from './Wrapper';
import style from '../styles/tabs.module.scss';
@ -11,12 +11,12 @@ interface IUiKitTabsProps extends IUiKitWrapperProps {
onChange: Function;
}
function UiKitTabs({
const UiKitTabs = React.forwardRef(({
value,
options,
onChange,
}: IUiKitTabsProps) {
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
}: IUiKitTabsProps, ref: any): JSX.Element => {
const { t } = useTranslation();
const hasValue = value || value === 0 || value === false;
const items = (options || [])
@ -24,8 +24,10 @@ function UiKitTabs({
const formattedOption = typeof option !== 'object'
? ({ id: option, title: option })
: option;
const isSelected = hasValue && value === formattedOption?.id;
const title = localization.get(formattedOption?.title)
const title = t(formattedOption?.title)
?? formattedOption?.id
?? '';
@ -57,6 +59,8 @@ function UiKitTabs({
{items}
</div>
);
}
});
UiKitTabs.displayName = 'UiKitTabs';
export default UiKitTabs;

View file

@ -0,0 +1,22 @@
import React from 'react';
import { IUiKitWrapperProps } from './Wrapper';
import style from '../styles/tags.module.scss';
interface IUiKitTagProps extends IUiKitWrapperProps {
value: string | number;
}
function UiKitTag({
value,
}: IUiKitTagProps) {
return (
<div className={style.ui_kit_tags_item}>
{value}
</div>
);
}
UiKitTag.displayName = 'UiKitTag';
export default UiKitTag;

View file

@ -0,0 +1,35 @@
import React from 'react';
import { IUiKitWrapperProps } from './Wrapper';
import UiKitTag from './Tag';
import style from '../styles/tags.module.scss';
interface IUiKitTagsProps extends IUiKitWrapperProps {
value: any;
}
function UiKitTags({
value,
}: IUiKitTagsProps) {
const values = Array.isArray(value) ? value : [value];
const formattedValues = values.filter((v) => v);
console.dir(formattedValues);
const items = formattedValues
.map((tagValue: any) => (
<UiKitTag
key={tagValue}
value={tagValue}
/>
));
return (
<div className={style.ui_kit_tags}>
{items}
</div>
);
}
UiKitTags.displayName = 'UiKitTags';
export default UiKitTags;

View file

@ -1,6 +1,6 @@
import React, { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import localization from 'ts/helpers/Localization';
import style from '../styles/index.module.scss';
export interface IUiKitWrapperProps {
@ -23,25 +23,26 @@ function UiKitWrapper({
className,
children,
}: IUiKitWrapperProps) {
const { t } = useTranslation();
return (
<div
className={`${style.ui_kit_wrapper} ${className || ''}`}
title={localization.get(help)}
title={t(help || '')}
>
{title && (
<h6 className={style.ui_kit_title}>
{localization.get(title)}
{t(title)}
</h6>
)}
{description && (
<p className={style.ui_kit_description}>
{localization.get(description)}
{t(description)}
</p>
)}
{children}
{help && (
<p className={style.ui_kit_help}>
{localization.get(example)}
{t(example || '')}
</p>
)}
{error && (

View file

@ -0,0 +1,131 @@
@import 'src/styles/variables';
.ui_kit_button {
--button-color-bg: var(--color-button);
--button-color-text: #FFFFFF;
--button-color-border: var(--color-button);
--button-color-hover: var(--color-button-2);
--button-color-active: var(--color-button-3);
&_slim,
&_second {
--button-color-bg: #FFFFFF;
--button-color-text: var(--color-black);
--button-color-border: var(--color-border);
--button-color-hover: var(--color-border);
--button-color-active: var(--color-border);
}
&_link {
--button-color-bg: transparent;
--button-color-text: var(--color-button);
--button-color-border: transparent;
--button-color-hover: transparent;
--button-color-active: transparent;
}
}
.ui_kit_button {
font-weight: bold;
font-size: var(--font-xs);
display: inline-block;
height: 42px;
min-width: 42px;
padding: 0 var(--space-l);
margin: 0;
cursor: pointer;
line-height: 42px;
text-align: center;
box-sizing: border-box;
white-space: nowrap;
vertical-align: top;
border: 1px solid var(--button-color-border);
border-radius: var(--border-radius-s);
color: var(--button-color-text);
background-color: var(--button-color-bg);
&:hover {
background-color: var(--button-color-hover);
}
&:active {
background-color: var(--button-color-active);
}
&.disabled {
pointer-events: none;
opacity: 0.5;
}
&_slim {
font-weight: 100;
}
&_link {
font-weight: 100;
height: auto;
min-height: auto;
padding: 0;
line-height: 1.3;
text-decoration: underline;
&:hover {
text-decoration: none;
}
}
&_full_size {
display: block;
width: 99%;
margin: 12px auto;
&:first-child {
margin-top: 24px;
}
&:last-child {
margin-bottom: 24px;
}
}
}
.ui_kit_button + .ui_kit_button {
margin-right: 24px;
}
.ui_kit_button_full_size + .ui_kit_button_full_size {
margin-right: auto;
}
.ui_kit_button_menu {
--button-color-bg: #FFFFFF;
--button-color-text: var(--color-black);
--button-color-border: var(--color-border);
--button-color-hover: var(--color-border);
font-weight: bold;
font-size: var(--font-xs);
display: block;
height: 42px;
width: 100%;
padding: 0 var(--space-s);
margin: 0;
cursor: pointer;
line-height: 42px;
text-align: left;
box-sizing: border-box;
white-space: nowrap;
vertical-align: top;
border: none;
border-bottom: 1px solid var(--button-color-border);
border-radius: 0;
color: var(--button-color-text);
background-color: var(--button-color-bg);
&:hover {
background-color: var(--button-color-hover);
}
}

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.ui_kit_common {
font-size: var(--font-s);
@ -6,11 +6,11 @@
display: inline-block;
width: 100%;
height: 36px;
height: 42px;
padding: 0 var(--space-l);
margin: 0;
line-height: 36px;
line-height: 42px;
text-align: left;
box-sizing: border-box;
vertical-align: top;
@ -65,87 +65,6 @@
color: var(--color-12);
}
.ui_kit_button {
--button-color-bg: var(--color-button);
--button-color-text: #FFFFFF;
--button-color-border: var(--color-button);
--button-color-hover: var(--color-button-2);
--button-color-active: var(--color-button-3);
&_slim,
&_second {
--button-color-bg: #FFFFFF;
--button-color-text: var(--color-black);
--button-color-border: var(--color-border);
--button-color-hover: var(--color-border);
--button-color-active: var(--color-border);
}
&_link {
--button-color-bg: transparent;
--button-color-text: var(--color-button);
--button-color-border: transparent;
--button-color-hover: transparent;
--button-color-active: transparent;
}
}
.ui_kit_button {
font-weight: bold;
font-size: var(--font-xs);
display: inline-block;
height: 36px;
min-width: 36px;
padding: 0 var(--space-s);
margin: 0;
cursor: pointer;
line-height: 36px;
text-align: center;
box-sizing: border-box;
white-space: nowrap;
vertical-align: top;
border: 1px solid var(--button-color-border);
border-radius: var(--border-radius-s);
color: var(--button-color-text);
background-color: var(--button-color-bg);
&:hover {
background-color: var(--button-color-hover);
}
&:active {
background-color: var(--button-color-active);
}
&.disabled {
pointer-events: none;
opacity: 0.5;
}
&_slim {
font-weight: 100;
}
&_link {
font-weight: 100;
height: auto;
min-height: auto;
padding: 0;
line-height: 1.3;
text-decoration: underline;
&:hover {
text-decoration: none;
}
}
}
.ui_kit_button + .ui_kit_button {
margin-right: 24px;
}
.ui_kit_select {
padding: 0 var(--space-xs) 0 var(--space-l);
}
@ -166,35 +85,3 @@
background-color: #FFFFFF;
box-shadow: 0 0 5px #C0C0C0;
}
.ui_kit_button_menu {
--button-color-bg: #FFFFFF;
--button-color-text: var(--color-black);
--button-color-border: var(--color-border);
--button-color-hover: var(--color-border);
font-weight: bold;
font-size: var(--font-xs);
display: block;
height: 36px;
width: 100%;
padding: 0 var(--space-s);
margin: 0;
cursor: pointer;
line-height: 36px;
text-align: left;
box-sizing: border-box;
white-space: nowrap;
vertical-align: top;
border: none;
border-bottom: 1px solid var(--button-color-border);
border-radius: 0;
color: var(--button-color-text);
background-color: var(--button-color-bg);
&:hover {
background-color: var(--button-color-hover);
}
}

View file

@ -1,11 +1,11 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.ui_kit_switch {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 36px;
height: 42px;
padding: 0;
margin: 0;

View file

@ -0,0 +1,27 @@
@import 'src/styles/variables';
.ui_kit_tags {
display: block;
white-space: normal;
&_item {
display: inline-block;
padding: var(--space-xxxs) var(--space-xs);
margin: 0 var(--space-xs) var(--space-xs) 0;
font-size: var(--font-s);
font-weight: 100;
text-align: center;
text-decoration: none;
box-sizing: border-box;
line-height: 1.3;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: var(--border-radius-s);
border: 1px solid var(--color-border);
background-color: var(--color-border);
color: var(--color-black);
}
}

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.year_chart_month {
--day-size: 16px;

View file

@ -1,4 +1,4 @@
@import '../../../../styles/variables';
@import 'src/styles/variables';
.year_chart_month {
&_info {

View file

@ -40,10 +40,10 @@ export default class DataGripByAuthor {
statistic.types[commit.type] = statistic.types[commit.type] ? (statistic.types[commit.type] + 1) : 1;
statistic.scopes[commit.scope] = statistic.scopes[commit.scope] ? (statistic.scopes[commit.scope] + 1) : 1;
statistic.hours.push(commit.hours);
statistic.messageLength.push(commit.message.length);
statistic.totalMessageLength += commit.message.length || 0;
statistic.maxMessageLength = commit.message.length > statistic.maxMessageLength
? commit.message.length
statistic.messageLength.push(commit.text.length);
statistic.totalMessageLength += commit.text.length || 0;
statistic.maxMessageLength = commit.text.length > statistic.maxMessageLength
? commit.text.length
: statistic.maxMessageLength;
statistic.commitsByDayAndHour[commit.day][commit.hours] += 1;
statistic.commitsByHour[commit.hours] += 1;
@ -72,9 +72,9 @@ export default class DataGripByAuthor {
hours: [commit.hours],
commitsByDayAndHour,
commitsByHour,
messageLength: [commit.message.length || 0],
totalMessageLength: commit.message.length || 0,
maxMessageLength: commit.message.length || 0,
messageLength: [commit.text.length || 0],
totalMessageLength: commit.text.length || 0,
maxMessageLength: commit.text.length || 0,
wordStatistics: DataGripByAuthor.#updateWordStatistics(commit),
moneyByMonth: {},
};
@ -125,12 +125,13 @@ export default class DataGripByAuthor {
const LIMIT_WORD_LENGTH = 2;
const disabledWords = { for: 1, fix: 1 };
commit.message.toLowerCase().split(' ').forEach(word => {
commit.text.toLowerCase().split(' ').forEach(word => {
if (word.length <= LIMIT_WORD_LENGTH || disabledWords[word]) return;
total[word] = total[word]
? (total[word] + 1)
: 1;
});
return total;
}

View file

@ -0,0 +1,87 @@
import ICommit from 'ts/interfaces/Commit';
import IHashMap from 'ts/interfaces/HashMap';
import settingsStore from 'ts/store/Settings';
export default class DataGripByTasks {
commits: IHashMap<ICommit[]> = {};
statistic: any = [];
clear() {
this.commits = {};
this.statistic = [];
}
addCommit(commit: ICommit) {
if (this.commits[commit.task]) {
this.#updateCommitByTask(commit);
} else {
this.#addCommitByTask(commit);
}
}
#updateCommitByTask(commit: ICommit) {
this.commits[commit.task].push(commit);
}
#addCommitByTask(commit: ICommit) {
this.commits[commit.task] = [commit];
}
updateTotalInfo(PRs: any) {
this.statistic = Object.entries(this.commits)
.map(([task, commits]: [string, ICommit[]]) => {
const firstCommit = commits[0];
const lastCommit = commits[commits.length - 1];
const from = firstCommit.milliseconds;
const pr = PRs.prByTask[task] ? PRs.pr[PRs.prByTask[task]] : null;
const shortInfo = {
task,
author: firstCommit.author,
from,
commits: 1,
daysInWork: 1,
prDate: pr?.milliseconds,
prDelayDays: pr?.delayDays,
prAuthor: firstCommit.author === pr?.author ? null : pr?.author,
comments: firstCommit.text,
types: firstCommit.type && firstCommit.type !== 'не подписан' ? [firstCommit.type] : [],
scope: firstCommit.scope && firstCommit.scope !== 'неопределенна' ? [firstCommit.scope] : [],
};
if (commits.length === 1) return shortInfo;
const authors = new Set();
const messages = new Set();
const types = new Set();
const scope = new Set();
commits.forEach((commit: ICommit) => {
authors.add(commit.author);
messages.add(commit.text);
if (commit.type !== 'не подписан') types.add(commit.type);
if (commit.scope !== 'неопределенна') scope.add(commit.scope);
});
const authorsList = Array.from(authors).join(', ');
const comments = Array.from(messages).join(', ');
const to = lastCommit.milliseconds;
const daysInWork = Math.ceil((to - from) / settingsStore.ONE_DAY) + 1;
return {
...shortInfo,
to: to !== from ? to : undefined,
commits: commits.length,
daysInWork,
authors: authorsList,
comments,
types: Array.from(types),
scope: Array.from(scope),
};
})
.filter((dot) => dot.task)
.sort((dotA, dotB) => dotB.from - dotA.from);
this.commits = {};
}
}

View file

@ -12,6 +12,7 @@ import MinMaxCounter from './components/counter';
import DataGripByExtension from './components/extension';
import DataGripByGet from './components/get';
import DataGripByPR from './components/pr';
import DataGripByTasks from './components/tasks';
class DataGrip {
firstLastCommit: any = new MinMaxCounter();
@ -36,6 +37,8 @@ class DataGrip {
pr: any = new DataGripByPR();
tasks: any = new DataGripByTasks();
initializationInfo: any = {};
clear() {
@ -50,6 +53,7 @@ class DataGrip {
this.extension.clear();
this.get.clear();
this.pr.clear();
this.tasks.clear();
}
addCommit(commit: ICommit | ISystemCommit) {
@ -63,6 +67,7 @@ class DataGrip {
this.timestamp.addCommit(commit);
this.get.addCommit(commit);
this.week.addCommit(commit);
this.tasks.addCommit(commit);
}
}
@ -75,6 +80,7 @@ class DataGrip {
this.week.updateTotalInfo(this.author);
this.recommendations.updateTotalInfo(this);
this.pr.updateTotalInfo(this.author);
this.tasks.updateTotalInfo(this.pr);
}
updateByInitialization() {

Some files were not shown because too many files have changed in this diff Show more