PERF: generates dates tooltip on demand (#13944)

This commit is contained in:
Joffrey JAFFEUX
2021-08-04 16:28:07 +02:00
committed by GitHub
parent 6b87ae3d4c
commit 11668ee85b
3 changed files with 137 additions and 78 deletions

View File

@ -1,10 +1,72 @@
import deprecated from "discourse-common/lib/deprecated";
import { getOwner } from "discourse-common/lib/get-owner";
import { hidePopover, showPopover } from "discourse/lib/d-popover";
import LocalDateBuilder from "../lib/local-date-builder"; import LocalDateBuilder from "../lib/local-date-builder";
import showModal from "discourse/lib/show-modal";
import { withPluginApi } from "discourse/lib/plugin-api"; import { withPluginApi } from "discourse/lib/plugin-api";
import showModal from "discourse/lib/show-modal";
export function applyLocalDates(dates, siteSettings) {
if (!siteSettings.discourse_local_dates_enabled) {
return;
}
const currentUserTZ = moment.tz.guess();
dates.forEach((element) => {
const opts = buildOptionsFromElement(element, siteSettings);
const localDateBuilder = new LocalDateBuilder(opts, currentUserTZ).build();
element.innerText = "";
element.insertAdjacentHTML(
"beforeend",
`
<svg class="fa d-icon d-icon-globe-americas svg-icon" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#globe-americas"></use>
</svg>
<span class="relative-time">${localDateBuilder.formated}</span>
`
);
element.setAttribute("aria-label", localDateBuilder.textPreview);
const classes = ["cooked-date"];
if (localDateBuilder.pastEvent) {
classes.push("past");
}
element.classList.add(...classes);
});
}
function buildOptionsFromElement(element, siteSettings) {
const opts = {};
const dataset = element.dataset;
opts.time = dataset.time;
opts.date = dataset.date;
opts.recurring = dataset.recurring;
opts.timezones = (
dataset.timezones ||
siteSettings.discourse_local_dates_default_timezones ||
"Etc/UTC"
)
.split("|")
.filter(Boolean);
opts.timezone = dataset.timezone;
opts.calendar = (dataset.calendar || "on") === "on";
opts.displayedTimezone = dataset.displayedTimezone;
opts.format = dataset.format || (opts.time ? "LLL" : "LL");
opts.countdown = dataset.countdown;
return opts;
}
function initializeDiscourseLocalDates(api) { function initializeDiscourseLocalDates(api) {
api.decorateCooked( const siteSettings = api.container.lookup("site-settings:main");
($elem) => $(".discourse-local-date", $elem).applyLocalDates(),
api.decorateCookedElement(
(elem) => {
applyLocalDates(
elem.querySelectorAll(".discourse-local-date"),
siteSettings
);
},
{ id: "discourse-local-date" } { id: "discourse-local-date" }
); );
@ -30,37 +92,11 @@ function initializeDiscourseLocalDates(api) {
}); });
} }
export default { function buildHtmlPreview(element, siteSettings) {
name: "discourse-local-dates", const opts = buildOptionsFromElement(element, siteSettings);
initialize(container) {
const siteSettings = container.lookup("site-settings:main");
if (siteSettings.discourse_local_dates_enabled) {
const currentUserTZ = moment.tz.guess();
$.fn.applyLocalDates = function () {
return this.each(function () {
const opts = {};
const dataset = this.dataset;
opts.time = dataset.time;
opts.date = dataset.date;
opts.recurring = dataset.recurring;
opts.timezones = (
dataset.timezones ||
siteSettings.discourse_local_dates_default_timezones ||
"Etc/UTC"
)
.split("|")
.filter(Boolean);
opts.timezone = dataset.timezone;
opts.calendar = (dataset.calendar || "on") === "on";
opts.displayedTimezone = dataset.displayedTimezone;
opts.format = dataset.format || (opts.time ? "LLL" : "LL");
opts.countdown = dataset.countdown;
const localDateBuilder = new LocalDateBuilder( const localDateBuilder = new LocalDateBuilder(
opts, opts,
currentUserTZ moment.tz.guess()
).build(); ).build();
const htmlPreviews = localDateBuilder.previews.map((preview) => { const htmlPreviews = localDateBuilder.previews.map((preview) => {
@ -85,32 +121,55 @@ export default {
const previewsNode = document.createElement("div"); const previewsNode = document.createElement("div");
previewsNode.classList.add("locale-dates-previews"); previewsNode.classList.add("locale-dates-previews");
htmlPreviews.forEach((htmlPreview) => htmlPreviews.forEach((htmlPreview) => previewsNode.appendChild(htmlPreview));
previewsNode.appendChild(htmlPreview)
);
this.innerText = ""; return previewsNode.outerHTML;
this.insertAdjacentHTML(
"beforeend",
`
<svg class="fa d-icon d-icon-globe-americas svg-icon" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#globe-americas"></use>
</svg>
<span class="relative-time">${localDateBuilder.formated}</span>
`
);
this.setAttribute("aria-label", localDateBuilder.textPreview);
this.dataset.htmlTooltip = previewsNode.outerHTML;
const classes = ["cooked-date"];
if (localDateBuilder.pastEvent) {
classes.push("past");
} }
this.classList.add(...classes);
export default {
name: "discourse-local-dates",
showDatePopover(event) {
const siteSettings = getOwner(this).lookup("site-settings:main");
if (event?.target?.classList?.contains("discourse-local-date")) {
showPopover(event, {
htmlContent: buildHtmlPreview(event.target, siteSettings),
}); });
}
},
hideDatePopover(event) {
if (event?.target?.classList?.contains("discourse-local-date")) {
hidePopover(event);
}
},
initialize(container) {
const router = container.lookup("router:main");
router.on("routeWillChange", hidePopover);
window.addEventListener("click", this.showDatePopover);
window.addEventListener("mouseover", this.showDatePopover);
window.addEventListener("mouseout", this.hideDatePopover);
const siteSettings = container.lookup("site-settings:main");
if (siteSettings.discourse_local_dates_enabled) {
$.fn.applyLocalDates = function () {
deprecated(
"`$.applyLocalDates()` is deprecated, import and use `applyLocalDates()` instead."
);
return applyLocalDates(this.toArray(), siteSettings);
}; };
withPluginApi("0.8.8", initializeDiscourseLocalDates); withPluginApi("0.8.8", initializeDiscourseLocalDates);
} }
}, },
teardown() {
window.removeEventListener("click", this.showDatePopover);
window.removeEventListener("mouseover", this.showDatePopover);
window.removeEventListener("mouseout", this.hideDatePopover);
},
}; };

View File

@ -140,11 +140,7 @@ function closeBuffer(buffer, state, text) {
} }
export function setup(helper) { export function setup(helper) {
helper.allowList([ helper.allowList(["span.discourse-local-date", "span[aria-label]"]);
"span.discourse-local-date",
"span[data-*]",
"span[aria-label]",
]);
helper.registerOptions((opts, siteSettings) => { helper.registerOptions((opts, siteSettings) => {
opts.datesEmailFormat = siteSettings.discourse_local_dates_email_format; opts.datesEmailFormat = siteSettings.discourse_local_dates_email_format;

View File

@ -1,4 +1,8 @@
.discourse-local-date { .discourse-local-date {
> * {
pointer-events: none;
}
&.cooked-date { &.cooked-date {
color: var(--primary); color: var(--primary);
cursor: pointer; cursor: pointer;