diff --git a/about.json b/about.json index 9f51100..9d5da53 100644 --- a/about.json +++ b/about.json @@ -12,9 +12,6 @@ "svg_icons": ["fire"], "serialize_topic_is_hot": true }, - "components": [ - "https://github.com/discourse/discourse-sidebar-new-topic-button.git" - ], "color_schemes": { "Horizon": { "primary": "1A1A1A", diff --git a/common/common.scss b/common/common.scss index c774676..069fe3d 100644 --- a/common/common.scss +++ b/common/common.scss @@ -11,6 +11,7 @@ @import "nav-pills"; @import "search-banner"; @import "sidebar"; +@import "sidebar-new-topic-button"; @import "topic"; @import "topic-cards"; @import "variables"; diff --git a/javascripts/discourse/api-initializers/sidebar-new-topic-button-connector.js b/javascripts/discourse/api-initializers/sidebar-new-topic-button-connector.js new file mode 100644 index 0000000..67b78e6 --- /dev/null +++ b/javascripts/discourse/api-initializers/sidebar-new-topic-button-connector.js @@ -0,0 +1,6 @@ +import { apiInitializer } from "discourse/lib/api"; +import SidebarNewTopicButton from "../components/sidebar-new-topic-button"; + +export default apiInitializer("1.8.0", (api) => { + api.renderInOutlet("before-sidebar-sections", SidebarNewTopicButton); +}); diff --git a/javascripts/discourse/components/sidebar-new-topic-button.gjs b/javascripts/discourse/components/sidebar-new-topic-button.gjs new file mode 100644 index 0000000..1379567 --- /dev/null +++ b/javascripts/discourse/components/sidebar-new-topic-button.gjs @@ -0,0 +1,96 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import didInsert from "@ember/render-modifiers/modifiers/did-insert"; +import didUpdate from "@ember/render-modifiers/modifiers/did-update"; +import { service } from "@ember/service"; +import { gt } from "truth-helpers"; +import CreateTopicButton from "discourse/components/create-topic-button"; +import not from "truth-helpers/helpers/not"; + +export default class SidebarNewTopicButton extends Component { + @service composer; + @service currentUser; + @service siteSettings; + @service router; + + @tracked category; + @tracked tag; + + get shouldRender() { + return this.currentUser && !this.router.currentRouteName.includes("admin"); + } + + get canCreateTopic() { + return this.currentUser?.can_create_topic; + } + + get draftCount() { + return this.currentUser?.get("draft_count"); + } + + get createTopicTargetCategory() { + if (this.category?.canCreateTopic) { + return this.category; + } + + if (this.siteSettings.default_subcategory_on_read_only_category) { + return this.category?.subcategoryWithCreateTopicPermission; + } + } + + get tagRestricted() { + return this.tag?.staff; + } + + get createTopicDisabled() { + return ( + (this.category && !this.createTopicTargetCategory) || + (this.tagRestricted && !this.currentUser.staff) + ); + } + + get categoryReadOnlyBanner() { + if (this.category && this.currentUser && this.createTopicDisabled) { + return this.category.read_only_banner; + } + } + + get createTopicClass() { + const baseClasses = "btn-default sidebar-new-topic-button"; + return this.categoryReadOnlyBanner + ? `${baseClasses} disabled` + : baseClasses; + } + + @action + createNewTopic() { + this.composer.openNewTopic({ category: this.category, tags: this.tag?.id }); + } + + @action + getCategoryandTag() { + this.category = this.router.currentRoute.attributes?.category || null; + this.tag = this.router.currentRoute.attributes?.tag || null; + } + + +} diff --git a/scss/sidebar-new-topic-button.scss b/scss/sidebar-new-topic-button.scss new file mode 100644 index 0000000..4bd8aad --- /dev/null +++ b/scss/sidebar-new-topic-button.scss @@ -0,0 +1,48 @@ +.navigation-controls { + .topic-drafts-menu-trigger, + .fk-d-button-tooltip { + display: none; + } +} + +.sidebar-new-topic-button { + flex: 1 1 auto; + + &__wrapper { + box-sizing: border-box; + display: flex; + + .mobile-view & { + margin: 0 0 1rem; + } + + &:has(.topic-drafts-menu-trigger) { + .sidebar-new-topic-button { + border-radius: var(--d-button-border-radius) 0 0 + var(--d-button-border-radius); + border-right: 1px solid var(--primary-300); + } + } + + .fk-d-button-tooltip { + flex: 1 1 auto; + } + + .topic-drafts-menu-trigger { + flex: 0 1 auto; + margin: 0; + border-radius: 0 var(--d-button-border-radius) + var(--d-button-border-radius) 0; + } + } +} + +li.sidebar-section-link-wrapper[data-list-item-name="New Topic"] { + display: none; +} + +.has-full-page-chat { + .sidebar-new-topic-button__wrapper { + display: none; + } +} diff --git a/spec/system/anon_sidebar_topic_button_spec.rb b/spec/system/anon_sidebar_topic_button_spec.rb new file mode 100644 index 0000000..7aafa3c --- /dev/null +++ b/spec/system/anon_sidebar_topic_button_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +RSpec.describe "Sidebar New Topic Button", system: true do + before { upload_theme } + + it "does not render the sidebar button for anons" do + visit("/latest") + expect(page).not_to have_css(".sidebar-new-topic-button__wrapper") + expect(page).not_to have_css(".sidebar-new-topic-button:not(.disabled)") + end +end diff --git a/spec/system/sidebar_topic_button_spec.rb b/spec/system/sidebar_topic_button_spec.rb new file mode 100644 index 0000000..d1bb1e6 --- /dev/null +++ b/spec/system/sidebar_topic_button_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +RSpec.describe "Sidebar New Topic Button", system: true do + before { upload_theme } + fab!(:group) + fab!(:user) { Fabricate(:user, trust_level: 3, groups: [group]) } + fab!(:category) + fab!(:private_category) do + c = Fabricate(:category_with_definition) + c.set_permissions(group => :readonly) + c.save + c + end + + before { sign_in(user) } + + it "renders the new topic button in the sidebar" do + visit("/latest") + expect(page).to have_css(".sidebar-new-topic-button__wrapper") + expect(page).to have_css(".sidebar-new-topic-button:not(.disabled)") + end + + it "opens the composer when clicked" do + visit("/") + find(".sidebar-new-topic-button").click + expect(page).to have_css("#reply-title") + end + + it "shows draft menu when drafts exist" do + Draft.create!(user: user, draft_key: "topic_1", data: {}) + + visit("/") + expect(page).to have_css(".sidebar-new-topic-button__wrapper .topic-drafts-menu-trigger") + end + + it "disables button when visiting read-only category" do + visit("/c/#{private_category.slug}/#{private_category.id}") + + expect(page).to have_css(".sidebar-new-topic-button[disabled]") + + visit("/c/#{category.slug}/#{category.id}") + + expect(page).not_to have_css(".sidebar-new-topic-button[disabled]") + end +end