I’m working on a kit that shows me a table of future events. It’s fine, but I seriously can’t stop myself from clicking things in tables. I’m trying to stop logseq from entering editing mode when I click the white space within a table cell.
For some reason I can’t get a mutation observer to react when the table comes into and out of existence with editing mode.
// [:edit "nevermind this."]
window.eventTableNode = document.querySelector(".compact");
// Maybe if I attach the objects to window?
window.futureEventsCallback = (mutationList, observer) => {
for (const mutation of mutationList) {
console.log(`A mutation has been observed. Mutation type: ${mutation.type}`);
}
}
window.observer = new MutationObserver(futureEventsCallback);
if (eventTableNode) {
const config = { attributes: true, childList: true, subtree: true };
observer.observe(eventTableNode, config);
console.log("Observer started");
} else {
console.log("Target node not found");
}
Here’s the code for the future events table generator:
logseq page futureEventsTable
:
logseq.kits.setStatic(async function futureEventsTable(div) {
// Start counting from startDate date into the future. You probably want
// to start from today
const fromDate = new Date();
const futureEventsPromise = (async (startDate = fromDate) => {
// Logseq's :journal-day uses the format date YYYYMMDD.
const logseqStartDate = ((date = startDate) => {
const month = (date.getMonth() + 1).toString().padStart(2, "0"),
day = date.getDate().toString().padStart(2, "0"),
year = date.getFullYear().toString();
return [year, month, day].join("");
})();
const futureEventsArray = await (async (startDate = logseqStartDate) => {
if (typeof startDate != "string") {
console.log(
17,
`function futureEventsArray: Expected startDate
to be a string, but it was not.`
);
}
const advancedQuery = `
[:find ?date ?day ?content ?props
:keys date day content properties
:where
[?e :block/properties ?props]
[(get ?props :event) ?event]
[(get ?props :date) ?date]
[?e :block/refs ?refs]
[?e :block/content ?content]
[?refs :block/journal-day ?day]
[(>= ?day ${startDate})]
]`;
const queryResults = await logseq.api.datascript_query(advancedQuery);
// The expected format for the :date property is that it includes a single
// linked reference. Logseq returns that as a single-item array.
const flatFutureEventsArray = queryResults?.flat().map((appointment) => ({
...appointment,
date: appointment.date[0],
}));
return flatFutureEventsArray;
})();
const chronologicalEvents = ((activities = futureEventsArray) => {
if (typeof activities.sort != "function") {
console.log(
46,
`function chronologicalEvents: Expected futureEventsArray
to be an object, but it was not.`
);
return [];
}
return [...activities].sort((a, b) => {
return a.day - b.day;
});
})();
const futureEventsWithCountdown = ((
activities = chronologicalEvents,
earlierDate = startDate
) => {
if (activities.length == 0) return -1; // No future activiuties
activities.forEach((activity) => {
const nextActivityDay = activity.day.toString();
const year = parseInt(nextActivityDay.slice(0, 4), 10);
const month = parseInt(nextActivityDay.slice(4, 6), 10) - 1; // Adjust for zero-indexed months
const day = parseInt(nextActivityDay.slice(6, 8), 10);
const nextActivityDate = new Date(year, month, day);
const daysUntil = Math.ceil(
(nextActivityDate - earlierDate) / (1000 * 60 * 60 * 24)
);
console.log(daysUntil);
activity.daysUntil = daysUntil;
});
return activities;
})();
return futureEventsWithCountdown;
})();
result = await futureEventsPromise;
console.table(result);
const tableHTML = `
<table class="compact">
<thead>
<tr>
<th>Days<br>Until</th>
<th>Event</th>
</tr>
</thead>
<tbody>
${result
.map(
(event, index) => `
<tr>
<td rowspan="2">${event.daysUntil}</td>
<td class="clickable" id="event-table-${index}"><a href="${event.uuid}">${event.properties.event}</a></td>
</tr>
<tr>
<td class="event-info">${event.date} ${event.time} ${event.with}<br></td>
</tr>`
)
.join("")}
</tbody>
</table>
`;
div.innerHTML = tableHTML;
// Mutation observer goes here.
});
This is the macro to trigger the future event table.
config.edn
:macros {
:futureEventsTable "[:div {:class \"kit inline\" :data-kit \"futureEventsTable\" } ]" ;;
}
Here’s some test data in case you want to test the kit javascript
-
event:: Birthday party
activity:: [[social]] [[event]]
with:: [[@Someone]]
location:: [[.Somewhere]]
date:: [[Thursday, Aug 22nd, 2024]]
time:: 2200
-
event:: Something else
activity:: [[appointment]]
with:: [[@Someone else]]
location:: [[.Somewhere else]]
date:: [[Saturday, Aug 31st, 2024]]
time:: 1200