mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
JIRA-1234 fix(fox): cocs
This commit is contained in:
parent
c7f3a4768c
commit
81a605de6e
|
@ -1,17 +1,19 @@
|
|||
{
|
||||
"files": {
|
||||
"main.css": "./static/css/main.98731101.css",
|
||||
"main.js": "./static/js/main.c257580d.js",
|
||||
"main.css": "./static/css/main.372cdf70.css",
|
||||
"main.js": "./static/js/main.bc524aaf.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",
|
||||
"main.98731101.css.map": "./static/css/main.98731101.css.map",
|
||||
"main.c257580d.js.map": "./static/js/main.c257580d.js.map"
|
||||
"static/media/arrow_left.svg": "./static/media/arrow_left.d053cbdc58069cfc01de.svg",
|
||||
"static/media/arrow_right.svg": "./static/media/arrow_right.7caaf9eb44d9210be019.svg",
|
||||
"main.372cdf70.css.map": "./static/css/main.372cdf70.css.map",
|
||||
"main.bc524aaf.js.map": "./static/js/main.bc524aaf.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.98731101.css",
|
||||
"static/js/main.c257580d.js"
|
||||
"static/css/main.372cdf70.css",
|
||||
"static/js/main.bc524aaf.js"
|
||||
]
|
||||
}
|
Binary file not shown.
Binary file not shown.
3
build/assets/menu/arrow_left.svg
Normal file
3
build/assets/menu/arrow_left.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 198 B |
3
build/assets/menu/arrow_right.svg
Normal file
3
build/assets/menu/arrow_right.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 188 B |
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="ru"><head><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1,user-scalable=no,maximum-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Cache-Control" content="no-cache"><meta http-equiv="cleartype" content="on"><meta name="HandheldFriendly" content="True"><meta name="format-detection" content="telephone=no"><meta name="format-detection" content="address=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script type="text/javascript">var report=[]</script><script src="/log.txt"></script><script src="./log.txt"></script><script src="../log.txt"></script><script src="./log-0.txt"></script><script src="./log-1.txt"></script><script src="./log-2.txt"></script><script src="./log-3.txt"></script><script src="./log-4.txt"></script><script src="./log-5.txt"></script><script src="./log-6.txt"></script><script src="./report/log-0.txt"></script><script src="./report/log-1.txt"></script><script src="./report/log-2.txt"></script><script src="./report/log-3.txt"></script><script src="./report/log-4.txt"></script><script src="./report/log-5.txt"></script><script src="./report/log-6.txt"></script><link rel="icon" href="./favicon.svg"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><title>Git статистика</title><meta name="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="keywords" content="git, статистика, аудит, история, log, мониторинг, контроль сотрудников"><meta name="author" content="Bakhirev Aleksei"><meta name="copyright" content="(c) Bakhirev Aleksei"><meta http-equiv="Reply-to" content="alexey-bakhirev@yandex.ru"><meta name="application-name" content="GIT Статистика"><meta name="msapplication-tooltip" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:title" content="GIT Статистика"><meta property="og:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta property="og:image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta property="og:site_name" content="Assayo"><meta property="og:url" content="http://assayo.jp/"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="GIT Статистика"><meta name="twitter:description" content="Простой и быстрый отчёт по истории коммитов в git."><meta name="twitter:creator" content="Bakhirev Aleksei"><meta name="twitter:image:src" content="http://assayo.jp/assets/seo/custom_icon_256.png"><meta name="twitter:domain" content="assayo.jp"><meta name="twitter:site" content="assayo.jp"><meta itemprop="name" content="GIT Статистика"><meta itemprop="description" content="Простой и быстрый отчёт по истории коммитов в git."><meta itemprop="image" content="http://assayo.jp/assets/seo/custom_icon_256.png"><script defer="defer" src="./static/js/main.c257580d.js"></script><link href="./static/css/main.98731101.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="en"><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.bc524aaf.js"></script><link href="./static/css/main.372cdf70.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
2
build/static/css/main.372cdf70.css
Normal file
2
build/static/css/main.372cdf70.css
Normal file
File diff suppressed because one or more lines are too long
1
build/static/css/main.372cdf70.css.map
Normal file
1
build/static/css/main.372cdf70.css.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
build/static/js/main.bc524aaf.js
Normal file
3
build/static/js/main.bc524aaf.js
Normal file
File diff suppressed because one or more lines are too long
1
build/static/js/main.bc524aaf.js.map
Normal file
1
build/static/js/main.bc524aaf.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
build/static/media/arrow_left.d053cbdc58069cfc01de.svg
Normal file
3
build/static/media/arrow_left.d053cbdc58069cfc01de.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 198 B |
3
build/static/media/arrow_right.7caaf9eb44d9210be019.svg
Normal file
3
build/static/media/arrow_right.7caaf9eb44d9210be019.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<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>
|
After Width: | Height: | Size: 188 B |
|
@ -25,7 +25,7 @@ const Header = observer(({
|
|||
<img
|
||||
id={`${id}-close`}
|
||||
src="./assets/close.svg"
|
||||
className={`${style.modal_window_close} ${className || ''}`}
|
||||
className={style.modal_window_close}
|
||||
onClick={(event: any) => {
|
||||
event.stopPropagation();
|
||||
onClose();
|
||||
|
|
|
@ -28,7 +28,7 @@ function Modal({
|
|||
return ReactDOM.createPortal((
|
||||
<div
|
||||
id={`${id}-wrapper`}
|
||||
className={`${style.modal_window_wrapper || ''} ${className || ''}`}
|
||||
className={`${style.modal_window_wrapper || ''}`}
|
||||
onClick={(event: any) => {
|
||||
event.stopPropagation();
|
||||
if (event.target?.id !== `${id}-wrapper`) return;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
import Description from 'ts/components/Description';
|
||||
import UiKitButton from 'ts/components/UiKit/components/Button';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import RECOMMENDATION_TYPES from 'ts/helpers/Recommendations/contstants';
|
||||
|
||||
import { getFormattedTitle, getDescriptionText } from '../helpers';
|
||||
import style from '../styles/card.module.scss';
|
||||
|
||||
function getClassName(recommendation?: any) {
|
||||
|
@ -16,59 +18,40 @@ function getClassName(recommendation?: any) {
|
|||
}[type || RECOMMENDATION_TYPES.INFO] ?? style.recommendations_card_fact;
|
||||
}
|
||||
|
||||
function getDescriptionText(recommendation?: any) {
|
||||
const descriptionArgs = recommendation?.arguments?.description;
|
||||
const { description } = recommendation;
|
||||
const list = Array.isArray(description)
|
||||
? description
|
||||
: [description];
|
||||
|
||||
return list.map((textId: string) => (
|
||||
localization.get(textId, descriptionArgs)
|
||||
)).join('\n');
|
||||
}
|
||||
|
||||
interface IRecommendationsProps {
|
||||
recommendation: any;
|
||||
onClick: Function;
|
||||
}
|
||||
|
||||
function Card({
|
||||
recommendation,
|
||||
onClick,
|
||||
}: IRecommendationsProps) {
|
||||
if (!recommendation) return null;
|
||||
|
||||
const { title } = recommendation;
|
||||
let formattedTitle = title || '';
|
||||
if (Array.isArray(title)) {
|
||||
formattedTitle = title.length > 1
|
||||
? `${title[0]} +${title.length - 1}`
|
||||
: title[0];
|
||||
}
|
||||
|
||||
const className = getClassName(recommendation);
|
||||
const title = getFormattedTitle(recommendation);
|
||||
const titleArgs = recommendation?.arguments?.title;
|
||||
const parts = getDescriptionText(recommendation).split('\n');
|
||||
const previewText = parts.shift();
|
||||
const mainText = parts.join('\n');
|
||||
|
||||
return (
|
||||
<div className={`${style.recommendations_card} ${className}`}>
|
||||
<div className={style.recommendations_card_wrapper}>
|
||||
<h5 className={style.recommendations_card_title}>
|
||||
<span className={style.recommendations_card_icon}></span>
|
||||
{localization.get(formattedTitle, titleArgs)}
|
||||
</h5>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={previewText || ''}
|
||||
/>
|
||||
<div className={style.recommendations_card_shortcut}>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={mainText || ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h5 className={style.recommendations_card_title}>
|
||||
<span className={style.recommendations_card_icon}></span>
|
||||
{localization.get(title, titleArgs)}
|
||||
</h5>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={previewText || ''}
|
||||
/>
|
||||
<UiKitButton
|
||||
type="link"
|
||||
className={style.recommendations_card_button}
|
||||
onClick={onClick}
|
||||
>
|
||||
Подробнее
|
||||
</UiKitButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
import React from 'react';
|
||||
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 { getFormattedTitle, getDescriptionText } from '../helpers';
|
||||
import recommendationStore from '../store/index';
|
||||
|
||||
import style from '../styles/modal.module.scss';
|
||||
|
||||
function getClassName(recommendation?: any) {
|
||||
const type = recommendation?.type;
|
||||
return {
|
||||
[RECOMMENDATION_TYPES.INFO]: style.recommendations_modal_info,
|
||||
[RECOMMENDATION_TYPES.FACT]: style.recommendations_modal_fact,
|
||||
[RECOMMENDATION_TYPES.WARNING]: style.recommendations_modal_warning,
|
||||
[RECOMMENDATION_TYPES.ALERT]: style.recommendations_modal_error,
|
||||
}[type || RECOMMENDATION_TYPES.INFO] ?? style.recommendations_modal_fact;
|
||||
}
|
||||
|
||||
const RecommendationDescription = observer(() => {
|
||||
const { recommendation } = recommendationStore;
|
||||
if (!recommendation) return null;
|
||||
|
||||
const title = getFormattedTitle(recommendation);
|
||||
const titleArgs = recommendation?.arguments?.title;
|
||||
const className = getClassName(recommendation);
|
||||
const parts = getDescriptionText(recommendation).split('\n');
|
||||
const subTitle = parts.shift();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className={`${className} ${style.recommendations_modal}`}
|
||||
onClose={() => {
|
||||
recommendationStore.close();
|
||||
}}
|
||||
>
|
||||
<Header className={style.recommendations_modal_header}>
|
||||
<span className={style.recommendations_modal_title}>
|
||||
{localization.get(title, titleArgs)}
|
||||
</span>
|
||||
<p className={style.recommendations_modal_sub_title}>
|
||||
{subTitle}
|
||||
</p>
|
||||
</Header>
|
||||
<Body>
|
||||
<Description
|
||||
className={style.recommendations_modal_description}
|
||||
text={parts}
|
||||
/>
|
||||
</Body>
|
||||
<Footer className={style.recommendations_modal_footer}>
|
||||
<UiKitButton
|
||||
type="slim"
|
||||
onClick={() => {
|
||||
recommendationStore.close();
|
||||
}}
|
||||
>
|
||||
{localization.get('page.print.modal.cancel')}
|
||||
</UiKitButton>
|
||||
</Footer>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default RecommendationDescription;
|
25
src/ts/components/Recommendations/helpers/index.tsx
Normal file
25
src/ts/components/Recommendations/helpers/index.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import localization from 'ts/helpers/Localization';
|
||||
|
||||
export function getFormattedTitle(recommendation: any) {
|
||||
const { title } = recommendation;
|
||||
|
||||
if (!Array.isArray(title)) {
|
||||
return title || '';
|
||||
}
|
||||
|
||||
return title.length > 1
|
||||
? `${title[0]} +${title.length - 1}`
|
||||
: title[0];
|
||||
}
|
||||
|
||||
export function getDescriptionText(recommendation?: any) {
|
||||
const { description } = recommendation;
|
||||
const descriptionArgs = recommendation?.arguments?.description;
|
||||
const list = Array.isArray(description)
|
||||
? description
|
||||
: [description];
|
||||
|
||||
return list.map((textId: string) => (
|
||||
localization.get(textId, descriptionArgs)
|
||||
)).join('\n');
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
import React, { useLayoutEffect, useRef, useState } from 'react';
|
||||
import React from 'react';
|
||||
|
||||
import Title from 'ts/components/Title';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
|
||||
import Card from './components/Card';
|
||||
import recommendationStore from './store/index';
|
||||
import style from './styles/index.module.scss';
|
||||
|
||||
interface IRecommendationsProps {
|
||||
|
@ -10,49 +14,30 @@ interface IRecommendationsProps {
|
|||
function Recommendations({
|
||||
recommendations,
|
||||
}: IRecommendationsProps) {
|
||||
const [maxCardsOnDisplay, setMaxCardsOnDisplay] = useState<number>(5);
|
||||
const [isOpen, setOpen] = useState<boolean>(false);
|
||||
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const width = ref?.current?.offsetWidth;
|
||||
const placeForCard = (width - 30) / (220 + 24);
|
||||
setMaxCardsOnDisplay(placeForCard);
|
||||
}, []);
|
||||
|
||||
const className = isOpen
|
||||
? style.recommendations_full
|
||||
: style.recommendations_short;
|
||||
|
||||
const children = (recommendations || [])
|
||||
const cards = (recommendations || [])
|
||||
.filter(item => item)
|
||||
.map((recommendation) => (
|
||||
<Card
|
||||
key={recommendation[1]}
|
||||
recommendation={recommendation}
|
||||
onClick={() => {
|
||||
recommendationStore.open(recommendation);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
const visibleChildren = children.slice(0, isOpen ? Infinity : maxCardsOnDisplay);
|
||||
|
||||
if (!children.length) return null;
|
||||
if (!cards.length) return null;
|
||||
|
||||
const title = localization.get('recommendations.title');
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={className}
|
||||
>
|
||||
{isOpen ? children : visibleChildren}
|
||||
{!isOpen && children.length > maxCardsOnDisplay && (
|
||||
<div
|
||||
className={style.more}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
»
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<>
|
||||
<Title title={title}/>
|
||||
<div className={style.recommendations_container}>
|
||||
{cards}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
30
src/ts/components/Recommendations/store/index.tsx
Normal file
30
src/ts/components/Recommendations/store/index.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { makeObservable, observable, action } from 'mobx';
|
||||
|
||||
export interface IRecommendationStore {
|
||||
open: Function;
|
||||
close: Function;
|
||||
}
|
||||
|
||||
class RecommendationStore implements IRecommendationStore {
|
||||
recommendation: any | null = null;
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
recommendation: observable,
|
||||
open: action,
|
||||
close: action,
|
||||
});
|
||||
}
|
||||
|
||||
open(recommendation: any) {
|
||||
this.recommendation = recommendation;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.recommendation = null;
|
||||
}
|
||||
}
|
||||
|
||||
const recommendationStore = new RecommendationStore();
|
||||
|
||||
export default recommendationStore;
|
|
@ -1,166 +1,98 @@
|
|||
@import '../../../../styles/variables';
|
||||
|
||||
.recommendations {
|
||||
&_short,
|
||||
&_full {
|
||||
position: relative;
|
||||
display: block;
|
||||
max-height: 108px;
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
&_full {
|
||||
max-height: none;
|
||||
}
|
||||
.recommendations_card {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
width: 220px;
|
||||
margin: 0 24px var(--space-l) 0;
|
||||
padding: var(--space-m) var(--space-l);
|
||||
|
||||
&_more,
|
||||
&_card {
|
||||
display: inline-block;
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
border-left-width: var(--space-s);
|
||||
border-radius: var(--border-radius-m);
|
||||
|
||||
&_title {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-xs);
|
||||
|
||||
display: block;
|
||||
width: 90%;
|
||||
padding: 0;
|
||||
margin: 0 0 var(--space-xs);
|
||||
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
|
||||
border-radius: var(--border-radius-m);
|
||||
background-color: white;
|
||||
text-decoration: none;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
&_more {
|
||||
&_icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
margin: 0 0 8px 0;
|
||||
text-align: center;
|
||||
line-height: 100px;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--color-border);
|
||||
color: #AAAAAA;
|
||||
top: var(--space-s);
|
||||
right: var(--space-s);
|
||||
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
&_card {
|
||||
position: relative;
|
||||
width: 220px;
|
||||
margin: 0 12px 16px 0;
|
||||
border-left: none;
|
||||
|
||||
&_wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: block;
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
padding: 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: var(--border-radius-m);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 8px solid var(--color-border);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&_icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
&_info {
|
||||
--color-temp-border: #97C2A9;
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #E3F8EC;
|
||||
--color-temp-title: #58866B;
|
||||
}
|
||||
|
||||
&_fact {
|
||||
--color-temp-border: var(--color-11);
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #EFF7FF;
|
||||
--color-temp-title: var(--color-first);
|
||||
}
|
||||
|
||||
&_warning {
|
||||
--color-temp-border: var(--color-21);
|
||||
--color-temp-icon: url('/assets/recommendations/warning.svg');
|
||||
--color-temp-bg: #FFF5F2;
|
||||
--color-temp-title: #E8B06D;
|
||||
}
|
||||
|
||||
&_error {
|
||||
--color-temp-border: var(--color-12);
|
||||
--color-temp-icon: url('/assets/recommendations/alert.svg');
|
||||
--color-temp-bg: #FFEFEE;
|
||||
--color-temp-title: #DD8B87;
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-xs);
|
||||
|
||||
display: block;
|
||||
padding: 2px 0 0 24px;
|
||||
margin: 0 auto 4px auto;
|
||||
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
vertical-align: bottom;
|
||||
color: var(--color-temp-title);
|
||||
}
|
||||
|
||||
&_wrapper {
|
||||
background-color: var(--color-temp-bg);
|
||||
border-left-color: var(--color-temp-border);
|
||||
}
|
||||
&_button {
|
||||
position: absolute;
|
||||
bottom: var(--space-xs);
|
||||
right: var(--space-s);
|
||||
}
|
||||
|
||||
&_info {
|
||||
--color-temp-border: #97C2A9;
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #E3F8EC;
|
||||
--color-temp-title: #58866B;
|
||||
}
|
||||
|
||||
&_fact {
|
||||
--color-temp-border: var(--color-11);
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #EFF7FF;
|
||||
--color-temp-title: var(--color-first);
|
||||
}
|
||||
|
||||
&_warning {
|
||||
--color-temp-border: var(--color-21);
|
||||
--color-temp-icon: url('/assets/recommendations/warning.svg');
|
||||
--color-temp-bg: #FFF5F2;
|
||||
--color-temp-title: #E8B06D;
|
||||
}
|
||||
|
||||
&_error {
|
||||
--color-temp-border: var(--color-12);
|
||||
--color-temp-icon: url('/assets/recommendations/alert.svg');
|
||||
--color-temp-bg: #FFEFEE;
|
||||
--color-temp-title: #DD8B87;
|
||||
}
|
||||
|
||||
&_title {
|
||||
color: var(--color-temp-title);
|
||||
}
|
||||
|
||||
&_icon {
|
||||
background-image: var(--color-temp-icon);
|
||||
}
|
||||
|
||||
&_button {
|
||||
color: var(--color-temp-title);
|
||||
}
|
||||
|
||||
background-color: var(--color-temp-bg);
|
||||
border-left-color: var(--color-temp-border);
|
||||
}
|
||||
|
||||
.recommendations_card:hover > .recommendations_card_wrapper {
|
||||
z-index: 2;
|
||||
width: 170%;
|
||||
max-height: 450px;
|
||||
box-shadow: 2px 2px 3px #999999;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.recommendations_card_wrapper::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.recommendations_card_wrapper::-webkit-scrollbar-thumb {
|
||||
background: #AAAAAA;
|
||||
}
|
||||
|
||||
.recommendations_title {
|
||||
color: var(--color-temp-border);
|
||||
}
|
||||
|
||||
.recommendations_card_icon {
|
||||
background-image: var(--color-temp-icon);
|
||||
}
|
||||
|
||||
.recommendations_card_shortcut {
|
||||
display: none;
|
||||
padding: 6px 0 0 0;
|
||||
margin: 6px 0 0 0;
|
||||
border-top: 1px solid var(--color-temp-border);
|
||||
}
|
||||
|
||||
.recommendations_card:hover .recommendations_card_shortcut {
|
||||
display: block;
|
||||
}
|
|
@ -1,27 +1,22 @@
|
|||
@import '../../../../styles/variables';
|
||||
@import 'styles/variables';
|
||||
|
||||
.recommendations_short,
|
||||
.recommendations_full {
|
||||
.recommendations_container {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0 0 12px 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
height: 8px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #AAAAAA;
|
||||
}
|
||||
}
|
||||
|
||||
.more {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
margin: 0 0 8px 0;
|
||||
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius-m);
|
||||
line-height: 100px;
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-black);
|
||||
background-color: white;
|
||||
}
|
64
src/ts/components/Recommendations/styles/modal.module.scss
Normal file
64
src/ts/components/Recommendations/styles/modal.module.scss
Normal file
|
@ -0,0 +1,64 @@
|
|||
@import 'styles/variables';
|
||||
|
||||
.recommendations_modal {
|
||||
&_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&_header {
|
||||
padding-bottom: var(--space-m);
|
||||
margin-bottom: var(--space-s);
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
&_footer {
|
||||
padding: var(--space-s) var(--space-xxl) var(--space-l) var(--space-xxl);
|
||||
}
|
||||
|
||||
&_sub_title {
|
||||
font-weight: 100;
|
||||
font-size: var(--font-s);
|
||||
margin: var(--space-xs) 0 0 0;
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
&_description {
|
||||
margin-bottom: var(--space-s);
|
||||
color: var(--color-black);
|
||||
}
|
||||
|
||||
&_info {
|
||||
--color-temp-border: #97C2A9;
|
||||
--color-temp-bg: #E3F8EC;
|
||||
--color-temp-title: #58866B;
|
||||
}
|
||||
|
||||
&_fact {
|
||||
--color-temp-border: var(--color-11);
|
||||
--color-temp-bg: #EFF7FF;
|
||||
--color-temp-title: var(--color-first);
|
||||
}
|
||||
|
||||
&_warning {
|
||||
--color-temp-border: var(--color-21);
|
||||
--color-temp-bg: #FFF5F2;
|
||||
--color-temp-title: #E8B06D;
|
||||
}
|
||||
|
||||
&_error {
|
||||
--color-temp-border: var(--color-12);
|
||||
--color-temp-bg: #FFEFEE;
|
||||
--color-temp-title: #DD8B87;
|
||||
}
|
||||
|
||||
&_header {
|
||||
border-bottom-color: var(--color-temp-border);
|
||||
}
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
border-left-width: var(--space-s);
|
||||
background-color: var(--color-temp-bg);
|
||||
border-left-color: var(--color-temp-border);
|
||||
}
|
||||
|
77
src/ts/components/RecommendationsOld/components/Card.tsx
Normal file
77
src/ts/components/RecommendationsOld/components/Card.tsx
Normal file
|
@ -0,0 +1,77 @@
|
|||
import React from 'react';
|
||||
|
||||
import Description from 'ts/components/Description';
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import RECOMMENDATION_TYPES from 'ts/helpers/Recommendations/contstants';
|
||||
|
||||
import style from '../styles/card.module.scss';
|
||||
|
||||
function getClassName(recommendation?: any) {
|
||||
const type = recommendation?.type;
|
||||
return {
|
||||
[RECOMMENDATION_TYPES.INFO]: style.recommendations_card_info,
|
||||
[RECOMMENDATION_TYPES.FACT]: style.recommendations_card_fact,
|
||||
[RECOMMENDATION_TYPES.WARNING]: style.recommendations_card_warning,
|
||||
[RECOMMENDATION_TYPES.ALERT]: style.recommendations_card_error,
|
||||
}[type || RECOMMENDATION_TYPES.INFO] ?? style.recommendations_card_fact;
|
||||
}
|
||||
|
||||
function getDescriptionText(recommendation?: any) {
|
||||
const descriptionArgs = recommendation?.arguments?.description;
|
||||
const { description } = recommendation;
|
||||
const list = Array.isArray(description)
|
||||
? description
|
||||
: [description];
|
||||
|
||||
return list.map((textId: string) => (
|
||||
localization.get(textId, descriptionArgs)
|
||||
)).join('\n');
|
||||
}
|
||||
|
||||
interface IRecommendationsProps {
|
||||
recommendation: any;
|
||||
}
|
||||
|
||||
function Card({
|
||||
recommendation,
|
||||
}: IRecommendationsProps) {
|
||||
if (!recommendation) return null;
|
||||
|
||||
const { title } = recommendation;
|
||||
let formattedTitle = title || '';
|
||||
if (Array.isArray(title)) {
|
||||
formattedTitle = title.length > 1
|
||||
? `${title[0]} +${title.length - 1}`
|
||||
: title[0];
|
||||
}
|
||||
|
||||
const className = getClassName(recommendation);
|
||||
const titleArgs = recommendation?.arguments?.title;
|
||||
const parts = getDescriptionText(recommendation).split('\n');
|
||||
const previewText = parts.shift();
|
||||
const mainText = parts.join('\n');
|
||||
|
||||
return (
|
||||
<div className={`${style.recommendations_card} ${className}`}>
|
||||
<div className={style.recommendations_card_wrapper}>
|
||||
<h5 className={style.recommendations_card_title}>
|
||||
<span className={style.recommendations_card_icon}></span>
|
||||
{localization.get(formattedTitle, titleArgs)}
|
||||
</h5>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={previewText || ''}
|
||||
/>
|
||||
<div className={style.recommendations_card_shortcut}>
|
||||
<Description
|
||||
style={{ color: '#12131B' }}
|
||||
text={mainText || ''}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Card;
|
60
src/ts/components/RecommendationsOld/index.tsx
Normal file
60
src/ts/components/RecommendationsOld/index.tsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React, { useLayoutEffect, useRef, useState } from 'react';
|
||||
|
||||
import Card from './components/Card';
|
||||
import style from './styles/index.module.scss';
|
||||
|
||||
interface IRecommendationsProps {
|
||||
recommendations: any[];
|
||||
}
|
||||
|
||||
function Recommendations({
|
||||
recommendations,
|
||||
}: IRecommendationsProps) {
|
||||
const [maxCardsOnDisplay, setMaxCardsOnDisplay] = useState<number>(5);
|
||||
const [isOpen, setOpen] = useState<boolean>(false);
|
||||
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const width = ref?.current?.offsetWidth;
|
||||
const placeForCard = (width - 30) / (220 + 24);
|
||||
setMaxCardsOnDisplay(placeForCard);
|
||||
}, []);
|
||||
|
||||
const className = isOpen
|
||||
? style.recommendations_full
|
||||
: style.recommendations_short;
|
||||
|
||||
const children = (recommendations || [])
|
||||
.filter(item => item)
|
||||
.map((recommendation) => (
|
||||
<Card
|
||||
key={recommendation[1]}
|
||||
recommendation={recommendation}
|
||||
/>
|
||||
));
|
||||
const visibleChildren = children.slice(0, isOpen ? Infinity : maxCardsOnDisplay);
|
||||
|
||||
if (!children.length) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={className}
|
||||
>
|
||||
{isOpen ? children : visibleChildren}
|
||||
{!isOpen && children.length > maxCardsOnDisplay && (
|
||||
<div
|
||||
className={style.more}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
»
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Recommendations;
|
166
src/ts/components/RecommendationsOld/styles/card.module.scss
Normal file
166
src/ts/components/RecommendationsOld/styles/card.module.scss
Normal file
|
@ -0,0 +1,166 @@
|
|||
@import '../../../../styles/variables';
|
||||
|
||||
.recommendations {
|
||||
&_short,
|
||||
&_full {
|
||||
position: relative;
|
||||
display: block;
|
||||
max-height: 108px;
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
&_full {
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
&_more,
|
||||
&_card {
|
||||
display: inline-block;
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
|
||||
border-radius: var(--border-radius-m);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&_more {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 30px;
|
||||
margin: 0 0 8px 0;
|
||||
text-align: center;
|
||||
line-height: 100px;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--color-border);
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
&_card {
|
||||
position: relative;
|
||||
width: 220px;
|
||||
margin: 0 12px 16px 0;
|
||||
border-left: none;
|
||||
|
||||
&_wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: block;
|
||||
min-height: 100px;
|
||||
max-height: 100px;
|
||||
padding: 16px;
|
||||
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: var(--border-radius-m);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 8px solid var(--color-border);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
&_icon {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 100% auto;
|
||||
}
|
||||
|
||||
&_info {
|
||||
--color-temp-border: #97C2A9;
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #E3F8EC;
|
||||
--color-temp-title: #58866B;
|
||||
}
|
||||
|
||||
&_fact {
|
||||
--color-temp-border: var(--color-11);
|
||||
--color-temp-icon: url('/assets/recommendations/info.svg');
|
||||
--color-temp-bg: #EFF7FF;
|
||||
--color-temp-title: var(--color-first);
|
||||
}
|
||||
|
||||
&_warning {
|
||||
--color-temp-border: var(--color-21);
|
||||
--color-temp-icon: url('/assets/recommendations/warning.svg');
|
||||
--color-temp-bg: #FFF5F2;
|
||||
--color-temp-title: #E8B06D;
|
||||
}
|
||||
|
||||
&_error {
|
||||
--color-temp-border: var(--color-12);
|
||||
--color-temp-icon: url('/assets/recommendations/alert.svg');
|
||||
--color-temp-bg: #FFEFEE;
|
||||
--color-temp-title: #DD8B87;
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-xs);
|
||||
|
||||
display: block;
|
||||
padding: 2px 0 0 24px;
|
||||
margin: 0 auto 4px auto;
|
||||
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
vertical-align: bottom;
|
||||
color: var(--color-temp-title);
|
||||
}
|
||||
|
||||
&_wrapper {
|
||||
background-color: var(--color-temp-bg);
|
||||
border-left-color: var(--color-temp-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recommendations_card:hover > .recommendations_card_wrapper {
|
||||
z-index: 2;
|
||||
width: 170%;
|
||||
max-height: 450px;
|
||||
box-shadow: 2px 2px 3px #999999;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.recommendations_card_wrapper::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.recommendations_card_wrapper::-webkit-scrollbar-thumb {
|
||||
background: #AAAAAA;
|
||||
}
|
||||
|
||||
.recommendations_title {
|
||||
color: var(--color-temp-border);
|
||||
}
|
||||
|
||||
.recommendations_card_icon {
|
||||
background-image: var(--color-temp-icon);
|
||||
}
|
||||
|
||||
.recommendations_card_shortcut {
|
||||
display: none;
|
||||
padding: 6px 0 0 0;
|
||||
margin: 6px 0 0 0;
|
||||
border-top: 1px solid var(--color-temp-border);
|
||||
}
|
||||
|
||||
.recommendations_card:hover .recommendations_card_shortcut {
|
||||
display: block;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
@import '../../../../styles/variables';
|
||||
|
||||
.recommendations_short,
|
||||
.recommendations_full {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
.more {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
margin: 0 0 8px 0;
|
||||
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
white-space: normal;
|
||||
|
||||
cursor: pointer;
|
||||
border-radius: var(--border-radius-m);
|
||||
line-height: 100px;
|
||||
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-black);
|
||||
background-color: white;
|
||||
}
|
|
@ -5,6 +5,7 @@ import style from '../styles/index.module.scss';
|
|||
|
||||
export function getCustomClassName(type?: string, disabled?: boolean) {
|
||||
let customClassName = {
|
||||
link: style.ui_kit_button_link,
|
||||
slim: style.ui_kit_button_slim,
|
||||
second: style.ui_kit_button_second,
|
||||
primary: style.ui_kit_button_primary,
|
||||
|
@ -17,8 +18,8 @@ export function getCustomClassName(type?: string, disabled?: boolean) {
|
|||
}
|
||||
|
||||
interface IUiKitButtonProps extends IUiKitWrapperProps {
|
||||
type?: string,
|
||||
onClick: Function,
|
||||
type?: 'primary' | 'second' | 'link' | 'slim',
|
||||
onClick?: Function,
|
||||
}
|
||||
|
||||
function UiKitButton({
|
||||
|
|
|
@ -81,6 +81,14 @@
|
|||
--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 {
|
||||
|
@ -120,6 +128,18 @@
|
|||
&_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 {
|
||||
|
|
6
src/ts/helpers/isMobile.ts
Normal file
6
src/ts/helpers/isMobile.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
// @ts-ignore
|
||||
const userAgent: string = navigator.userAgent || navigator.vendor || window.opera || '';
|
||||
const isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(userAgent)
|
||||
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4));
|
||||
|
||||
export default isMobile;
|
|
@ -4,7 +4,7 @@ import dataGripStore from 'ts/store/DataGrip';
|
|||
import { getDate, getDateByTimestamp } from 'ts/helpers/formatter';
|
||||
import RECOMMENDATION_TYPES from 'ts/helpers/Recommendations/contstants';
|
||||
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import NothingFound from 'ts/components/NothingFound';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import BarChart from 'ts/components/BarChart';
|
||||
|
@ -42,7 +42,7 @@ function Changes({ statistic }: IChangesProps) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
<Title title="Количество изменённых строк по дням"/>
|
||||
<PageWrapper template="box">
|
||||
<BarChart
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
|||
import dataGripStore from 'ts/store/DataGrip';
|
||||
import { getDate, getDateByTimestamp } from 'ts/helpers/formatter';
|
||||
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import NothingFound from 'ts/components/NothingFound';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import BarChart from 'ts/components/BarChart';
|
||||
|
@ -45,7 +45,7 @@ function Commits({ statistic }: ICommitsProps) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
<Title title="page.common.commits.title"/>
|
||||
<PageWrapper template="box">
|
||||
<BarChart
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import NothingFound from 'ts/components/NothingFound';
|
||||
import PageWrapper from 'ts/components/Page/wrapper';
|
||||
import CandyChart from 'ts/components/CandyChart';
|
||||
|
@ -37,7 +37,7 @@ function PopularWords({ statistic, mode }: IPopularWordsProps) {
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Title title="page.common.words.title"/>
|
||||
<PageWrapper template="table">
|
||||
|
|
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import Description from 'ts/components/Description';
|
||||
|
||||
function getFlatRecommendations(translations: any, list: any[] = []) {
|
||||
if (!translations) return list;
|
||||
|
||||
|
|
|
@ -1,34 +1,64 @@
|
|||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import localization from 'ts/helpers/Localization';
|
||||
import { TEAM, PERSON } from '../../helpers/menu';
|
||||
|
||||
import style from '../../styles/light_header.module.scss';
|
||||
|
||||
function getPagesAndIndex(type?: string, page?: string) {
|
||||
const pages = (type === 'person' ? PERSON : TEAM)
|
||||
.filter((item: any) => item.id);
|
||||
|
||||
const index = pages
|
||||
.map((item: any) => item.id)
|
||||
.indexOf(page);
|
||||
|
||||
return { pages, index };
|
||||
}
|
||||
|
||||
function getLink(page: any, type?: string, userId?: string) {
|
||||
const nextLink = page?.link || '';
|
||||
return type === 'person'
|
||||
? `${nextLink}${userId}`
|
||||
: nextLink;
|
||||
}
|
||||
|
||||
function LightHeader() {
|
||||
const { type, page } = useParams<any>();
|
||||
const navigate = useNavigate();
|
||||
const { type, page, userId } = useParams<any>();
|
||||
const title = type && page
|
||||
? localization.get(`sidebar.${type}.${page}`)
|
||||
: localization.get('sidebar.team.total');
|
||||
|
||||
return (
|
||||
<header className={style.light_header}>
|
||||
<div
|
||||
className={style.light_header_button}
|
||||
onClick={() => {
|
||||
console.log('x');
|
||||
}}
|
||||
/>
|
||||
<h2 className={style.light_header_title}>
|
||||
{title}
|
||||
</h2>
|
||||
<div
|
||||
className={style.light_header_button}
|
||||
onClick={() => {
|
||||
console.log('x');
|
||||
}}
|
||||
/>
|
||||
</header>
|
||||
<>
|
||||
<header className={style.light_header}>
|
||||
<div
|
||||
className={style.light_header_button}
|
||||
onClick={() => {
|
||||
const { pages, index } = getPagesAndIndex(type, page);
|
||||
if (index < 1) return;
|
||||
const nextLink = getLink(pages[index - 1], type, userId);
|
||||
navigate(nextLink);
|
||||
}}
|
||||
/>
|
||||
<h2 className={style.light_header_title}>
|
||||
{title}
|
||||
</h2>
|
||||
<div
|
||||
className={style.light_header_button}
|
||||
onClick={() => {
|
||||
const { pages, index } = getPagesAndIndex(type, page);
|
||||
if (index < 0
|
||||
|| index === (pages.length - 1)) return;
|
||||
const nextLink = getLink(pages[index + 1], type, userId);
|
||||
navigate(nextLink);
|
||||
}}
|
||||
/>
|
||||
</header>
|
||||
<div className={style.light_header_gap} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import style from '../../styles/footer.module.scss';
|
||||
|
||||
|
@ -13,9 +14,19 @@ function Button({
|
|||
title,
|
||||
icon,
|
||||
}: IButtonProps) {
|
||||
console.dir(id);
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<figure className={style.footer_button}>
|
||||
<figure
|
||||
className={style.footer_button}
|
||||
onClick={() => {
|
||||
const link = {
|
||||
team: '/team/total',
|
||||
person: '/person/total/0',
|
||||
settings: '/team/settings',
|
||||
}[id];
|
||||
if (link) navigate(link);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={style.footer_button_icon}
|
||||
style={{ backgroundImage: `url(${icon})` }}
|
||||
|
|
147
src/ts/pages/PageWrapper/helpers/menu.ts
Normal file
147
src/ts/pages/PageWrapper/helpers/menu.ts
Normal file
|
@ -0,0 +1,147 @@
|
|||
export const TEAM = [
|
||||
{
|
||||
id: 'total',
|
||||
link: '/team/total',
|
||||
title: 'sidebar.team.total',
|
||||
icon: './assets/menu/team_common.svg',
|
||||
},
|
||||
{
|
||||
id: 'scope',
|
||||
link: '/team/scope',
|
||||
title: 'sidebar.team.scope',
|
||||
icon: './assets/menu/team_feat.svg',
|
||||
},
|
||||
{
|
||||
id: 'author',
|
||||
link: '/team/author',
|
||||
title: 'sidebar.team.author',
|
||||
icon: './assets/menu/team_work.svg',
|
||||
},
|
||||
{
|
||||
id: 'type',
|
||||
link: '/team/type',
|
||||
title: 'sidebar.team.type',
|
||||
icon: './assets/menu/team_type.svg',
|
||||
},
|
||||
{
|
||||
id: 'pr',
|
||||
link: '/team/pr',
|
||||
title: 'sidebar.team.pr',
|
||||
icon: './assets/menu/pull_request.svg',
|
||||
},
|
||||
{},
|
||||
{
|
||||
id: 'day',
|
||||
link: '/team/day',
|
||||
title: 'sidebar.team.day',
|
||||
icon: './assets/menu/team_week.svg',
|
||||
},
|
||||
{
|
||||
id: 'week',
|
||||
link: '/team/week',
|
||||
title: 'sidebar.team.week',
|
||||
icon: './assets/menu/team_week.svg',
|
||||
},
|
||||
{
|
||||
id: 'month',
|
||||
link: '/team/month',
|
||||
title: 'sidebar.team.month',
|
||||
icon: './assets/menu/team_date_1.svg',
|
||||
},
|
||||
{
|
||||
id: 'hours',
|
||||
link: '/team/hours',
|
||||
title: 'sidebar.team.hours',
|
||||
icon: './assets/menu/team_date_2.svg',
|
||||
},
|
||||
{},
|
||||
{
|
||||
id: 'tree',
|
||||
link: '/team/tree',
|
||||
title: 'sidebar.team.tree',
|
||||
icon: './assets/menu/team_files.svg',
|
||||
},
|
||||
{
|
||||
id: 'commits',
|
||||
link: '/team/commits',
|
||||
title: 'sidebar.team.commits',
|
||||
icon: './assets/menu/pull-request.svg',
|
||||
},
|
||||
{
|
||||
id: 'changes',
|
||||
link: '/team/changes',
|
||||
title: 'sidebar.team.changes',
|
||||
icon: './assets/menu/branch.svg',
|
||||
},
|
||||
{
|
||||
id: 'words',
|
||||
link: '/team/words',
|
||||
title: 'sidebar.team.words',
|
||||
icon: './assets/menu/team_words.svg',
|
||||
},
|
||||
];
|
||||
|
||||
export const PERSON = [
|
||||
{
|
||||
id: 'total',
|
||||
link: '/person/total/',
|
||||
title: 'sidebar.person.total',
|
||||
icon: './assets/menu/team_common.svg',
|
||||
},
|
||||
{
|
||||
id: 'money',
|
||||
link: '/person/money/',
|
||||
title: 'sidebar.person.money',
|
||||
icon: './assets/menu/per_money.svg',
|
||||
},
|
||||
{
|
||||
id: 'speed',
|
||||
link: '/person/speed/',
|
||||
title: 'sidebar.person.speed',
|
||||
icon: './assets/menu/per_speed.svg',
|
||||
},
|
||||
{},
|
||||
{
|
||||
id: 'day',
|
||||
link: '/person/day/',
|
||||
title: 'sidebar.person.day',
|
||||
icon: './assets/menu/team_week.svg',
|
||||
},
|
||||
{
|
||||
id: 'week',
|
||||
link: '/person/week/',
|
||||
title: 'sidebar.person.week',
|
||||
icon: './assets/menu/team_week.svg',
|
||||
},
|
||||
{
|
||||
id: 'month',
|
||||
link: '/person/month/',
|
||||
title: 'sidebar.person.month',
|
||||
icon: './assets/menu/team_date_1.svg',
|
||||
},
|
||||
{
|
||||
id: 'hours',
|
||||
link: '/person/hours/',
|
||||
title: 'sidebar.person.hours',
|
||||
icon: './assets/menu/team_date_2.svg',
|
||||
},
|
||||
{},
|
||||
{
|
||||
id: 'commits',
|
||||
link: '/person/commits/',
|
||||
title: 'sidebar.person.commits',
|
||||
icon: './assets/menu/pull-request.svg',
|
||||
},
|
||||
{
|
||||
id: 'changes',
|
||||
link: '/person/changes/',
|
||||
title: 'sidebar.person.changes',
|
||||
icon: './assets/menu/branch.svg',
|
||||
},
|
||||
{
|
||||
id: 'words',
|
||||
link: '/person/words/',
|
||||
title: 'sidebar.person.words',
|
||||
icon: './assets/menu/team_words.svg',
|
||||
},
|
||||
];
|
|
@ -1,5 +1,8 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
|
||||
import Recommendations from 'ts/components/Recommendations/components/ModalDescription';
|
||||
import isMobile from 'ts/helpers/isMobile';
|
||||
|
||||
import SideBar from './components/sidebar';
|
||||
import Header from './components/header';
|
||||
import Footer from './components/footer';
|
||||
|
@ -15,7 +18,6 @@ interface IPageWrapper {
|
|||
function PageWrapper({
|
||||
children,
|
||||
}: IPageWrapper) {
|
||||
const isMobile = false;
|
||||
return (
|
||||
<div className={style.page_wrapper}>
|
||||
{!isMobile && <SideBar />}
|
||||
|
@ -27,6 +29,7 @@ function PageWrapper({
|
|||
{children}
|
||||
</div>
|
||||
<Print />
|
||||
<Recommendations />
|
||||
{isMobile && <Footer />}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
@import '../../../../styles/variables';
|
||||
|
||||
.light_header {
|
||||
grid-area: header;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
display: flex;
|
||||
height: 72px;
|
||||
padding: 0;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
box-shadow: -6px var(--space-xs) var(--space-s) #EEEEEE;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
&_gap {
|
||||
grid-area: header;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
&_title {
|
||||
font-size: 24px;
|
||||
font-weight: 100;
|
||||
|
|
|
@ -16,7 +16,7 @@ import Column from 'ts/components/Table/components/Column';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
|
||||
import { getMax } from 'ts/pages/Common/helpers/getMax';
|
||||
import ICommonPageProps from 'ts/components/Page/interfaces/CommonPageProps';
|
||||
|
@ -131,7 +131,7 @@ const Week = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<DataLoader
|
||||
to="response"
|
||||
|
|
|
@ -21,7 +21,7 @@ import Column from 'ts/components/Table/components/Column';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
|
||||
import { getMax, getMaxByLength } from 'ts/pages/Common/helpers/getMax';
|
||||
import Description from 'ts/components/Description';
|
||||
|
@ -163,7 +163,7 @@ const Author = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Title title="page.team.author.title"/>
|
||||
<DataLoader
|
||||
|
|
|
@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite';
|
|||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import HoursChart from 'ts/components/HoursChart';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
|
@ -15,7 +15,7 @@ const Hours = observer((): React.ReactElement => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
<Title title="page.team.hours.title"/>
|
||||
<PageWrapper template="table">
|
||||
<HoursChart statistic={statistic} />
|
||||
|
|
|
@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite';
|
|||
|
||||
import dataGripStore from 'ts/store/DataGrip';
|
||||
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import YearChart from 'ts/components/YearChart';
|
||||
import Title from 'ts/components/Title';
|
||||
|
||||
|
@ -21,7 +21,7 @@ const Month = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations}/>
|
||||
<Recommendations recommendations={recommendations}/>
|
||||
)}
|
||||
<Title title="page.team.month.title"/>
|
||||
<PageWrapper template="table">
|
||||
|
|
|
@ -17,7 +17,7 @@ import Column from 'ts/components/Table/components/Column';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
|
||||
interface IScopeViewProps {
|
||||
response?: IPagination<any>;
|
||||
|
@ -123,7 +123,7 @@ const Scope = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Title title="page.team.scope.title"/>
|
||||
<DataLoader
|
||||
|
|
|
@ -18,7 +18,7 @@ import Column from 'ts/components/Table/components/Column';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
import Description from 'ts/components/Description';
|
||||
|
||||
import { getMax } from 'ts/pages/Common/helpers/getMax';
|
||||
|
@ -123,7 +123,7 @@ const Type = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
<Title title="page.team.type.title"/>
|
||||
<DataLoader
|
||||
|
|
|
@ -18,7 +18,7 @@ import Column from 'ts/components/Table/components/Column';
|
|||
import { ColumnTypesEnum } from 'ts/components/Table/interfaces/Column';
|
||||
import LineChart from 'ts/components/LineChart';
|
||||
import getOptions from 'ts/components/LineChart/helpers/getOptions';
|
||||
import RecommendationsWrapper from 'ts/components/Recommendations/wrapper';
|
||||
import Recommendations from 'ts/components/Recommendations';
|
||||
|
||||
import { getMax } from 'ts/pages/Common/helpers/getMax';
|
||||
|
||||
|
@ -162,7 +162,7 @@ const Week = observer(({
|
|||
return (
|
||||
<>
|
||||
{mode !== 'print' && (
|
||||
<RecommendationsWrapper recommendations={recommendations} />
|
||||
<Recommendations recommendations={recommendations} />
|
||||
)}
|
||||
{mode === 'print' && (
|
||||
<Title title="page.team.week.title"/>
|
||||
|
|
Loading…
Reference in a new issue