From 519f52238e083743fbe66f2553eb7e69d6a6819a Mon Sep 17 00:00:00 2001 From: jjaffeux Date: Fri, 7 Aug 2020 21:43:55 +0200 Subject: [PATCH] FEATURE: allows to manually close an event --- .../discourse-post-event-builder.js.es6 | 75 ++++--------------- .../widgets/discourse-post-event.js.es6 | 39 +++++++++- .../discourse/widgets/more-dropdown.js.es6 | 24 ++++-- .../javascripts/lib/raw-event-helper.js.es6 | 56 ++++++++++++++ .../common/discourse-post-event.scss | 7 ++ config/locales/client.en.yml | 2 + 6 files changed, 131 insertions(+), 72 deletions(-) create mode 100644 assets/javascripts/lib/raw-event-helper.js.es6 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 12d968db..fd225e1c 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 bfa9a547..de3a9c15 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 ) }} diff --git a/assets/javascripts/discourse/widgets/more-dropdown.js.es6 b/assets/javascripts/discourse/widgets/more-dropdown.js.es6 index f19b035d..f313c8e9 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", - param: attrs.postEventId + param: attrs.eventModel.id }); + + if (!attrs.eventModel.is_expired) { + content.push({ + icon: "times", + id: "closePostEvent", + label: "discourse_post_event.event_ui.close_event", + class: "danger", + param: attrs.eventModel + }); + } } return content; diff --git a/assets/javascripts/lib/raw-event-helper.js.es6 b/assets/javascripts/lib/raw-event-helper.js.es6 new file mode 100644 index 00000000..2adbd576 --- /dev/null +++ b/assets/javascripts/lib/raw-event-helper.js.es6 @@ -0,0 +1,56 @@ +export function buildParams(startsAt, endsAt, eventModel) { + const params = {}; + + if (startsAt) { + params.start = moment(startsAt) + .utc() + .format("YYYY-MM-DD HH:mm"); + } else { + params.start = moment() + .utc() + .format("YYYY-MM-DD HH:mm"); + } + + if (eventModel.status) { + params.status = eventModel.status; + } + + if (eventModel.name) { + params.name = eventModel.name; + } + + if (eventModel.url) { + params.url = eventModel.url; + } + + if (endsAt) { + params.end = moment(endsAt) + .utc() + .format("YYYY-MM-DD HH:mm"); + } + + if (eventModel.status === "private") { + params.allowedGroups = (eventModel.raw_invitees || []).join(","); + } + + return params; +} + +export function replaceRaw(params, raw) { + const eventRegex = new RegExp(`\\[event\\s(.*?)\\]`, "m"); + const eventMatches = raw.match(eventRegex); + + if (eventMatches && eventMatches[1]) { + const markdownParams = []; + Object.keys(params).forEach(param => { + const value = params[param]; + if (value && value.length) { + markdownParams.push(`${param}="${params[param]}"`); + } + }); + + return raw.replace(eventRegex, `[event ${markdownParams.join(" ")}]`); + } + + return false; +} diff --git a/assets/stylesheets/common/discourse-post-event.scss b/assets/stylesheets/common/discourse-post-event.scss index b780e0c2..1d6fb9c6 100644 --- a/assets/stylesheets/common/discourse-post-event.scss +++ b/assets/stylesheets/common/discourse-post-event.scss @@ -62,6 +62,13 @@ display: none; } } + + .item-closePostEvent { + .d-icon, + span { + color: $danger; + } + } } } } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 4b80c78c..ad4aa4f1 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -305,6 +305,7 @@ en: export_event: Export event created_by: Created by bulk_invite: Bulk Invite + close_event: Close event invitees_modal: title_invited: "List of invited users" title_participated: "List of users who participated" @@ -326,6 +327,7 @@ en: create_event_title: Create Event update_event_title: Edit Event confirm_delete: Are you sure you want to delete this event? + confirm_close: Are you sure you want to close this event? create: Create update: Save attach: Create event