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..f37c15557d 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 9728528f8e..038ab6f904 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -360,6 +360,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/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