Skip to content

Commit

Permalink
feat(DocPage): add updated at meta
Browse files Browse the repository at this point in the history
  • Loading branch information
Feverqwe committed Jan 15, 2024
1 parent ebb4d6e commit 8b0dcab
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/components/DocPage/DocPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {ReactPortal} from 'react';
import React, {Fragment, ReactPortal} from 'react';

import {Link} from '@gravity-ui/icons';
import block from 'bem-cn-lite';
Expand Down Expand Up @@ -28,6 +28,7 @@ import {HTML} from '../HTML';
import {MiniToc} from '../MiniToc';
import {SearchBar, withHighlightedSearchWords} from '../SearchBar';
import {TocNavPanel} from '../TocNavPanel';
import UpdatedAtDate from '../UpdatedAtDate/UpdatedAtDate';

import './DocPage.scss';

Expand Down Expand Up @@ -382,18 +383,30 @@ class DocPage extends React.Component<DocPageInnerProps, DocPageState> {
return null;
}

const updatedAt = this.renderUpdatedAt(meta?.updatedAt);
const author = this.renderAuthor(!meta?.contributors?.length);
const contributors = this.renderContributors();

const separator = author && contributors && <div className={b('separator')}>{','}</div>;

return (
<div className={b('page-contributors')}>
{author} {separator} {contributors}
{[updatedAt, author, contributors].filter(Boolean).map((element, idx, arr) => (
<Fragment key={idx}>
{element}
{arr.length - 1 !== idx && <div className={b('separator')}>{','}</div>}
</Fragment>
))}
</div>
);
}

private renderUpdatedAt(updatedAt?: string) {
if (!updatedAt) {
return null;
}

return <UpdatedAtDate updatedAt={updatedAt} />;
}

private renderAuthor(onlyAuthor: boolean) {
const {meta} = this.props;

Expand Down
10 changes: 10 additions & 0 deletions src/components/UpdatedAtDate/UpdatedAtDate.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@import '../../styles/mixins';

.updated-at-date {
display: flex;
margin: 0 0 32px;

&__title {
@include contributors-text();
}
}
36 changes: 36 additions & 0 deletions src/components/UpdatedAtDate/UpdatedAtDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, {memo, useMemo} from 'react';

import block from 'bem-cn-lite';

import {configure, getConfig} from '../../config';
import {useTranslation} from '../../hooks';
import {format} from '../../utils/date';

import './UpdatedAtDate.scss';

const b = block('updated-at-date');

export interface UpdatedAtDateProps {
updatedAt: string;
translationName?: string;
}

const UpdatedAtDate: React.FC<UpdatedAtDateProps> = (props) => {
const {updatedAt, translationName = 'updated-at-date'} = props;
const {t} = useTranslation(translationName);

const updatedAtFormatted = useMemo(() => {
configure();
const config = getConfig();
return format(updatedAt, 'longDateTime', config.localeCode);
}, [updatedAt]);

return (
<div className={b()}>
<div className={b('title')}>{t<string>('title')}</div>
{updatedAtFormatted}
</div>
);
};

export default memo(UpdatedAtDate);
3 changes: 3 additions & 0 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,8 @@
"paginator": {
"next": "Next page",
"prev": "Previous page"
},
"updated-at-date": {
"label-updated-at": "Updated at"
}
}
3 changes: 3 additions & 0 deletions src/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,8 @@
"paginator": {
"next": "Следующая страница",
"prev": "Предыдущая страница"
},
"updated-at-date": {
"label-updated-at": "Обновлено"
}
}
2 changes: 2 additions & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export enum ControlSizes {
export interface Config {
lang?: string;
loc?: Loc;
localeCode?: string;
}

export interface DocSettings {
Expand Down Expand Up @@ -92,6 +93,7 @@ export interface DocMeta {
contributors?: Contributor[];
author?: unknown | Contributor;
__system?: Record<string, unknown>;
updatedAt?: string;
}

export interface TocData {
Expand Down
75 changes: 75 additions & 0 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
interface DateTimeFormatter {
longDate: Intl.DateTimeFormat;
shortDate: Intl.DateTimeFormat;
longMonthDay: Intl.DateTimeFormat;
shortMonthDay: Intl.DateTimeFormat;
longDateTime: Intl.DateTimeFormat;
shortDateTime: Intl.DateTimeFormat;
shortTime: Intl.DateTimeFormat;
nanoTime: Intl.DateTimeFormat;
year: Intl.DateTimeFormat;
}

const defaultRegion = 'ru-RU';

const dateTimeFormatters: Map<string, DateTimeFormatter> = new Map();

function getDateTimeFormatter(localeCode: string): DateTimeFormatter {
if (!dateTimeFormatters.has(localeCode)) {
const formatters = {
// December 20, 2012
longDate: new Intl.DateTimeFormat(localeCode, {
year: 'numeric',
month: 'long',
day: 'numeric',
}),
// 4/30/2021
shortDate: new Intl.DateTimeFormat(localeCode, {
year: 'numeric',
month: 'numeric',
day: 'numeric',
}),
// December 20
longMonthDay: new Intl.DateTimeFormat(localeCode, {month: 'long', day: 'numeric'}),
// 12/20
shortMonthDay: new Intl.DateTimeFormat(localeCode, {month: 'numeric', day: 'numeric'}),
// April 27, 2021, 3:03 PM
longDateTime: new Intl.DateTimeFormat(localeCode, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
}),
// 4/30/2021, 2:30 PM
shortDateTime: new Intl.DateTimeFormat(localeCode, {
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
}),
// 12:30
shortTime: new Intl.DateTimeFormat(localeCode, {hour: 'numeric', minute: 'numeric'}),
// 30:58
nanoTime: new Intl.DateTimeFormat(localeCode, {
minute: 'numeric',
second: 'numeric',
}),
// 2023
year: new Intl.DateTimeFormat(localeCode, {
year: 'numeric',
}),
};
dateTimeFormatters.set(localeCode, formatters);
}

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- formatter will be always inserted above
return dateTimeFormatters.get(localeCode)!;
}

export const format = (
date: string | number,
formatCode: keyof DateTimeFormatter,
localeCode = defaultRegion,
) => getDateTimeFormatter(localeCode)[formatCode].format(new Date(date));

0 comments on commit 8b0dcab

Please sign in to comment.