FEATURE: allows to manually close an event

FEATURE: allows to manually close an event

diff --git a/assets/javascripts/discourse/controllers/discourse-post-event-builder.js.es6 b/assets/javascripts/discourse/controllers/discourse-post-event-builder.js.es6
index 12d968d..fd225e1 100644
--- a/assets/javascripts/discourse/controllers/discourse-post-event-builder.js.es6
+++ b/assets/javascripts/discourse/controllers/discourse-post-event-builder.js.es6
@@ -8,6 +8,8 @@ import { equal } from "@ember/object/computed";
 import { extractError } from "discourse/lib/ajax-error";
 import { Promise } from "rsvp";
 
+import { buildParams, replaceRaw } from "../../lib/raw-event-helper";
+
 export default Controller.extend(ModalFunctionality, {
   init() {
     this._super(...arguments);
@@ -116,7 +118,11 @@ export default Controller.extend(ModalFunctionality, {
       return;
     }
 
-    const eventParams = this._buildEventParams();
+    const eventParams = buildParams(
+      this.startsAt,
+      this.endsAt,
+      this.model.eventModel
+    );
     const markdownParams = [];
     Object.keys(eventParams).forEach(key => {
       let value = eventParams[key];
@@ -145,8 +151,12 @@ export default Controller.extend(ModalFunctionality, {
 
       const updateRawPromise = new Promise(resolve => {
         const raw = post.raw;
-        const eventParams = this._buildEventParams();
-        const newRaw = this._replaceRawEvent(eventParams, raw);
+        const eventParams = buildParams(
+          this.startsAt,
+          this.endsAt,
+          this.model.eventModel
+        );
+        const newRaw = replaceRaw(eventParams, raw);
 
         if (newRaw) {
           const props = {
@@ -171,67 +181,8 @@ export default Controller.extend(ModalFunctionality, {
     });
   },
 
-  _buildEventParams() {
-    const eventParams = {};
-
-    if (this.startsAt) {
-      eventParams.start = moment(this.startsAt)
-        .utc()
-        .format("YYYY-MM-DD HH:mm");
-    } else {
-      eventParams.start = moment()
-        .utc()
-        .format("YYYY-MM-DD HH:mm");
-    }
-
-    if (this.model.eventModel.status) {
-      eventParams.status = this.model.eventModel.status;
-    }
-
-    if (this.model.eventModel.name) {
-      eventParams.name = this.model.eventModel.name;
-    }
-
-    if (this.model.eventModel.url) {
-      eventParams.url = this.model.eventModel.url;
-    }
-
-    if (this.endsAt) {
-      eventParams.end = moment(this.endsAt)
-        .utc()
-        .format("YYYY-MM-DD HH:mm");
-    }
-
-    if (this.model.eventModel.status === "private") {
-      eventParams.allowedGroups = (
-        this.model.eventModel.raw_invitees || []
-      ).join(",");
-    }
-
-    return eventParams;
-  },
-
   _removeRawEvent(raw) {
     const eventRegex = new RegExp(`\\[event\\s(.*?)\\]\\n\\[\\/event\\]`, "m");
     return raw.replace(eventRegex, "");
-  },
-
-  _replaceRawEvent(eventParams, raw) {
-    const eventRegex = new RegExp(`\\[event\\s(.*?)\\]`, "m");
-    const eventMatches = raw.match(eventRegex);
-
-    if (eventMatches && eventMatches[1]) {
-      const markdownParams = [];
-      Object.keys(eventParams).forEach(eventParam => {
-        const value = eventParams[eventParam];
-        if (value && value.length) {
-          markdownParams.push(`${eventParam}="${eventParams[eventParam]}"`);
-        }
-      });
-
-      return raw.replace(eventRegex, `[event ${markdownParams.join(" ")}]`);
-    }
-
-    return false;
   }
 });
diff --git a/assets/javascripts/discourse/widgets/discourse-post-event.js.es6 b/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
index bfa9a54..de3a9c1 100644
--- a/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
+++ b/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
@@ -1,3 +1,4 @@
+import TextLib from "discourse/lib/text";
 import { exportEntity } from "discourse/lib/export-csv";
 import { emojiUnescape } from "discourse/lib/text";
 import cleanTitle from "discourse/plugins/discourse-calendar/lib/clean-title";
@@ -8,6 +9,7 @@ import hbs from "discourse/widgets/hbs-compiler";
 import { createWidget } from "discourse/widgets/widget";
 import { routeAction } from "discourse/helpers/route-action";
 import getURL from "discourse-common/lib/get-url";
+import { buildParams, replaceRaw } from "../../lib/raw-event-helper";
 
 export default createWidget("discourse-post-event", {
   tagName: "div.discourse-post-event-widget",
@@ -53,6 +55,39 @@ export default createWidget("discourse-post-event", {
     });
   },
 
+  closePostEvent(eventModel) {
+    bootbox.confirm(
+      I18n.t("discourse_post_event.builder_modal.confirm_close"),
+      I18n.t("no_value"),
+      I18n.t("yes_value"),
+      confirmed => {
+        if (confirmed) {
+          return this.store.find("post", eventModel.id).then(post => {
+            const raw = post.raw;
+            const eventParams = buildParams(
+              eventModel.starts_at ? moment(eventModel.starts_at) : moment(),
+              moment(),
+              eventModel
+            );
+            const newRaw = replaceRaw(eventParams, raw);
+
+            if (newRaw) {
+              const props = {
+                raw: newRaw,
+                edit_reason: I18n.t("discourse_post_event.edit_reason")
+              };
+
+              return TextLib.cookAsync(newRaw).then(cooked => {
+                props.cooked = cooked.string;
+                return post.save(props);
+              });
+            }
+          });
+        }
+      }
+    );
+  },
+
   changeWatchingInviteeStatus(status) {
     if (this.state.eventModel.watching_invitee) {
       this.store.update(
@@ -167,10 +202,8 @@ export default createWidget("discourse-post-event", {
           widget="more-dropdown"
           attrs=(hash
             canActOnEvent=this.transformed.canActOnEvent
-            postEventId=state.eventModel.id
-            isExpired=state.eventModel.is_expired
-            creatorUsername=state.eventModel.creator.username
             isPublicEvent=this.transformed.isPublicEvent
+            eventModel=state.eventModel
           )
         }}
       </header>
diff --git a/assets/javascripts/discourse/widgets/more-dropdown.js.es6 b/assets/javascripts/discourse/widgets/more-dropdown.js.es6
index f19b035..f313c8e 100644
--- a/assets/javascripts/discourse/widgets/more-dropdown.js.es6
+++ b/assets/javascripts/discourse/widgets/more-dropdown.js.es6
@@ -38,7 +38,7 @@ export default createWidget("more-dropdown", {
   _buildContent(attrs) {
     const content = [];
 
-    if (!attrs.isExpired) {
+    if (!attrs.eventModel.is_expired) {
       content.push({
         id: "addToCalendar",
         icon: "file",
@@ -52,17 +52,17 @@ export default createWidget("more-dropdown", {
         icon: "envelope",
         translatedLabel: I18n.t(
           "discourse_post_event.event_ui.send_pm_to_creator",
-          { username: attrs.creatorUsername }
+          { username: attrs.eventModel.creator.username }
         )
       });
     }
 
-    if (!attrs.isExpired && attrs.canActOnEvent && attrs.isPublicEvent) {
+    if (!attrs.is_expired && attrs.canActOnEvent && attrs.isPublicEvent) {
       content.push({
         id: "inviteUserOrGroup",
         icon: "user-plus",
         label: "discourse_post_event.event_ui.invite",
-        param: attrs.postEventId
+        param: attrs.eventModel.id
       });
     }
 
@@ -73,22 +73,32 @@ export default createWidget("more-dropdown", {
         icon: "file-csv",
         id: "exportPostEvent",
         label: "discourse_post_event.event_ui.export_event",
-        param: attrs.postEventId
+        param: attrs.eventModel.id
       });
 
       content.push({
         icon: "file-upload",
         id: "bulkInvite",
         label: "discourse_post_event.event_ui.bulk_invite",
-        param: attrs.postEventId
+        param: attrs.eventModel.id
       });
 
       content.push({
         icon: "pencil-alt",
         id: "editPostEvent",
         label: "discourse_post_event.event_ui.edit_event",

[... diff too long, it was truncated ...]

GitHub sha: 519f5223