Добавлены комментарии в код виджета календаря на 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 { 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) => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue