diff --git a/app/javascript/mastodon/features/getting_started/index.jsx b/app/javascript/mastodon/features/getting_started/index.jsx index 628bbe62bb..8d26115dfa 100644 --- a/app/javascript/mastodon/features/getting_started/index.jsx +++ b/app/javascript/mastodon/features/getting_started/index.jsx @@ -12,9 +12,11 @@ import { connect } from 'react-redux'; import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react'; import ExploreIcon from '@/material-icons/400-24px/explore.svg?react'; +import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react'; import PeopleIcon from '@/material-icons/400-24px/group.svg?react'; import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react'; import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; +import AdministrationIcon from '@/material-icons/400-24px/manufacturing.svg?react'; import MenuIcon from '@/material-icons/400-24px/menu.svg?react'; import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react'; import PublicIcon from '@/material-icons/400-24px/public.svg?react'; @@ -25,6 +27,7 @@ import Column from 'mastodon/components/column'; import ColumnHeader from 'mastodon/components/column_header'; import LinkFooter from 'mastodon/features/ui/components/link_footer'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; +import { canManageReports, canViewAdminDashboard } from 'mastodon/permissions'; import { me, showTrends } from '../../initial_state'; import { NavigationBar } from '../compose/components/navigation_bar'; @@ -43,6 +46,8 @@ const messages = defineMessages({ direct: { id: 'navigation_bar.direct', defaultMessage: 'Private mentions' }, bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + administration: { id: 'navigation_bar.administration', defaultMessage: 'Administration' }, + moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' }, blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, @@ -99,7 +104,7 @@ class GettingStarted extends ImmutablePureComponent { render () { const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props; - const { signedIn } = this.props.identity; + const { signedIn, permissions } = this.props.identity; const navItems = []; @@ -136,6 +141,13 @@ class GettingStarted extends ImmutablePureComponent { , , ); + + if (canManageReports(permissions)) { + navItems.push(); + } + if (canViewAdminDashboard(permissions)) { + navItems.push(); + } } return ( diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx index 2648923bfc..d30ea0ac5d 100644 --- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx +++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx @@ -7,16 +7,17 @@ import { Link } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; - import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import BookmarksActiveIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react'; import BookmarksIcon from '@/material-icons/400-24px/bookmarks.svg?react'; import ExploreActiveIcon from '@/material-icons/400-24px/explore-fill.svg?react'; import ExploreIcon from '@/material-icons/400-24px/explore.svg?react'; +import ModerationIcon from '@/material-icons/400-24px/gavel.svg?react'; import HomeActiveIcon from '@/material-icons/400-24px/home-fill.svg?react'; import HomeIcon from '@/material-icons/400-24px/home.svg?react'; import ListAltActiveIcon from '@/material-icons/400-24px/list_alt-fill.svg?react'; import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; +import AdministrationIcon from '@/material-icons/400-24px/manufacturing.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import NotificationsActiveIcon from '@/material-icons/400-24px/notifications-fill.svg?react'; import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react'; @@ -34,6 +35,7 @@ import { NavigationPortal } from 'mastodon/components/navigation_portal'; import { identityContextPropShape, withIdentity } from 'mastodon/identity_context'; import { timelinePreview, trendsEnabled } from 'mastodon/initial_state'; import { transientSingleColumn } from 'mastodon/is_mobile'; +import { canManageReports, canViewAdminDashboard } from 'mastodon/permissions'; import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications'; import ColumnLink from './column_link'; @@ -51,6 +53,8 @@ const messages = defineMessages({ bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' }, lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, + administration: { id: 'navigation_bar.administration', defaultMessage: 'Administration' }, + moderation: { id: 'navigation_bar.moderation', defaultMessage: 'Moderation' }, followsAndFollowers: { id: 'navigation_bar.follows_and_followers', defaultMessage: 'Follows and followers' }, about: { id: 'navigation_bar.about', defaultMessage: 'About' }, search: { id: 'navigation_bar.search', defaultMessage: 'Search' }, @@ -114,7 +118,7 @@ class NavigationPanel extends Component { render () { const { intl } = this.props; - const { signedIn, disabledAccountId } = this.props.identity; + const { signedIn, disabledAccountId, permissions } = this.props.identity; let banner = undefined; @@ -176,6 +180,9 @@ class NavigationPanel extends Component {
+ + {canManageReports(permissions) && } + {canViewAdminDashboard(permissions) && } )} diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 88920431fb..343af40424 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -467,6 +467,7 @@ "mute_modal.you_wont_see_mentions": "You won't see posts that mention them.", "mute_modal.you_wont_see_posts": "They can still see your posts, but you won't see theirs.", "navigation_bar.about": "About", + "navigation_bar.administration": "Administration", "navigation_bar.advanced_interface": "Open in advanced web interface", "navigation_bar.blocks": "Blocked users", "navigation_bar.bookmarks": "Bookmarks", @@ -483,6 +484,7 @@ "navigation_bar.follows_and_followers": "Follows and followers", "navigation_bar.lists": "Lists", "navigation_bar.logout": "Logout", + "navigation_bar.moderation": "Moderation", "navigation_bar.mutes": "Muted users", "navigation_bar.opened_in_classic_interface": "Posts, accounts, and other specific pages are opened by default in the classic web interface.", "navigation_bar.personal": "Personal", diff --git a/app/javascript/mastodon/permissions.ts b/app/javascript/mastodon/permissions.ts index b583535c00..8f015610ea 100644 --- a/app/javascript/mastodon/permissions.ts +++ b/app/javascript/mastodon/permissions.ts @@ -1,4 +1,23 @@ export const PERMISSION_INVITE_USERS = 0x0000000000010000; export const PERMISSION_MANAGE_USERS = 0x0000000000000400; export const PERMISSION_MANAGE_FEDERATION = 0x0000000000000020; + export const PERMISSION_MANAGE_REPORTS = 0x0000000000000010; +export const PERMISSION_VIEW_DASHBOARD = 0x0000000000000008; + +// These helpers don't quite align with the names/categories in UserRole, +// but are likely "good enough" for the use cases at present. +// +// See: https://docs.joinmastodon.org/entities/Role/#permission-flags + +export function canViewAdminDashboard(permissions: number) { + return ( + (permissions & PERMISSION_VIEW_DASHBOARD) === PERMISSION_VIEW_DASHBOARD + ); +} + +export function canManageReports(permissions: number) { + return ( + (permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS + ); +}