Добавлены комментарии в код виджета календаря на frontend-е

This commit is contained in:
Pavel Gnedov 2024-02-02 09:39:14 +07:00
parent d9c3345594
commit 3c2fe9af95

View file

@ -6,6 +6,8 @@ import * as DashboardStoreNs from '../dashboard-store';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { IssueHref } from '../../misc-components/issue-href'; import { IssueHref } from '../../misc-components/issue-href';
// Описание основных и вспомогательных моделей данных для календаря:
export const CalendarEvent = types.model({ export const CalendarEvent = types.model({
from: types.string, from: types.string,
fromTimestamp: types.number, fromTimestamp: types.number,
@ -51,81 +53,6 @@ function getEventKey(e: IIssueAndEvent): string {
return `${e.issue.id}-${fromKey}-${toKey}-${description}`; return `${e.issue.id}-${fromKey}-${toKey}-${description}`;
} }
export const EventsStore = types
.model({
events: types.array(IssueAndEvent),
})
.views((self) => {
const getRelativeDate = (issueAndEvent: IIssueAndEvent): string | null => {
const from = Luxon.DateTime.fromMillis(issueAndEvent.event.fromTimestamp);
return from.toRelativeCalendar();
};
const getStartOfDayTimestamp = (issueAndEvent: IIssueAndEvent): number => {
const from = Luxon.DateTime.fromMillis(issueAndEvent.event.fromTimestamp);
return from.startOf('day').toMillis();
};
return {
eventsMap: (): Record<string, IIssueAndEvent> => {
return self.events.reduce((acc, issueAndEvent) => {
const key = getEventKey(issueAndEvent);
acc[key] = issueAndEvent;
return acc;
}, {} as Record<string, IIssueAndEvent>);
},
orderedByDates: (): InDay[] => {
const res: Record<number, InDay> = self.events.reduce(
(acc, issueAndEvent) => {
const order = getStartOfDayTimestamp(issueAndEvent);
const formattedDate = DateTime.fromMillis(
issueAndEvent.event.fromTimestamp,
).toFormat(DATE_FORMAT);
if (!acc[order]) {
acc[order] = {
order: order,
relativeDate: getRelativeDate(issueAndEvent),
formattedDate: formattedDate,
events: [],
};
}
const key = getEventKey(issueAndEvent);
acc[order].events.push(key);
return acc;
},
{} as Record<number, InDay>,
);
return Object.values(res).sort((a, b) => a.order - b.order);
},
formattedDateTimes: (): Record<string, IFormattedDateTime> => {
const res: Record<string, IFormattedDateTime> = self.events.reduce(
(acc, event) => {
const key = getEventKey(event);
acc[key] = getFormattedDateTime(event);
return acc;
},
{} as Record<string, IFormattedDateTime>,
);
return res;
},
};
})
.actions((self) => {
return {
setEvents: (events: any): void => {
self.events = events;
},
};
});
export type IEventsStore = Instance<typeof EventsStore>;
export type Props = {
store: DashboardStoreNs.IWidget;
};
function getFormattedDateTime( function getFormattedDateTime(
issueAndEvent: IIssueAndEvent, issueAndEvent: IIssueAndEvent,
): IFormattedDateTime { ): IFormattedDateTime {
@ -152,6 +79,99 @@ function getFormattedDateTime(
}); });
} }
function getRelativeDate(issueAndEvent: IIssueAndEvent): string | null {
const from = Luxon.DateTime.fromMillis(issueAndEvent.event.fromTimestamp);
return from.toRelativeCalendar();
}
function getStartOfDayTimestamp(issueAndEvent: IIssueAndEvent): number {
const from = Luxon.DateTime.fromMillis(issueAndEvent.event.fromTimestamp);
return from.startOf('day').toMillis();
}
/** Стор данных для виджета "Календарь следующих событий" */
export const EventsStore = types
.model({
events: types.array(IssueAndEvent),
})
.views((self) => {
return {
/** Геттер мапы событий в формате eventKey -> issue+event */
eventsMap: (): Record<string, IIssueAndEvent> => {
return self.events.reduce((acc, issueAndEvent) => {
const key = getEventKey(issueAndEvent);
acc[key] = issueAndEvent;
return acc;
}, {} as Record<string, IIssueAndEvent>);
},
/**
* Геттер сгруппированных по дням данных.
*
* Ключ группы определяется по timestamp-у указывающему на начало дня
*
* Дополнительные поля relativeDate и formattedDate для отображения в виджете подробной
* информации об этой группе событий
*/
orderedByDates: (): InDay[] => {
const res: Record<number, InDay> = self.events.reduce(
(acc, issueAndEvent) => {
const order = getStartOfDayTimestamp(issueAndEvent);
const formattedDate = DateTime.fromMillis(
issueAndEvent.event.fromTimestamp,
).toFormat(DATE_FORMAT);
if (!acc[order]) {
acc[order] = {
order: order,
relativeDate: getRelativeDate(issueAndEvent),
formattedDate: formattedDate,
events: [],
};
}
const key = getEventKey(issueAndEvent);
acc[order].events.push(key);
return acc;
},
{} as Record<number, InDay>,
);
return Object.values(res).sort((a, b) => a.order - b.order);
},
/**
* Мапа событий с отформатированными значениями даты и времени
*
* * Ключ - это ключ события
* * Значение - вспомогательная информация для человеко-читаемого вывода даты и времени
*/
formattedDateTimes: (): Record<string, IFormattedDateTime> => {
const res: Record<string, IFormattedDateTime> = self.events.reduce(
(acc, event) => {
const key = getEventKey(event);
acc[key] = getFormattedDateTime(event);
return acc;
},
{} as Record<string, IFormattedDateTime>,
);
return res;
},
};
})
.actions((self) => {
return {
/** Сеттер основных данных */
setEvents: (events: any): void => {
self.events = events;
},
};
});
export type IEventsStore = Instance<typeof EventsStore>;
/**
* Компонент для отображения данных из стора EventsStore
*
* @see {EventsStore}
*/
export const CalendarList = observer( export const CalendarList = observer(
(props: { store: IEventsStore }): JSX.Element => { (props: { store: IEventsStore }): JSX.Element => {
const list = props.store.orderedByDates().map((events) => { const list = props.store.orderedByDates().map((events) => {
@ -186,6 +206,16 @@ export const CalendarList = observer(
}, },
); );
export type Props = {
store: DashboardStoreNs.IWidget;
};
/**
* Основной компонент календаря
*
* Он нужен для преобразования стора абстрактного виджета в стор специфичный для
* календаря
*/
export const CalendarNextEvents = observer((props: Props): JSX.Element => { export const CalendarNextEvents = observer((props: Props): JSX.Element => {
const calendarListStore = EventsStore.create(); const calendarListStore = EventsStore.create();
onSnapshot(props.store, (storeState) => { onSnapshot(props.store, (storeState) => {