Добавлены комментарии в код виджета календаря на frontend-е
This commit is contained in:
parent
d9c3345594
commit
3c2fe9af95
1 changed files with 105 additions and 75 deletions
|
|
@ -6,6 +6,8 @@ import * as DashboardStoreNs from '../dashboard-store';
|
|||
import { DateTime } from 'luxon';
|
||||
import { IssueHref } from '../../misc-components/issue-href';
|
||||
|
||||
// Описание основных и вспомогательных моделей данных для календаря:
|
||||
|
||||
export const CalendarEvent = types.model({
|
||||
from: types.string,
|
||||
fromTimestamp: types.number,
|
||||
|
|
@ -51,81 +53,6 @@ function getEventKey(e: IIssueAndEvent): string {
|
|||
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(
|
||||
issueAndEvent: IIssueAndEvent,
|
||||
): 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(
|
||||
(props: { store: IEventsStore }): JSX.Element => {
|
||||
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 => {
|
||||
const calendarListStore = EventsStore.create();
|
||||
onSnapshot(props.store, (storeState) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue