mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
PERF: generates dates tooltip on demand (#13944)
This commit is contained in:
@ -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,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 {
|
export default {
|
||||||
name: "discourse-local-dates",
|
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) {
|
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");
|
const siteSettings = container.lookup("site-settings:main");
|
||||||
if (siteSettings.discourse_local_dates_enabled) {
|
if (siteSettings.discourse_local_dates_enabled) {
|
||||||
const currentUserTZ = moment.tz.guess();
|
|
||||||
|
|
||||||
$.fn.applyLocalDates = function () {
|
$.fn.applyLocalDates = function () {
|
||||||
return this.each(function () {
|
deprecated(
|
||||||
const opts = {};
|
"`$.applyLocalDates()` is deprecated, import and use `applyLocalDates()` instead."
|
||||||
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(
|
return applyLocalDates(this.toArray(), siteSettings);
|
||||||
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);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user