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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 showModal from "discourse/lib/show-modal";
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) {
api.decorateCooked(
($elem) => $(".discourse-local-date", $elem).applyLocalDates(),
const siteSettings = api.container.lookup("site-settings:main");
api.decorateCookedElement(
(elem) => {
applyLocalDates(
elem.querySelectorAll(".discourse-local-date"),
siteSettings
);
},
{ id: "discourse-local-date" }
);
@ -30,87 +92,84 @@ function initializeDiscourseLocalDates(api) {
});
}
function buildHtmlPreview(element, siteSettings) {
const opts = buildOptionsFromElement(element, siteSettings);
const localDateBuilder = new LocalDateBuilder(
opts,
moment.tz.guess()
).build();
const htmlPreviews = localDateBuilder.previews.map((preview) => {
const previewNode = document.createElement("div");
previewNode.classList.add("preview");
if (preview.current) {
previewNode.classList.add("current");
}
const timezoneNode = document.createElement("span");
timezoneNode.classList.add("timezone");
timezoneNode.innerText = preview.timezone;
previewNode.appendChild(timezoneNode);
const dateTimeNode = document.createElement("span");
dateTimeNode.classList.add("date-time");
dateTimeNode.innerText = preview.formated;
previewNode.appendChild(dateTimeNode);
return previewNode;
});
const previewsNode = document.createElement("div");
previewsNode.classList.add("locale-dates-previews");
htmlPreviews.forEach((htmlPreview) => previewsNode.appendChild(htmlPreview));
return previewsNode.outerHTML;
}
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) {
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;
deprecated(
"`$.applyLocalDates()` is deprecated, import and use `applyLocalDates()` instead."
);
const localDateBuilder = new LocalDateBuilder(
opts,
currentUserTZ
).build();
const htmlPreviews = localDateBuilder.previews.map((preview) => {
const previewNode = document.createElement("div");
previewNode.classList.add("preview");
if (preview.current) {
previewNode.classList.add("current");
}
const timezoneNode = document.createElement("span");
timezoneNode.classList.add("timezone");
timezoneNode.innerText = preview.timezone;
previewNode.appendChild(timezoneNode);
const dateTimeNode = document.createElement("span");
dateTimeNode.classList.add("date-time");
dateTimeNode.innerText = preview.formated;
previewNode.appendChild(dateTimeNode);
return previewNode;
});
const previewsNode = document.createElement("div");
previewsNode.classList.add("locale-dates-previews");
htmlPreviews.forEach((htmlPreview) =>
previewsNode.appendChild(htmlPreview)
);
this.innerText = "";
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);
});
return applyLocalDates(this.toArray(), siteSettings);
};
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) {
helper.allowList([
"span.discourse-local-date",
"span[data-*]",
"span[aria-label]",
]);
helper.allowList(["span.discourse-local-date", "span[aria-label]"]);
helper.registerOptions((opts, siteSettings) => {
opts.datesEmailFormat = siteSettings.discourse_local_dates_email_format;

View File

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