From eef8d2c8552ec72f71fb6ff09cb095405ea40439 Mon Sep 17 00:00:00 2001 From: Emelia Smith Date: Fri, 29 Nov 2024 08:36:17 +0100 Subject: [PATCH] Add link from Web UI for Hashtags to the Moderation UI (#31448) Co-authored-by: Eugen Rochko --- .../components/hashtag_header.jsx | 21 ++++++++++++--- app/javascript/mastodon/locales/en.json | 1 + app/javascript/mastodon/permissions.ts | 1 + .../styles/mastodon/components.scss | 26 ++++++++++++++++++- app/serializers/rest/tag_serializer.rb | 6 ++++- 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/hashtag_header.jsx b/app/javascript/mastodon/features/hashtag_timeline/components/hashtag_header.jsx index d2fe8851f6..415cf7bf10 100644 --- a/app/javascript/mastodon/features/hashtag_timeline/components/hashtag_header.jsx +++ b/app/javascript/mastodon/features/hashtag_timeline/components/hashtag_header.jsx @@ -4,12 +4,17 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePropTypes from 'react-immutable-proptypes'; +import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import { Button } from 'mastodon/components/button'; import { ShortNumber } from 'mastodon/components/short_number'; +import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; +import { withIdentity } from 'mastodon/identity_context'; +import { PERMISSION_MANAGE_TAXONOMIES } from 'mastodon/permissions'; const messages = defineMessages({ followHashtag: { id: 'hashtag.follow', defaultMessage: 'Follow hashtag' }, unfollowHashtag: { id: 'hashtag.unfollow', defaultMessage: 'Unfollow hashtag' }, + adminModeration: { id: 'hashtag.admin_moderation', defaultMessage: 'Open moderation interface for #{name}' }, }); const usesRenderer = (displayNumber, pluralReady) => ( @@ -45,11 +50,18 @@ const usesTodayRenderer = (displayNumber, pluralReady) => ( /> ); -export const HashtagHeader = injectIntl(({ tag, intl, disabled, onClick }) => { +export const HashtagHeader = withIdentity(injectIntl(({ tag, intl, disabled, onClick, identity }) => { if (!tag) { return null; } + const { signedIn, permissions } = identity; + const menu = []; + + if (signedIn && (permissions & PERMISSION_MANAGE_TAXONOMIES) === PERMISSION_MANAGE_TAXONOMIES ) { + menu.push({ text: intl.formatMessage(messages.adminModeration, { name: tag.get("name") }), href: `/admin/tags/${tag.get('id')}` }); + } + const [uses, people] = tag.get('history').reduce((arr, day) => [arr[0] + day.get('uses') * 1, arr[1] + day.get('accounts') * 1], [0, 0]); const dividingCircle = {' ยท '}; @@ -57,7 +69,10 @@ export const HashtagHeader = injectIntl(({ tag, intl, disabled, onClick }) => {

#{tag.get('name')}

-
@@ -69,7 +84,7 @@ export const HashtagHeader = injectIntl(({ tag, intl, disabled, onClick }) => {
); -}); +})); HashtagHeader.propTypes = { tag: ImmutablePropTypes.map, diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 6a44856837..71ab620226 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -363,6 +363,7 @@ "footer.status": "Status", "generic.saved": "Saved", "getting_started.heading": "Getting started", + "hashtag.admin_moderation": "Open moderation interface for #{name}", "hashtag.column_header.tag_mode.all": "and {additional}", "hashtag.column_header.tag_mode.any": "or {additional}", "hashtag.column_header.tag_mode.none": "without {additional}", diff --git a/app/javascript/mastodon/permissions.ts b/app/javascript/mastodon/permissions.ts index 8f015610ea..d7695d2f5c 100644 --- a/app/javascript/mastodon/permissions.ts +++ b/app/javascript/mastodon/permissions.ts @@ -1,5 +1,6 @@ export const PERMISSION_INVITE_USERS = 0x0000000000010000; export const PERMISSION_MANAGE_USERS = 0x0000000000000400; +export const PERMISSION_MANAGE_TAXONOMIES = 0x0000000000000100; export const PERMISSION_MANAGE_FEDERATION = 0x0000000000000020; export const PERMISSION_MANAGE_REPORTS = 0x0000000000000010; diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 0bb5b00412..df3a770648 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -8000,7 +8000,7 @@ noscript { } .icon-button { - border: 1px solid lighten($ui-base-color, 12%); + border: 1px solid var(--background-border-color); border-radius: 4px; box-sizing: content-box; padding: 5px; @@ -9952,6 +9952,30 @@ noscript { line-height: 33px; font-weight: 700; } + + &__buttons { + display: flex; + align-items: center; + gap: 8px; + + .button { + flex-shrink: 1; + white-space: nowrap; + min-width: 80px; + } + + .icon-button { + border: 1px solid var(--background-border-color); + border-radius: 4px; + box-sizing: content-box; + padding: 5px; + + .icon { + width: 24px; + height: 24px; + } + } + } } } diff --git a/app/serializers/rest/tag_serializer.rb b/app/serializers/rest/tag_serializer.rb index 017b572718..a2bcb5fd1f 100644 --- a/app/serializers/rest/tag_serializer.rb +++ b/app/serializers/rest/tag_serializer.rb @@ -3,10 +3,14 @@ class REST::TagSerializer < ActiveModel::Serializer include RoutingHelper - attributes :name, :url, :history + attributes :id, :name, :url, :history attribute :following, if: :current_user? + def id + object.id.to_s + end + def url tag_url(object) end