mirror of
https://github.com/discourse/discourse.git
synced 2025-03-23 00:57:54 +08:00
DEV: Improve the sidebar section expansion handling (#27805)
Handles the cases where the sections titles are Unicode only strings, allowing them to be expanded separately if the Unicode string contains letters. Also prevents a sidebar section with the header hidden to be displayed collapsed.
This commit is contained in:
parent
dd67375de7
commit
bbd67eff08
@ -1,5 +1,5 @@
|
||||
import SidebarCustomSection from "../common/custom-sections";
|
||||
import SidebarCustomSections from "../common/custom-sections";
|
||||
|
||||
export default class SidebarAnonymousCustomSections extends SidebarCustomSection {
|
||||
export default class SidebarAnonymousCustomSections extends SidebarCustomSections {
|
||||
anonymous = true;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import Component from "@glimmer/component";
|
||||
import { service } from "@ember/service";
|
||||
import CustomSection from "./custom-section";
|
||||
|
||||
export default class SidebarCustomSection extends Component {
|
||||
export default class SidebarCustomSections extends Component {
|
||||
@service currentUser;
|
||||
@service router;
|
||||
@service messageBus;
|
||||
|
@ -5,6 +5,7 @@ import { action } from "@ember/object";
|
||||
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||
import { service } from "@ember/service";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import {
|
||||
getCollapsedSidebarSectionKey,
|
||||
getSidebarSectionContentId,
|
||||
@ -60,7 +61,7 @@ export default class SidebarSection extends Component {
|
||||
}
|
||||
|
||||
get displaySectionContent() {
|
||||
if (!isEmpty(this.sidebarState.filter)) {
|
||||
if (this.args.hideSectionHeader || !isEmpty(this.sidebarState.filter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -115,7 +116,15 @@ export default class SidebarSection extends Component {
|
||||
<div
|
||||
{{didInsert this.setExpandedState}}
|
||||
data-section-name={{@sectionName}}
|
||||
class="sidebar-section-wrapper sidebar-section"
|
||||
class={{concatClass
|
||||
"sidebar-section"
|
||||
"sidebar-section-wrapper"
|
||||
(if
|
||||
this.displaySectionContent
|
||||
"sidebar-section--expanded"
|
||||
"sidebar-section--collapsed"
|
||||
)
|
||||
}}
|
||||
...attributes
|
||||
>
|
||||
{{#unless @hideSectionHeader}}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import SidebarCustomSection from "../common/custom-sections";
|
||||
import SidebarCustomSections from "../common/custom-sections";
|
||||
|
||||
export default class SidebarUserCustomSections extends SidebarCustomSection {
|
||||
export default class SidebarUserCustomSections extends SidebarCustomSections {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.messageBus.subscribe("/refresh-sidebar-sections", this._refresh);
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { setOwner } from "@ember/application";
|
||||
import { service } from "@ember/service";
|
||||
import { isPresent } from "@ember/utils";
|
||||
import SidebarSectionForm from "discourse/components/modal/sidebar-section-form";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import SectionLink from "discourse/lib/sidebar/section-link";
|
||||
import { unicodeSlugify } from "discourse/lib/utilities";
|
||||
import { bind } from "discourse-common/utils/decorators";
|
||||
import I18n from "discourse-i18n";
|
||||
|
||||
@ -19,7 +21,9 @@ export default class Section {
|
||||
setOwner(this, owner);
|
||||
|
||||
this.section = section;
|
||||
this.slug = section.slug;
|
||||
this.slug = isPresent(section.slug)
|
||||
? section.slug
|
||||
: unicodeSlugify(section.title);
|
||||
|
||||
this.links = this.section.links.map((link) => {
|
||||
return new SectionLink(link, this, this.router);
|
||||
|
@ -372,6 +372,24 @@ export function slugify(string) {
|
||||
.replace(/-+$/, ""); // Remove trailing dashes
|
||||
}
|
||||
|
||||
export function unicodeSlugify(string) {
|
||||
try {
|
||||
return string
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.normalize("NFD") // normalize the string to remove diacritics
|
||||
.replace(/\s|_+/g, "-") // replace spaces and underscores with dashes
|
||||
.replace(/[^\p{Letter}\d\-]+/gu, "") // Remove non-letter characters except for dashes
|
||||
.replace(/--+/g, "-") // replace multiple dashes with a single dash
|
||||
.replace(/^-+/, "") // Remove leading dashes
|
||||
.replace(/-+$/, ""); // Remove trailing dashes
|
||||
} catch (e) {
|
||||
// in case the regex construct \p{Letter} is not supported by the browser
|
||||
// fall back to the basic slugify function
|
||||
return slugify(string);
|
||||
}
|
||||
}
|
||||
|
||||
export function toNumber(input) {
|
||||
return typeof input === "number" ? input : parseFloat(input);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import {
|
||||
setDefaultHomepage,
|
||||
slugify,
|
||||
toAsciiPrintable,
|
||||
unicodeSlugify,
|
||||
} from "discourse/lib/utilities";
|
||||
import {
|
||||
mdTable,
|
||||
@ -202,6 +203,37 @@ module("Unit | Utilities", function (hooks) {
|
||||
);
|
||||
});
|
||||
|
||||
test("unicodeSlugify", function (assert) {
|
||||
const asciiString = "--- 0__( Some--cool Discourse Site! )__0 --- ";
|
||||
const accentedString = "Créme_Brûlée!";
|
||||
const unicodeString = "談話";
|
||||
const unicodeStringWithEmojis = "⌘😁 談話";
|
||||
|
||||
assert.strictEqual(
|
||||
unicodeSlugify(asciiString),
|
||||
"0-some-cool-discourse-site-0",
|
||||
"it properly slugifies an ASCII string"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
unicodeSlugify(accentedString),
|
||||
"creme-brulee",
|
||||
"it removes diacritics"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
unicodeSlugify(unicodeString),
|
||||
"談話",
|
||||
"it keeps unicode letters"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
unicodeSlugify(unicodeStringWithEmojis),
|
||||
"談話",
|
||||
"it removes emojis and symbols"
|
||||
);
|
||||
});
|
||||
|
||||
test("fillMissingDates", function (assert) {
|
||||
const startDate = "2017-11-12"; // YYYY-MM-DD
|
||||
const endDate = "2017-12-12"; // YYYY-MM-DD
|
||||
|
@ -395,4 +395,39 @@ describe "Custom sidebar sections", type: :system do
|
||||
|
||||
expect(section_modal).to have_disabled_save
|
||||
end
|
||||
|
||||
it "allows the user to expand/collapse section containing unicode titles separately" do
|
||||
sidebar_section1 = Fabricate(:sidebar_section, title: "談話", user: user)
|
||||
Fabricate(:sidebar_url, name: "Sidebar Latest", value: "/latest").tap do |sidebar_url|
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section1, linkable: sidebar_url)
|
||||
end
|
||||
|
||||
sidebar_section2 = Fabricate(:sidebar_section, title: "趣", user: user)
|
||||
Fabricate(:sidebar_url, name: "Sidebar Categories", value: "/categories").tap do |sidebar_url|
|
||||
Fabricate(:sidebar_section_link, sidebar_section: sidebar_section2, linkable: sidebar_url)
|
||||
end
|
||||
|
||||
sign_in user
|
||||
|
||||
visit("/latest")
|
||||
|
||||
expect(sidebar).to have_section_expanded("談話")
|
||||
expect(sidebar).to have_section_expanded("趣")
|
||||
|
||||
sidebar.click_section_header("談話")
|
||||
expect(sidebar).to have_section_collapsed("談話")
|
||||
expect(sidebar).to have_section_expanded("趣")
|
||||
|
||||
sidebar.click_section_header("趣")
|
||||
expect(sidebar).to have_section_collapsed("談話")
|
||||
expect(sidebar).to have_section_collapsed("趣")
|
||||
|
||||
sidebar.click_section_header("談話")
|
||||
expect(sidebar).to have_section_expanded("談話")
|
||||
expect(sidebar).to have_section_collapsed("趣")
|
||||
|
||||
sidebar.click_section_header("趣")
|
||||
expect(sidebar).to have_section_expanded("談話")
|
||||
expect(sidebar).to have_section_expanded("趣")
|
||||
end
|
||||
end
|
||||
|
@ -19,7 +19,11 @@ module PageObjects
|
||||
end
|
||||
|
||||
def find_section(name)
|
||||
find(".sidebar-section[data-section-name='#{name}']")
|
||||
find(sidebar_section_selector(name))
|
||||
end
|
||||
|
||||
def click_section_header(name)
|
||||
find("#{sidebar_section_selector(name)} .sidebar-section-header").click
|
||||
end
|
||||
|
||||
def click_section_link(name)
|
||||
@ -59,6 +63,14 @@ module PageObjects
|
||||
has_no_css?(".sidebar-sections [data-section-name='#{name.parameterize}']")
|
||||
end
|
||||
|
||||
def has_section_expanded?(name)
|
||||
has_css?("#{sidebar_section_selector(name)}.sidebar-section--expanded")
|
||||
end
|
||||
|
||||
def has_section_collapsed?(name)
|
||||
has_css?("#{sidebar_section_selector(name)}.sidebar-section--collapsed")
|
||||
end
|
||||
|
||||
def switch_to_chat
|
||||
find(".sidebar__panel-switch-button[data-key='chat']").click
|
||||
end
|
||||
@ -183,6 +195,10 @@ module PageObjects
|
||||
|
||||
private
|
||||
|
||||
def sidebar_section_selector(name)
|
||||
".sidebar-section[data-section-name='#{name}']"
|
||||
end
|
||||
|
||||
def section_link_present?(name, href: nil, active: false, target: nil, count: 1, present:)
|
||||
attributes = { exact_text: name }
|
||||
attributes[:href] = href if href
|
||||
|
Loading…
x
Reference in New Issue
Block a user