groovy baby yeah!

This commit is contained in:
tobi 2024-04-25 18:07:58 +02:00
parent 4cae02b5cb
commit 8872421e76
10 changed files with 646 additions and 567 deletions

View file

@ -17,7 +17,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { StrictMode } from "react";
import React, { StrictMode, Suspense, useMemo } from "react";
import "./style.css";
import { createRoot } from "react-dom/client";
@ -29,18 +29,21 @@ import Loading from "./components/loading";
import { Account } from "./lib/types/account";
import { BaseUrlContext, RoleContext } from "./lib/navigation/util";
import { SidebarMenu } from "./lib/navigation/menu";
import { UserMenu, UserRouter } from "./views/user/routes";
import { ModerationMenu, ModerationRouter } from "./views/moderation/routes";
import { AdminMenu, AdminRouter } from "./views/admin/routes";
import { Redirect, Route, Router } from "wouter";
import AdminMenu from "./views/admin/menu";
import ModerationMenu from "./views/moderation/menu";
import UserMenu from "./views/user/menu";
import UserRouter from "./views/user/router";
import { ErrorBoundary } from "./lib/navigation/error";
import ModerationRouter from "./views/moderation/router";
import AdminRouter from "./views/admin/router";
interface AppProps {
account: Account;
}
export function App({ account }: AppProps) {
const roles: string[] = [ account.role.name ];
const roles: string[] = useMemo(() => [ account.role.name ], [account]);
return (
<RoleContext.Provider value={roles}>
<BaseUrlContext.Provider value={"/settings"}>
@ -51,15 +54,19 @@ export function App({ account }: AppProps) {
</SidebarMenu>
<section className="with-sidebar">
<Router base="/settings">
<UserRouter />
<ModerationRouter />
<AdminRouter />
{/*
Redirect to first part of UserRouter if
just the bare settings page is open, so
user isn't greeted with a blank page.
*/}
<Route><Redirect to="/user/profile" /></Route>
<ErrorBoundary>
<Suspense fallback={<Loading />}>
<UserRouter />
<ModerationRouter />
<AdminRouter />
{/*
Redirect to first part of UserRouter if
just the bare settings page is open, so
user isn't greeted with a blank page.
*/}
<Route><Redirect to="/user/profile" /></Route>
</Suspense>
</ErrorBoundary>
</Router>
</section>
</BaseUrlContext.Provider>

View file

@ -601,31 +601,33 @@ span.form-info {
@media screen and (max-width: 60rem) {
/* vertical layout */
#root {
padding: 1rem;
padding: 0.5rem;
margin: 0;
grid-template-columns: 100%;
grid-template-rows: auto auto;
.sidebar {
div.sidebar {
justify-self: auto;
margin-bottom: 2rem;
margin-bottom: 0;
}
.sidebar, section.with-sidebar {
div.sidebar, section.with-sidebar {
border-top-left-radius: $br;
border-top-right-radius: $br;
border-bottom-left-radius: $br;
border-bottom-right-radius: $br;
}
.sidebar a:first-child h2 {
section.with-sidebar {
grid-column: 1;
padding: 1rem;
}
div.sidebar a:first-child h2 {
border-top-right-radius: $br;
}
}
section {
grid-column: 1;
}
.user-profile .overview {
grid-template-columns: auto;
grid-template-rows: auto 1fr;

View file

@ -0,0 +1,129 @@
/*
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/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React from "react";
import { useHasPermission } from "../../lib/navigation/util";
/*
EXPORTED COMPONENTS
*/
/**
* - /settings/admin/instance/settings
* - /settings/admin/instance/rules
* - /settings/admin/instance/rules/:ruleId
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
export default function AdminMenu() {
const permissions = ["admin"];
const admin = useHasPermission(permissions);
if (!admin) {
return null;
}
return (
<MenuItem
name="Administration"
itemUrl="admin"
defaultChild="actions"
permissions={permissions}
>
<AdminInstanceMenu />
<AdminEmojisMenu />
<AdminActionsMenu />
</MenuItem>
);
}
/*
INTERNAL COMPONENTS
*/
function AdminInstanceMenu() {
return (
<MenuItem
name="Instance"
itemUrl="instance"
defaultChild="settings"
icon="fa-sitemap"
>
<MenuItem
name="Settings"
itemUrl="settings"
icon="fa-sliders"
/>
<MenuItem
name="Rules"
itemUrl="rules"
icon="fa-dot-circle-o"
/>
</MenuItem>
);
}
function AdminActionsMenu() {
return (
<MenuItem
name="Actions"
itemUrl="actions"
defaultChild="media"
icon="fa-bolt"
>
<MenuItem
name="Media"
itemUrl="media"
icon="fa-photo"
/>
<MenuItem
name="Keys"
itemUrl="keys"
icon="fa-key-modern"
/>
</MenuItem>
);
}
function AdminEmojisMenu() {
return (
<MenuItem
name="Custom Emoji"
itemUrl="emojis"
defaultChild="local"
icon="fa-smile-o"
>
<MenuItem
name="Local"
itemUrl="local"
icon="fa-home"
/>
<MenuItem
name="Remote"
itemUrl="remote"
icon="fa-cloud"
/>
</MenuItem>
);
}

View file

@ -0,0 +1,151 @@
/*
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/>.
*/
import React from "react";
import { BaseUrlContext, useBaseUrl, useHasPermission } from "../../lib/navigation/util";
import { Redirect, Route, Router, Switch } from "wouter";
import { ErrorBoundary } from "../../lib/navigation/error";
import InstanceSettings from "./instance/settings";
import InstanceRules from "./instance/rules";
import InstanceRuleDetail from "./instance/ruledetail";
import Media from "./actions/media";
import Keys from "./actions/keys";
import EmojiOverview from "./emoji/local/overview";
import EmojiDetail from "./emoji/local/detail";
import RemoteEmoji from "./emoji/remote";
/*
EXPORTED COMPONENTS
*/
/**
* - /settings/instance/settings
* - /settings/instance/rules
* - /settings/instance/rules/:ruleId
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
export default function AdminRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/admin";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<AdminInstanceRouter />
<AdminEmojisRouter />
<AdminActionsRouter />
</Router>
</BaseUrlContext.Provider>
);
}
/*
INTERNAL COMPONENTS
*/
/**
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
*/
function AdminEmojisRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/emojis";
const absBase = parentUrl + thisBase;
const permissions = ["admin"];
const admin = useHasPermission(permissions);
if (!admin) {
return null;
}
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path="/local" component={EmojiOverview} />
<Route path="/local/:emojiId" component={EmojiDetail} />
<Route path="/remote" component={RemoteEmoji} />
<Route><Redirect to="/local" /></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
function AdminActionsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/actions";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path="/media" component={Media} />
<Route path="/keys" component={Keys} />
<Route><Redirect to="/media" /></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/instance/settings
* - /settings/instance/rules
* - /settings/instance/rules/:ruleId
*/
function AdminInstanceRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/instance";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path="/settings" component={InstanceSettings}/>
<Route path="/rules" component={InstanceRules} />
<Route path="/rules/:ruleId" component={InstanceRuleDetail} />
<Route><Redirect to="/settings" /></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}

View file

@ -1,263 +0,0 @@
/*
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/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React, { Suspense, lazy } from "react";
import { BaseUrlContext, useBaseUrl, useHasPermission } from "../../lib/navigation/util";
import { Redirect, Route, Router, Switch } from "wouter";
import Loading from "../../components/loading";
import { ErrorBoundary } from "../../lib/navigation/error";
/*
EXPORTED COMPONENTS
*/
/**
* - /settings/admin/instance/settings
* - /settings/admin/instance/rules
* - /settings/admin/instance/rules/:ruleId
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
export function AdminMenu() {
// Don't route if logged-in user
// doesn't have permissions to access.
if (!useHasPermission(["admin"])) {
return null;
}
return (
<MenuItem
name="Administration"
itemUrl="admin"
defaultChild="actions"
permissions={["admin"]}
>
<AdminInstanceMenu />
<AdminEmojisMenu />
<AdminActionsMenu />
</MenuItem>
);
}
/**
* - /settings/instance/settings
* - /settings/instance/rules
* - /settings/instance/rules/:ruleId
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
export function AdminRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/admin";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<AdminInstanceRouter />
<AdminEmojisRouter />
<AdminActionsRouter />
</Router>
</BaseUrlContext.Provider>
);
}
/*
INTERNAL COMPONENTS
*/
/*
MENUS
*/
function AdminInstanceMenu() {
return (
<MenuItem
name="Instance"
itemUrl="instance"
defaultChild="settings"
icon="fa-sitemap"
>
<MenuItem
name="Settings"
itemUrl="settings"
icon="fa-sliders"
/>
<MenuItem
name="Rules"
itemUrl="rules"
icon="fa-dot-circle-o"
/>
</MenuItem>
);
}
function AdminActionsMenu() {
return (
<MenuItem
name="Actions"
itemUrl="actions"
defaultChild="media"
icon="fa-bolt"
>
<MenuItem
name="Media"
itemUrl="media"
icon="fa-photo"
/>
<MenuItem
name="Keys"
itemUrl="keys"
icon="fa-key-modern"
/>
</MenuItem>
);
}
function AdminEmojisMenu() {
return (
<MenuItem
name="Custom Emoji"
itemUrl="emojis"
defaultChild="local"
icon="fa-smile-o"
>
<MenuItem
name="Local"
itemUrl="local"
icon="fa-home"
/>
<MenuItem
name="Remote"
itemUrl="remote"
icon="fa-cloud"
/>
</MenuItem>
);
}
/*
ROUTERS
*/
/**
* - /settings/admin/emojis
* - /settings/admin/emojis/local
* - /settings/admin/emojis/local/:emojiId
* - /settings/admin/emojis/remote
*/
function AdminEmojisRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/emojis";
const absBase = parentUrl + thisBase;
const EmojiOverview = lazy(() => import('./emoji/local/overview'));
const EmojiDetail = lazy(() => import('./emoji/local/detail'));
const RemoteEmoji = lazy(() => import('./emoji/remote'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/local" component={EmojiOverview} />
<Route path="/local/:emojiId" component={EmojiDetail} />
<Route path="/remote" component={RemoteEmoji} />
<Route><Redirect to="/local" /></Route>
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/admin/actions
* - /settings/admin/actions/media
* - /settings/admin/actions/keys
*/
function AdminActionsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/actions";
const absBase = parentUrl + thisBase;
const Media = lazy(() => import('./actions/media'));
const Keys = lazy(() => import('./actions/keys'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/media" component={Media} />
<Route path="/keys" component={Keys} />
<Route><Redirect to="/media" /></Route>
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/instance/settings
* - /settings/instance/rules
* - /settings/instance/rules/:ruleId
*/
function AdminInstanceRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/instance";
const absBase = parentUrl + thisBase;
const InstanceSettings = lazy(() => import('./instance/settings'));
const InstanceRules = lazy(() => import("./instance/rules"));
const InstanceRuleDetail = lazy(() => import('./instance/ruledetail'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/settings" component={InstanceSettings}/>
<Route path="/rules" component={InstanceRules} />
<Route path="/rules/:ruleId" component={InstanceRuleDetail} />
<Route><Redirect to="/settings" /></Route>
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}

View file

@ -0,0 +1,121 @@
/*
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/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React from "react";
import { useHasPermission } from "../../lib/navigation/util";
/*
EXPORTED COMPONENTS
*/
/**
* - /settings/moderation/reports/overview
* - /settings/moderation/reports/:reportId
* - /settings/moderation/accounts/overview
* - /settings/moderation/accounts/pending
* - /settings/moderation/accounts/:accountID
* - /settings/moderation/domain-permissions/:permType
* - /settings/moderation/domain-permissions/:permType/:domain
* - /settings/moderation/domain-permissions/import-export
* - /settings/moderation/domain-permissions/process
*/
export default function ModerationMenu() {
const permissions = ["moderator"];
const moderator = useHasPermission(permissions);
if (!moderator) {
return null;
}
return (
<MenuItem
name="Moderation"
itemUrl="moderation"
defaultChild="reports"
permissions={permissions}
>
<ModerationReportsMenu />
<ModerationAccountsMenu />
<ModerationDomainPermsMenu />
</MenuItem>
);
}
/*
INTERNAL COMPONENTS
*/
function ModerationReportsMenu() {
return (
<MenuItem
name="Reports"
itemUrl="reports"
icon="fa-flag"
/>
);
}
function ModerationAccountsMenu() {
return (
<MenuItem
name="Accounts"
itemUrl="accounts"
defaultChild="overview"
icon="fa-users"
>
<MenuItem
name="Overview"
itemUrl="overview"
icon="fa-list"
/>
<MenuItem
name="Pending"
itemUrl="pending"
icon="fa-question"
/>
</MenuItem>
);
}
function ModerationDomainPermsMenu() {
return (
<MenuItem
name="Domain Permissions"
itemUrl="domain-permissions"
defaultChild="blocks"
icon="fa-hubzilla"
>
<MenuItem
name="Blocks"
itemUrl="blocks"
icon="fa-close"
/>
<MenuItem
name="Allows"
itemUrl="allows"
icon="fa-check"
/>
<MenuItem
name="Import/Export"
itemUrl="import-export"
icon="fa-floppy-o"
/>
</MenuItem>
);
}

View file

@ -0,0 +1,149 @@
/*
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/>.
*/
import React from "react";
import { BaseUrlContext, useBaseUrl, useHasPermission } from "../../lib/navigation/util";
import { Redirect, Route, Router, Switch } from "wouter";
import { ReportOverview } from "./reports/overview";
import ReportDetail from "./reports/detail";
import { ErrorBoundary } from "../../lib/navigation/error";
import ImportExport from "./domain-permissions/import-export";
import DomainPermissionsOverview from "./domain-permissions/overview";
import DomainPermDetail from "./domain-permissions/detail";
import AccountsOverview from "./accounts";
import AccountsPending from "./accounts/pending";
import AccountDetail from "./accounts/detail";
/*
EXPORTED COMPONENTS
*/
/**
* - /settings/moderation/reports/overview
* - /settings/moderation/reports/:reportId
* - /settings/moderation/accounts/overview
* - /settings/moderation/accounts/pending
* - /settings/moderation/accounts/:accountID
* - /settings/moderation/domain-permissions/:permType
* - /settings/moderation/domain-permissions/:permType/:domain
* - /settings/moderation/domain-permissions/import-export
* - /settings/moderation/domain-permissions/process
*/
export default function ModerationRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/moderation";
const absBase = parentUrl + thisBase;
const permissions = ["moderator"];
const moderator = useHasPermission(permissions);
if (!moderator) {
return null;
}
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ModerationReportsRouter />
<ModerationAccountsRouter />
<ModerationDomainPermsRouter />
</Router>
</BaseUrlContext.Provider>
);
}
/*
INTERNAL COMPONENTS
*/
/**
* - /settings/moderation/reports/overview
* - /settings/moderation/reports/:reportId
*/
function ModerationReportsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/reports";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path={"/:reportId"} component={ReportDetail} />
<Route component={ReportOverview}/>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/moderation/accounts/overview
* - /settings/moderation/accounts/pending
* - /settings/moderation/accounts/:accountID
*/
function ModerationAccountsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/accounts";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path="/overview" component={AccountsOverview}/>
<Route path="/pending" component={AccountsPending}/>
<Route path="/:accountID" component={AccountDetail}/>
<Route><Redirect to="/overview"/></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/moderation/domain-permissions/:permType
* - /settings/moderation/domain-permissions/:permType/:domain
* - /settings/moderation/domain-permissions/import-export
* - /settings/moderation/domain-permissions/process
*/
function ModerationDomainPermsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/domain-permissions";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Switch>
<Route path="/import-export" component={ImportExport} />
<Route path="/process" component={ImportExport} />
<Route path="/:permType" component={DomainPermissionsOverview} />
<Route path="/:permType/:domain" component={DomainPermDetail} />
<Route><Redirect to="/blocks"/></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}

View file

@ -1,230 +0,0 @@
/*
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/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React, { lazy, Suspense } from "react";
import { BaseUrlContext, useBaseUrl, useHasPermission } from "../../lib/navigation/util";
import { Redirect, Route, Router, Switch } from "wouter";
import { ReportOverview } from "./reports/overview";
import ReportDetail from "./reports/detail";
import { ErrorBoundary } from "../../lib/navigation/error";
import Loading from "../../components/loading";
/*
EXPORTED COMPONENTS
*/
/**
* Moderation menu. Reports, accounts,
* domain permissions import + export.
*/
export function ModerationMenu() {
return (
<MenuItem
name="Moderation"
itemUrl="moderation"
defaultChild="reports"
permissions={["moderator"]}
>
<ModerationReportsMenu />
<ModerationAccountsMenu />
<ModerationDomainPermsMenu />
</MenuItem>
);
}
/**
* Moderation router. Reports, accounts,
* domain permissions import + export.
*/
export function ModerationRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/moderation";
const absBase = parentUrl + thisBase;
// Don't route if logged-in user
// doesn't have permissions to access.
if (!useHasPermission(["moderator"])) {
return null;
}
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ModerationReportsRouter />
<ModerationAccountsRouter />
<ModerationDomainPermsRouter />
</Router>
</BaseUrlContext.Provider>
);
}
/*
INTERNAL COMPONENTS
*/
/*
MENUS
*/
function ModerationReportsMenu() {
return (
<MenuItem
name="Reports"
itemUrl="reports"
icon="fa-flag"
/>
);
}
function ModerationAccountsMenu() {
return (
<MenuItem
name="Accounts"
itemUrl="accounts"
defaultChild="overview"
icon="fa-users"
>
<MenuItem
name="Overview"
itemUrl="overview"
icon="fa-list"
/>
<MenuItem
name="Pending"
itemUrl="pending"
icon="fa-question"
/>
</MenuItem>
);
}
function ModerationDomainPermsMenu() {
return (
<MenuItem
name="Domain Permissions"
itemUrl="domain-permissions"
defaultChild="blocks"
icon="fa-hubzilla"
>
<MenuItem
name="Blocks"
itemUrl="blocks"
icon="fa-close"
/>
<MenuItem
name="Allows"
itemUrl="allows"
icon="fa-check"
/>
<MenuItem
name="Import/Export"
itemUrl="import-export"
icon="fa-floppy-o"
/>
</MenuItem>
);
}
/*
ROUTERS
*/
function ModerationReportsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/reports";
const absBase = parentUrl + thisBase;
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<Switch>
<Route path={"/:reportId"} component={ReportDetail} />
<Route component={ReportOverview}/>
</Switch>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/moderation/accounts/overview
* - /settings/moderation/accounts/pending
* - /settings/moderation/accounts/:accountID
*/
function ModerationAccountsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/accounts";
const absBase = parentUrl + thisBase;
const AccountsOverview = lazy(() => import('./accounts'));
const AccountsPending = lazy(() => import('./accounts/pending'));
const AccountDetail = lazy(() => import('./accounts/detail'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/overview" component={AccountsOverview}/>
<Route path="/pending" component={AccountsPending}/>
<Route path="/:accountID" component={AccountDetail}/>
<Route><Redirect to="/overview"/></Route>
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}
/**
* - /settings/moderation/domain-permissions/:permType
* - /settings/moderation/domain-permissions/:permType/:domain
* - /settings/moderation/domain-permissions/import-export
* - /settings/moderation/domain-permissions/process
*/
function ModerationDomainPermsRouter() {
const parentUrl = useBaseUrl();
const thisBase = "/domain-permissions";
const absBase = parentUrl + thisBase;
const DomainPermissionsOverview = lazy(() => import('./domain-permissions/overview'));
const DomainPermDetail = lazy(() => import('./domain-permissions/detail'));
const ImportExport = lazy(() => import('./domain-permissions/import-export'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/import-export" component={ImportExport} />
<Route path="/process" component={ImportExport} />
<Route path="/:permType" component={DomainPermissionsOverview} />
<Route path="/:permType/:domain" component={DomainPermDetail} />
<Route><Redirect to="/blocks"/></Route>
</Switch>
</Suspense>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>
);
}

View file

@ -0,0 +1,52 @@
/*
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/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React from "react";
/**
* - /settings/user/profile
* - /settings/user/settings
* - /settings/user/migration
*/
export default function UserMenu() {
return (
<MenuItem
name="User"
itemUrl="user"
defaultChild="profile"
>
<MenuItem
name="Profile"
itemUrl="profile"
icon="fa-user"
/>
<MenuItem
name="Settings"
itemUrl="settings"
icon="fa-cogs"
/>
<MenuItem
name="Migration"
itemUrl="migration"
icon="fa-exchange"
/>
</MenuItem>
);
}

View file

@ -17,73 +17,34 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { MenuItem } from "../../lib/navigation/menu";
import React, { lazy, Suspense } from "react";
import React from "react";
import { BaseUrlContext, useBaseUrl } from "../../lib/navigation/util";
import { Redirect, Route, Router, Switch } from "wouter";
import { ErrorBoundary } from "../../lib/navigation/error";
import Loading from "../../components/loading";
import UserProfile from "./profile";
import UserMigration from "./migration";
import UserSettings from "./settings";
/**
* - /settings/user/profile
* - /settings/user/settings
* - /settings/user/migration
*/
export function UserMenu() {
return (
<MenuItem
name="User"
itemUrl="user"
defaultChild="profile"
>
{/* Profile */}
<MenuItem
name="Profile"
itemUrl="profile"
icon="fa-user"
/>
{/* Settings */}
<MenuItem
name="Settings"
itemUrl="settings"
icon="fa-cogs"
/>
{/* Migration */}
<MenuItem
name="Migration"
itemUrl="migration"
icon="fa-exchange"
/>
</MenuItem>
);
}
/**
* - /settings/user/profile
* - /settings/user/settings
* - /settings/user/migration
*/
export function UserRouter() {
export default function UserRouter() {
const baseUrl = useBaseUrl();
const thisBase = "/user";
const absBase = baseUrl + thisBase;
const UserProfile = lazy(() => import('./profile'));
const UserSettings = lazy(() => import('./settings'));
const UserMigration = lazy(() => import('./migration'));
return (
<BaseUrlContext.Provider value={absBase}>
<Router base={thisBase}>
<ErrorBoundary>
<Suspense fallback={<Loading/>}>
<Switch>
<Route path="/profile" component={UserProfile} />
<Route path="/settings" component={UserSettings} />
<Route path="/migration" component={UserMigration} />
<Route><Redirect to="/profile" /></Route>
</Switch>
</Suspense>
<Switch>
<Route path="/profile" component={UserProfile} />
<Route path="/settings" component={UserSettings} />
<Route path="/migration" component={UserMigration} />
<Route><Redirect to="/profile" /></Route>
</Switch>
</ErrorBoundary>
</Router>
</BaseUrlContext.Provider>