Merge pull request #1261 from rom1dep/calendar_enh_attributes

feat(view/calendar): let the user specify attributes to be promoted o…
This commit is contained in:
Elian Doran 2025-02-23 19:16:35 +02:00 committed by GitHub
commit 143b91936c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -48,6 +48,11 @@ const TPL = `
.calendar-container .fc-button { .calendar-container .fc-button {
padding: 0.2em 0.5em; padding: 0.2em 0.5em;
} }
.calendar-container .promoted-attribute {
font-size: 0.85em;
opacity: 0.85;
}
</style> </style>
<div class="calendar-container"> <div class="calendar-container">
@ -119,13 +124,24 @@ export default class CalendarView extends ViewMode {
height: "100%", height: "100%",
eventContent: (e => { eventContent: (e => {
let html = ""; let html = "";
const { iconClass, promotedAttributes } = e.event.extendedProps;
const iconClass = e.event.extendedProps.iconClass; // Title and icon
if (iconClass) { if (iconClass) {
html += `<span class="${iconClass}"></span> `; html += `<span class="${iconClass}"></span> `;
} }
html += utils.escapeHtml(e.event.title); html += utils.escapeHtml(e.event.title);
// Promoted attributes
if (promotedAttributes) {
for (const [ name, value ] of Object.entries(promotedAttributes)) {
html += `\
<div class="promoted-attribute">
<span class="promoted-attribute-name">${name}</span>: <span class="promoted-attribute-value">${value}</span>
</div>`;
}
}
return { html }; return { html };
}), }),
dateClick: async (e) => { dateClick: async (e) => {
@ -279,7 +295,7 @@ export default class CalendarView extends ViewMode {
const events: EventSourceInput = []; const events: EventSourceInput = [];
for (const note of notes) { for (const note of notes) {
let startDate = note.getLabelValue("startDate"); const startDate = note.getLabelValue("startDate");
if (note.hasChildren()) { if (note.hasChildren()) {
const childrenEventData = await this.#buildEvents(note.getChildNoteIds()); const childrenEventData = await this.#buildEvents(note.getChildNoteIds());
@ -304,6 +320,13 @@ export default class CalendarView extends ViewMode {
const titles = await CalendarView.#parseCustomTitle(customTitle, note); const titles = await CalendarView.#parseCustomTitle(customTitle, note);
const color = note.getLabelValue("calendar:color") ?? note.getLabelValue("color"); const color = note.getLabelValue("calendar:color") ?? note.getLabelValue("color");
const events: EventInput[] = []; const events: EventInput[] = [];
const calendarPromotedAttributes = note.getLabelValue("calendar:promotedAttributes");
let promotedAttributesData = null;
if (calendarPromotedAttributes) {
promotedAttributesData = await this.#buildPromotedAttributes(note, calendarPromotedAttributes);
}
for (const title of titles) { for (const title of titles) {
const eventData: EventInput = { const eventData: EventInput = {
title: title, title: title,
@ -311,7 +334,8 @@ export default class CalendarView extends ViewMode {
url: `#${note.noteId}`, url: `#${note.noteId}`,
noteId: note.noteId, noteId: note.noteId,
color: color ?? undefined, color: color ?? undefined,
iconClass: note.getLabelValue("iconClass") iconClass: note.getLabelValue("iconClass"),
promotedAttributes: promotedAttributesData
}; };
const endDateOffset = CalendarView.#offsetDate(endDate ?? startDate, 1); const endDateOffset = CalendarView.#offsetDate(endDate ?? startDate, 1);
@ -323,6 +347,35 @@ export default class CalendarView extends ViewMode {
return events; return events;
} }
static async #buildPromotedAttributes(note: FNote, calendarPromotedAttributes: string) {
const promotedAttributeNames = calendarPromotedAttributes.split(",");
const filteredPromotedAttributes = note.getPromotedDefinitionAttributes().filter((attr) => promotedAttributeNames.includes(attr.name));
const result: Record<string, string> = {};
for (const promotedAttribute of filteredPromotedAttributes) {
const [ type, name ] = promotedAttribute.name.split(":", 2);
const definition = promotedAttribute.getDefinition();
if (definition.multiplicity !== "single") {
// TODO: Add support for multiple definitions.
continue;
}
// TODO: Add support for relations
if (type !== "label" || !note.hasLabel(name)) {
continue;
}
const value = note.getLabelValue(name);
const friendlyName = definition.promotedAlias ?? name;
if (friendlyName && value) {
result[friendlyName] = value;
}
}
return result;
}
static async #parseCustomTitle(customTitleValue: string | null, note: FNote, allowRelations = true): Promise<string[]> { static async #parseCustomTitle(customTitleValue: string | null, note: FNote, allowRelations = true): Promise<string[]> {
if (customTitleValue) { if (customTitleValue) {
const attributeName = customTitleValue.substring(1); const attributeName = customTitleValue.substring(1);