mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 07:12:26 -05:00 
			
		
		
		
	
		
			
	
	
		
			136 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			136 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* | ||
|  | 	GoToSocial | ||
|  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | ||
|  | 	SPDX-License-Identifier: AGPL-3.0-or-later | ||
|  | 
 | ||
|  | 	This program is free software: you can redistribute it and/or modify | ||
|  | 	it under the terms of the GNU Affero General Public License as published by | ||
|  | 	the Free Software Foundation, either version 3 of the License, or | ||
|  | 	(at your option) any later version. | ||
|  | 
 | ||
|  | 	This program is distributed in the hope that it will be useful, | ||
|  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  | 	GNU Affero General Public License for more details. | ||
|  | 
 | ||
|  | 	You should have received a copy of the GNU Affero General Public License | ||
|  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||
|  | */ | ||
|  | 
 | ||
|  | const React = require("react"); | ||
|  | const { nanoid } = require("nanoid"); | ||
|  | const { Redirect } = require("wouter"); | ||
|  | 
 | ||
|  | const { urlSafe } = require("./util"); | ||
|  | 
 | ||
|  | const { | ||
|  | 	Sidebar, | ||
|  | 	ViewRouter, | ||
|  | 	MenuComponent | ||
|  | } = require("./components"); | ||
|  | 
 | ||
|  | function createNavigation(rootUrl, menus) { | ||
|  | 	const root = { | ||
|  | 		url: rootUrl, | ||
|  | 		links: [], | ||
|  | 	}; | ||
|  | 
 | ||
|  | 	const routing = []; | ||
|  | 
 | ||
|  | 	const menuTree = menus.map((creatorFunc) => | ||
|  | 		creatorFunc(root, routing) | ||
|  | 	); | ||
|  | 
 | ||
|  | 	return { | ||
|  | 		Sidebar: Sidebar(menuTree, routing), | ||
|  | 		ViewRouter: ViewRouter(routing, root.redirectUrl) | ||
|  | 	}; | ||
|  | } | ||
|  | 
 | ||
|  | function MenuEntry(name, opts, contents) { | ||
|  | 	if (contents == undefined) { // opts argument is optional
 | ||
|  | 		contents = opts; | ||
|  | 		opts = {}; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return function createMenuEntry(root, routing) { | ||
|  | 		const type = Array.isArray(contents) ? "category" : "view"; | ||
|  | 
 | ||
|  | 		let urlParts = [root.url]; | ||
|  | 		if (opts.url != "") { | ||
|  | 			urlParts.push(opts.url ?? urlSafe(name)); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		const url = urlParts.join("/"); | ||
|  | 		let routingUrl = url; | ||
|  | 
 | ||
|  | 		if (opts.wildcard) { | ||
|  | 			routingUrl += "/:wildcard*"; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		const entry = { | ||
|  | 			name, type, | ||
|  | 			url, routingUrl, | ||
|  | 			key: nanoid(), | ||
|  | 			permissions: opts.permissions ?? false, | ||
|  | 			icon: opts.icon, | ||
|  | 			links: [routingUrl], | ||
|  | 			level: (root.level ?? -1) + 1, | ||
|  | 			redirectUrl: opts.defaultUrl | ||
|  | 		}; | ||
|  | 
 | ||
|  | 		if (type == "category") { | ||
|  | 			let entries = contents.map((creatorFunc) => creatorFunc(entry, routing)); | ||
|  | 			let routes = []; | ||
|  | 
 | ||
|  | 			entries.forEach((e) => { | ||
|  | 				// move empty wildcard routes to end of category, to prevent overlap
 | ||
|  | 				if (e.url == entry.url) { | ||
|  | 					routes.unshift(e); | ||
|  | 				} else { | ||
|  | 					routes.push(e); | ||
|  | 				} | ||
|  | 			}); | ||
|  | 			routes.reverse(); | ||
|  | 
 | ||
|  | 			routing.push(...routes); | ||
|  | 
 | ||
|  | 			if (opts.redirectUrl != entry.url) { | ||
|  | 				routing.push({ | ||
|  | 					key: entry.key, | ||
|  | 					url: entry.url, | ||
|  | 					permissions: entry.permissions, | ||
|  | 					routingUrl: entry.redirectUrl + "/:fallback*", | ||
|  | 					view: React.createElement(Redirect, { to: entry.redirectUrl }) | ||
|  | 				}); | ||
|  | 				entry.url = entry.redirectUrl; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			root.links.push(...entry.links); | ||
|  | 
 | ||
|  | 			entry.MenuEntry = React.createElement( | ||
|  | 				MenuComponent, | ||
|  | 				entry, | ||
|  | 				entries.map((e) => e.MenuEntry) | ||
|  | 			); | ||
|  | 		} else { | ||
|  | 			entry.links.push(routingUrl); | ||
|  | 			root.links.push(routingUrl); | ||
|  | 
 | ||
|  | 			entry.view = React.createElement(contents, { baseUrl: url }); | ||
|  | 			entry.MenuEntry = React.createElement(MenuComponent, entry); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (root.redirectUrl == undefined) { | ||
|  | 			root.redirectUrl = entry.url; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return entry; | ||
|  | 	}; | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = { | ||
|  | 	createNavigation, | ||
|  | 	Menu: MenuEntry, | ||
|  | 	Item: MenuEntry | ||
|  | }; |