update
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 200 KiB |
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 200 KiB |
33
src/ts/components/CardWithBanner/index.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import themeSettings from 'ts/store/ThemeSettings';
|
||||||
|
|
||||||
|
import style from 'ts/components/CardWithIcon/index.module.scss';
|
||||||
|
|
||||||
|
interface ICardWithBannerProps {
|
||||||
|
long?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function CardWithBanner({
|
||||||
|
long = false,
|
||||||
|
}: ICardWithBannerProps): React.ReactElement | null {
|
||||||
|
const config = themeSettings.getBanner();
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
const { link, banner } = config;
|
||||||
|
const className = long
|
||||||
|
? style.card_with_icon_long
|
||||||
|
: style.card_with_icon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={link || ''}
|
||||||
|
target="_blank"
|
||||||
|
className={className}
|
||||||
|
style={{ backgroundImage: `url(${banner})` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CardWithBanner;
|
|
@ -7,12 +7,19 @@
|
||||||
min-height: 270px;
|
min-height: 270px;
|
||||||
margin: 0 24px 24px 0;
|
margin: 0 24px 24px 0;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
text-decoration: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
|
|
||||||
|
background-repeat: repeat;
|
||||||
|
background-size: auto 100%;
|
||||||
|
background-position: center center;
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
display: block;
|
display: block;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -59,7 +66,7 @@
|
||||||
|
|
||||||
.card_with_icon_long {
|
.card_with_icon_long {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 0 16px 0;
|
margin: 0 0 24px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_with_icon:nth-child(2n+2) {
|
.card_with_icon:nth-child(2n+2) {
|
||||||
|
|
|
@ -21,7 +21,10 @@ function LineChart({
|
||||||
details,
|
details,
|
||||||
className,
|
className,
|
||||||
}: ILineChartProps): React.ReactElement | null {
|
}: ILineChartProps): React.ReactElement | null {
|
||||||
if (!value || value === 0) return null;
|
if (!value) return null;
|
||||||
|
if (options.suffix === 'stop') {
|
||||||
|
console.log('xxx');
|
||||||
|
}
|
||||||
|
|
||||||
const width = Math.round((value ?? 100) * (100 / options.max));
|
const width = Math.round((value ?? 100) * (100 / options.max));
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ function LineChart({
|
||||||
return (
|
return (
|
||||||
<div className={`${style.line_chart} ${className || ''}`}>
|
<div className={`${style.line_chart} ${className || ''}`}>
|
||||||
<Line
|
<Line
|
||||||
value={value ?? 100}
|
value={value}
|
||||||
width={width}
|
width={width}
|
||||||
suffix={options.suffix}
|
suffix={options.suffix}
|
||||||
formatter={options.formatter}
|
formatter={options.formatter}
|
||||||
|
|
24
src/ts/components/Recommendations/components/Banner.tsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import themeSettings from 'ts/store/ThemeSettings';
|
||||||
|
|
||||||
|
import style from '../styles/card.module.scss';
|
||||||
|
|
||||||
|
function Banner() {
|
||||||
|
const config = themeSettings.getBanner();
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
const { link, banner } = config;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={link || ''}
|
||||||
|
target="_blank"
|
||||||
|
className={`${style.recommendations_card} ${style.recommendations_card_banner}`}
|
||||||
|
style={{ backgroundImage: `url(${banner})` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Banner;
|
|
@ -4,6 +4,7 @@ import Title from 'ts/components/Title';
|
||||||
import localization from 'ts/helpers/Localization';
|
import localization from 'ts/helpers/Localization';
|
||||||
|
|
||||||
import Card from './components/Card';
|
import Card from './components/Card';
|
||||||
|
import Banner from './components/Banner';
|
||||||
import CardForPrint from './components/CardForPrint';
|
import CardForPrint from './components/CardForPrint';
|
||||||
import recommendationStore from './store/index';
|
import recommendationStore from './store/index';
|
||||||
import style from './styles/index.module.scss';
|
import style from './styles/index.module.scss';
|
||||||
|
@ -35,6 +36,9 @@ function Recommendations({
|
||||||
)));
|
)));
|
||||||
|
|
||||||
if (!cards.length) return null;
|
if (!cards.length) return null;
|
||||||
|
if (mode !== 'print') {
|
||||||
|
cards.push(<Banner />);
|
||||||
|
}
|
||||||
|
|
||||||
const title = localization.get('recommendations.title');
|
const title = localization.get('recommendations.title');
|
||||||
const className = mode === 'print'
|
const className = mode === 'print'
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
|
text-decoration: none;
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
break-inside: avoid;
|
break-inside: avoid;
|
||||||
|
|
||||||
|
@ -103,5 +104,14 @@
|
||||||
|
|
||||||
background-color: var(--color-temp-bg);
|
background-color: var(--color-temp-bg);
|
||||||
border-left-color: var(--color-temp-border);
|
border-left-color: var(--color-temp-border);
|
||||||
|
|
||||||
|
&_banner {
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-left-color: var(--color-border);
|
||||||
|
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 180% auto;
|
||||||
|
background-position: center center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ function SplashScreen(): React.ReactElement | null {
|
||||||
return (
|
return (
|
||||||
<div className={style.splash_screen}>
|
<div className={style.splash_screen}>
|
||||||
<div className={style.splash_screen_container}>
|
<div className={style.splash_screen_container}>
|
||||||
<Logo />
|
<Logo center />
|
||||||
<div className={progress.progress_bar}></div>
|
<div className={progress.progress_bar}></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,26 +5,44 @@ import themeSettings from 'ts/store/ThemeSettings';
|
||||||
|
|
||||||
import style from '../../styles/logo.module.scss';
|
import style from '../../styles/logo.module.scss';
|
||||||
|
|
||||||
function Logo() {
|
interface ILogoProps {
|
||||||
|
center?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Logo({ center }: ILogoProps) {
|
||||||
const {
|
const {
|
||||||
icon, link, title, isOpenInNewTab,
|
isDefault,
|
||||||
|
icon,
|
||||||
|
link,
|
||||||
|
title,
|
||||||
|
isOpenInNewTab,
|
||||||
} = themeSettings.getLogo();
|
} = themeSettings.getLogo();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<figure className={style.logo}>
|
<figure
|
||||||
|
className={center
|
||||||
|
? `${style.logo} ${style.logo_center}`
|
||||||
|
: style.logo}
|
||||||
|
>
|
||||||
<Link
|
<Link
|
||||||
to={link}
|
to={link || ''}
|
||||||
target={isOpenInNewTab ? '_blank' : ''}
|
target={isOpenInNewTab ? '_blank' : ''}
|
||||||
className={style.logo_link}
|
className={style.logo_link}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={icon}
|
src={icon || ''}
|
||||||
title={title}
|
title={title || ''}
|
||||||
className={style.logo_icon}
|
className={isDefault
|
||||||
|
? `${style.logo_icon} ${style.logo_default}`
|
||||||
|
: style.logo_icon}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</figure>
|
</figure>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logo.defaultProps = {
|
||||||
|
center: false,
|
||||||
|
};
|
||||||
|
|
||||||
export default Logo;
|
export default Logo;
|
||||||
|
|
|
@ -2,36 +2,32 @@
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 0 24px 0 0;
|
padding: 0 var(--space-xxl) 0 0;
|
||||||
margin: 0 0 27px 0;
|
margin: 0 0 var(--space-m) 0;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
|
&_center {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&_link {
|
&_link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&_icon {
|
&_icon {
|
||||||
height: 20px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.logo_title {
|
&_default {
|
||||||
font-weight: bold;
|
height: var(--space-xxl);
|
||||||
font-size: 18px;
|
margin-bottom: var(--space-m);
|
||||||
display: inline-block;
|
}
|
||||||
margin: 0 0 0 46px;
|
|
||||||
line-height: 32px;
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
|
||||||
letter-spacing: 7px;
|
|
||||||
color: #DCE3F6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1000px) {
|
@media (max-width: 1000px) {
|
||||||
|
@ -39,8 +35,4 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo_title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
width: calc(100% - 24px);
|
width: calc(100% - 24px);
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
margin: 0 0 40px 0;
|
margin: 0 0 28px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { observer } from 'mobx-react-lite';
|
||||||
import { getShortNumber } from 'ts/helpers/formatter';
|
import { getShortNumber } from 'ts/helpers/formatter';
|
||||||
|
|
||||||
import CardWithIcon from 'ts/components/CardWithIcon';
|
import CardWithIcon from 'ts/components/CardWithIcon';
|
||||||
|
import CardWithBanner from 'ts/components/CardWithBanner';
|
||||||
import NothingFound from 'ts/components/NothingFound';
|
import NothingFound from 'ts/components/NothingFound';
|
||||||
import IsStaff from 'ts/components/NothingFound/components/IsStaff';
|
import IsStaff from 'ts/components/NothingFound/components/IsStaff';
|
||||||
import PageWrapper from 'ts/components/Page/wrapper';
|
import PageWrapper from 'ts/components/Page/wrapper';
|
||||||
|
@ -56,6 +57,7 @@ const Speed = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||||
title="page.person.speed.line.title"
|
title="page.person.speed.line.title"
|
||||||
description="page.person.speed.line.description"
|
description="page.person.speed.line.description"
|
||||||
/>
|
/>
|
||||||
|
<CardWithBanner />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</PageColumn>
|
</PageColumn>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
import getAchievementByAuthor from 'ts/helpers/achievement/byAuthor';
|
||||||
import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
|
import ACHIEVEMENT_TYPE from 'ts/helpers/achievement/constants/type';
|
||||||
|
|
||||||
|
import CardWithBanner from 'ts/components/CardWithBanner';
|
||||||
import CardWithIcon from 'ts/components/CardWithIcon';
|
import CardWithIcon from 'ts/components/CardWithIcon';
|
||||||
import Achievements from 'ts/components/Achievement';
|
import Achievements from 'ts/components/Achievement';
|
||||||
import Description from 'ts/components/Description';
|
import Description from 'ts/components/Description';
|
||||||
|
@ -69,6 +70,7 @@ const Total = observer(({ user }: IPersonCommonProps): React.ReactElement => {
|
||||||
title="page.team.total.commits.title"
|
title="page.team.total.commits.title"
|
||||||
description="page.team.total.commits.description"
|
description="page.team.total.commits.description"
|
||||||
/>
|
/>
|
||||||
|
<CardWithBanner long />
|
||||||
</div>
|
</div>
|
||||||
{false && <Title title="page.person.character.title"/>}
|
{false && <Title title="page.person.character.title"/>}
|
||||||
{false && <Character user={statistic} />}
|
{false && <Character user={statistic} />}
|
||||||
|
|
|
@ -36,6 +36,7 @@ function AllPR({
|
||||||
order: dataGripStore.dataGrip.author.list,
|
order: dataGripStore.dataGrip.author.list,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(commitsChart);
|
||||||
return (
|
return (
|
||||||
<DataView
|
<DataView
|
||||||
rowsForExcel={rowsForExcel}
|
rowsForExcel={rowsForExcel}
|
||||||
|
|
|
@ -51,8 +51,7 @@ function ReleaseView({ response, updateSort, rowsForExcel, mode }: IReleaseViewP
|
||||||
formatter={(row: any) => {
|
formatter={(row: any) => {
|
||||||
const content = row.pr.map((commit: any) => (
|
const content = row.pr.map((commit: any) => (
|
||||||
dataGripStore?.dataGrip?.pr?.pr?.[commit.prId]
|
dataGripStore?.dataGrip?.pr?.pr?.[commit.prId]
|
||||||
));
|
)).filter((item: any) => item?.firstCommit);
|
||||||
console.log(dataGripStore?.dataGrip?.pr?.pr?.['2810']);
|
|
||||||
return (
|
return (
|
||||||
<AllPR // @ts-ignore
|
<AllPR // @ts-ignore
|
||||||
response={{ content }}
|
response={{ content }}
|
||||||
|
|
|
@ -1,5 +1,40 @@
|
||||||
import { makeObservable, observable, action } from 'mobx';
|
import { makeObservable, observable, action } from 'mobx';
|
||||||
|
|
||||||
|
const LOGO = {
|
||||||
|
isDefault: true,
|
||||||
|
icon: './assets/logo.svg',
|
||||||
|
isOpenInNewTab: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const EXTERNAL_LOGO = {
|
||||||
|
vk_frontend_du2: {
|
||||||
|
icon: './social/vk/frontend_du2.png',
|
||||||
|
banner: './social/vk/frontend_du2.jpg',
|
||||||
|
link: 'https://vk.com/frontend_du2',
|
||||||
|
title: 'Сообщество о веб-разработке и программировании',
|
||||||
|
},
|
||||||
|
vk_take_off_staff: {
|
||||||
|
icon: './social/vk/take_off_staff.png',
|
||||||
|
banner: './social/vk/take_off_staff.jpg',
|
||||||
|
link: 'https://vk.com/takeoff_staff',
|
||||||
|
},
|
||||||
|
vk_awesomejs: {
|
||||||
|
icon: './social/vk/awesomejs.png',
|
||||||
|
banner: './social/vk/awesomejs.jpg',
|
||||||
|
link: 'https://vk.com/awesomejs',
|
||||||
|
},
|
||||||
|
vk_frontend_dev: {
|
||||||
|
icon: './social/vk/frontend_dev.png',
|
||||||
|
banner: './social/vk/frontend_dev.jpg',
|
||||||
|
link: 'https://vk.com/frontend_dev',
|
||||||
|
},
|
||||||
|
vk_front_work: {
|
||||||
|
icon: './social/vk/front_work.png',
|
||||||
|
banner: './social/vk/front_work.jpg',
|
||||||
|
link: 'https://frontends.work/?ref=assayo',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
class ThemeSettings {
|
class ThemeSettings {
|
||||||
urlParameters: any = {};
|
urlParameters: any = {};
|
||||||
|
|
||||||
|
@ -15,12 +50,19 @@ class ThemeSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
getLogo() {
|
getLogo() {
|
||||||
return {
|
let config = EXTERNAL_LOGO[this.urlParameters?.ref || ''];
|
||||||
icon: './assets/logo.svg',
|
if (!config) return LOGO;
|
||||||
link: '',
|
|
||||||
title: '',
|
config.isOpenInNewTab = true;
|
||||||
isOpenInNewTab: false,
|
return config;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
getBanner() {
|
||||||
|
let config = EXTERNAL_LOGO[this.urlParameters?.ref || ''];
|
||||||
|
if (!config) return null;
|
||||||
|
|
||||||
|
config.isOpenInNewTab = true;
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|