diff --git a/assets/javascripts/initializers/discourse-post-event-decorator.js.es6 b/assets/javascripts/initializers/discourse-post-event-decorator.js.es6
index c6548175..c3fbcbe9 100644
--- a/assets/javascripts/initializers/discourse-post-event-decorator.js.es6
+++ b/assets/javascripts/initializers/discourse-post-event-decorator.js.es6
@@ -9,53 +9,66 @@ function _decorateEvent(api, cooked, post) {
_attachWidget(api, cooked, post);
}
-function _decorateEventPreview(api, cooked) {
- const eventContainer = cooked.querySelector(".discourse-post-event");
+function _validEventPreview(eventContainer) {
+ eventContainer.innerHTML = "";
+ eventContainer.classList.add("discourse-post-event-preview");
- if (eventContainer) {
- if (!eventContainer.dataset.start) {
- return;
- }
-
- const eventPreviewContainer = document.createElement("div");
- eventPreviewContainer.classList.add("discourse-post-event-preview");
-
- const statusLocaleKey = `discourse_post_event.models.event.status.${eventContainer
- .dataset.status || "public"}.title`;
- if (I18n.lookup(statusLocaleKey, { locale: "en" })) {
- const statusContainer = document.createElement("div");
- statusContainer.classList.add("event-preview-status");
- statusContainer.innerText = I18n.t(statusLocaleKey);
- eventPreviewContainer.appendChild(statusContainer);
- }
-
- const datesContainer = document.createElement("div");
- datesContainer.classList.add("event-preview-dates");
-
- const startsAt = moment
- .utc(eventContainer.dataset.start)
- .tz(moment.tz.guess());
-
- const endsAtValue = eventContainer.dataset.end;
- const format = guessDateFormat(
- startsAt,
- endsAtValue && moment.utc(endsAtValue).tz(moment.tz.guess())
- );
-
- let datesString = `${startsAt.format(format)}`;
- if (endsAtValue) {
- datesString += ` → ${moment
- .utc(endsAtValue)
- .tz(moment.tz.guess())
- .format(format)}`;
- }
- datesContainer.innerHTML = datesString;
-
- eventPreviewContainer.appendChild(datesContainer);
-
- eventContainer.innerHTML = "";
- eventContainer.appendChild(eventPreviewContainer);
+ const statusLocaleKey = `discourse_post_event.models.event.status.${eventContainer
+ .dataset.status || "public"}.title`;
+ if (I18n.lookup(statusLocaleKey, { locale: "en" })) {
+ const statusContainer = document.createElement("div");
+ statusContainer.classList.add("event-preview-status");
+ statusContainer.innerText = I18n.t(statusLocaleKey);
+ eventContainer.appendChild(statusContainer);
}
+
+ const datesContainer = document.createElement("div");
+ datesContainer.classList.add("event-preview-dates");
+
+ const startsAt = moment
+ .utc(eventContainer.dataset.start)
+ .tz(moment.tz.guess());
+
+ const endsAtValue = eventContainer.dataset.end;
+ const format = guessDateFormat(
+ startsAt,
+ endsAtValue && moment.utc(endsAtValue).tz(moment.tz.guess())
+ );
+
+ let datesString = `${startsAt.format(format)}`;
+ if (endsAtValue) {
+ datesString += ` → ${moment
+ .utc(endsAtValue)
+ .tz(moment.tz.guess())
+ .format(format)}`;
+ }
+ datesContainer.innerHTML = datesString;
+
+ eventContainer.appendChild(datesContainer);
+}
+
+function _invalidEventPreview(eventContainer) {
+ eventContainer.classList.add(
+ "discourse-post-event-preview",
+ "alert",
+ "alert-error"
+ );
+ eventContainer.classList.remove("discourse-post-event");
+ eventContainer.innerText = I18n.t(
+ "discourse_post_event.preview.more_than_one_event"
+ );
+}
+
+function _decorateEventPreview(api, cooked) {
+ const eventContainers = cooked.querySelectorAll(".discourse-post-event");
+
+ eventContainers.forEach((eventContainer, index) => {
+ if (index > 0) {
+ _invalidEventPreview(eventContainer);
+ } else {
+ _validEventPreview(eventContainer);
+ }
+ });
}
let _glued = [];
diff --git a/assets/stylesheets/common/discourse-post-event-preview.scss b/assets/stylesheets/common/discourse-post-event-preview.scss
index 8b73c019..2df21b7f 100644
--- a/assets/stylesheets/common/discourse-post-event-preview.scss
+++ b/assets/stylesheets/common/discourse-post-event-preview.scss
@@ -1,11 +1,11 @@
.discourse-post-event-preview {
background: $secondary;
- display: flex;
- flex: 1 0 auto;
align-items: center;
flex-direction: column;
padding: 0.5em;
border: 1px solid $primary-low;
+ display: flex;
+ flex: 1 0 auto;
.event-preview-status {
margin: 0 0 0.5em 0;
@@ -14,4 +14,12 @@
.event-preview-dates {
font-weight: 700;
}
+
+ &.alert-error {
+ border-color: lighten($danger, 25);
+ }
+}
+
+.discourse-post-event-preview + .discourse-post-event-preview {
+ margin-top: 1em;
}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 0af8c815..52d6d389 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -19,6 +19,8 @@ en:
search: "Search..."
group_availability: "%{group} availability"
discourse_post_event:
+ preview:
+ more_than_one_event: You can’t have more than one event.
edit_reason: Event updated
models:
invitee:
diff --git a/test/javascripts/acceptance/discourse-post-event/composer-preview-test.js.es6 b/test/javascripts/acceptance/discourse-post-event/composer-preview-test.js.es6
new file mode 100644
index 00000000..c241f757
--- /dev/null
+++ b/test/javascripts/acceptance/discourse-post-event/composer-preview-test.js.es6
@@ -0,0 +1,85 @@
+import discoursePostEventAcceptance, {
+ utcToLocal
+} from "./discourse-post-event-helper";
+
+discoursePostEventAcceptance("composer-preview");
+
+test("an event with a start date", async assert => {
+ await visit("/");
+ await click("#create-topic");
+ await fillIn(".d-editor-input", '[event start="2020-02-03"]\n[/event]');
+
+ const preview = find(".d-editor-preview .discourse-post-event");
+ assert.ok(exists(preview), "it creates the preview");
+ assert.equal(
+ preview.find(".event-preview-status").text(),
+ I18n.t("discourse_post_event.models.event.status.public.title"),
+ "it displays the status"
+ );
+ assert.equal(
+ preview.find(".event-preview-dates .start").text(),
+ utcToLocal("2020-02-03"),
+ "it displays the start date"
+ );
+});
+
+test("an event with a start date and end date", async assert => {
+ await visit("/");
+ await click("#create-topic");
+ await fillIn(
+ ".d-editor-input",
+ '[event start="2020-02-03" end="2002-03-04"]\n[/event]'
+ );
+
+ const preview = find(".d-editor-preview .discourse-post-event");
+ assert.equal(
+ preview.find(".event-preview-dates .start").text(),
+ utcToLocal("2020-02-03"),
+ "it displays the start date"
+ );
+ assert.equal(
+ preview.find(".event-preview-dates .end").text(),
+ utcToLocal("2002-03-04"),
+ "it displays the start date"
+ );
+});
+
+test("an event with a status", async assert => {
+ await visit("/");
+ await click("#create-topic");
+ await fillIn(
+ ".d-editor-input",
+ '[event status="private" start="2020-02-03"]\n[/event]'
+ );
+
+ const preview = find(".d-editor-preview .discourse-post-event");
+ assert.equal(
+ preview.find(".event-preview-status").text(),
+ I18n.t("discourse_post_event.models.event.status.private.title"),
+ "it displays the status"
+ );
+});
+
+test("more than one event", async assert => {
+ await visit("/");
+ await click("#create-topic");
+ await fillIn(
+ ".d-editor-input",
+ '[event start="2020-02-03"]\n[/event]\n\n[event start="2021-04-03"]\n[/event]'
+ );
+
+ const preview = find(
+ ".d-editor-preview .discourse-post-event-preview[data-start=2020-02-03]"
+ );
+ assert.ok(exists(preview), "it displays the first event");
+
+ const errorPreview = find(
+ ".d-editor-preview .discourse-post-event-preview.alert-error"
+ );
+ assert.ok(exists(errorPreview), "it displays the error");
+ assert.equal(
+ errorPreview.text(),
+ I18n.t("discourse_post_event.preview.more_than_one_event"),
+ "it displays the error"
+ );
+});
diff --git a/test/javascripts/acceptance/discourse-post-event/discourse-post-event-helper.js.es6 b/test/javascripts/acceptance/discourse-post-event/discourse-post-event-helper.js.es6
new file mode 100644
index 00000000..ece8122c
--- /dev/null
+++ b/test/javascripts/acceptance/discourse-post-event/discourse-post-event-helper.js.es6
@@ -0,0 +1,26 @@
+import { acceptance } from "helpers/qunit-helpers";
+
+export function utcToLocal(date, format = "LLL") {
+ return moment
+ .utc(date)
+ .local()
+ .format(format);
+}
+
+export default function discoursePostEventAcceptance(moduleName, options = {}) {
+ acceptance(
+ `discourse-post-event/${moduleName}`,
+ Object.assign(
+ {},
+ {
+ settings: {
+ calendar_enabled: true,
+ discourse_post_event_enabled: true
+ },
+
+ loggedIn: true
+ },
+ options
+ )
+ );
+}