mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 02:51:14 +08:00
FEATURE: save local date to calendar (#14486)
It allows saving local date to calendar. Modal is giving option to pick between ics and google. User choice can be remembered as a default for the next actions.
This commit is contained in:

committed by
GitHub

parent
6ab5f70090
commit
cb5b0cb9d8
@ -4,6 +4,8 @@ import { hidePopover, showPopover } from "discourse/lib/d-popover";
|
||||
import LocalDateBuilder from "../lib/local-date-builder";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { downloadCalendar } from "discourse/lib/download-calendar";
|
||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||
|
||||
export function applyLocalDates(dates, siteSettings) {
|
||||
if (!siteSettings.discourse_local_dates_enabled) {
|
||||
@ -162,9 +164,54 @@ function buildHtmlPreview(element, siteSettings) {
|
||||
previewsNode.classList.add("locale-dates-previews");
|
||||
htmlPreviews.forEach((htmlPreview) => previewsNode.appendChild(htmlPreview));
|
||||
|
||||
previewsNode.appendChild(_downloadCalendarNode(element));
|
||||
|
||||
return previewsNode.outerHTML;
|
||||
}
|
||||
|
||||
function _downloadCalendarNode(element) {
|
||||
const node = document.createElement("div");
|
||||
node.classList.add("download-calendar");
|
||||
node.innerHTML = `${renderIcon("string", "file")} ${I18n.t(
|
||||
"download_calendar.add_to_calendar"
|
||||
)}`;
|
||||
const [startDataset, endDataset] = _rangeElements(element).map(
|
||||
(dateElement) => dateElement.dataset
|
||||
);
|
||||
node.setAttribute(
|
||||
"data-starts-at",
|
||||
moment
|
||||
.tz(
|
||||
`${startDataset.date} ${startDataset.time || ""}`,
|
||||
startDataset.timezone
|
||||
)
|
||||
.toISOString()
|
||||
);
|
||||
if (endDataset) {
|
||||
node.setAttribute(
|
||||
"data-ends-at",
|
||||
moment
|
||||
.tz(`${endDataset.date} ${endDataset.time || ""}`, endDataset.timezone)
|
||||
.toISOString()
|
||||
);
|
||||
}
|
||||
if (!startDataset.time && !endDataset) {
|
||||
node.setAttribute(
|
||||
"data-ends-at",
|
||||
moment
|
||||
.tz(`${startDataset.date}`, startDataset.timezone)
|
||||
.add(24, "hours")
|
||||
.toISOString()
|
||||
);
|
||||
}
|
||||
node.setAttribute(
|
||||
"data-title",
|
||||
document.querySelector("#topic-title a").innerText
|
||||
);
|
||||
node.setAttribute("data-post-id", element.closest("article").dataset.postId);
|
||||
return node;
|
||||
}
|
||||
|
||||
function _calculateDuration(element) {
|
||||
const [startDataset, endDataset] = _rangeElements(element).map(
|
||||
(dateElement) => dateElement.dataset
|
||||
@ -199,6 +246,17 @@ export default {
|
||||
htmlContent: buildHtmlPreview(event.target, siteSettings),
|
||||
});
|
||||
}
|
||||
} else if (event?.target?.classList?.contains("download-calendar")) {
|
||||
const dataset = event.target.dataset;
|
||||
hidePopover(event);
|
||||
downloadCalendar(dataset.postId, dataset.title, [
|
||||
{
|
||||
startsAt: dataset.startsAt,
|
||||
endsAt: dataset.endsAt,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
hidePopover(event);
|
||||
}
|
||||
},
|
||||
|
||||
@ -213,7 +271,6 @@ export default {
|
||||
router.on("routeWillChange", hidePopover);
|
||||
|
||||
window.addEventListener("click", this.showDatePopover);
|
||||
window.addEventListener("mouseout", this.hideDatePopover);
|
||||
|
||||
const siteSettings = container.lookup("site-settings:main");
|
||||
if (siteSettings.discourse_local_dates_enabled) {
|
||||
@ -231,6 +288,5 @@ export default {
|
||||
|
||||
teardown() {
|
||||
window.removeEventListener("click", this.showDatePopover);
|
||||
window.removeEventListener("mouseout", this.hideDatePopover);
|
||||
},
|
||||
};
|
||||
|
@ -40,6 +40,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.download-calendar {
|
||||
text-align: right;
|
||||
cursor: pointer;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.discourse-local-dates-create-modal-footer {
|
||||
|
@ -0,0 +1,68 @@
|
||||
import {
|
||||
acceptance,
|
||||
exists,
|
||||
query,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { click, visit } from "@ember/test-helpers";
|
||||
import I18n from "I18n";
|
||||
import { test } from "qunit";
|
||||
import { fixturesByUrl } from "discourse/tests/helpers/create-pretender";
|
||||
import sinon from "sinon";
|
||||
|
||||
acceptance(
|
||||
"Local Dates - Download calendar without default calendar option set",
|
||||
function (needs) {
|
||||
needs.user({ default_calendar: "none_selected" });
|
||||
needs.settings({ discourse_local_dates_enabled: true });
|
||||
needs.pretender((server, helper) => {
|
||||
const response = { ...fixturesByUrl["/t/281.json"] };
|
||||
server.get("/t/281.json", () => helper.response(response));
|
||||
});
|
||||
|
||||
test("Display pick calendar modal", async function (assert) {
|
||||
await visit("/t/local-dates/281");
|
||||
|
||||
await click(".discourse-local-date");
|
||||
await click(document.querySelector(".download-calendar"));
|
||||
assert.equal(
|
||||
query("#discourse-modal-title").textContent.trim(),
|
||||
I18n.t("download_calendar.title"),
|
||||
"it should display modal to select calendar"
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
acceptance(
|
||||
"Local Dates - Download calendar with default calendar option set",
|
||||
function (needs) {
|
||||
needs.user({ default_calendar: "google" });
|
||||
needs.settings({ discourse_local_dates_enabled: true });
|
||||
needs.pretender((server, helper) => {
|
||||
const response = { ...fixturesByUrl["/t/281.json"] };
|
||||
server.get("/t/281.json", () => helper.response(response));
|
||||
});
|
||||
|
||||
needs.hooks.beforeEach(function () {
|
||||
let win = { focus: function () {} };
|
||||
sinon.stub(window, "open").returns(win);
|
||||
sinon.stub(win, "focus");
|
||||
});
|
||||
|
||||
test("saves into default calendar", async function (assert) {
|
||||
await visit("/t/local-dates/281");
|
||||
|
||||
await click(".discourse-local-date");
|
||||
await click(document.querySelector(".download-calendar"));
|
||||
assert.ok(!exists(document.querySelector("#discourse-modal-title")));
|
||||
assert.ok(
|
||||
window.open.calledWith(
|
||||
"https://www.google.com/calendar/event?action=TEMPLATE&text=Local%20dates%20&dates=20210930T110000Z/20210930T120000Z",
|
||||
"_blank",
|
||||
"noopener",
|
||||
"noreferrer"
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
Reference in New Issue
Block a user