MMM-2022 lol(kek): 4eburek

This commit is contained in:
bakhirev 2023-12-03 13:18:16 +03:00
parent a22abc0dc5
commit ffe71996f1
14 changed files with 149 additions and 84 deletions

View file

@ -42,7 +42,7 @@
<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="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.">

View file

@ -41,10 +41,10 @@ function Console({ className, textForCopy, children }: IConsoleProps) {
className={`${style.console_copy}`}
onClick={() => {
copyInBuffer(textForCopy);
notificationsStore.show('Текст скопирован');
notificationsStore.show(localization.get('uiKit.console.notification'));
}}
>
{localization.get('uiKit.console')}
{localization.get('uiKit.console.button')}
</Button>
</div>
);

View file

@ -5,6 +5,7 @@ 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 viewSettings from 'ts/store/ViewSettings';
import style from './index.module.scss';
import PageWrapper from '../Page/wrapper';
@ -32,7 +33,10 @@ function DataView({
children,
}: IDataViewProps): React.ReactElement | null {
const urlParams = useParams<any>();
const [localType, setType] = useState<string>(type || 'table');
const defaultType = viewSettings.getItem(urlParams, 'table');
console.log(defaultType);
const [localType, setType] = useState<string>(type || defaultType);
console.log(localType);
if (!rows || !rows.length) return null;
@ -64,7 +68,9 @@ function DataView({
src={icon}
className={style.data_view_icon}
onClick={() => {
setType(localType === 'table' ? 'cards' : 'table');
const newType = localType === 'table' ? 'cards' : 'table';
setType(newType);
viewSettings.setItem(urlParams, newType, 'table');
}}
/>
</div>
@ -99,7 +105,7 @@ function DataView({
DataView.defaultProps = {
rows: [],
sort: [],
type: 'table',
type: undefined,
columnCount: undefined,
updateSort: () => {
},

View file

@ -31,6 +31,19 @@
margin-bottom: 4px;
}
&_link {
text-decoration: underline;
color: var(--color-button);
&:hover {
text-decoration: none;
}
&:visited {
color: var(--color-button);
}
}
&_list {
position: relative;
padding: 0 0 0 22px;

View file

@ -6,9 +6,10 @@ import cssStyle from './index.module.scss';
interface ICommonProps {
text: string;
style: any;
className?: string;
}
function getTextWithLink(text: string) {
function getTextWithLink(text: string, className?: string) {
const parts = (text || '')
.split(/(\[[^\]]+\])/gim)
.map((value: string) => {
@ -18,7 +19,10 @@ function getTextWithLink(text: string) {
<Link
key={value}
target="_blank"
to={link}>
rel="noreferrer"
className={className || ''}
to={link}
>
{title}
</Link>
);
@ -26,43 +30,43 @@ function getTextWithLink(text: string) {
return (<>{parts}</>) ;
}
function getTextWithStyle(text: string) {
function getTextWithStyle(text: string, className?: string) {
const parts = (text || '')
.split('*')
.map((value: string, index: number) => (index % 2
? (<b key={value}>{getTextWithLink(value)}</b>)
: (<span key={value}>{getTextWithLink(value)}</span>)
? (<b key={value}>{getTextWithLink(value, className)}</b>)
: (<span key={value}>{getTextWithLink(value, className)}</span>)
));
return (<>{parts}</>) ;
}
function List({ text, style }: ICommonProps) {
function List({ text, style, className }: ICommonProps) {
return (
<p
className={cssStyle.description_list}
style={style || {}}
className={`${cssStyle.description_list} ${className || ''}`}
>
{getTextWithStyle(text)}
{getTextWithStyle(text, className)}
</p>
);
}
function Title({ text, style }: ICommonProps) {
function Title({ text, style, className }: ICommonProps) {
return (
<h6
className={cssStyle.description_title}
style={style || {}}
className={`${cssStyle.description_title} ${className || ''}`}
>
{getTextWithStyle(text)}
{getTextWithStyle(text, className)}
</h6>
);
}
function SimpleText({ text, style }: ICommonProps) {
function SimpleText({ text, style, className }: ICommonProps) {
return (
<p
className={cssStyle.description_text}
style={style || {}}
className={`${cssStyle.description_text} ${className || ''}`}
>
{getTextWithStyle(text)}
</p>
@ -72,9 +76,10 @@ function SimpleText({ text, style }: ICommonProps) {
interface IDescriptionProps {
text?: string | string[];
style?: any;
className?: string;
}
function Description({ text, style }: IDescriptionProps) {
function Description({ text, style, className }: IDescriptionProps) {
const paragraphs = !Array.isArray(text)
? (text || '').trim().split(/\n+/gm)
: text;
@ -82,29 +87,35 @@ function Description({ text, style }: IDescriptionProps) {
const items = paragraphs.map((paragraph) => {
const prefix = paragraph.substring(0, 2);
const mainText = paragraph.substring(2);
if (prefix === '- ') {
return (
<List
key={mainText}
text={mainText}
style={style}
className={className}
/>
);
}
if (prefix === '# ') {
return (
<Title
key={mainText}
text={mainText}
style={style}
className={className}
/>
);
}
return (
<SimpleText
key={mainText}
text={paragraph}
style={style}
className={className}
/>
);
});

View file

@ -1,3 +1,5 @@
import localization from './Localization';
function getFormattedType(dataGrip: any): string {
const popularType = dataGrip.extension.statistic?.[0] || {};
const extension = popularType?.extension || '';
@ -45,7 +47,7 @@ function getFormattedType(dataGrip: any): string {
export default function getTitle(dataGrip: any, commits: any) {
if (!commits.length) {
return 'Git Statistics';
return localization.get('common.title');
}
const type = getFormattedType(dataGrip) || '';

View file

@ -19,10 +19,10 @@ const Common = observer((): React.ReactElement | null => {
<InputString
title="page.settings.document.name"
value={title}
placeholder="Git Statistics"
placeholder={localization.get('common.title')}
onChange={(value: string) => {
setTitle(value);
document.title = value || 'Git Statistics';
document.title = value || localization.get('common.title');
applicationHasCustom.title = true;
}}
/>

View file

@ -1,7 +1,7 @@
import React from 'react';
import { Link } from 'react-router-dom';
import Console from 'ts/components/Console';
import Description from 'ts/components/Description';
import {
getStringFromFileList,
getStringsForParser,
@ -14,27 +14,14 @@ import style from './styles/index.module.scss';
function WarningInfo() {
return (
<h4 className={style.welcome_warning}>
<p>
{'Сервис '}
<span className={style.welcome_warning_bold}>НЕ ХРАНИТ</span>
{' и '}
<span className={style.welcome_warning_bold}>НЕ ПЕРЕДАЁТ</span>
{' ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.'}
</p>
<p>
{'Сервис '}
<span className={style.welcome_warning_bold}>НЕ СОБИРАЕТ СТАТИСТИКУ</span>
{' по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из '}
<a
href='https://github.com/bakhirev/assayo'
target="_blank"
rel="noreferrer"
className={style.welcome_warning_link}
>
исходников
</a>
{'.'}
</p>
<Description
text={localization.get('page.welcome.warning1')}
className={style.welcome_warning_text}
/>
<Description
text={localization.get('page.welcome.warning2')}
className={style.welcome_warning_text}
/>
</h4>
);
}
@ -54,16 +41,10 @@ function Welcome() {
className={style.welcome_console}
textForCopy={command}
/>
<p className={style.welcome_description}>
{localization.get('page.welcome.description1')}
<Link
className={`${style.welcome_link}`}
target="_blank"
to="https://git-scm.com/docs/gitmailmap">
.mailmap
</Link>
{localization.get('page.welcome.description2')}
</p>
<Description
text={localization.get('page.welcome.description')}
className={`${style.welcome_description}`}
/>
<h2 className={style.welcome_last_title}>
{localization.get('page.welcome.step2') === 'page.welcome.step2'
? ''

View file

@ -23,34 +23,23 @@
}
&_warning {
font-weight: 100;
font-size: var(--font-s);
width: 100%;
margin: 0 auto;
padding: 6px;
box-sizing: border-box;
line-height: 1.5;
text-align: center;
border-bottom: 3px solid red;
background-color: #FCDADA;
&_bold {
font-weight: bold;
color: red;
&_text {
text-align: center;
color: #B50404;
}
&_link {
text-decoration: underline;
color: var(--color-button);
&:hover {
text-decoration: none;
}
}
}
&_link,
&_description {
font-size: var(--font-xs);
@ -66,12 +55,6 @@
color: #878FA1;
}
&_link {
display: inline;
margin: 16px 4px 0 4px;
text-decoration: underline;
}
&_first_title,
&_last_title {
font-size: 42px;

View file

@ -0,0 +1,69 @@
import { observable, action, makeObservable } from 'mobx';
class ViewSettingsStore {
key: string = 'view_settings';
version: number = 1;
settings: any = {};
constructor() {
this.load();
makeObservable(this, {
settings: observable,
load: action,
setItem: action,
});
}
load() {
const settings = JSON.parse(localStorage.getItem(this.key) || '{}') || {};
if (settings.version === this.version) {
this.settings = settings.settings;
}
}
save() {
if (Object.keys(this.settings).length === 0) {
localStorage.removeItem(this.key);
return;
}
localStorage.setItem(this.key, JSON.stringify({
version: this.version,
settings: this.settings,
}));
}
#getPath(path: any): string {
if (!path) return '';
if (Array.isArray(path)) {
return path.join('.');
} else if (typeof path === 'object') {
return [path.type, path.page].join('.');
}
return path;
}
setItem(path: any, value: any, defaultValue?: any) {
const formattedPath = this.#getPath(path);
if (!formattedPath) return;
if (!value || value === defaultValue) {
delete this.settings[formattedPath];
} else {
this.settings[formattedPath] = value;
}
this.save();
}
getItem(path: any, defaultValue?: any): any {
const formattedPath = this.#getPath(path);
return this.settings?.[formattedPath] || defaultValue;
}
}
const viewSettings = new ViewSettingsStore();
export default viewSettings;

View file

@ -1,5 +1,6 @@
export default `
§ uiKit.console: Copy
§ uiKit.console.button: Copy
§ uiKit.console.notification: Text was copied
§ uiKit.dataLoader.page: Page
§ uiKit.dataLoader.size: Displayed
§ uiKit.dataLoader.from: out of
@ -22,6 +23,7 @@ The work of employees with such status on this project can be neglected as their
Therefore, the system does not calculate a number of indicators for him.
If this is an error and this employee needs to be calculated as usual, go to the Settings section and change his type.
§ common.title: Git statistics
§ common.filters: Filters
§ common.notifications.save: The changes have been saved
§ common.notifications.setting: The settings have been saved

View file

@ -1,11 +1,9 @@
export default `
§ page.welcome.step1: Execute the command in the root of your project.
§ page.welcome.step3: Drag and Drop.
§ page.welcome.step3: Drag and drop
§ page.welcome.step4: the log.txt file onto this page.
§ page.welcome.description1: Git will create a log.txt file. It contains data for report generation. Or use git shortlog -s -n -e if you don't need a report. Create a file.
§ page.welcome.description2: [Create a .mailmap file|https://git-scm.com/docs/gitmailmap] in the root of the project to consolidate employee statistics.
§ page.welcome.description: Git will create a log.txt file. It contains data for report generation. Or use git shortlog -s -n -e if you don't need a report. Create a [.mailmap file|https://git-scm.com/docs/gitmailmap] in the root of the project to consolidate employee statistics.
§ page.welcome.warning1: The service *DOES NOT STORE* and *DOES NOT TRANSFER* your data. All calculations are performed locally in your browser on your machine.
§ page.welcome.description: Git will create a log.txt file. It contains data for report generation. Or use git shortlog -s -n -e if you don't need a report. Create a [.mailmap|https://git-scm.com/docs/gitmailmap] file in the root of the project to consolidate employee statistics.
§ page.welcome.warning1: The service *DOES NOT SAVE* and *DOES NOT TRANSFER* your data. All calculations are performed locally in your browser on your machine.
§ page.welcome.warning2: The service *DOES NOT COLLECT STATISTICS* on projects. You can disconnect the internet, check traffic, and even build a local version from the [source|https://github.com/bakhirev/assayo].
§ page.common.words.title: Word Statistics.
§ page.common.words.description: the most popular word. Occurs $1 times.

View file

@ -1,5 +1,6 @@
export default `
§ uiKit.console: Копировать
§ uiKit.console.button: Копировать
§ uiKit.console.notification: Текст скопирован
§ uiKit.dataLoader.page: Страница
§ uiKit.dataLoader.size: Отображается по
§ uiKit.dataLoader.from: из
@ -22,6 +23,7 @@ export default `
Поэтому система не рассчитывает для него ряд показателей.
Если это ошибка и данного сотрудника нужно рассчитать как обычного, перейдите в раздел «Настройки» и измените его тип.
§ common.title: Git статистика
§ common.filters: Фильтры
§ common.notifications.save: Изменения сохранены
§ common.notifications.setting: Настройки сохранены

View file

@ -2,8 +2,6 @@ export default `
§ page.welcome.step1: Выполните команду в корне вашего проекта
§ page.welcome.step3: Перетащите
§ page.welcome.step4: файл log.txt на эту страницу
§ page.welcome.description1: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл
§ page.welcome.description2: [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
§ page.welcome.description: Git создаст файл log.txt. Он содержит данные для построения отчёта. Или git shortlog -s -n -e если отчёт вам не нужен. Создайте файл [.mailmap|https://git-scm.com/docs/gitmailmap] в корне проекта, чтобы объединить статистику по сотрудникам.
§ page.welcome.warning1: Сервис *НЕ ХРАНИТ* и *НЕ ПЕРЕДАЁТ* ваши данные. Все расчёты выполняются локально в вашем браузере прямо на вашей машине.
§ page.welcome.warning2: Сервис *НЕ СОБИРАЕТ СТАТИСТИКУ* по проектам. Вы можете отключить интернет, проверить трафик и даже собрать локальный билд из [исходников|https://github.com/bakhirev/assayo].