mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 16:21:41 +00:00
update
This commit is contained in:
parent
b87d79cff9
commit
407d51c291
13
build/asset-manifest.json
Normal file
13
build/asset-manifest.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"files": {
|
||||||
|
"main.css": "./static/css/main.1e4b6bfb.css",
|
||||||
|
"main.js": "./static/js/main.a991d9b4.js",
|
||||||
|
"index.html": "./index.html",
|
||||||
|
"main.1e4b6bfb.css.map": "./static/css/main.1e4b6bfb.css.map",
|
||||||
|
"main.a991d9b4.js.map": "./static/js/main.a991d9b4.js.map"
|
||||||
|
},
|
||||||
|
"entrypoints": [
|
||||||
|
"static/css/main.1e4b6bfb.css",
|
||||||
|
"static/js/main.a991d9b4.js"
|
||||||
|
]
|
||||||
|
}
|
|
@ -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="default"><meta name="theme-color" content="white"/><meta name="defaultLanguage" content="ru"><meta name="availableLanguages" content="en, es, fr, ja, pt, de, zh, ru"><link rel="canonical" href="https://assayo.online/demo/"><script type="text/javascript">var report=[]</script><script src='./log.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='../log.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='../../log.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='/log.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><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="https://assayo.online/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="https://assayo.online/"><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="https://assayo.online/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.online"><meta name="twitter:site" content="assayo.online"><meta itemprop="name" content="Git Statistics"><meta itemprop="description" content="Simple and fast report on Git commit history."><meta itemprop="image" content="https://assayo.online/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/index.js"></script><link href="./static/index.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="default"><meta name="theme-color" content="white"/><meta name="defaultLanguage" content="ru"><meta name="availableLanguages" content="en, es, fr, ja, pt, de, zh, ru"><link rel="canonical" href="https://assayo.online/demo/"><script type="text/javascript">var report=[]</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="https://assayo.online/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="https://assayo.online/"><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="https://assayo.online/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.online"><meta name="twitter:site" content="assayo.online"><meta itemprop="name" content="Git Statistics"><meta itemprop="description" content="Simple and fast report on Git commit history."><meta itemprop="image" content="https://assayo.online/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.a991d9b4.js"></script><link href="./static/css/main.1e4b6bfb.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
1
build/static/css/main.1e4b6bfb.css.map
Normal file
1
build/static/css/main.1e4b6bfb.css.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
build/static/js/main.a991d9b4.js
Normal file
3
build/static/js/main.a991d9b4.js
Normal file
File diff suppressed because one or more lines are too long
76
build/static/js/main.a991d9b4.js.LICENSE.txt
Normal file
76
build/static/js/main.a991d9b4.js.LICENSE.txt
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*! sheetjs (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||||
|
|
||||||
|
/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react-dom.production.min.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react-jsx-runtime.production.min.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* react.production.min.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @license React
|
||||||
|
* scheduler.production.min.js
|
||||||
|
*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @remix-run/router v1.3.1
|
||||||
|
*
|
||||||
|
* Copyright (c) Remix Software Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE.md file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React Router DOM v6.8.0
|
||||||
|
*
|
||||||
|
* Copyright (c) Remix Software Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE.md file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React Router v6.8.0
|
||||||
|
*
|
||||||
|
* Copyright (c) Remix Software Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE.md file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @license MIT
|
||||||
|
*/
|
1
build/static/js/main.a991d9b4.js.map
Normal file
1
build/static/js/main.a991d9b4.js.map
Normal file
File diff suppressed because one or more lines are too long
78281
build/test.txt
Normal file
78281
build/test.txt
Normal file
File diff suppressed because it is too large
Load diff
79
src/ts/components/CustomSelect/components/List.tsx
Normal file
79
src/ts/components/CustomSelect/components/List.tsx
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import UiKitSelectOption from './Option';
|
||||||
|
|
||||||
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
|
interface UiKitSelectListProps {
|
||||||
|
value: any;
|
||||||
|
options: any;
|
||||||
|
search?: string;
|
||||||
|
keyCode?: string;
|
||||||
|
setKeyCode: Function;
|
||||||
|
className?: string;
|
||||||
|
onClick: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitSelectList({
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
search,
|
||||||
|
keyCode,
|
||||||
|
className,
|
||||||
|
setKeyCode,
|
||||||
|
onClick,
|
||||||
|
}: UiKitSelectListProps) {
|
||||||
|
const [selectedIndex, setSelectedIndex] = useState<number>(-1);
|
||||||
|
|
||||||
|
console.log(value);
|
||||||
|
const searchResult = options
|
||||||
|
?.filter((option: any) => option.title.indexOf(search) !== -1);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!keyCode) return;
|
||||||
|
if (keyCode === 'down') {
|
||||||
|
let nextIndex = selectedIndex + 1;
|
||||||
|
if (nextIndex >= searchResult.length) nextIndex = 0;
|
||||||
|
setSelectedIndex(nextIndex);
|
||||||
|
}
|
||||||
|
if (keyCode === 'up') {
|
||||||
|
let nextIndex = selectedIndex - 1;
|
||||||
|
if (nextIndex < 0) nextIndex = searchResult.length - 1;
|
||||||
|
setSelectedIndex(nextIndex);
|
||||||
|
}
|
||||||
|
if (keyCode === 'enter') {
|
||||||
|
const selected = searchResult[selectedIndex];
|
||||||
|
onClick(selected, selectedIndex);
|
||||||
|
}
|
||||||
|
setKeyCode('');
|
||||||
|
}, [keyCode]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedIndex(-1);
|
||||||
|
}, [search]);
|
||||||
|
|
||||||
|
const items = searchResult?.map((option: any, index: number) => {
|
||||||
|
return (
|
||||||
|
<UiKitSelectOption
|
||||||
|
key={option.id}
|
||||||
|
focus={index === selectedIndex}
|
||||||
|
option={option}
|
||||||
|
className={className}
|
||||||
|
onClick={() => {
|
||||||
|
onClick(option.source, index);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!items.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className={`${style.ui_kit_select_list} scroll_y ${className || ''}`}>
|
||||||
|
{items}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default UiKitSelectList;
|
33
src/ts/components/CustomSelect/components/Option.tsx
Normal file
33
src/ts/components/CustomSelect/components/Option.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
|
interface UiKitSelectOptionProps {
|
||||||
|
option: any;
|
||||||
|
focus?: boolean;
|
||||||
|
className?: string;
|
||||||
|
onClick: (event: React.MouseEvent<HTMLLIElement, MouseEvent>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitSelectOption({
|
||||||
|
option,
|
||||||
|
focus,
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
}: UiKitSelectOptionProps) {
|
||||||
|
let localClassName = [style.ui_kit_select_option];
|
||||||
|
if (className) localClassName.push(className);
|
||||||
|
if (focus) localClassName.push(style.ui_kit_select_option_focus);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
className={localClassName.join(' ')}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{option.title}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default UiKitSelectOption;
|
74
src/ts/components/CustomSelect/components/Search.tsx
Normal file
74
src/ts/components/CustomSelect/components/Search.tsx
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
import { CLOSE_DELAY } from '../helpers/constants';
|
||||||
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
|
function getKeyCode(key?: string): string {
|
||||||
|
return {
|
||||||
|
ArrowUp: 'up',
|
||||||
|
ArrowDown: 'down',
|
||||||
|
Enter: 'enter',
|
||||||
|
}[key || ''] || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UiKitSelectSearchProps {
|
||||||
|
value: string;
|
||||||
|
placeholder?: string;
|
||||||
|
className?: string;
|
||||||
|
onClose: Function;
|
||||||
|
onChange: Function;
|
||||||
|
onKeyDown: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitSelectSearch({
|
||||||
|
value,
|
||||||
|
placeholder,
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
|
onClose,
|
||||||
|
onKeyDown,
|
||||||
|
}: UiKitSelectSearchProps) {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const [timer, setTimer] = useState<any>(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
// @ts-ignore
|
||||||
|
if (ref?.current) ref.current.focus();
|
||||||
|
}, CLOSE_DELAY);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<input
|
||||||
|
ref={ref}
|
||||||
|
type="text"
|
||||||
|
value={value}
|
||||||
|
placeholder={placeholder}
|
||||||
|
className={`${style.ui_kit_select_search} ${className || ''}`}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
onChange(event.target.value);
|
||||||
|
}}
|
||||||
|
onBlur={() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
const timerId = setTimeout(() => {
|
||||||
|
onClose();
|
||||||
|
}, CLOSE_DELAY);
|
||||||
|
setTimer(timerId);
|
||||||
|
}}
|
||||||
|
onFocus={() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}}
|
||||||
|
onKeyDown={() => {
|
||||||
|
// onKeyDown(getKeyCode(event.key));
|
||||||
|
}}
|
||||||
|
onKeyUp={(event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
onKeyDown(getKeyCode(event.key));
|
||||||
|
// onKeyDown('');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default UiKitSelectSearch;
|
28
src/ts/components/CustomSelect/components/Value.tsx
Normal file
28
src/ts/components/CustomSelect/components/Value.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
|
interface UiKitSelectValueProps {
|
||||||
|
value: any;
|
||||||
|
options: any;
|
||||||
|
className?: string;
|
||||||
|
onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitSelectValue({
|
||||||
|
value,
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
}: UiKitSelectValueProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${style.ui_kit_select_value} ${className || ''}`}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default UiKitSelectValue;
|
1
src/ts/components/CustomSelect/helpers/constants.ts
Normal file
1
src/ts/components/CustomSelect/helpers/constants.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export const CLOSE_DELAY = 250;
|
49
src/ts/components/CustomSelect/helpers/index.ts
Normal file
49
src/ts/components/CustomSelect/helpers/index.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
function getStringFromObject(value: any) {
|
||||||
|
return value?.title
|
||||||
|
|| value?.name
|
||||||
|
|| value?.label
|
||||||
|
|| value?.description
|
||||||
|
|| value?.value
|
||||||
|
|| value?.id
|
||||||
|
|| value?.uuid
|
||||||
|
|| value?.key
|
||||||
|
|| JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIdFromObject(value: any, index: number) {
|
||||||
|
return value?.id
|
||||||
|
?? value?.uuid
|
||||||
|
?? value?.key
|
||||||
|
?? index
|
||||||
|
?? getStringFromObject(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValue(
|
||||||
|
value: any,
|
||||||
|
formatter: (a: any, i?: number) => string,
|
||||||
|
) {
|
||||||
|
const type = typeof value;
|
||||||
|
if (type === 'boolean') return value ? 'yes' : 'no';
|
||||||
|
if (type === 'number' || type === 'string') return value;
|
||||||
|
if (!value) return '';
|
||||||
|
|
||||||
|
return Array.isArray(value)
|
||||||
|
? value.map(formatter).join(', ')
|
||||||
|
: formatter(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTitle(value: any) {
|
||||||
|
return getValue(value, getStringFromObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getId(value: any, index: number) {
|
||||||
|
return getValue(value, (v: any) => getIdFromObject(v, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOption(value: any, index: number) {
|
||||||
|
return {
|
||||||
|
id: getId(value, index),
|
||||||
|
title: getTitle(value),
|
||||||
|
source: value,
|
||||||
|
};
|
||||||
|
}
|
78
src/ts/components/CustomSelect/index.tsx
Normal file
78
src/ts/components/CustomSelect/index.tsx
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import UiKitSelectValue from './components/Value';
|
||||||
|
import UiKitSelectSearch from './components/Search';
|
||||||
|
import UiKitSelectList from './components/List';
|
||||||
|
import { getOption, getTitle } from './helpers';
|
||||||
|
|
||||||
|
import style from './styles/index.module.scss';
|
||||||
|
|
||||||
|
interface UiKitSelectProps {
|
||||||
|
value: any;
|
||||||
|
options: any;
|
||||||
|
className?: string;
|
||||||
|
onChange?: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitSelect({
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
className,
|
||||||
|
onChange,
|
||||||
|
}: UiKitSelectProps) {
|
||||||
|
const [openSearch, setOpenSearch] = useState<boolean>(false);
|
||||||
|
const [search, setSearch] = useState<string>('');
|
||||||
|
const [keyCode, setKeyCode] = useState<string>('');
|
||||||
|
|
||||||
|
const formattedOptions = useMemo(() => options?.map(getOption) || [], [options]);
|
||||||
|
const formattedValue = useMemo(() => {
|
||||||
|
const selectedOption = options.find((option: any) => option.id === value);
|
||||||
|
return getTitle(selectedOption) || getTitle(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${style.ui_kit_select_container} ${className || ''}`}>
|
||||||
|
{!openSearch ? (
|
||||||
|
<UiKitSelectValue
|
||||||
|
value={formattedValue}
|
||||||
|
options={formattedOptions}
|
||||||
|
className={className}
|
||||||
|
onClick={() => setOpenSearch(true)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{openSearch ? (
|
||||||
|
<UiKitSelectSearch
|
||||||
|
value={search}
|
||||||
|
placeholder={formattedValue}
|
||||||
|
className={className}
|
||||||
|
onChange={setSearch}
|
||||||
|
onKeyDown={setKeyCode}
|
||||||
|
onClose={() => {
|
||||||
|
setSearch('');
|
||||||
|
setOpenSearch(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{openSearch ? (
|
||||||
|
<UiKitSelectList
|
||||||
|
value={value}
|
||||||
|
options={formattedOptions}
|
||||||
|
search={search}
|
||||||
|
keyCode={keyCode}
|
||||||
|
setKeyCode={setKeyCode}
|
||||||
|
className={className}
|
||||||
|
onClick={(selected: any) => {
|
||||||
|
setSearch('');
|
||||||
|
setOpenSearch(false);
|
||||||
|
if (onChange) onChange(selected?.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default UiKitSelect;
|
67
src/ts/components/CustomSelect/styles/index.module.scss
Normal file
67
src/ts/components/CustomSelect/styles/index.module.scss
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.ui_kit_select {
|
||||||
|
&_value,
|
||||||
|
&_search,
|
||||||
|
&_option {
|
||||||
|
font-size: var(--font-s);
|
||||||
|
font-weight: 100;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 42px;
|
||||||
|
padding: 0 var(--space-l);
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
line-height: 42px;
|
||||||
|
text-align: left;
|
||||||
|
box-sizing: border-box;
|
||||||
|
vertical-align: top;
|
||||||
|
outline-color: transparent;
|
||||||
|
|
||||||
|
border-radius: var(--border-radius-s);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
color: var(--color-black);
|
||||||
|
background-color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_list {
|
||||||
|
position: absolute;
|
||||||
|
top: 45px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
max-height: 300px;
|
||||||
|
padding: var(--space-xxs) 0;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
border-radius: var(--border-radius-s);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
box-shadow: 0 0 5px var(--color-border);
|
||||||
|
background-color: var(--color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_option {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&_focus,
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui_kit_select_option + .ui_kit_select_option {
|
||||||
|
border-top: 1px solid var(--color-border);
|
||||||
|
}
|
69
src/ts/components/DataView/store/index.ts
Normal file
69
src/ts/components/DataView/store/index.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { observable, action, makeObservable } from 'mobx';
|
||||||
|
|
||||||
|
class DataViewStore {
|
||||||
|
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 dataViewStore = new DataViewStore();
|
||||||
|
|
||||||
|
export default dataViewStore;
|
52
src/ts/components/UiKit/components/Checkbox.tsx
Normal file
52
src/ts/components/UiKit/components/Checkbox.tsx
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import Wrapper, { IUiKitWrapperProps } from './Wrapper';
|
||||||
|
import style from '../styles/checkbox.module.scss';
|
||||||
|
|
||||||
|
interface IUiKitCheckboxProps extends IUiKitWrapperProps {
|
||||||
|
value: any;
|
||||||
|
onChange: Function;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UiKitCheckbox({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
help,
|
||||||
|
error,
|
||||||
|
className,
|
||||||
|
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
}: IUiKitCheckboxProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const id = `checkbox-${Math.ceil(Math.random() * 10000)}`;
|
||||||
|
return (
|
||||||
|
<Wrapper
|
||||||
|
description={description}
|
||||||
|
help={help}
|
||||||
|
error={error}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
<div className={style.ui_kit_checkbox}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={id}
|
||||||
|
checked={!!value}
|
||||||
|
className={style.ui_kit_checkbox_box}
|
||||||
|
onChange={() => {
|
||||||
|
onChange(!value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor={id}
|
||||||
|
className={style.ui_kit_checkbox_title}
|
||||||
|
>
|
||||||
|
{t(title || '')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UiKitCheckbox;
|
35
src/ts/components/UiKit/styles/checkbox.module.scss
Normal file
35
src/ts/components/UiKit/styles/checkbox.module.scss
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.ui_kit_checkbox {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
padding: 0 0 0 32px;
|
||||||
|
|
||||||
|
&_box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
width: var(--space-xl);
|
||||||
|
height: var(--space-xl);
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: var(--border-radius-s);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
&_title {
|
||||||
|
font-size: var(--font-s);
|
||||||
|
font-weight: 100;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
padding: var(--space-xxxs) 0 0;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: normal;
|
||||||
|
|
||||||
|
color: var(--color-black);
|
||||||
|
}
|
||||||
|
}
|
21
src/ts/helpers/Depersonalized/FakeName.ts
Normal file
21
src/ts/helpers/Depersonalized/FakeName.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import IHashMap from 'ts/interfaces/HashMap';
|
||||||
|
|
||||||
|
export default class FakeName {
|
||||||
|
refOldNewName: IHashMap<string> = {};
|
||||||
|
|
||||||
|
dictionary: string[] = [];
|
||||||
|
|
||||||
|
index: number = 0;
|
||||||
|
|
||||||
|
constructor(dictionary: string[]) {
|
||||||
|
this.dictionary = dictionary;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(name: string) {
|
||||||
|
if (!this.refOldNewName[name]) {
|
||||||
|
this.refOldNewName[name] = this.dictionary[this.index] || `${Math.random()}`;
|
||||||
|
this.index += 1;
|
||||||
|
}
|
||||||
|
return this.refOldNewName[name];
|
||||||
|
}
|
||||||
|
}
|
111
src/ts/helpers/Depersonalized/constants.ts
Normal file
111
src/ts/helpers/Depersonalized/constants.ts
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
export const FAKE_AUTHORS = [
|
||||||
|
'Fyodor Dostoevsky',
|
||||||
|
'Dante Alighieri',
|
||||||
|
'Lev Tolstoy',
|
||||||
|
'Victor Hugo',
|
||||||
|
'William Shakespeare',
|
||||||
|
'Johann Wolfgang von Goethe',
|
||||||
|
'Miguel de Cervantes y Saavedra',
|
||||||
|
'Italo Calvino',
|
||||||
|
'Stendhal',
|
||||||
|
'Charles Baudelaire',
|
||||||
|
'Marcel Proust',
|
||||||
|
'Giovanni Boccaccio',
|
||||||
|
'Alexander Pushkin',
|
||||||
|
'Jalaluddin Muhammad Rumi',
|
||||||
|
'Franz Kafka',
|
||||||
|
'Anton Chekhov',
|
||||||
|
'Gabriel García Márquez',
|
||||||
|
'Umberto Eco',
|
||||||
|
'J.R.R. Tolkien',
|
||||||
|
'William Faulkner',
|
||||||
|
'Aesop',
|
||||||
|
'Arthur Rimbaud',
|
||||||
|
'Aristophanes',
|
||||||
|
'Ivan Turgenev',
|
||||||
|
'Sophocles',
|
||||||
|
'Molière',
|
||||||
|
'Charles Dickens',
|
||||||
|
'Maxim Gorky',
|
||||||
|
'George Orwell',
|
||||||
|
'Edgar Allan Poe',
|
||||||
|
'Publius Vergilius Maro',
|
||||||
|
'Julio Cortázar',
|
||||||
|
'Nazim Hikmet',
|
||||||
|
'Oscar Wilde',
|
||||||
|
'Jean de La Fontaine',
|
||||||
|
'Rainer Maria Rilke',
|
||||||
|
'Lord Byron',
|
||||||
|
'Hans Christian Andersen',
|
||||||
|
'Thomas Mann',
|
||||||
|
'Alexandre Dumas',
|
||||||
|
'James Joyce',
|
||||||
|
'Louis-Ferdinand Céline',
|
||||||
|
'Boris Pasternak',
|
||||||
|
'Federico García Lorca',
|
||||||
|
'Pablo Neruda',
|
||||||
|
'Borges',
|
||||||
|
'Beaumarchais',
|
||||||
|
'Naguib Mahfouz',
|
||||||
|
'Ursula K. Le Guin',
|
||||||
|
'Nikolay Gogol',
|
||||||
|
'Honoré de Balzac',
|
||||||
|
'Ernest Hemingway',
|
||||||
|
'Neil Gaiman',
|
||||||
|
'Jean Racine',
|
||||||
|
'Albert Camus',
|
||||||
|
'Jean-Paul Sartre',
|
||||||
|
'Chingiz Aitmatov',
|
||||||
|
'John Steinbeck',
|
||||||
|
'Milan Kundera',
|
||||||
|
'Jules Verne',
|
||||||
|
'Mark Twain',
|
||||||
|
'Francois Rabelais',
|
||||||
|
'Yasar Kemal',
|
||||||
|
'George Bernard Shaw',
|
||||||
|
'Arthur Conan Doyle',
|
||||||
|
'Jane Austen',
|
||||||
|
'Geoffrey Chaucer',
|
||||||
|
'Antoine de Saint-Exupéry',
|
||||||
|
'Erich Maria Remarque',
|
||||||
|
'J.D. Salinger',
|
||||||
|
'Virginia Woolf',
|
||||||
|
'Louis Aragon',
|
||||||
|
'Herman Melville',
|
||||||
|
'Alphonse Daudet',
|
||||||
|
'Mikhail Sholokhov',
|
||||||
|
'Stefan Zweig',
|
||||||
|
'José Saramago',
|
||||||
|
'Bertolt Brecht',
|
||||||
|
'Mario Vargas Llosa',
|
||||||
|
'T.S. Eliot',
|
||||||
|
'Guy de Maupassant',
|
||||||
|
'John Keats',
|
||||||
|
'Sabahattin Ali',
|
||||||
|
'Ahmet Hamdi Tanpinar',
|
||||||
|
'John Fante',
|
||||||
|
'Henri-Frédéric Blanc',
|
||||||
|
'Isaac Asimov',
|
||||||
|
'Fitzgerald Scott',
|
||||||
|
'J.M. Coetzee',
|
||||||
|
'Kazuo Ishiguro',
|
||||||
|
'Hermann Hesse',
|
||||||
|
'Robert Louis Stevenson',
|
||||||
|
'Salman Rushdie',
|
||||||
|
'Mario Vargas Llosa',
|
||||||
|
'Aldous Huxley',
|
||||||
|
'Paul Valéry',
|
||||||
|
'Thomas Pynchon',
|
||||||
|
'H.P. Lovecraft',
|
||||||
|
'Haruki Murakami',
|
||||||
|
'Nikos Kazantzakis',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const FAKE_EMAILS = FAKE_AUTHORS
|
||||||
|
.map((name: string, index: number) => (
|
||||||
|
name.replace(/([\s.]+)|([^A-Za-z]+)/gim, '-').toLowerCase() + index + '@yahoo.com'
|
||||||
|
));
|
||||||
|
|
||||||
|
export const FAKE_TASK_PREFIXES = 'axeurtyqwpsdfghjklzcvbnm'
|
||||||
|
.split('')
|
||||||
|
.map((symbol) => (new Array(5)).fill(symbol.toUpperCase()).join(''));
|
60
src/ts/helpers/Depersonalized/index.ts
Normal file
60
src/ts/helpers/Depersonalized/index.ts
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import ICommit, { ISystemCommit } from 'ts/interfaces/Commit';
|
||||||
|
|
||||||
|
import {
|
||||||
|
FAKE_AUTHORS,
|
||||||
|
FAKE_EMAILS,
|
||||||
|
FAKE_TASK_PREFIXES,
|
||||||
|
} from './constants';
|
||||||
|
import FakeName from './FakeName';
|
||||||
|
|
||||||
|
export default class Depersonalized {
|
||||||
|
fakeName: any = null;
|
||||||
|
|
||||||
|
fakeEmail: any = null;
|
||||||
|
|
||||||
|
fakeTaskPrefix: any = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.fakeName = new FakeName(FAKE_AUTHORS);
|
||||||
|
this.fakeEmail = new FakeName(FAKE_EMAILS);
|
||||||
|
this.fakeTaskPrefix = new FakeName(FAKE_TASK_PREFIXES);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCommit(commit: ICommit | ISystemCommit): ICommit | ISystemCommit {
|
||||||
|
const author = this.fakeName.get(commit.author);
|
||||||
|
const email = this.fakeEmail.get(commit.author);
|
||||||
|
|
||||||
|
if (!commit.task) {
|
||||||
|
return {
|
||||||
|
...commit,
|
||||||
|
author,
|
||||||
|
email,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const taskPrefix = commit.task.split(/[-_\s:#=]+/gim).shift() || '';
|
||||||
|
const newTaskPrefix = this.fakeTaskPrefix.get(taskPrefix);
|
||||||
|
const task = commit.task.replace(taskPrefix, newTaskPrefix);
|
||||||
|
const message = commit.message.replace(taskPrefix, newTaskPrefix);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const branch = commit.branch // @ts-ignore
|
||||||
|
? commit.branch.replace(taskPrefix, newTaskPrefix)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const toBranch = commit.toBranch// @ts-ignore
|
||||||
|
? commit.toBranch.replace(taskPrefix, newTaskPrefix)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...commit,
|
||||||
|
task,
|
||||||
|
message,
|
||||||
|
author,
|
||||||
|
email,
|
||||||
|
branch,
|
||||||
|
toBranch,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,9 +3,11 @@ import { observer } from 'mobx-react-lite';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import InputString from 'ts/components/UiKit/components/InputString';
|
import InputString from 'ts/components/UiKit/components/InputString';
|
||||||
import Select from 'ts/components/UiKit/components/Select';
|
import UiKitSelect from 'ts/components/UiKit/components/Select';
|
||||||
|
import UiKitCheckbox from 'ts/components/UiKit/components/Checkbox';
|
||||||
import PageBox from 'ts/components/Page/Box';
|
import PageBox from 'ts/components/Page/Box';
|
||||||
import Title from 'ts/components/Title';
|
import Title from 'ts/components/Title';
|
||||||
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
import localization from 'ts/helpers/Localization';
|
import localization from 'ts/helpers/Localization';
|
||||||
import { applicationHasCustom } from 'ts/helpers/RPC';
|
import { applicationHasCustom } from 'ts/helpers/RPC';
|
||||||
|
|
||||||
|
@ -32,7 +34,7 @@ const Common = observer((): React.ReactElement | null => {
|
||||||
applicationHasCustom.title = true;
|
applicationHasCustom.title = true;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Select
|
<UiKitSelect
|
||||||
title="page.settings.document.language"
|
title="page.settings.document.language"
|
||||||
value={language}
|
value={language}
|
||||||
options={[
|
options={[
|
||||||
|
@ -50,6 +52,13 @@ const Common = observer((): React.ReactElement | null => {
|
||||||
setLanguage(id);
|
setLanguage(id);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<UiKitCheckbox
|
||||||
|
value={dataGripStore.isDepersonalized}
|
||||||
|
title="page.settings.document.depersonalize"
|
||||||
|
onChange={() => {
|
||||||
|
dataGripStore.depersonalized(!dataGripStore.isDepersonalized);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</PageBox>
|
</PageBox>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import getTitle from 'ts/helpers/Title';
|
||||||
|
|
||||||
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
|
import { setDefaultValues } from 'ts/pages/Settings/helpers/getEmptySettings';
|
||||||
import { applicationHasCustom } from 'ts/helpers/RPC';
|
import { applicationHasCustom } from 'ts/helpers/RPC';
|
||||||
|
import Depersonalized from 'ts/helpers/Depersonalized';
|
||||||
|
|
||||||
import filtersInHeaderStore from './FiltersInHeader';
|
import filtersInHeaderStore from './FiltersInHeader';
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ interface IDataGripStore {
|
||||||
dataGrip: any;
|
dataGrip: any;
|
||||||
fileGrip: any;
|
fileGrip: any;
|
||||||
status: DataParseStatusEnum;
|
status: DataParseStatusEnum;
|
||||||
|
isDepersonalized: boolean;
|
||||||
setCommits: (log?: string[]) => void;
|
setCommits: (log?: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +38,8 @@ class DataGripStore implements IDataGripStore {
|
||||||
|
|
||||||
hash: number = 0;
|
hash: number = 0;
|
||||||
|
|
||||||
|
isDepersonalized: boolean = false;
|
||||||
|
|
||||||
status: DataParseStatusEnum = DataParseStatusEnum.PROCESSING;
|
status: DataParseStatusEnum = DataParseStatusEnum.PROCESSING;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -43,8 +47,10 @@ class DataGripStore implements IDataGripStore {
|
||||||
commits: observable,
|
commits: observable,
|
||||||
dataGrip: observable,
|
dataGrip: observable,
|
||||||
hash: observable,
|
hash: observable,
|
||||||
|
isDepersonalized: observable,
|
||||||
status: observable,
|
status: observable,
|
||||||
setCommits: action,
|
setCommits: action,
|
||||||
|
depersonalized: action,
|
||||||
updateStatistic: action,
|
updateStatistic: action,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -88,15 +94,31 @@ class DataGripStore implements IDataGripStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
depersonalized(status?: boolean) {
|
||||||
|
this.isDepersonalized = !!status;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updateStatistic();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
updateStatistic() {
|
updateStatistic() {
|
||||||
dataGrip.clear();
|
dataGrip.clear();
|
||||||
fileGrip.clear();
|
fileGrip.clear();
|
||||||
|
|
||||||
|
const depersonalized = new Depersonalized();
|
||||||
this.commits.forEach((commit: ICommit | ISystemCommit) => {
|
this.commits.forEach((commit: ICommit | ISystemCommit) => {
|
||||||
if (commit.timestamp < filtersInHeaderStore.from
|
if (commit.timestamp < filtersInHeaderStore.from
|
||||||
|| commit.timestamp > filtersInHeaderStore.to) return;
|
|| commit.timestamp > filtersInHeaderStore.to) return;
|
||||||
dataGrip.addCommit(commit);
|
|
||||||
fileGrip.addCommit(commit);
|
const localCommit = this.isDepersonalized
|
||||||
|
? depersonalized.getCommit(commit)
|
||||||
|
: commit;
|
||||||
|
|
||||||
|
dataGrip.addCommit(localCommit);
|
||||||
|
fileGrip.addCommit(localCommit);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(depersonalized.fakeTaskPrefix);
|
||||||
fileGrip.updateTotalInfo();
|
fileGrip.updateTotalInfo();
|
||||||
dataGrip.updateTotalInfo();
|
dataGrip.updateTotalInfo();
|
||||||
achievements.updateByGrip(dataGrip, fileGrip);
|
achievements.updateByGrip(dataGrip, fileGrip);
|
||||||
|
|
71
src/ts/store/FiltersInHeader.ts
Normal file
71
src/ts/store/FiltersInHeader.ts
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { makeObservable, observable, action } from 'mobx';
|
||||||
|
import { ONE_DAY } from 'ts/helpers/formatter';
|
||||||
|
|
||||||
|
import ICommit from '../interfaces/Commit';
|
||||||
|
|
||||||
|
interface IFiltersInHeaderStore {
|
||||||
|
defaultFrom: string;
|
||||||
|
defaultTo: string;
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
|
||||||
|
updateByCommits: (firstCommit: ICommit, lastCommit: ICommit) => void,
|
||||||
|
setFilterByDateType: (type: string) => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
class FiltersInHeaderStore implements IFiltersInHeaderStore {
|
||||||
|
defaultFrom: string = ''; // "2021-02-09"
|
||||||
|
|
||||||
|
defaultTo: string = ''; // "2021-02-09"
|
||||||
|
|
||||||
|
from: string = ''; // "2021-02-09"
|
||||||
|
|
||||||
|
to: string = ''; // "2021-02-09"
|
||||||
|
|
||||||
|
lastCommitTime: number = 0; // 1612828800000
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
makeObservable(this, {
|
||||||
|
defaultFrom: observable,
|
||||||
|
defaultTo: observable,
|
||||||
|
from: observable,
|
||||||
|
to: observable,
|
||||||
|
|
||||||
|
updateByCommits: action,
|
||||||
|
setFilterByDateType: action,
|
||||||
|
updateProperty: action,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateByCommits(firstCommit: ICommit, lastCommit: ICommit) {
|
||||||
|
this.defaultFrom = firstCommit.timestamp;
|
||||||
|
this.defaultTo = lastCommit.timestamp;
|
||||||
|
this.from = this.defaultFrom;
|
||||||
|
this.to = this.defaultTo;
|
||||||
|
this.lastCommitTime = (new Date(this.defaultTo)).getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilterByDateType(type: string) {
|
||||||
|
const count = {
|
||||||
|
year: 365,
|
||||||
|
halfYear: 183,
|
||||||
|
month: 30,
|
||||||
|
week: 7,
|
||||||
|
day: 1,
|
||||||
|
}[type];
|
||||||
|
|
||||||
|
this.from = count
|
||||||
|
? (new Date(this.lastCommitTime - ONE_DAY * count)).toISOString().split('T')[0]
|
||||||
|
: this.defaultFrom;
|
||||||
|
|
||||||
|
this.to = this.defaultTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProperty(propertyName: string, value?: any) {
|
||||||
|
this[propertyName] = value ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const filtersInHeaderStore = new FiltersInHeaderStore();
|
||||||
|
|
||||||
|
export default filtersInHeaderStore;
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Настройки отображения
|
§ page.settings.document.title: Настройки отображения
|
||||||
§ page.settings.document.name: Заголовок страницы
|
§ page.settings.document.name: Заголовок страницы
|
||||||
§ page.settings.document.language: Язык интерфейса
|
§ page.settings.document.language: Язык интерфейса
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Префиксы ссылок
|
§ page.settings.links.title: Префиксы ссылок
|
||||||
§ page.settings.links.task: Для номеров задач
|
§ page.settings.links.task: Для номеров задач
|
||||||
§ page.settings.links.pr: Для PR
|
§ page.settings.links.pr: Для PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Настройки отображения
|
§ page.settings.document.title: Настройки отображения
|
||||||
§ page.settings.document.name: Заголовок страницы
|
§ page.settings.document.name: Заголовок страницы
|
||||||
§ page.settings.document.language: Язык интерфейса
|
§ page.settings.document.language: Язык интерфейса
|
||||||
|
§ page.settings.document.depersonalize: Деперсонализировать данные
|
||||||
§ page.settings.links.title: Префиксы ссылок
|
§ page.settings.links.title: Префиксы ссылок
|
||||||
§ page.settings.links.task: Для номеров задач
|
§ page.settings.links.task: Для номеров задач
|
||||||
§ page.settings.links.pr: Для PR
|
§ page.settings.links.pr: Для PR
|
||||||
|
|
|
@ -2,6 +2,7 @@ export default `
|
||||||
§ page.settings.document.title: Display settings
|
§ page.settings.document.title: Display settings
|
||||||
§ page.settings.document.name: Page title
|
§ page.settings.document.name: Page title
|
||||||
§ page.settings.document.language: Interface language
|
§ page.settings.document.language: Interface language
|
||||||
|
§ page.settings.document.depersonalize: Depersonalize the data
|
||||||
§ page.settings.links.title: Link prefixes
|
§ page.settings.links.title: Link prefixes
|
||||||
§ page.settings.links.task: For task numbers
|
§ page.settings.links.task: For task numbers
|
||||||
§ page.settings.links.pr: For PR
|
§ page.settings.links.pr: For PR
|
||||||
|
|
Loading…
Reference in a new issue