diff --git a/backend/locales/en.json b/backend/locales/en.json
index b88ff119d..2359c0df9 100644
--- a/backend/locales/en.json
+++ b/backend/locales/en.json
@@ -1885,6 +1885,7 @@
"editor.redirect.pickerTitle": "Select Redirection Target",
"editor.redirect.showInterstitial": "Show Interstitial",
"editor.redirect.showInterstitialHint": "Show a short notice saying where the reader is going before taking them there. Off sends them straight on.",
+ "editor.redirect.showInTreeHint": "List this redirection in the site's browse menu. Off keeps it out, which is usually what a doorway left behind for an old path should do. It is listed in the file manager either way.",
"editor.redirect.summaryDirect": "Readers arriving at this page are sent to {target} right away.",
"editor.redirect.summaryIncomplete": "This redirection has no target yet, and cannot be saved until it does.",
"editor.redirect.summaryInterstitial": "Readers arriving at this page are told they are being sent to {target}, then taken there a few seconds later.",
diff --git a/backend/models/pages.ts b/backend/models/pages.ts
index a32d8b787..66788e2ad 100644
--- a/backend/models/pages.ts
+++ b/backend/models/pages.ts
@@ -894,7 +894,13 @@ class Pages {
editor,
hash,
icon: input.icon ?? '',
- isBrowsable: input.isBrowsable ?? true,
+ /*
+ A redirection is a doorway rather than a destination, so it stays out of the browse menu
+ unless its author says otherwise -- the same default the redirect editor's own toggle
+ opens on. Unlike `isSearchable` below this is a choice and not a rule: a redirection that
+ IS the name readers look for belongs in the menu, and saying so is all it takes.
+ */
+ isBrowsable: input.isBrowsable ?? !isRedirect,
// -> A redirection has nothing to find: a result for it would be a result whose page is a
// doorway to the page the reader actually wanted, which is the one search should offer
isSearchable: isRedirect ? false : (input.isSearchable ?? true),
diff --git a/frontend/public/_assets/icons/blueprint-analytics.svg b/frontend/public/_assets/icons/blueprint-analytics.svg
new file mode 100644
index 000000000..4759ed170
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-analytics.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/blueprint-comment.svg b/frontend/public/_assets/icons/blueprint-comment.svg
new file mode 100644
index 000000000..6ac9a75fb
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-comment.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/blueprint-module.svg b/frontend/public/_assets/icons/blueprint-module.svg
new file mode 100644
index 000000000..de6b17764
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-module.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/blueprint-plugin.svg b/frontend/public/_assets/icons/blueprint-plugin.svg
new file mode 100644
index 000000000..0c614f30a
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-plugin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/blueprint-security-lock.svg b/frontend/public/_assets/icons/blueprint-security-lock.svg
new file mode 100644
index 000000000..0abb10725
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-security-lock.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/blueprint-ssd.svg b/frontend/public/_assets/icons/blueprint-ssd.svg
new file mode 100644
index 000000000..1e38a003b
--- /dev/null
+++ b/frontend/public/_assets/icons/blueprint-ssd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/fluent-buoy.svg b/frontend/public/_assets/icons/fluent-buoy.svg
new file mode 100644
index 000000000..6d5f9b0d9
--- /dev/null
+++ b/frontend/public/_assets/icons/fluent-buoy.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/_assets/icons/fluent-edit-property.svg b/frontend/public/_assets/icons/fluent-edit-property.svg
new file mode 100644
index 000000000..420346062
--- /dev/null
+++ b/frontend/public/_assets/icons/fluent-edit-property.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/components/EditorRedirect.vue b/frontend/src/components/EditorRedirect.vue
index a081576d2..fd342b0d8 100644
--- a/frontend/src/components/EditorRedirect.vue
+++ b/frontend/src/components/EditorRedirect.vue
@@ -69,6 +69,23 @@
+
+
+
+
+
+ {{ t('editor.props.showInTree') }}
+ {{ t('editor.redirect.showInTreeHint') }}
+
+
+
+
+
+
+
@@ -126,8 +143,9 @@ import { usePageStore } from '@/stores/page'
* The `redirect` editor: a page that sends its reader somewhere else.
*
* There is no content to write, so this is a form rather than an editor — a title, where the page
- * points, and whether the reader is told about it on the way. All three are the page's own fields:
- * the title is the page's, and the other two are its content, as JSON. See `helpers/pageRedirect.js`.
+ * points, whether it is offered in the browse menu, and whether the reader is told about it on the
+ * way. Two of those are the page's own fields — the title and `isBrowsable`, which the properties
+ * panel also edits — and the other two are its content, as JSON. See `helpers/pageRedirect.js`.
*
* What the page then DOES with that is `PageRedirect.vue`, which is what the page view draws in place
* of an article.
@@ -181,6 +199,18 @@ function setTitle(title) {
touch()
}
+/**
+ * Whether the page is offered in the browse menu, which is the page's `isBrowsable` field rather than
+ * anything about the redirection — the same toggle the properties panel carries, put here because it
+ * is the question a redirection actually raises. Off for a new one: a redirection is usually a doorway
+ * left behind for an old path, and a menu of those is a menu of the same pages twice. The file manager
+ * lists it either way; this is the reader's menu, not the author's.
+ */
+function setIsBrowsable(isBrowsable) {
+ pageStore.isBrowsable = isBrowsable
+ touch()
+}
+
function setShowInterstitial(showInterstitial) {
state.showInterstitial = showInterstitial
touch()
diff --git a/frontend/src/stores/page.js b/frontend/src/stores/page.js
index bd1ed2f4f..e5fc4f4f4 100644
--- a/frontend/src/stores/page.js
+++ b/frontend/src/stores/page.js
@@ -437,13 +437,15 @@ export const usePageStore = defineStore('page', {
// -> A page being created has no stored source to lose: whatever it starts with IS the source
contentLoaded: true,
render: '',
- isBrowsable: true,
/*
- A redirection is browsable like any other page and findable in none: a search result for one
- would stand in front of the page the reader actually wanted. The server settles this either
- way -- see `createPage` in `models/pages.ts` -- so this is the store agreeing with it rather
- than deciding it.
+ A redirection is in neither the browse menu nor search by default: the first because it is a
+ doorway rather than a page to land on, the second because a result for one would stand in
+ front of the page the reader actually wanted. The server settles both the same way -- see
+ `createPage` in `models/pages.ts` -- so this is the store agreeing with it rather than
+ deciding it. The difference is that browsing is a choice the author can turn back on, in the
+ redirect editor or the properties panel, and searching is not offered at all.
*/
+ isBrowsable: editor !== 'redirect',
isSearchable: editor !== 'redirect',
// -> The page being created is very often the one that was missing, and it is not missing now
notFound: false,