diff --git a/about.json b/about.json index bce1c6a..9d070aa 100755 --- a/about.json +++ b/about.json @@ -1,6 +1,6 @@ { - "name": "discourse-tag-banners", + "name": "Tag Banners", "component": true, - "about_url": "", - "license_url": "" + "about_url": "https://meta.discourse.org/t/tag-banners/124240", + "license_url": "https://github.com/discourse/discourse-tag-banners/blob/main/LICENSE" } diff --git a/common/common.scss b/common/common.scss index 14e97dc..cd8e6d6 100644 --- a/common/common.scss +++ b/common/common.scss @@ -4,10 +4,9 @@ width: 100%; justify-content: center; background: var(--primary-very-low); - min-height: 10em; // prevents hop when tag name loads .tag-title-contents { - max-width: 700px; + max-width: 46em; padding: 3.5em 3em 3em; @media screen and (max-width: 450px) { diff --git a/javascripts/discourse/components/discourse-tag-banners.hbs b/javascripts/discourse/components/discourse-tag-banners.hbs new file mode 100644 index 0000000..1ae4157 --- /dev/null +++ b/javascripts/discourse/components/discourse-tag-banners.hbs @@ -0,0 +1,30 @@ +{{#if (not (and this.site.mobileView (not (theme-setting "show_on_mobile"))))}} + {{#if this.shouldRender}} +
+
+

+ {{this.formattedTagName}} + {{#if this.formattedAdditionalTagNames}} + & + {{this.formattedAdditionalTagNames}} + {{/if}} +

+ {{#unless this.isIntersection}} + {{! hide descriptions on tag intersections}} + {{#if (theme-setting "show_tag_description")}} +

{{this.tag.description}}

+ {{/if}} + {{/unless}} +
+
+ {{/if}} +{{/if}} diff --git a/javascripts/discourse/components/discourse-tag-banners.js b/javascripts/discourse/components/discourse-tag-banners.js new file mode 100644 index 0000000..02d0098 --- /dev/null +++ b/javascripts/discourse/components/discourse-tag-banners.js @@ -0,0 +1,78 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { action } from "@ember/object"; +import { inject as service } from "@ember/service"; + +export default class DiscourseTagBanners extends Component { + @service store; + @service router; + @service site; + @tracked tag = null; + @tracked keepDuringLoadingRoute = false; + @tracked isIntersection = false; + + #formatTagName(tagName = "") { + // for intersections: tag1/tag2 => tag1 & tag2 + tagName = tagName.replace(/\//g, " & "); + + if (settings.remove_tag_hyphen) { + tagName = tagName.replace(/-/g, " "); + } + if (settings.remove_tag_underscore) { + tagName = tagName.replace(/_/g, " "); + } + return tagName; + } + + get currentRouteParams() { + return this.router?.currentRoute?.params; + } + + get shouldRender() { + return ( + (this.currentRouteParams.tag_id !== "none" && + this.currentRouteParams?.tag_id) || + (this.keepDuringLoadingRoute && + this.router.currentRoute.name.includes("loading")) + ); + } + + get formattedTagName() { + return this.#formatTagName(this.tag?.name); + } + + get formattedAdditionalTagNames() { + const additionalTags = this.currentRouteParams.additional_tags; + return additionalTags ? this.#formatTagName(additionalTags) : ""; + } + + get additionalClass() { + if (this.formattedAdditionalTagNames === "") { + return "single-tag"; + } + + let tagList = this.formattedAdditionalTagNames.split(" & "); + return tagList.map((e) => `tag-banner-${e}`).join(" "); + } + + @action + async getTagInfo() { + const tag = this.currentRouteParams?.tag_id; + if (tag) { + const result = await this.store.find("tag-info", tag); + this.tag = result; + this.isIntersection = this.currentRouteParams.additional_tags; + this.keepDuringLoadingRoute = true; + } else { + if (!this.router.currentRoute.name.includes("loading")) { + this.keepDuringLoadingRoute = false; + } + } + } + + @action + resetTag() { + this.keepDuringLoadingRoute = false; + this.tag = null; + } +} diff --git a/javascripts/discourse/connectors/above-site-header/tag-header-widget.hbs b/javascripts/discourse/connectors/above-site-header/tag-header-widget.hbs index d412de7..ba4d93c 100644 --- a/javascripts/discourse/connectors/above-site-header/tag-header-widget.hbs +++ b/javascripts/discourse/connectors/above-site-header/tag-header-widget.hbs @@ -1,3 +1,3 @@ {{#if (theme-setting "show_above_site_header")}} - {{mount-widget widget="tag-header-widget"}} + {{/if}} diff --git a/javascripts/discourse/connectors/below-site-header/tag-header-widget.hbs b/javascripts/discourse/connectors/below-site-header/tag-header-widget.hbs index c471e45..7fd736f 100644 --- a/javascripts/discourse/connectors/below-site-header/tag-header-widget.hbs +++ b/javascripts/discourse/connectors/below-site-header/tag-header-widget.hbs @@ -1,3 +1,3 @@ {{#if (theme-setting "show_below_site_header")}} - {{mount-widget widget="tag-header-widget"}} + {{/if}} diff --git a/javascripts/discourse/initializers/discourse-tag-banners.js b/javascripts/discourse/initializers/discourse-tag-banners.js deleted file mode 100644 index 0855ae2..0000000 --- a/javascripts/discourse/initializers/discourse-tag-banners.js +++ /dev/null @@ -1,15 +0,0 @@ -import { withPluginApi } from "discourse/lib/plugin-api"; - -export default { - name: "discourse-tag-banners", - - initialize() { - withPluginApi("0.8", (api) => { - api.decorateWidget("tag-header-widget:after", (helper) => { - helper.widget.appEvents.on("page:changed", () => { - helper.widget.scheduleRerender(); - }); - }); - }); - }, -}; diff --git a/javascripts/discourse/widgets/tag-header-widget.js b/javascripts/discourse/widgets/tag-header-widget.js deleted file mode 100644 index f50d06b..0000000 --- a/javascripts/discourse/widgets/tag-header-widget.js +++ /dev/null @@ -1,96 +0,0 @@ -import { createWidget } from "discourse/widgets/widget"; -import { getOwner } from "discourse-common/lib/get-owner"; -import { h } from "virtual-dom"; - -export default createWidget("tag-header-widget", { - tagName: "span", - - buildKey: () => `tag-header-widget`, - - defaultState() { - return { loaded: false, tag: null }; - }, - - getTagInfo(tag) { - this.store.find("tag-info", tag).then((result) => { - this.state.tag = result; - this.state.loaded = true; - this.scheduleRerender(); - }); - }, - - html() { - const router = getOwner(this).lookup("router:main"); - const route = router.currentRoute; - const hideMobile = - !settings.show_on_mobile && this.site.mobileView ? true : false; - - if (route && route.params && route.params.hasOwnProperty("tag_id")) { - let tag = route.params.tag_id; - let formattedTagName = tag; - - let additionalTags = route.params.additional_tags; - let formattedAdditionalTagNames = additionalTags; - - if (settings.remove_tag_hyphen) { - formattedTagName = formattedTagName.replace(/-/g, " "); - formattedAdditionalTagNames = formattedAdditionalTagNames - ? formattedAdditionalTagNames.replace(/-/g, " ") - : null; - } - - if (settings.remove_tag_underscore) { - formattedTagName = formattedTagName.replace(/_/g, " "); - formattedAdditionalTagNames = formattedAdditionalTagNames - ? formattedAdditionalTagNames.replace(/_/g, " ") - : null; - } - - if (!hideMobile && tag !== "none") { - document.querySelector("body").classList.add("tag-banner"); - - let additionalClass; - let tagDescription; - - if (additionalTags) { - let tagList = formattedAdditionalTagNames.split("/"); - let additionalClassList = tagList.map(function (e) { - return `tag-banner-${e}`; - }); - formattedAdditionalTagNames = h("span", ` & ${tagList.join(" & ")}`); - additionalClass = additionalClassList.join("."); - } else { - additionalClass = "single-tag"; - } - - if (!this.state.loaded) { - this.getTagInfo(tag); - } else { - if (this.state.tag.name !== tag) { - // update the tag description when the route's tag changes - this.getTagInfo(tag); - } - - if (additionalTags || !settings.show_tag_description) { - tagDescription = ""; - } else { - tagDescription = this.state.tag.description; - } - - return h( - `div.tag-title-header .tag-banner-${tag} .${additionalClass}`, - h("div.tag-title-contents", [ - h("h1", [ - h("span", formattedTagName), - formattedAdditionalTagNames, - ]), - h("p", tagDescription), - ]) - ); - } - } else { - document.querySelector("body").classList.remove("tag-banner"); - } - } - }, -});