diff --git a/app/soapbox/actions/admin.js b/app/soapbox/actions/admin.js index 04fdd1a31..b16ef5a8b 100644 --- a/app/soapbox/actions/admin.js +++ b/app/soapbox/actions/admin.js @@ -1,5 +1,5 @@ import api from '../api'; -import { importFetchedStatuses } from 'soapbox/actions/importer'; +import { importFetchedAccount, importFetchedStatuses } from 'soapbox/actions/importer'; export const ADMIN_CONFIG_FETCH_REQUEST = 'ADMIN_CONFIG_FETCH_REQUEST'; export const ADMIN_CONFIG_FETCH_SUCCESS = 'ADMIN_CONFIG_FETCH_SUCCESS'; @@ -73,7 +73,11 @@ export function fetchReports(params) { return api(getState) .get('/api/pleroma/admin/reports', { params }) .then(({ data: { reports } }) => { - reports.forEach(report => dispatch(importFetchedStatuses(report.statuses))); + reports.forEach(report => { + dispatch(importFetchedAccount(report.account)); + dispatch(importFetchedAccount(report.actor)); + dispatch(importFetchedStatuses(report.statuses)); + }); dispatch({ type: ADMIN_REPORTS_FETCH_SUCCESS, reports, params }); }).catch(error => { dispatch({ type: ADMIN_REPORTS_FETCH_FAIL, error, params }); diff --git a/app/soapbox/actions/moderation.js b/app/soapbox/actions/moderation.js new file mode 100644 index 000000000..7edc3e775 --- /dev/null +++ b/app/soapbox/actions/moderation.js @@ -0,0 +1,72 @@ +import { defineMessages } from 'react-intl'; +import { openModal } from 'soapbox/actions/modal'; +import { deactivateUsers, deleteUsers, deleteStatus } from 'soapbox/actions/admin'; +import snackbar from 'soapbox/actions/snackbar'; + +const messages = defineMessages({ + deactivateUserPrompt: { id: 'confirmations.admin.deactivate_user.message', defaultMessage: 'You are about to deactivate {acct}. Deactivating a user is a reversible action.' }, + deactivateUserConfirm: { id: 'confirmations.admin.deactivate_user.confirm', defaultMessage: 'Deactivate {acct}' }, + userDeactivated: { id: 'admin.users.user_deactivated_message', defaultMessage: '{acct} was deactivated' }, + deleteUserPrompt: { id: 'confirmations.admin.delete_user.message', defaultMessage: 'You are about to delete {acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.' }, + deleteUserConfirm: { id: 'confirmations.admin.delete_user.confirm', defaultMessage: 'Delete {acct}' }, + userDeleted: { id: 'admin.users.user_deleted_message', defaultMessage: '{acct} was deleted' }, + deleteStatusPrompt: { id: 'confirmations.admin.delete_status.message', defaultMessage: 'You are about to delete a post by {acct}. This action cannot be undone.' }, + deleteStatusConfirm: { id: 'confirmations.admin.delete_status.confirm', defaultMessage: 'Delete post' }, + statusDeleted: { id: 'admin.statuses.status_deleted_message', defaultMessage: 'Post by {acct} was deleted' }, +}); + +export function deactivateUserModal(intl, accountId, afterConfirm = () => {}) { + return function(dispatch, getState) { + const state = getState(); + const acct = state.getIn(['accounts', accountId, 'acct']); + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.deactivateUserPrompt, { acct: `@${acct}` }), + confirm: intl.formatMessage(messages.deactivateUserConfirm, { acct: `@${acct}` }), + onConfirm: () => { + dispatch(deactivateUsers([acct])).then(() => { + const message = intl.formatMessage(messages.userDeactivated, { acct: `@${acct}` }); + dispatch(snackbar.success(message)); + afterConfirm(); + }).catch(() => {}); + }, + })); + }; +} + +export function deleteUserModal(intl, accountId, afterConfirm = () => {}) { + return function(dispatch, getState) { + const state = getState(); + const acct = state.getIn(['accounts', accountId, 'acct']); + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.deleteUserPrompt, { acct: `@${acct}` }), + confirm: intl.formatMessage(messages.deleteUserConfirm, { acct: `@${acct}` }), + onConfirm: () => { + dispatch(deleteUsers([acct])).then(() => { + const message = intl.formatMessage(messages.userDeleted, { acct: `@${acct}` }); + dispatch(snackbar.success(message)); + afterConfirm(); + }).catch(() => {}); + }, + })); + }; +} + +export function deleteStatusModal(intl, statusId, afterConfirm = () => {}) { + return function(dispatch, getState) { + const state = getState(); + const accountId = state.getIn(['statuses', statusId, 'account']); + const acct = state.getIn(['accounts', accountId, 'acct']); + + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.deleteStatusPrompt, { acct: `@${acct}` }), + confirm: intl.formatMessage(messages.deleteStatusConfirm), + onConfirm: () => { + dispatch(deleteStatus(statusId)).then(() => { + const message = intl.formatMessage(messages.statusDeleted, { acct: `@${acct}` }); + dispatch(snackbar.success(message)); + }).catch(() => {}); + afterConfirm(); + }, + })); + }; +} diff --git a/app/soapbox/components/status_action_bar.js b/app/soapbox/components/status_action_bar.js index 1c2a9207b..5895dde9e 100644 --- a/app/soapbox/components/status_action_bar.js +++ b/app/soapbox/components/status_action_bar.js @@ -45,6 +45,9 @@ const messages = defineMessages({ copy: { id: 'status.copy', defaultMessage: 'Copy link to post' }, group_remove_account: { id: 'status.remove_account_from_group', defaultMessage: 'Remove account from group' }, group_remove_post: { id: 'status.remove_post_from_group', defaultMessage: 'Remove post from group' }, + deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate {acct}' }, + deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete {acct}' }, + deleteStatus: { id: 'admin.statuses.actions.delete_status', defaultMessage: 'Delete post' }, }); class StatusActionBar extends ImmutablePureComponent { @@ -67,6 +70,9 @@ class StatusActionBar extends ImmutablePureComponent { onBlock: PropTypes.func, onReport: PropTypes.func, onEmbed: PropTypes.func, + onDeactivateUser: PropTypes.func, + onDeleteUser: PropTypes.func, + onDeleteStatus: PropTypes.func, onMuteConversation: PropTypes.func, onPin: PropTypes.func, withDismiss: PropTypes.bool, @@ -242,6 +248,18 @@ class StatusActionBar extends ImmutablePureComponent { this.props.onGroupRemoveStatus(status.getIn(['group', 'id']), status.get('id')); } + handleDeactivateUser = () => { + this.props.onDeactivateUser(this.props.status); + } + + handleDeleteUser = () => { + this.props.onDeleteUser(this.props.status); + } + + handleDeleteStatus = () => { + this.props.onDeleteStatus(this.props.status); + } + _makeMenu = (publicStatus) => { const { status, intl, withDismiss, withGroupAdmin, me, isStaff } = this.props; const mutingConversation = status.get('muted'); @@ -291,6 +309,9 @@ class StatusActionBar extends ImmutablePureComponent { menu.push(null); menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/pleroma/admin/#/users/${status.getIn(['account', 'id'])}/` }); // menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + menu.push({ text: intl.formatMessage(messages.deactivateUser, { acct: `@${status.getIn(['account', 'acct'])}` }), action: this.handleDeactivateUser }); + menu.push({ text: intl.formatMessage(messages.deleteUser, { acct: `@${status.getIn(['account', 'acct'])}` }), action: this.handleDeleteUser }); + menu.push({ text: intl.formatMessage(messages.deleteStatus), action: this.handleDeleteStatus }); } if (withGroupAdmin) { diff --git a/app/soapbox/containers/status_container.js b/app/soapbox/containers/status_container.js index 989b393c5..abb0da6c4 100644 --- a/app/soapbox/containers/status_container.js +++ b/app/soapbox/containers/status_container.js @@ -36,6 +36,7 @@ import { } from '../actions/groups'; import { getSettings } from '../actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import { deactivateUserModal, deleteUserModal, deleteStatusModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -208,6 +209,18 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ dispatch(groupRemoveStatus(groupId, statusId)); }, + onDeactivateUser(status) { + dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']))); + }, + + onDeleteUser(status) { + dispatch(deleteUserModal(intl, status.getIn(['account', 'id']))); + }, + + onDeleteStatus(status) { + dispatch(deleteStatusModal(intl, status.get('id'))); + }, + }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status)); diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index 116b43565..80bba5c6d 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -46,6 +46,8 @@ const messages = defineMessages({ unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' }, admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' }, + deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate {acct}' }, + deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete {acct}' }, }); const mapStateToProps = state => { @@ -169,6 +171,8 @@ class Header extends ImmutablePureComponent { if (account.get('id') !== me && isStaff) { menu.push(null); menu.push({ text: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/pleroma/admin/#/users/${account.get('id')}/`, newTab: true }); + menu.push({ text: intl.formatMessage(messages.deactivateUser, { acct: `@${account.get('acct')}` }), action: this.props.onDeactivateUser }); + menu.push({ text: intl.formatMessage(messages.deleteUser, { acct: `@${account.get('acct')}` }), action: this.props.onDeleteUser }); } return menu; diff --git a/app/soapbox/features/account_timeline/components/header.js b/app/soapbox/features/account_timeline/components/header.js index 534a12dbc..86798d3ab 100644 --- a/app/soapbox/features/account_timeline/components/header.js +++ b/app/soapbox/features/account_timeline/components/header.js @@ -84,6 +84,14 @@ export default class Header extends ImmutablePureComponent { this.props.onAddToList(this.props.account); } + handleDeactivateUser = () => { + this.props.onDeactivateUser(this.props.account); + } + + handleDeleteUser = () => { + this.props.onDeleteUser(this.props.account); + } + render() { const { account, identity_proofs } = this.props; const moved = (account) ? account.get('moved') : false; @@ -107,6 +115,8 @@ export default class Header extends ImmutablePureComponent { onUnblockDomain={this.handleUnblockDomain} onEndorseToggle={this.handleEndorseToggle} onAddToList={this.handleAddToList} + onDeactivateUser={this.handleDeactivateUser} + onDeleteUser={this.handleDeleteUser} username={this.props.username} /> diff --git a/app/soapbox/features/account_timeline/containers/header_container.js b/app/soapbox/features/account_timeline/containers/header_container.js index 6eebe0772..8d6438894 100644 --- a/app/soapbox/features/account_timeline/containers/header_container.js +++ b/app/soapbox/features/account_timeline/containers/header_container.js @@ -24,6 +24,7 @@ import { List as ImmutableList } from 'immutable'; import { getSettings } from 'soapbox/actions/settings'; import { startChat, openChat } from 'soapbox/actions/chats'; import { isMobile } from 'soapbox/is_mobile'; +import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, @@ -145,6 +146,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }).catch(() => {}); }, + + onDeactivateUser(account) { + dispatch(deactivateUserModal(intl, account.get('id'))); + }, + + onDeleteUser(account) { + dispatch(deleteUserModal(intl, account.get('id'))); + }, }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header)); diff --git a/app/soapbox/features/admin/components/report.js b/app/soapbox/features/admin/components/report.js index a1e7d82bb..6c6b7face 100644 --- a/app/soapbox/features/admin/components/report.js +++ b/app/soapbox/features/admin/components/report.js @@ -9,20 +9,14 @@ import Button from 'soapbox/components/button'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; import Accordion from 'soapbox/features/ui/components/accordion'; import ReportStatus from './report_status'; -import { closeReports, deactivateUsers, deleteUsers } from 'soapbox/actions/admin'; +import { closeReports } from 'soapbox/actions/admin'; import snackbar from 'soapbox/actions/snackbar'; -import { openModal } from 'soapbox/actions/modal'; +import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ reportClosed: { id: 'admin.reports.report_closed_message', defaultMessage: 'Report on {acct} was closed' }, - deactivateUser: { id: 'admin.reports.actions.deactivate_user', defaultMessage: 'Deactivate {acct}' }, - deactivateUserPrompt: { id: 'confirmations.admin.deactivate_user.message', defaultMessage: 'You are about to deactivate {acct}. Deactivating a user is a reversible action.' }, - deactivateUserConfirm: { id: 'confirmations.admin.deactivate_user.confirm', defaultMessage: 'Deactivate {acct}' }, - userDeactivated: { id: 'admin.reports.user_deactivated_message', defaultMessage: '{acct} was deactivated' }, - deleteUser: { id: 'admin.reports.actions.delete_user', defaultMessage: 'Delete {acct}' }, - deleteUserPrompt: { id: 'confirmations.admin.delete_user.message', defaultMessage: 'You are about to delete {acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.' }, - deleteUserConfirm: { id: 'confirmations.admin.delete_user.confirm', defaultMessage: 'Delete {acct}' }, - userDeleted: { id: 'admin.reports.user_deleted_message', defaultMessage: '{acct} was deleted' }, + deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate {acct}' }, + deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete {acct}' }, }); export default @connect() @@ -60,34 +54,14 @@ class Report extends ImmutablePureComponent { handleDeactivateUser = () => { const { intl, dispatch, report } = this.props; - const nickname = report.getIn(['account', 'acct']); - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deactivateUserPrompt, { acct: `@${nickname}` }), - confirm: intl.formatMessage(messages.deactivateUserConfirm, { acct: `@${nickname}` }), - onConfirm: () => { - dispatch(deactivateUsers([nickname])).then(() => { - const message = intl.formatMessage(messages.userDeactivated, { acct: `@${nickname}` }); - dispatch(snackbar.success(message)); - }).catch(() => {}); - this.handleCloseReport(); - }, - })); + const accountId = report.getIn(['account', 'id']); + dispatch(deactivateUserModal(intl, accountId, () => this.handleCloseReport())); } handleDeleteUser = () => { const { intl, dispatch, report } = this.props; - const nickname = report.getIn(['account', 'acct']); - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deleteUserPrompt, { acct: `@${nickname}` }), - confirm: intl.formatMessage(messages.deleteUserConfirm, { acct: `@${nickname}` }), - onConfirm: () => { - dispatch(deleteUsers([nickname])).then(() => { - const message = intl.formatMessage(messages.userDeleted, { acct: `@${nickname}` }); - dispatch(snackbar.success(message)); - }).catch(() => {}); - this.handleCloseReport(); - }, - })); + const accountId = report.getIn(['account', 'id']); + dispatch(deleteUserModal(intl, accountId, () => this.handleCloseReport())); } handleAccordionToggle = setting => { diff --git a/app/soapbox/features/admin/components/report_status.js b/app/soapbox/features/admin/components/report_status.js index d98e9c755..63c9a3a66 100644 --- a/app/soapbox/features/admin/components/report_status.js +++ b/app/soapbox/features/admin/components/report_status.js @@ -5,19 +5,15 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages } from 'react-intl'; import StatusContent from 'soapbox/components/status_content'; import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; -import { deleteStatus } from 'soapbox/actions/admin'; -import snackbar from 'soapbox/actions/snackbar'; import { openModal } from 'soapbox/actions/modal'; import noop from 'lodash/noop'; import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components'; import Bundle from 'soapbox/features/ui/components/bundle'; +import { deleteStatusModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ viewStatus: { id: 'admin.reports.actions.view_status', defaultMessage: 'View post' }, - deleteStatus: { id: 'admin.reports.actions.delete_status', defaultMessage: 'Delete post' }, - deleteStatusPrompt: { id: 'confirmations.admin.delete_status.message', defaultMessage: 'You are about to delete a post by {acct}. This action cannot be undone.' }, - deleteStatusConfirm: { id: 'confirmations.admin.delete_status.confirm', defaultMessage: 'Delete post' }, - statusDeleted: { id: 'admin.reports.status_deleted_message', defaultMessage: 'Post by {acct} was deleted' }, + deleteStatus: { id: 'admin.statuses.actions.delete_status', defaultMessage: 'Delete post' }, }); export default @connect() @@ -104,19 +100,8 @@ class ReportStatus extends ImmutablePureComponent { handleDeleteStatus = () => { const { intl, dispatch, status } = this.props; - const nickname = status.getIn(['account', 'acct']); const statusId = status.get('id'); - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.deleteStatusPrompt, { acct: `@${nickname}` }), - confirm: intl.formatMessage(messages.deleteStatusConfirm), - onConfirm: () => { - dispatch(deleteStatus(statusId)).then(() => { - const message = intl.formatMessage(messages.statusDeleted, { acct: `@${nickname}` }); - dispatch(snackbar.success(message)); - }).catch(() => {}); - this.handleCloseReport(); - }, - })); + dispatch(deleteStatusModal(intl, statusId)); } render() { diff --git a/app/soapbox/features/status/components/action_bar.js b/app/soapbox/features/status/components/action_bar.js index 6fb88fb86..2e8e6f375 100644 --- a/app/soapbox/features/status/components/action_bar.js +++ b/app/soapbox/features/status/components/action_bar.js @@ -36,6 +36,9 @@ const messages = defineMessages({ copy: { id: 'status.copy', defaultMessage: 'Copy link to post' }, bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' }, unbookmark: { id: 'status.unbookmark', defaultMessage: 'Remove bookmark' }, + deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate {acct}' }, + deleteUser: { id: 'admin.users.actions.delete_user', defaultMessage: 'Delete {acct}' }, + deleteStatus: { id: 'admin.statuses.actions.delete_status', defaultMessage: 'Delete post' }, }); const mapStateToProps = state => { @@ -74,6 +77,9 @@ class ActionBar extends React.PureComponent { onReport: PropTypes.func, onPin: PropTypes.func, onEmbed: PropTypes.func, + onDeactivateUser: PropTypes.func, + onDeleteUser: PropTypes.func, + onDeleteStatus: PropTypes.func, intl: PropTypes.object.isRequired, onOpenUnauthorizedModal: PropTypes.func.isRequired, me: SoapboxPropTypes.me, @@ -221,6 +227,18 @@ class ActionBar extends React.PureComponent { } } + handleDeactivateUser = () => { + this.props.onDeactivateUser(this.props.status); + } + + handleDeleteUser = () => { + this.props.onDeleteUser(this.props.status); + } + + handleDeleteStatus = () => { + this.props.onDeleteStatus(this.props.status); + } + setRef = c => { this.node = c; } @@ -276,6 +294,9 @@ class ActionBar extends React.PureComponent { menu.push(null); menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/pleroma/admin/#/users/${status.getIn(['account', 'id'])}/` }); // menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + menu.push({ text: intl.formatMessage(messages.deactivateUser, { acct: `@${status.getIn(['account', 'acct'])}` }), action: this.handleDeactivateUser }); + menu.push({ text: intl.formatMessage(messages.deleteUser, { acct: `@${status.getIn(['account', 'acct'])}` }), action: this.handleDeleteUser }); + menu.push({ text: intl.formatMessage(messages.deleteStatus), action: this.handleDeleteStatus }); } } diff --git a/app/soapbox/features/status/containers/detailed_status_container.js b/app/soapbox/features/status/containers/detailed_status_container.js index 509587636..e9c64e384 100644 --- a/app/soapbox/features/status/containers/detailed_status_container.js +++ b/app/soapbox/features/status/containers/detailed_status_container.js @@ -31,6 +31,7 @@ import { openModal } from '../../../actions/modal'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { showAlertForError } from '../../../actions/alerts'; import { getSettings } from 'soapbox/actions/settings'; +import { deactivateUserModal, deleteUserModal, deleteStatusModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -190,6 +191,18 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onDeactivateUser(status) { + dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']))); + }, + + onDeleteUser(status) { + dispatch(deleteUserModal(intl, status.getIn(['account', 'id']))); + }, + + onDeleteStatus(status) { + dispatch(deleteStatusModal(intl, status.get('id'))); + }, + }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(DetailedStatus)); diff --git a/app/soapbox/features/status/index.js b/app/soapbox/features/status/index.js index f64ac5f74..a48cedaa4 100644 --- a/app/soapbox/features/status/index.js +++ b/app/soapbox/features/status/index.js @@ -47,6 +47,7 @@ import { textForScreenReader, defaultMediaVisibility } from '../../components/st import Icon from 'soapbox/components/icon'; import { getSettings } from 'soapbox/actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; +import { deactivateUserModal, deleteUserModal, deleteStatusModal } from 'soapbox/actions/moderation'; const messages = defineMessages({ deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, @@ -302,6 +303,21 @@ class Status extends ImmutablePureComponent { this.props.dispatch(openModal('EMBED', { url: status.get('url') })); } + handleDeactivateUser = (status) => { + const { dispatch, intl } = this.props; + dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']))); + } + + handleDeleteUser = (status) => { + const { dispatch, intl } = this.props; + dispatch(deleteUserModal(intl, status.getIn(['account', 'id']))); + } + + handleDeleteStatus = (status) => { + const { dispatch, intl } = this.props; + dispatch(deleteStatusModal(intl, status.get('id'))); + } + handleHotkeyMoveUp = () => { this.handleMoveUp(this.props.status.get('id')); } @@ -523,6 +539,9 @@ class Status extends ImmutablePureComponent { onPin={this.handlePin} onBookmark={this.handleBookmark} onEmbed={this.handleEmbed} + onDeactivateUser={this.handleDeactivateUser} + onDeleteUser={this.handleDeleteUser} + onDeleteStatus={this.handleDeleteStatus} allowedEmoji={this.props.allowedEmoji} /> diff --git a/app/soapbox/locales/pl.json b/app/soapbox/locales/pl.json index 7d36ac753..cde3d1e94 100644 --- a/app/soapbox/locales/pl.json +++ b/app/soapbox/locales/pl.json @@ -68,11 +68,11 @@ "admin.dashcounters.user_count_label": "użytkownicy", "admin.dashwidgets.software_header": "Oprogramowanie", "admin.moderation_log.empty_message": "Nie wykonałeś(-aś) jeszcze żadnych działań moderacyjnych. Kiedy jakieś zostaną wykonane, ich historia pojawi się tutaj.", - "admin.reports.actions.deactivate_user": "Dezaktywuj {acct}", - "admin.reports.actions.delete_user": "Usuń {acct}", - "admin.reports.actions.delete_sstatus": "Usuń wpis", - "admin.reports.actions.user_deactivated_message": "Zdezaktywowano {acct}", - "admin.reports.actions.user_deleted_message": "Usunięto {acct}", + "admin.users.actions.deactivate_user": "Dezaktywuj {acct}", + "admin.users.actions.delete_user": "Usuń {acct}", + "admin.statuses.actions.delete_status": "Usuń wpis", + "admin.users.actions.user_deactivated_message": "Zdezaktywowano {acct}", + "admin.users.actions.user_deleted_message": "Usunięto {acct}", "admin.reports.actions.view_status": "Wyświetl wpis", "admin.reports.empty_message": "Brak otwartych zgłoszeń. Gdy użytkownik zostanie zgłoszony, pojawi się on tutaj.", "admin.reports.report_closed_message": "Zamknięto zgłoszenie dotyczące {acct}", diff --git a/app/styles/components/admin.scss b/app/styles/components/admin.scss index caf9ddbcb..db09ed55f 100644 --- a/app/styles/components/admin.scss +++ b/app/styles/components/admin.scss @@ -131,10 +131,13 @@ &__content { padding: 0 16px; flex: 1; + overflow: hidden; } &__title { font-weight: bold; + text-overflow: ellipsis; + overflow: hidden; a { color: var(--primary-text-color); @@ -144,6 +147,10 @@ &__quote { font-size: 14px; + a { + color: var(--brand-color--hicontrast); + } + .byline { font-size: 12px; @@ -180,6 +187,10 @@ } } + &__status-content { + overflow: hidden; + } + &__status { display: flex; border-bottom: 1px solid var(--accent-color--med);