gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

index.js (3233B)


      1 /*
      2 	GoToSocial
      3 	Copyright (C) GoToSocial Authors admin@gotosocial.org
      4 	SPDX-License-Identifier: AGPL-3.0-or-later
      5 
      6 	This program is free software: you can redistribute it and/or modify
      7 	it under the terms of the GNU Affero General Public License as published by
      8 	the Free Software Foundation, either version 3 of the License, or
      9 	(at your option) any later version.
     10 
     11 	This program is distributed in the hope that it will be useful,
     12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 	GNU Affero General Public License for more details.
     15 
     16 	You should have received a copy of the GNU Affero General Public License
     17 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
     18 */
     19 
     20 "use strict";
     21 
     22 const React = require("react");
     23 const { nanoid } = require("nanoid");
     24 const { Redirect } = require("wouter");
     25 
     26 const { urlSafe } = require("./util");
     27 
     28 const {
     29 	Sidebar,
     30 	ViewRouter,
     31 	MenuComponent
     32 } = require("./components");
     33 
     34 function createNavigation(rootUrl, menus) {
     35 	const root = {
     36 		url: rootUrl,
     37 		links: [],
     38 	};
     39 
     40 	const routing = [];
     41 
     42 	const menuTree = menus.map((creatorFunc) =>
     43 		creatorFunc(root, routing)
     44 	);
     45 
     46 	return {
     47 		Sidebar: Sidebar(menuTree, routing),
     48 		ViewRouter: ViewRouter(routing, root.redirectUrl)
     49 	};
     50 }
     51 
     52 function MenuEntry(name, opts, contents) {
     53 	if (contents == undefined) { // opts argument is optional
     54 		contents = opts;
     55 		opts = {};
     56 	}
     57 
     58 	return function createMenuEntry(root, routing) {
     59 		const type = Array.isArray(contents) ? "category" : "view";
     60 
     61 		let urlParts = [root.url];
     62 		if (opts.url != "") {
     63 			urlParts.push(opts.url ?? urlSafe(name));
     64 		}
     65 
     66 		const url = urlParts.join("/");
     67 		let routingUrl = url;
     68 
     69 		if (opts.wildcard) {
     70 			routingUrl += "/:wildcard*";
     71 		}
     72 
     73 		const entry = {
     74 			name, type,
     75 			url, routingUrl,
     76 			key: nanoid(),
     77 			permissions: opts.permissions ?? false,
     78 			icon: opts.icon,
     79 			links: [routingUrl],
     80 			level: (root.level ?? -1) + 1,
     81 			redirectUrl: opts.defaultUrl
     82 		};
     83 
     84 		if (type == "category") {
     85 			let entries = contents.map((creatorFunc) => creatorFunc(entry, routing));
     86 			let routes = [];
     87 
     88 			entries.forEach((e) => {
     89 				// move empty wildcard routes to end of category, to prevent overlap
     90 				if (e.url == entry.url) {
     91 					routes.unshift(e);
     92 				} else {
     93 					routes.push(e);
     94 				}
     95 			});
     96 			routes.reverse();
     97 
     98 			routing.push(...routes);
     99 
    100 			if (opts.redirectUrl != entry.url) {
    101 				routing.push({
    102 					key: entry.key,
    103 					url: entry.url,
    104 					permissions: entry.permissions,
    105 					routingUrl: entry.redirectUrl + "/:fallback*",
    106 					view: React.createElement(Redirect, { to: entry.redirectUrl })
    107 				});
    108 				entry.url = entry.redirectUrl;
    109 			}
    110 
    111 			root.links.push(...entry.links);
    112 
    113 			entry.MenuEntry = React.createElement(
    114 				MenuComponent,
    115 				entry,
    116 				entries.map((e) => e.MenuEntry)
    117 			);
    118 		} else {
    119 			entry.links.push(routingUrl);
    120 			root.links.push(routingUrl);
    121 
    122 			entry.view = React.createElement(contents, { baseUrl: url });
    123 			entry.MenuEntry = React.createElement(MenuComponent, entry);
    124 		}
    125 
    126 		if (root.redirectUrl == undefined) {
    127 			root.redirectUrl = entry.url;
    128 		}
    129 
    130 		return entry;
    131 	};
    132 }
    133 
    134 module.exports = {
    135 	createNavigation,
    136 	Menu: MenuEntry,
    137 	Item: MenuEntry
    138 };