From d135b764d5d58d68518d70e606cd9384c47431e2 Mon Sep 17 00:00:00 2001 From: Ian Morland Date: Mon, 3 Jan 2022 13:57:38 +0000 Subject: [PATCH 1/5] Notification on merge --- extend.php | 9 +- js/src/forum/addNotifications.js | 8 ++ .../DiscussionMergedNotification.js | 26 +++++ js/src/forum/extend/extendNotifications.ts | 14 +++ js/src/forum/index.js | 3 + resources/locale/en.yml | 3 + .../views/emails/discussionMerged.blade.php | 6 + ...SendNotificationWhenDiscussionIsMerged.php | 60 ++++++++++ .../NotifyParticipantsWhenMerged.php | 25 ++++ .../DiscussionMergedBlueprint.php | 110 ++++++++++++++++++ 10 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 js/src/forum/addNotifications.js create mode 100644 js/src/forum/components/DiscussionMergedNotification.js create mode 100644 js/src/forum/extend/extendNotifications.ts create mode 100644 resources/views/emails/discussionMerged.blade.php create mode 100644 src/Jobs/SendNotificationWhenDiscussionIsMerged.php create mode 100644 src/Listeners/NotifyParticipantsWhenMerged.php create mode 100644 src/Notification/DiscussionMergedBlueprint.php diff --git a/extend.php b/extend.php index 259a96d..f40b683 100644 --- a/extend.php +++ b/extend.php @@ -34,7 +34,8 @@ ->type(DiscussionMergePost::class), (new Extend\Event()) - ->listen(DiscussionWasMerged::class, Listeners\CreatePostWhenMerged::class), + ->listen(DiscussionWasMerged::class, Listeners\CreatePostWhenMerged::class) + ->listen(DiscussionWasMerged::class, Listeners\NotifyParticipantsWhenMerged::class), (new Extend\ApiSerializer(DiscussionSerializer::class)) ->attribute('canMerge', function (DiscussionSerializer $serializer, AbstractModel $discussion) { @@ -43,4 +44,10 @@ (new Extend\Settings()) ->serializeToForum('fof-merge-discussions.search_limit', 'fof-merge-discussions.search_limit', 'intVal', 4), + + (new Extend\View()) + ->namespace('fof-merge-discussions', __DIR__.'/resources/views'), + + (new Extend\Notification()) + ->type(Notification\DiscussionMergedBlueprint::class, DiscussionSerializer::class, ['alert', 'email']), ]; diff --git a/js/src/forum/addNotifications.js b/js/src/forum/addNotifications.js new file mode 100644 index 0000000..7497c69 --- /dev/null +++ b/js/src/forum/addNotifications.js @@ -0,0 +1,8 @@ +import app from 'flarum/forum/app'; +import DiscussionMergedNotification from './components/DiscussionMergedNotification'; +import extendNotifications from "./extend/extendNotifications"; + +export default function() { + app.notificationComponents.discussionMerged = DiscussionMergedNotification; + extendNotifications(); +} diff --git a/js/src/forum/components/DiscussionMergedNotification.js b/js/src/forum/components/DiscussionMergedNotification.js new file mode 100644 index 0000000..a51f3b6 --- /dev/null +++ b/js/src/forum/components/DiscussionMergedNotification.js @@ -0,0 +1,26 @@ +import app from 'flarum/forum/app'; +import Notification from 'flarum/forum/components/Notification'; + +export default class DiscussionMergedNotification extends Notification { + icon() { + return 'fas fa-code-branch fa-flip-vertical'; + } + + href() { + const notification = this.attrs.notification; + const discussion = notification.subject(); + + return app.route.discussion(discussion); + } + + content() { + const notification = this.attrs.notification; + const user = notification.fromUser(); + const oldTitle = notification.content(); + + return app.translator.trans('fof-merge-discussions.forum.notification.discussion_merged', { + user, + oldTitle + }); + } +} diff --git a/js/src/forum/extend/extendNotifications.ts b/js/src/forum/extend/extendNotifications.ts new file mode 100644 index 0000000..02c51ce --- /dev/null +++ b/js/src/forum/extend/extendNotifications.ts @@ -0,0 +1,14 @@ +import app from 'flarum/forum/app'; +import { extend } from 'flarum/common/extend'; +import ItemList from 'flarum/common/utils/ItemList'; +import NotificationGrid from 'flarum/forum/components/NotificationGrid'; + +export default function () { + extend(NotificationGrid.prototype, 'notificationTypes', function (items: ItemList) { + items.add('discussionMerged', { + name: 'discussionMerged', + icon: 'fas fa-code-branch fa-flip-vertical', + label: app.translator.trans('fof-merge-discussions.forum.notification.preferences.discussion_merged'), + }); + }); +} diff --git a/js/src/forum/index.js b/js/src/forum/index.js index fc50d6a..c5f437f 100644 --- a/js/src/forum/index.js +++ b/js/src/forum/index.js @@ -6,6 +6,7 @@ import DiscussionControls from 'flarum/forum/utils/DiscussionControls'; import DiscussionMergeModal from './components/DiscussionMergeModal'; import DiscussionMergePost from './components/DiscussionMergePost'; +import addNotifications from './addNotifications'; app.initializers.add('fof/merge-discussions', () => { app.store.models.discussions.prototype.canMerge = Model.attribute('canMerge'); @@ -26,4 +27,6 @@ app.initializers.add('fof/merge-discussions', () => { ) ); }); + + addNotifications(); }); diff --git a/resources/locale/en.yml b/resources/locale/en.yml index 8c7247f..4386a17 100644 --- a/resources/locale/en.yml +++ b/resources/locale/en.yml @@ -12,6 +12,9 @@ fof-merge-discussions: load_preview_button: Preview submit_button: => fof-merge-discussions.ref.merge + notification: + discussion_merged: Your discussion {oldTitle} was merged into this discussion by {username}. + discussion: merge: => fof-merge-discussions.ref.merge diff --git a/resources/views/emails/discussionMerged.blade.php b/resources/views/emails/discussionMerged.blade.php new file mode 100644 index 0000000..baf594d --- /dev/null +++ b/resources/views/emails/discussionMerged.blade.php @@ -0,0 +1,6 @@ +{!! $translator->trans('fof-merge-discussions.email.body.merged', [ + '{recipient_display_name}' => $user->display_name, + '{actor_display_name}' => $blueprint->actor->display_name, + '{discussion_title}' => $blueprint->discussion->title, + '{discussion_url}' => $url->to('forum')->route('discussion', ['id' => $blueprint->discussion->id]), +]) !!} diff --git a/src/Jobs/SendNotificationWhenDiscussionIsMerged.php b/src/Jobs/SendNotificationWhenDiscussionIsMerged.php new file mode 100644 index 0000000..ec7e62a --- /dev/null +++ b/src/Jobs/SendNotificationWhenDiscussionIsMerged.php @@ -0,0 +1,60 @@ +discussion = $discussion; + $this->mergedDiscussions = $mergedDiscussions; + $this->actor = $actor; + } + + public function handle(NotificationSyncer $notifications): void + { + foreach ($this->mergedDiscussions as $mergedDiscussion) { + /** @var Discussion $mergedDiscussion */ + $user = User::find($mergedDiscussion->user_id); + + if ($user) { + $notifications->sync(new DiscussionMergedBlueprint($this->discussion, $this->actor, $mergedDiscussion), [$user]); + } + } + } +} diff --git a/src/Listeners/NotifyParticipantsWhenMerged.php b/src/Listeners/NotifyParticipantsWhenMerged.php new file mode 100644 index 0000000..03c9444 --- /dev/null +++ b/src/Listeners/NotifyParticipantsWhenMerged.php @@ -0,0 +1,25 @@ +push( + new Jobs\SendNotificationWhenDiscussionIsMerged($event->discussion, $event->mergedDiscussions, $event->actor) + ); + } +} diff --git a/src/Notification/DiscussionMergedBlueprint.php b/src/Notification/DiscussionMergedBlueprint.php new file mode 100644 index 0000000..643db7d --- /dev/null +++ b/src/Notification/DiscussionMergedBlueprint.php @@ -0,0 +1,110 @@ +discussion = $discussion; + $this->actor = $actor; + $this->mergedDiscussion = $mergedDiscussion; + } + + /** + * Get the user that sent the notification. + */ + public function getFromUser() + { + return $this->actor; + } + + /** + * Get the model that is the subject of this activity. + */ + public function getSubject() + { + return $this->discussion; + } + + /** + * Get the data to be stored in the notification. + */ + public function getData() + { + return $this->mergedDiscussion->title; + } + + /** + * Get the serialized type of this activity. + * + * @return string + */ + public static function getType() + { + return 'discussionMerged'; + } + + /** + * Get the name of the model class for the subject of this activity. + * + * @return string + */ + public static function getSubjectModel() + { + return Discussion::class; + } + + /** + * Get the name of the view to construct a notification email with. + * + * @return string + */ + public function getEmailView() + { + return ['text' => 'fof-merge-discussions::emails.discussionMerged']; + } + + /** + * Get the subject line for the notification email. + * + * @return string + */ + public function getEmailSubject(TranslatorInterface $translator) + { + return $translator->trans('fof-merge-discussions.email.subject.merged', [ + '{display_name}' => $this->actor->display_name, + '{discussion_title}' => $this->discussion->title, + ]); + } +} From 664484f95fe1d619b51a019883e585347022b584 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 3 Jan 2022 13:57:58 +0000 Subject: [PATCH 2/5] Apply fixes from StyleCI --- src/Jobs/SendNotificationWhenDiscussionIsMerged.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jobs/SendNotificationWhenDiscussionIsMerged.php b/src/Jobs/SendNotificationWhenDiscussionIsMerged.php index ec7e62a..fe81f0d 100644 --- a/src/Jobs/SendNotificationWhenDiscussionIsMerged.php +++ b/src/Jobs/SendNotificationWhenDiscussionIsMerged.php @@ -51,7 +51,7 @@ public function handle(NotificationSyncer $notifications): void foreach ($this->mergedDiscussions as $mergedDiscussion) { /** @var Discussion $mergedDiscussion */ $user = User::find($mergedDiscussion->user_id); - + if ($user) { $notifications->sync(new DiscussionMergedBlueprint($this->discussion, $this->actor, $mergedDiscussion), [$user]); } From e7f8d11fe14a402fa1f34b0a245f70dbf13a38ec Mon Sep 17 00:00:00 2001 From: Ian Morland Date: Mon, 3 Jan 2022 14:47:02 +0000 Subject: [PATCH 3/5] Translations --- composer.json | 7 ++++++- .../forum/components/DiscussionMergedNotification.js | 3 ++- resources/locale/en.yml | 12 ++++++++++++ resources/views/emails/discussionMerged.blade.php | 3 ++- src/Notification/DiscussionMergedBlueprint.php | 8 ++++++-- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 4c7d181..17a8d82 100644 --- a/composer.json +++ b/composer.json @@ -19,13 +19,18 @@ } ], "require": { - "flarum/core": "^1.0.0" + "flarum/core": "^1.1.0" }, "authors": [ { "name": "David Sevilla Martín", "email": "me+fof@datitisev.me", "role": "Developer" + }, + { + "name": "IanM", + "email": "ian@blomstra.net", + "role": "Developer" } ], "autoload": { diff --git a/js/src/forum/components/DiscussionMergedNotification.js b/js/src/forum/components/DiscussionMergedNotification.js index a51f3b6..207b7e5 100644 --- a/js/src/forum/components/DiscussionMergedNotification.js +++ b/js/src/forum/components/DiscussionMergedNotification.js @@ -16,7 +16,8 @@ export default class DiscussionMergedNotification extends Notification { content() { const notification = this.attrs.notification; const user = notification.fromUser(); - const oldTitle = notification.content(); + const oldDiscussion = notification.content(); + const oldTitle = oldDiscussion.merged_title; return app.translator.trans('fof-merge-discussions.forum.notification.discussion_merged', { user, diff --git a/resources/locale/en.yml b/resources/locale/en.yml index 4386a17..2ee7f1b 100644 --- a/resources/locale/en.yml +++ b/resources/locale/en.yml @@ -14,6 +14,8 @@ fof-merge-discussions: notification: discussion_merged: Your discussion {oldTitle} was merged into this discussion by {username}. + preferences: + discussion_merged: A moderator merges one of my discussions with another discussion: merge: => fof-merge-discussions.ref.merge @@ -37,3 +39,13 @@ fof-merge-discussions: ref: merge: Merge + + email: + merged: + body: | + Hey {recipient_display_name}, + + Your discussion, {merged_discussion_title}, was merged into {discussion_title} by {actor_display_name} + + View it here {discussion_url} + subject: Your discussion "{merged_discussion_title}" was merged diff --git a/resources/views/emails/discussionMerged.blade.php b/resources/views/emails/discussionMerged.blade.php index baf594d..49ba725 100644 --- a/resources/views/emails/discussionMerged.blade.php +++ b/resources/views/emails/discussionMerged.blade.php @@ -1,6 +1,7 @@ -{!! $translator->trans('fof-merge-discussions.email.body.merged', [ +{!! $translator->trans('fof-merge-discussions.email.merged.body', [ '{recipient_display_name}' => $user->display_name, '{actor_display_name}' => $blueprint->actor->display_name, + '{merged_discussion_title}' => $blueprint->mergedDiscussion->title, '{discussion_title}' => $blueprint->discussion->title, '{discussion_url}' => $url->to('forum')->route('discussion', ['id' => $blueprint->discussion->id]), ]) !!} diff --git a/src/Notification/DiscussionMergedBlueprint.php b/src/Notification/DiscussionMergedBlueprint.php index 643db7d..fe319ff 100644 --- a/src/Notification/DiscussionMergedBlueprint.php +++ b/src/Notification/DiscussionMergedBlueprint.php @@ -62,7 +62,10 @@ public function getSubject() */ public function getData() { - return $this->mergedDiscussion->title; + return [ + 'merged_title' => $this->mergedDiscussion->title, + 'merged_id' => $this->mergedDiscussion->id, + ]; } /** @@ -102,9 +105,10 @@ public function getEmailView() */ public function getEmailSubject(TranslatorInterface $translator) { - return $translator->trans('fof-merge-discussions.email.subject.merged', [ + return $translator->trans('fof-merge-discussions.email.merged.subject', [ '{display_name}' => $this->actor->display_name, '{discussion_title}' => $this->discussion->title, + '{merged_discussion_title}' => $this->mergedDiscussion->title, ]); } } From c9c8f2388dbc2e8319c4141f38930fce76db55b8 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Mon, 3 Jan 2022 14:47:11 +0000 Subject: [PATCH 4/5] Apply fixes from StyleCI --- src/Notification/DiscussionMergedBlueprint.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Notification/DiscussionMergedBlueprint.php b/src/Notification/DiscussionMergedBlueprint.php index fe319ff..b23d895 100644 --- a/src/Notification/DiscussionMergedBlueprint.php +++ b/src/Notification/DiscussionMergedBlueprint.php @@ -64,7 +64,7 @@ public function getData() { return [ 'merged_title' => $this->mergedDiscussion->title, - 'merged_id' => $this->mergedDiscussion->id, + 'merged_id' => $this->mergedDiscussion->id, ]; } @@ -106,8 +106,8 @@ public function getEmailView() public function getEmailSubject(TranslatorInterface $translator) { return $translator->trans('fof-merge-discussions.email.merged.subject', [ - '{display_name}' => $this->actor->display_name, - '{discussion_title}' => $this->discussion->title, + '{display_name}' => $this->actor->display_name, + '{discussion_title}' => $this->discussion->title, '{merged_discussion_title}' => $this->mergedDiscussion->title, ]); } From b819d321c6c94bea319931fe8116c3ce371802ae Mon Sep 17 00:00:00 2001 From: Ian Morland Date: Mon, 3 Jan 2022 15:00:38 +0000 Subject: [PATCH 5/5] Tweak translations --- resources/locale/en.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/locale/en.yml b/resources/locale/en.yml index 2ee7f1b..124ec7c 100644 --- a/resources/locale/en.yml +++ b/resources/locale/en.yml @@ -15,7 +15,7 @@ fof-merge-discussions: notification: discussion_merged: Your discussion {oldTitle} was merged into this discussion by {username}. preferences: - discussion_merged: A moderator merges one of my discussions with another + discussion_merged: Someone merges one of my discussions with another discussion: merge: => fof-merge-discussions.ref.merge @@ -45,7 +45,7 @@ fof-merge-discussions: body: | Hey {recipient_display_name}, - Your discussion, {merged_discussion_title}, was merged into {discussion_title} by {actor_display_name} + Your discussion, {merged_discussion_title}, was merged into {discussion_title} by {actor_display_name}. - View it here {discussion_url} + View it here {discussion_url} . subject: Your discussion "{merged_discussion_title}" was merged