mirror of
https://github.com/laurent22/joplin.git
synced 2025-04-01 21:24:45 +02:00
Server: Add support for sidebar in user pages
This commit is contained in:
parent
07f128ae95
commit
053dbabf74
packages/server/src
services
utils/views
views
@ -5,22 +5,12 @@ import config from '../config';
|
||||
import { filename } from '@joplin/lib/path-utils';
|
||||
import { NotificationView } from '../utils/types';
|
||||
import { User } from '../services/database/types';
|
||||
import { makeUrl, SubPath, urlMatchesSchema, UrlType } from '../utils/routeUtils';
|
||||
import { makeUrl, SubPath, UrlType } from '../utils/routeUtils';
|
||||
import MarkdownIt = require('markdown-it');
|
||||
import { headerAnchor } from '@joplin/renderer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { adminDashboardUrl, adminEmailsUrl, adminTasksUrl, adminUserDeletionsUrl, adminUsersUrl, changesUrl, homeUrl, itemsUrl } from '../utils/urlUtils';
|
||||
|
||||
type MenuItemSelectedCondition = (selectedUrl: SubPath)=> boolean;
|
||||
|
||||
export interface MenuItem {
|
||||
title: string;
|
||||
url?: string;
|
||||
children?: MenuItem[];
|
||||
selected?: boolean;
|
||||
icon?: string;
|
||||
selectedCondition?: MenuItemSelectedCondition;
|
||||
}
|
||||
import { MenuItem, setSelectedMenu } from '../utils/views/menu';
|
||||
|
||||
export interface RenderOptions {
|
||||
partials?: any;
|
||||
@ -40,6 +30,7 @@ export interface View {
|
||||
cssFiles?: string[];
|
||||
jsFiles?: string[];
|
||||
strings?: Record<string, string>; // List of translatable strings
|
||||
sidebarMenu?: MenuItem[];
|
||||
}
|
||||
|
||||
interface GlobalParams {
|
||||
@ -111,22 +102,6 @@ export default class MustacheService {
|
||||
return `${config().layoutDir}/${name}.mustache`;
|
||||
}
|
||||
|
||||
private setSelectedMenu(selectedPath: SubPath, menuItems: MenuItem[]) {
|
||||
if (!selectedPath) return;
|
||||
if (!menuItems) return;
|
||||
|
||||
for (const menuItem of menuItems) {
|
||||
if (menuItem.url) {
|
||||
if (menuItem.selectedCondition) {
|
||||
menuItem.selected = menuItem.selectedCondition(selectedPath);
|
||||
} else {
|
||||
menuItem.selected = urlMatchesSchema(menuItem.url, selectedPath.schema);
|
||||
}
|
||||
}
|
||||
this.setSelectedMenu(selectedPath, menuItem.children);
|
||||
}
|
||||
}
|
||||
|
||||
private makeAdminMenu(selectedPath: SubPath): MenuItem[] {
|
||||
const output: MenuItem[] = [
|
||||
{
|
||||
@ -156,9 +131,7 @@ export default class MustacheService {
|
||||
},
|
||||
];
|
||||
|
||||
this.setSelectedMenu(selectedPath, output);
|
||||
|
||||
return output;
|
||||
return setSelectedMenu(selectedPath, output);
|
||||
}
|
||||
|
||||
private makeNavbar(selectedPath: SubPath, isAdmin: boolean): MenuItem[] {
|
||||
@ -190,9 +163,7 @@ export default class MustacheService {
|
||||
]);
|
||||
}
|
||||
|
||||
this.setSelectedMenu(selectedPath, output);
|
||||
|
||||
return output;
|
||||
return setSelectedMenu(selectedPath, output);
|
||||
}
|
||||
|
||||
private get defaultLayoutOptions(): GlobalParams {
|
||||
@ -318,6 +289,7 @@ export default class MustacheService {
|
||||
cssFiles: cssFiles,
|
||||
jsFiles: jsFiles,
|
||||
navbar: view.navbar,
|
||||
sidebarMenu: view.sidebarMenu,
|
||||
...view.content,
|
||||
};
|
||||
|
||||
|
39
packages/server/src/utils/views/menu.ts
Normal file
39
packages/server/src/utils/views/menu.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { SubPath, urlMatchesSchema } from '../routeUtils';
|
||||
|
||||
export type MenuItemSelectedCondition = (selectedUrl: SubPath)=> boolean;
|
||||
|
||||
export interface MenuItem {
|
||||
title: string;
|
||||
url?: string;
|
||||
children?: MenuItem[];
|
||||
selected?: boolean;
|
||||
icon?: string;
|
||||
selectedCondition?: MenuItemSelectedCondition;
|
||||
}
|
||||
|
||||
export const setSelectedMenu = (selectedPath: SubPath, menuItems: MenuItem[]) => {
|
||||
if (!selectedPath) return menuItems;
|
||||
if (!menuItems) return menuItems;
|
||||
|
||||
menuItems = menuItems.slice();
|
||||
|
||||
for (let i = 0; i < menuItems.length; i++) {
|
||||
const menuItem = menuItems[i];
|
||||
let selected = menuItem.selected;
|
||||
if (menuItem.url) {
|
||||
if (menuItem.selectedCondition) {
|
||||
selected = menuItem.selectedCondition(selectedPath);
|
||||
} else {
|
||||
selected = urlMatchesSchema(menuItem.url, selectedPath.schema);
|
||||
}
|
||||
}
|
||||
|
||||
menuItems[i] = {
|
||||
...menuItem,
|
||||
selected,
|
||||
children: setSelectedMenu(selectedPath, menuItem.children),
|
||||
};
|
||||
}
|
||||
|
||||
return menuItems;
|
||||
};
|
@ -25,13 +25,25 @@
|
||||
<div class="container main-container">
|
||||
{{> notifications}}
|
||||
|
||||
{{! ADMIN PAGE }}
|
||||
|
||||
{{#global.isAdminPage}}
|
||||
{{> adminLayout}}
|
||||
{{/global.isAdminPage}}
|
||||
|
||||
{{^global.isAdminPage}}
|
||||
{{{contentHtml}}}
|
||||
{{/global.isAdminPage}}
|
||||
{{! USER PAGE - WITH SIDEBAR }}
|
||||
|
||||
{{^sidebarMenu}}
|
||||
{{^global.isAdminPage}}
|
||||
{{{contentHtml}}}
|
||||
{{/global.isAdminPage}}
|
||||
{{/sidebarMenu}}
|
||||
|
||||
{{! USER PAGE - NO SIDEBAR }}
|
||||
|
||||
{{#sidebarMenu}}
|
||||
{{> sidebarLayout}}
|
||||
{{/sidebarMenu}}
|
||||
</div>
|
||||
</main>
|
||||
{{> footer}}
|
||||
|
20
packages/server/src/views/partials/sidebarLayout.mustache
Normal file
20
packages/server/src/views/partials/sidebarLayout.mustache
Normal file
@ -0,0 +1,20 @@
|
||||
<div style="display: flex; flex-direction: row;">
|
||||
<div style="display: flex; margin-right: 3rem; background-color: #f5f5f5; padding: 1.5rem;">
|
||||
<aside class="menu">
|
||||
{{#sidebarMenu}}
|
||||
<p class="menu-label">{{title}}</p>
|
||||
<ul class="menu-list">
|
||||
{{#children}}
|
||||
<li><a href="{{{url}}}" class="{{#selected}}is-active{{/selected}}">{{title}}</a></li>
|
||||
{{/children}}
|
||||
</ul>
|
||||
{{/sidebarMenu}}
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex: 1;">
|
||||
<div>
|
||||
{{{contentHtml}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user