diff --git a/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-edit.js b/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-edit.js index 5c1ecb503fb..71df6c93240 100644 --- a/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-edit.js +++ b/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-edit.js @@ -9,6 +9,7 @@ import I18n from "discourse-i18n"; export default class AutomationEdit extends Controller { @service dialog; + @service router; error = null; isUpdatingAutomation = false; isTriggeringAutomation = false; @@ -26,7 +27,7 @@ export default class AutomationEdit extends Controller { } @action - saveAutomation() { + saveAutomation(routeToIndex = false) { this.setProperties({ error: null, isUpdatingAutomation: true }); return ajax( @@ -40,6 +41,9 @@ export default class AutomationEdit extends Controller { ) .then(() => { this.send("refreshRoute"); + if (routeToIndex) { + this.router.transitionTo("adminPlugins.discourse-automation.index"); + } }) .catch((e) => this._showError(e)) .finally(() => { diff --git a/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-new.js b/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-new.js index 298007c854b..f082e38e33c 100644 --- a/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-new.js +++ b/plugins/automation/admin/assets/javascripts/admin/controllers/admin-plugins-discourse-automation-new.js @@ -1,38 +1,46 @@ +import { tracked } from "@glimmer/tracking"; import Controller from "@ember/controller"; -import EmberObject, { action } from "@ember/object"; -import { service } from "@ember/service"; -import { extractError } from "discourse/lib/ajax-error"; +import { action } from "@ember/object"; +import { inject as service } from "@ember/service"; export default class AutomationNew extends Controller { @service router; + @tracked filterText = ""; - form = null; - error = null; - - init() { - super.init(...arguments); - this._resetForm(); + @action + updateFilterText(event) { + this.filterText = event.target.value; } @action - saveAutomation() { - this.set("error", null); - - this.model.automation - .save(this.form.getProperties("name", "script")) - .then(() => { - this._resetForm(); - this.router.transitionTo( - "adminPlugins.discourse-automation.edit", - this.model.automation.id - ); - }) - .catch((e) => { - this.set("error", extractError(e)); - }); + resetFilterText() { + this.filterText = ""; } - _resetForm() { - this.set("form", EmberObject.create({ name: null, script: null })); + get scriptableContent() { + let scripts = this.model.scriptables.content; + let filter = this.filterText.toLowerCase(); + + if (!filter) { + return scripts; + } + + return scripts.filter((script) => { + const name = script.name ? script.name.toLowerCase() : ""; + const description = script.description + ? script.description.toLowerCase() + : ""; + return name.includes(filter) || description.includes(filter); + }); + } + + @action + selectScriptToEdit(newScript) { + this.model.automation.save({ script: newScript.id }).then(() => { + this.router.transitionTo( + "adminPlugins.discourse-automation.edit", + this.model.automation.id + ); + }); } } diff --git a/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-index.js b/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-index.js index da2410c18fc..586341b2027 100644 --- a/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-index.js +++ b/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-index.js @@ -1,13 +1,22 @@ import { action } from "@ember/object"; +import { service } from "@ember/service"; import DiscourseRoute from "discourse/routes/discourse"; export default class AutomationIndex extends DiscourseRoute { + @service router; + controllerName = "admin-plugins-discourse-automation-index"; model() { return this.store.findAll("discourse-automation-automation"); } + afterModel(model) { + if (!model.length) { + this.router.transitionTo("adminPlugins.discourse-automation.new"); + } + } + @action triggerRefresh() { this.refresh(); diff --git a/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-new.js b/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-new.js index 77c1145674b..9fe8164815e 100644 --- a/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-new.js +++ b/plugins/automation/admin/assets/javascripts/admin/routes/admin-plugins-discourse-automation-new.js @@ -6,6 +6,7 @@ export default class AutomationNew extends DiscourseRoute { model() { return hash({ + scripts: this.store.findAll("discourse-automation-automation"), scriptables: this.store.findAll("discourse-automation-scriptable"), automation: this.store.createRecord("discourse-automation-automation"), }); diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs index 9036e062855..d43749415d6 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs @@ -10,11 +10,12 @@
@@ -26,9 +27,9 @@
@@ -42,7 +43,7 @@
- {{#if model.automation.script.forced_triggerable}} + {{#if this.model.automation.script.forced_triggerable}}
{{i18n "discourse_automation.edit_automation.trigger_section.forced" @@ -56,47 +57,50 @@
- {{#if automationForm.trigger}} - {{#if model.automation.trigger.doc}} + {{#if this.automationForm.trigger}} + {{#if this.model.automation.trigger.doc}}
-

{{model.automation.trigger.doc}}

+

{{this.model.automation.trigger.doc}}

{{/if}} {{#if (and - model.automation.enabled - model.automation.trigger.settings.manual_trigger + this.model.automation.enabled + this.model.automation.trigger.settings.manual_trigger ) }}
- {{#if nextPendingAutomationAtFormatted}} + {{#if this.nextPendingAutomationAtFormatted}}

{{i18n "discourse_automation.edit_automation.trigger_section.next_pending_automation" - date=nextPendingAutomationAtFormatted + date=this.nextPendingAutomationAtFormatted }}

{{/if}}
@@ -104,50 +108,53 @@ {{#each triggerFields as |field|}} {{/each}} {{/if}} - {{#if automationForm.trigger}} - {{#if scriptFields}} + {{#if this.automationForm.trigger}} + {{#if this.scriptFields}}

{{i18n "discourse_automation.edit_automation.fields_section.title"}}

- {{#if model.automation.script.with_trigger_doc}} + {{#if this.model.automation.script.with_trigger_doc}}
-

{{model.automation.script.with_trigger_doc}}

+

{{this.model.automation.script.with_trigger_doc}}

{{/if}}
- {{#each scriptFields as |field|}} + {{#each this.scriptFields as |field|}} {{/each}}
{{/if}} - {{#if automationForm.trigger}} -
+ {{#if this.automationForm.trigger}} +
{{i18n "discourse_automation.models.automation.enabled.label" }}
@@ -155,10 +162,10 @@
diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs index f2a03138297..96c4e5cf2a2 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs @@ -33,6 +33,7 @@ {{else}} {{format-enabled-automation @@ -40,16 +41,23 @@ automation.trigger }} {{automation.name}} + >{{if + automation.name + automation.name + (i18n "discourse_automation.unnamed_automation") + }} {{if automation.trigger.id automation.trigger.name "-"}} {{automation.script.name}} (v{{automation.script.version}}) @@ -64,7 +72,7 @@ {{/if}} - + -{{else}} -
-

{{i18n "discourse_automation.no_automation_yet"}}

- -
{{/if}} \ No newline at end of file diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-new.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-new.hbs index 6343f6e4fa7..aeb84074276 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-new.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-new.hbs @@ -1,52 +1,33 @@
-
- -
- +
+

{{i18n "discourse_automation.select_script"}}

-
- -
+ +
+ + {{#unless this.model.scripts.length}} +
+

{{i18n "discourse_automation.no_automation_yet"}}

+ {{/unless}} -
- +
+ {{#each this.scriptableContent as |script|}} + + {{/each}} +
-
- -
-
- -
-
- -
-
-
\ No newline at end of file diff --git a/plugins/automation/app/controllers/discourse_automation/admin_automations_controller.rb b/plugins/automation/app/controllers/discourse_automation/admin_automations_controller.rb index 70721e9eeac..f0d9ba1bd6e 100644 --- a/plugins/automation/app/controllers/discourse_automation/admin_automations_controller.rb +++ b/plugins/automation/app/controllers/discourse_automation/admin_automations_controller.rb @@ -21,7 +21,7 @@ module DiscourseAutomation end def create - automation_params = params.require(:automation).permit(:name, :script, :trigger) + automation_params = params.require(:automation).permit(:script, :trigger) automation = DiscourseAutomation::Automation.new( diff --git a/plugins/automation/app/models/discourse_automation/automation.rb b/plugins/automation/app/models/discourse_automation/automation.rb index 223aac30a4b..7dab401d1be 100644 --- a/plugins/automation/app/models/discourse_automation/automation.rb +++ b/plugins/automation/app/models/discourse_automation/automation.rb @@ -30,9 +30,8 @@ module DiscourseAutomation @running_in_background = true end - MIN_NAME_LENGTH = 5 MAX_NAME_LENGTH = 100 - validates :name, length: { in: MIN_NAME_LENGTH..MAX_NAME_LENGTH } + validates :name, length: { maximum: MAX_NAME_LENGTH } def add_id_to_custom_field(target, custom_field_key) if ![Topic, Post, User].any? { |m| target.is_a?(m) } diff --git a/plugins/automation/assets/stylesheets/common/discourse-automation.scss b/plugins/automation/assets/stylesheets/common/discourse-automation.scss index 7ac22c3f026..544f5050951 100644 --- a/plugins/automation/assets/stylesheets/common/discourse-automation.scss +++ b/plugins/automation/assets/stylesheets/common/discourse-automation.scss @@ -7,6 +7,46 @@ td[role="button"] { cursor: pointer; } + + &__name { + word-break: break-word; + } + } + + .admin-section-landing__header { + display: flex; + align-items: center; + flex-wrap: wrap; + h2 { + margin: 0 auto 0 0; + } + &-filter { + margin: 0; + flex: 0 1 15em; + } + } + + .admin-section-landing__wrapper { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(16em, 1fr)); + gap: 1em 2em; + margin-top: 1em; + border-top: 3px solid var(--primary-low); // matches tbody border + padding-top: 1em; + } + + .admin-section-landing-item { + cursor: pointer; + display: grid; + grid-template-rows: subgrid; + grid-row: span 4; + gap: 0; + &__buttons { + display: none; // empty container + } + &__description { + max-width: 18.75em; + } } } @@ -42,26 +82,12 @@ } } + .alert-info { + margin-top: 1em; + } + .alert { padding: 1em; - background: var(--primary-very-low); - border-left-style: solid; - border-left-width: 5px; - - &.alert-info { - border-left-color: var(--tertiary-low); - } - - &.alert-warning { - border-left-color: var(--highlight); - background: var(--highlight-low); - } - - &.alert-error { - border-left-color: var(--danger); - background: var(--danger-low); - } - p { margin: 0; } diff --git a/plugins/automation/config/locales/client.en.yml b/plugins/automation/config/locales/client.en.yml index 6c9706486e8..aa0540b433d 100644 --- a/plugins/automation/config/locales/client.en.yml +++ b/plugins/automation/config/locales/client.en.yml @@ -8,7 +8,8 @@ en: select_trigger: Select a trigger confirm_automation_reset: This action will reset script and trigger options, new state will be saved, do you want to proceed? confirm_automation_trigger: This action will trigger the automation, do you want to proceed? - no_automation_yet: You haven’t created any automation yet. + no_automation_yet: You haven’t created any automations yet. Choose an option below to get started. + filter_placeholder: Filter by name or description... edit_automation: trigger_section: forced: This trigger is forced by script. @@ -384,6 +385,7 @@ en: fields: custom_field_name: label: "User Custom Field name" + unnamed_automation: "Unnamed automation" models: script: diff --git a/plugins/automation/config/locales/server.en.yml b/plugins/automation/config/locales/server.en.yml index 19694ccfb3a..804d431290a 100644 --- a/plugins/automation/config/locales/server.en.yml +++ b/plugins/automation/config/locales/server.en.yml @@ -99,6 +99,7 @@ en: doc: Allows to send multiple pms to a user. Each PM accepts a delay. suspend_user_by_email: title: Suspend user by email + description: Automatically suspend an account based on email address user_global_notice: title: User global notice description: Allows to display a global notice for a user @@ -135,6 +136,13 @@ en: button_text: Done add_user_to_group_through_custom_field: title: "Add user to group through User Custom Field" + description: "Automatically add users to groups when they log in or with a recurring check" group_category_notification_default: title: "Group Category Notification Default" description: "Set the default notification level of a category for members of a group" + send_chat_message: + title: "Send Chat Message" + description: "Send a custom chat message to a channel" + random_assign: + title: "Random Assign" + description: "Randomly assign topics to a group" diff --git a/plugins/automation/db/migrate/20241016174732_remove_name_requirement_from_automations.rb b/plugins/automation/db/migrate/20241016174732_remove_name_requirement_from_automations.rb new file mode 100644 index 00000000000..6d3f7a4e184 --- /dev/null +++ b/plugins/automation/db/migrate/20241016174732_remove_name_requirement_from_automations.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class RemoveNameRequirementFromAutomations < ActiveRecord::Migration[7.1] + def change + change_column_null :discourse_automation_automations, :name, true + end +end diff --git a/plugins/automation/spec/models/automation_spec.rb b/plugins/automation/spec/models/automation_spec.rb index 5ee8daf89bc..8d4811acf01 100644 --- a/plugins/automation/spec/models/automation_spec.rb +++ b/plugins/automation/spec/models/automation_spec.rb @@ -187,10 +187,6 @@ describe DiscourseAutomation::Automation do expect(automation).not_to be_valid expect(automation.errors[:name]).to eq(["is too long (maximum is 100 characters)"]) - automation = Fabricate.build(:automation, name: "b" * 4) - expect(automation).not_to be_valid - expect(automation.errors[:name]).to eq(["is too short (minimum is 5 characters)"]) - automation = Fabricate.build(:automation, name: "c" * 50) expect(automation).to be_valid end diff --git a/plugins/automation/spec/system/error_spec.rb b/plugins/automation/spec/system/error_spec.rb index f3b251359da..515be7339eb 100644 --- a/plugins/automation/spec/system/error_spec.rb +++ b/plugins/automation/spec/system/error_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -describe "DiscourseAutomation | error", type: :system do +describe "DiscourseAutomation | error", type: :system, js: true do fab!(:admin) before do @@ -10,14 +10,13 @@ describe "DiscourseAutomation | error", type: :system do context "when saving the form with an error" do it "shows the error correctly" do - visit("/admin/plugins/discourse-automation") + visit("/admin/plugins/discourse-automation/new") + find(".admin-section-landing__header-filter").set("create a post") + find(".admin-section-landing-item", match: :first).click - find(".new-automation").click - fill_in("automation-name", with: "aaaaa") - select_kit = PageObjects::Components::SelectKit.new(".scriptables") - select_kit.expand - select_kit.select_row_by_value("post") - find(".create-automation").click + expect(page).to have_selector("input[name='automation-name']") + + find('input[name="automation-name"]').set("aaaaa") select_kit = PageObjects::Components::SelectKit.new(".triggerables") select_kit.expand select_kit.select_row_by_value("recurring") @@ -29,6 +28,8 @@ describe "DiscourseAutomation | error", type: :system do { name: "topic", target: "script", target_name: "post" }, ), ) + + expect(find('input[name="automation-name"]').value).to eq("aaaaa") end end end diff --git a/plugins/automation/spec/system/new_automation_spec.rb b/plugins/automation/spec/system/new_automation_spec.rb index c455936523b..a4602aa2659 100644 --- a/plugins/automation/spec/system/new_automation_spec.rb +++ b/plugins/automation/spec/system/new_automation_spec.rb @@ -10,11 +10,13 @@ describe "DiscourseAutomation | New automation", type: :system, js: true do let(:new_automation_page) { PageObjects::Pages::NewAutomation.new } - context "when the script is not selected" do - it "shows an error" do - new_automation_page.visit.fill_name("aaaaa").create + context "when a script is clicked" do + it "navigates to automation edit route" do + new_automation_page.visit - expect(new_automation_page).to have_error(I18n.t("errors.messages.blank")) + find(".admin-section-landing-item__content", match: :first).click + + expect(page).to have_css(".scriptables") end end end diff --git a/plugins/automation/spec/system/smoke_test_spec.rb b/plugins/automation/spec/system/smoke_test_spec.rb index 30f7488c520..4847510d66a 100644 --- a/plugins/automation/spec/system/smoke_test_spec.rb +++ b/plugins/automation/spec/system/smoke_test_spec.rb @@ -22,13 +22,9 @@ describe "DiscourseAutomation | smoke test", type: :system, js: true do it "populate correctly" do visit("/admin/plugins/discourse-automation") - find(".new-automation").click + find(".admin-section-landing__header-filter").set("test") + find(".admin-section-landing-item__content", match: :first).click fill_in("automation-name", with: "aaaaa") - select_kit = PageObjects::Components::SelectKit.new(".scriptables") - select_kit.expand - select_kit.select_row_by_value("test") - find(".create-automation").click - select_kit = PageObjects::Components::SelectKit.new(".triggerables") select_kit.expand select_kit.select_row_by_value("post_created_edited") @@ -40,12 +36,9 @@ describe "DiscourseAutomation | smoke test", type: :system, js: true do it "works" do visit("/admin/plugins/discourse-automation") - find(".new-automation").click + find(".admin-section-landing__header-filter").set("user group membership through badge") + find(".admin-section-landing-item__content", match: :first).click fill_in("automation-name", with: "aaaaa") - select_kit = PageObjects::Components::SelectKit.new(".scriptables") - select_kit.expand - select_kit.select_row_by_value("user_group_membership_through_badge") - find(".create-automation").click select_kit = PageObjects::Components::SelectKit.new(".triggerables") select_kit.expand select_kit.select_row_by_value("user_first_logged_in") @@ -58,6 +51,6 @@ describe "DiscourseAutomation | smoke test", type: :system, js: true do find(".automation-enabled input").click find(".update-automation").click - expect(page).to have_field("automation-name", with: "aaaaa") + expect(page).to have_css('[role="button"]', text: "aaaaa") end end