From ecd1fdc5c7fb713131898039ca19ba08ca269350 Mon Sep 17 00:00:00 2001 From: Angus McLeod Date: Wed, 6 Oct 2021 19:55:50 +0800 Subject: [PATCH] FEATURE: Wizard Composer Mentionables Integration --- assets/javascripts/wizard-plugin.js.erb | 10 ++-- .../components/wizard-composer-editor.js.es6 | 58 +++++++++++++++++++ .../javascripts/wizard/models/custom.js.es6 | 11 ++-- .../components/wizard-field-composer.hbs | 1 + .../wizard/custom/autocomplete.scss | 2 + .../wizard/custom/mentionables.scss | 32 ++++++++++ assets/stylesheets/wizard/wizard_custom.scss | 1 + plugin.rb | 2 +- 8 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 assets/stylesheets/wizard/custom/mentionables.scss diff --git a/assets/javascripts/wizard-plugin.js.erb b/assets/javascripts/wizard-plugin.js.erb index 16175206..86b8c81e 100644 --- a/assets/javascripts/wizard-plugin.js.erb +++ b/assets/javascripts/wizard-plugin.js.erb @@ -3,14 +3,14 @@ Discourse.unofficial_plugins.each do |plugin| plugin_name = plugin.metadata.name if require_plugin_assets = CustomWizard::Field.require_assets[plugin_name] - plugin.each_globbed_asset do |f, is_dir| - next if f.include? "raw.hbs" + plugin.each_globbed_asset do |path, is_dir| + next if path.include? "raw.hbs" - if require_plugin_assets.any? { |dir| f.include?(dir) } + if require_plugin_assets.any? { |dir| path.include?(dir) } if is_dir - depend_on(f) + depend_on(path) else - require_asset(f) + require_asset(path) end end end diff --git a/assets/javascripts/wizard/components/wizard-composer-editor.js.es6 b/assets/javascripts/wizard/components/wizard-composer-editor.js.es6 index 2a92f12a..b60f7551 100644 --- a/assets/javascripts/wizard/components/wizard-composer-editor.js.es6 +++ b/assets/javascripts/wizard/components/wizard-composer-editor.js.es6 @@ -17,6 +17,7 @@ import { import { cacheShortUploadUrl } from "pretty-text/upload-short-url"; import { alias } from "@ember/object/computed"; import WizardI18n from "../lib/wizard-i18n"; +import Site from "../models/site"; const uploadMarkdownResolvers = []; @@ -55,6 +56,31 @@ export default ComposerEditor.extend({ }); } + const siteSettings = this.siteSettings; + if (siteSettings.mentionables_enabled) { + Site.currentProp("mentionable_items", this.wizard.mentionable_items); + const { SEPARATOR } = requirejs( + "discourse/plugins/discourse-mentionables/discourse/lib/discourse-markdown/mentionable-items" + ); + const { searchMentionableItem } = requirejs( + "discourse/plugins/discourse-mentionables/discourse/lib/mentionable-item-search" + ); + + $input.autocomplete({ + template: findRawTemplate("javascripts/mentionable-item-autocomplete"), + key: SEPARATOR, + afterComplete: (value) => { + this.composer.set("reply", value); + scheduleOnce("afterRender", () => $input.blur().focus()); + }, + transformComplete: (item) => item.model.slug, + dataSource: (term) => + term.match(/\s/) ? null : searchMentionableItem(term, siteSettings), + triggerRule: (textarea) => + !inCodeBlock(textarea.value, caretPosition(textarea)), + }); + } + if (this._enableAdvancedEditorPreviewSync()) { this._initInputPreviewSync($input, $preview); } else { @@ -293,10 +319,42 @@ export default ComposerEditor.extend({ unshift: true, sendAction: () => component.set("showHyperlinkBox", true), }); + + if (this.siteSettings.mentionables_enabled) { + const { SEPARATOR } = requirejs( + "discourse/plugins/discourse-mentionables/discourse/lib/discourse-markdown/mentionable-items" + ); + + toolbar.addButton({ + id: "insert-mentionable", + group: "extras", + icon: this.siteSettings.mentionables_composer_button_icon, + title: "mentionables.composer.insert.title", + perform: () => { + this.appEvents.trigger("wizard-editor:insert-text", { + fieldId: this.field.id, + text: SEPARATOR, + }); + const $textarea = $( + document.querySelector( + `.composer-field.${this.field.id} textarea.d-editor-input` + ) + ); + $textarea.trigger("keyup.autocomplete"); + }, + }); + } }, previewUpdated($preview) { highlightSyntax($preview[0], this.siteSettings, this.session); + + if (this.siteSettings.mentionables_enabled) { + const { linkSeenMentionableItems } = requirejs( + "discourse/plugins/discourse-mentionables/discourse/lib/mentionable-items-preview-styling" + ); + linkSeenMentionableItems($preview, this.siteSettings); + } this._super(...arguments); }, diff --git a/assets/javascripts/wizard/models/custom.js.es6 b/assets/javascripts/wizard/models/custom.js.es6 index a17233b2..a8439db1 100644 --- a/assets/javascripts/wizard/models/custom.js.es6 +++ b/assets/javascripts/wizard/models/custom.js.es6 @@ -4,6 +4,7 @@ import WizardField from "wizard/models/wizard-field"; import { ajax } from "wizard/lib/ajax"; import Step from "wizard/models/step"; import EmberObject from "@ember/object"; +import Site from "./site"; const CustomWizard = EmberObject.extend({ @computed("steps.length") @@ -102,11 +103,11 @@ CustomWizard.reopenClass({ } }); - Discourse.Site.currentProp("categoriesList", categories); - Discourse.Site.currentProp("sortedCategories", categories); - Discourse.Site.currentProp("listByActivity", categories); - Discourse.Site.currentProp("categoriesById", categoriesById); - Discourse.Site.currentProp( + Site.currentProp("categoriesList", categories); + Site.currentProp("sortedCategories", categories); + Site.currentProp("listByActivity", categories); + Site.currentProp("categoriesById", categoriesById); + Site.currentProp( "uncategorized_category_id", wizardJson.uncategorized_category_id ); diff --git a/assets/javascripts/wizard/templates/components/wizard-field-composer.hbs b/assets/javascripts/wizard/templates/components/wizard-field-composer.hbs index 802c0339..262f0e69 100644 --- a/assets/javascripts/wizard/templates/components/wizard-field-composer.hbs +++ b/assets/javascripts/wizard/templates/components/wizard-field-composer.hbs @@ -1,6 +1,7 @@ {{wizard-composer-editor field=field composer=composer + wizard=wizard groupsMentioned=(action "groupsMentioned") cannotSeeMention=(action "cannotSeeMention") importQuote=(action "importQuote") diff --git a/assets/stylesheets/wizard/custom/autocomplete.scss b/assets/stylesheets/wizard/custom/autocomplete.scss index 1b02dfcc..0e3e73e4 100644 --- a/assets/stylesheets/wizard/custom/autocomplete.scss +++ b/assets/stylesheets/wizard/custom/autocomplete.scss @@ -81,6 +81,7 @@ img.avatar { text-overflow: ellipsis; font-size: 14px; text-decoration: none; + color: var(--primary); img { margin-right: 5px; @@ -98,6 +99,7 @@ img.avatar { } &.selected { background-color: var(--tertiary); + color: var(--secondary); } &:hover { background-color: var(--highlight-low); diff --git a/assets/stylesheets/wizard/custom/mentionables.scss b/assets/stylesheets/wizard/custom/mentionables.scss new file mode 100644 index 00000000..6e60f4e7 --- /dev/null +++ b/assets/stylesheets/wizard/custom/mentionables.scss @@ -0,0 +1,32 @@ +span.mentionable-item { + font-weight: bold; +} + +a.mentionable-item span { + background-color: $primary-low; + padding: 3px; + border-radius: 3px; + color: $primary; +} + +.ac-mentionable-item ul li a { + display: flex; + align-items: center; +} + +.ac-mentionable-item-name { + padding-left: 0.5em; +} + +.ac-mentionable-item-image { + width: 25px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; + + img { + height: 100%; + object-fit: contain; + } +} diff --git a/assets/stylesheets/wizard/wizard_custom.scss b/assets/stylesheets/wizard/wizard_custom.scss index 6290ce6e..c826bcf7 100644 --- a/assets/stylesheets/wizard/wizard_custom.scss +++ b/assets/stylesheets/wizard/wizard_custom.scss @@ -18,3 +18,4 @@ @import "custom/composer"; @import "custom/events"; @import "custom/locations"; +@import "custom/mentionables"; diff --git a/plugin.rb b/plugin.rb index 0b2a25b2..f54973fa 100644 --- a/plugin.rb +++ b/plugin.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # name: discourse-custom-wizard # about: Create custom wizards -# version: 1.14.0.stable +# version: 1.15.0.stable # authors: Angus McLeod # url: https://github.com/paviliondev/discourse-custom-wizard # contact emails: angus@thepavilion.io