Skip to content

Commit

Permalink
FEATURE: Add highlight to dropdown options (#18)
Browse files Browse the repository at this point in the history
* FEATURE: Add highlight to dropdown options

* FEATURE: Add highlight to dropdown when it matches highlight url property

* DEV: refactor new-topic-dropdown to highlight the correct button

* DEV: move functions to service

* DEV: lint schema.rb and remove unsed import in js

* DEV: Add tests to ensure that the dropdown button is highlighted
  • Loading branch information
Grubba27 committed Jun 28, 2024
1 parent e6616ae commit 44db5f8
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 7 deletions.
9 changes: 4 additions & 5 deletions assets/javascripts/discourse/components/new-topic-dropdown.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { computed } from "@ember/object";
import { getOwner } from "@ember/owner";
import { inject as service } from "@ember/service";
import Composer from "discourse/models/composer";
Expand All @@ -8,6 +7,7 @@ export default DropdownSelectBoxComponent.extend({
classNames: ["new-topic-dropdown"],
siteSettings: service(),
historyStore: service(),
dropdownButtons: service(),

selectKitOptions: {
icon: "plus",
Expand All @@ -18,10 +18,9 @@ export default DropdownSelectBoxComponent.extend({
none: "topic.create",
},

content: computed("new-topic", function () {
return this.currentUser.topic_preset_buttons;
}),

get content() {
return this.dropdownButtons.buttons;
},
actions: {
onChange(selectedAction) {
const composerController = getOwner(this).lookup("controller:composer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default {
Composer.serializeOnCreate("tags_to_add");

withPluginApi("0.8.12", (api) => {
api.onPageChange(() =>
api.container.lookup("service:dropdown-buttons").refreshButtons()
);

api.modifyClass("model:composer", {
pluginId: "preset-topic-composer-initializer",
tag_groups: {},
Expand Down
78 changes: 78 additions & 0 deletions assets/javascripts/discourse/services/dropdown-buttons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { tracked } from "@glimmer/tracking";
import Service, { service } from "@ember/service";
import { TrackedArray } from "@ember-compat/tracked-built-ins";

export default class DropdownButtonsService extends Service {
@service router;
@service currentUser;
@tracked buttons = new TrackedArray();

constructor() {
super(...arguments);
this.refreshButtons();
}

refreshButtons() {
this.buttons = new TrackedArray(
this.currentUser.topic_preset_buttons
.map((b) => ({
...b,
highlightUrls: b.highlightUrls || [],
}))
.map((button) => {
if (
this.#shouldHighlightByCategoryID(button.categoryId) ||
button.highlightUrls.some((url) => this.#shouldHighlightByURL(url))
) {
button.classNames = "is-highlighted";
}
return button;
})
);
}

#shouldHighlightByURL(url) {
// case 1 - url does not contain *, e.g. example, it should match exact url "example"
// case 2 - url starts and ends with *, e.g. *example*, it should match any url containing "example"
// case 3 - url starts with *, e.g. *example, it should match any url ending with "example"
// case 4 - url ends with *, e.g. example*, it should match any url starting with "example"

const startsWithStar = url.startsWith("*");
const endsWithStar = url.endsWith("*");
const exactMatch = !startsWithStar && !endsWithStar;

if (exactMatch) {
return url === this.router.currentURL;
}

if (startsWithStar && endsWithStar) {
return this.router.currentURL.includes(url.replace(/\*/g, ""));
}

if (startsWithStar) {
return this.router.currentURL.endsWith(url.replace(/\*/g, ""));
}

if (endsWithStar) {
return this.router.currentURL.startsWith(url.replace(/\*/g, ""));
}

return false;
}

#shouldHighlightByCategoryID(categoryId) {
const isCategoryRoute =
this.router.currentRoute.localName === "category" &&
this.router.currentURL.startsWith("/c/");
if (!isCategoryRoute) {
return false;
}

const currentCategory = Number(this.router.currentURL.split("/").at(-1));
if (isNaN(currentCategory)) {
return false;
}

return categoryId === currentCategory;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,19 @@ def self.schema
title: "Category ID",
type: "number",
description:
"Enter the category ID this topic should be created in. Set to 0 to enable all categories.",
"Enter the category ID this topic should be created in, it will highlight button if in category. Set to 0 to enable all categories.",
minimum: 0,
},
highlightUrls: {
title: "Url patterns to highlight button",
type: "array",
uniqueItems: true,
items: {
type: "string",
description:
"Use * as wildcard, i.e. /tag/food* to match all urls that start with /tag/food* or *pizza* to match all urls with pizza in the url.",
},
},
tags: {
title: "Tags",
type: "string",
Expand Down
5 changes: 4 additions & 1 deletion spec/system/page_objects/components/preset_topic_dropdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ def select(title)
end

def button
@button ||= find(".select-kit.single-select.dropdown-select-box .select-kit-header")
@button ||=
find(".new-topic-dropdown").find(
".select-kit.single-select.dropdown-select-box .select-kit-header",
)
end
end
end
Expand Down
20 changes: 20 additions & 0 deletions spec/system/preset_topic_composer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def self.add_new_json(json)
"showTags" => false,
"tags" => "",
"access" => "",
:highlightUrls => %w[/tag/*],
},
)
SiteSettingHelper.add_new_json(
Expand Down Expand Up @@ -212,5 +213,24 @@ def self.add_new_json(json)

expect(preset_input.get_first_label).to eq(tag1.name)
end

it "should add is-highlighted class to the button when in matching url" do
visit "/tag/#{tag1.name}"
PageObjects::Components::PresetTopicDropdown.new.button.click

button = find(:css, ".is-highlighted")
expect(button).to have_text("New Question2")
end

it "should add is-highlighted class to the button when in categoryId" do
visit "/c/#{cat.slug}"
PageObjects::Components::PresetTopicDropdown.new.button.click

button = find("li[title='New Question2']")
expect(button[:class]).to include("is-highlighted")

button = find("li[title='New Question3']")
expect(button[:class]).to include("is-highlighted")
end
end
end

0 comments on commit 44db5f8

Please sign in to comment.