Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions common/common.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
@use "lib/viewport";

@if $Hide_dropdowns == "true" {
ol.category-breadcrumb {
display: none;
}
}

@if $Hide_default_links == "true" {
#navigation-bar {
li:not(.navigation-toggle, [class*="custom_"]) {
.list-control-toggle-link-content li:not([class*="custom_"]) {
display: none;
}

@include viewport.from(sm) {
#navigation-bar li:not([class*="custom_"]) {
display: none;
}
}
Expand Down
26 changes: 9 additions & 17 deletions javascripts/discourse/initializers/init-nav-bar-additions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,18 @@ export default {

initialize() {
withPluginApi((api) => {
const itemsSetting = settings.Nav_links;
const items = itemsSetting
.split("|")
.map((item) => item.trim())
.filter(Boolean);

for (const item of items) {
const splitSec = item.split(";").map((section) => section.trim());
const filter = splitSec[0];
const filterDasherized = splitSec[0].replace(/\s+/g, "-").toLowerCase();
const title = splitSec[1];
const location = splitSec[2];

for (const {
display_name: displayName,
title,
url,
} of settings.nav_links) {
Comment on lines +8 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is great

api.addNavigationBarItem({
name: `custom_${filterDasherized}`,
displayName: filter,
name: `custom_${displayName.replace(/\s+/g, "-").toLowerCase()}`,
displayName,
title,
href: location,
href: url,
forceActive: (category, args, router) =>
router.currentURL.includes(location),
router.currentURL?.split("?")[0] === url,
});
}
});
Expand Down
16 changes: 16 additions & 0 deletions locales/en.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
en:
theme_metadata:
settings:
nav_links:
description: Custom links to display in the topic list navigation
schema:
properties:
display_name:
label: Display name
description: The text that shows on the menu
title:
label: Title
description: The text that shows on hover
url:
label: URL
description: The link (e.g., /latest or https://discourse.org)
37 changes: 37 additions & 0 deletions migrations/settings/0001-migrate-nav-links-to-objects.js
Comment thread
awesomerobot marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export default function migrate(settings) {
if (!settings.has("Nav_links")) {
return settings;
}

const oldValue = settings.get("Nav_links");
settings.delete("Nav_links");

if (Array.isArray(oldValue)) {
settings.set("nav_links", oldValue);
return settings;
}

if (typeof oldValue === "string") {
const newLinks = [];

oldValue.split("|").forEach((link) => {
const [displayName, title, url] = link
.split(";")
.map((section) => section.trim());

if (displayName && url) {
const newLink = { display_name: displayName, url };

if (title) {
newLink.title = title;
}

newLinks.push(newLink);
}
});

settings.set("nav_links", newLinks);
}

return settings;
}
43 changes: 34 additions & 9 deletions settings.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
Nav_links:
type: list
default: "Latest;topics with recent posts;/latest|Categories;all topics grouped by category;/categories|Top;the most active topics in the last year, month, week or day;/top"
description:
en: |
Semicolon delimited in this order: <strong>display name;description;URL</strong>
<br/><strong>Display name:</strong> text that shows on the menu
<br/><strong>Description:</strong> text that shows on hover
<br/><strong>URL:</strong> the link (e.g., <code>/latest</code> or <code>https://discourse.org</code>)
nav_links:
type: objects
default:
- display_name: Latest
title: topics with recent posts
url: /latest
- display_name: Categories
title: all topics grouped by category
url: /categories
- display_name: Top
title: the most active topics in the last year, month, week or day
url: /top
schema:
name: link
identifier: display_name
properties:
display_name:
type: string
required: true
validations:
min_length: 1
max_length: 100
title:
type: string
validations:
min_length: 1
max_length: 1000
url:
type: string
required: true
validations:
min_length: 1
max_length: 2048
url: true
Hide_dropdowns:
default: false
description:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { module, test } from "qunit";
import migrate from "../../../../migrations/settings/0001-migrate-nav-links-to-objects";

module(
"Custom Top Navigation Links | Migrations | Settings | 0001-migrate-nav-links-to-objects",
function () {
test("does nothing when the old setting is not present", function (assert) {
const settings = new Map(Object.entries({ Hide_dropdowns: true }));

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(new Map(Object.entries({ Hide_dropdowns: true })))
);
});

test("migrate when value of setting is already an array", function (assert) {
const links = [
{
display_name: "Latest",
title: "topics with recent posts",
url: "/latest",
},
];
const settings = new Map(Object.entries({ Nav_links: links }));

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(new Map(Object.entries({ nav_links: links })))
);
});

test("migrate when old setting value is an empty string", function (assert) {
const settings = new Map(Object.entries({ Nav_links: "" }));

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(new Map(Object.entries({ nav_links: [] })))
);
});

test("migrate when old setting value is invalid", function (assert) {
const settings = new Map(
Object.entries({
Nav_links: "Missing URL|Missing URL 2;some title|;;/no-name",
})
);

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(new Map(Object.entries({ nav_links: [] })))
);
});

test("migrate when title is not provided", function (assert) {
const settings = new Map(
Object.entries({
Nav_links: "External link;;https://meta.discourse.org",
})
);

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(
new Map(
Object.entries({
nav_links: [
{
display_name: "External link",
url: "https://meta.discourse.org",
},
],
})
)
)
);
});

test("migrate", function (assert) {
const settings = new Map(
Object.entries({
Nav_links:
"Latest;topics with recent posts;/latest|Categories;all topics grouped by category;/categories|Top;the most active topics in the last year, month, week or day;/top",
})
);

const result = migrate(settings);

assert.deepEqual(
Object.fromEntries(result.entries()),
Object.fromEntries(
new Map(
Object.entries({
nav_links: [
{
display_name: "Latest",
title: "topics with recent posts",
url: "/latest",
},
{
display_name: "Categories",
title: "all topics grouped by category",
url: "/categories",
},
{
display_name: "Top",
title:
"the most active topics in the last year, month, week or day",
url: "/top",
},
],
})
)
)
);
});
}
);