diff --git a/app/soapbox/actions/admin.js b/app/soapbox/actions/admin.js index 94d8b2395..84857abba 100644 --- a/app/soapbox/actions/admin.js +++ b/app/soapbox/actions/admin.js @@ -33,6 +33,10 @@ export const ADMIN_USERS_DEACTIVATE_REQUEST = 'ADMIN_USERS_DEACTIVATE_REQUEST'; export const ADMIN_USERS_DEACTIVATE_SUCCESS = 'ADMIN_USERS_DEACTIVATE_SUCCESS'; export const ADMIN_USERS_DEACTIVATE_FAIL = 'ADMIN_USERS_DEACTIVATE_FAIL'; +export const ADMIN_STATUS_DELETE_REQUEST = 'ADMIN_STATUS_DELETE_REQUEST'; +export const ADMIN_STATUS_DELETE_SUCCESS = 'ADMIN_STATUS_DELETE_SUCCESS'; +export const ADMIN_STATUS_DELETE_FAIL = 'ADMIN_STATUS_DELETE_FAIL'; + export function fetchConfig() { return (dispatch, getState) => { dispatch({ type: ADMIN_CONFIG_FETCH_REQUEST }); @@ -141,3 +145,16 @@ export function approveUsers(nicknames) { }); }; } + +export function deleteStatus(id) { + return (dispatch, getState) => { + dispatch({ type: ADMIN_STATUS_DELETE_REQUEST, id }); + return api(getState) + .delete(`/api/pleroma/admin/statuses/${id}`) + .then(() => { + dispatch({ type: ADMIN_STATUS_DELETE_SUCCESS, id }); + }).catch(error => { + dispatch({ type: ADMIN_STATUS_DELETE_FAIL, error, id }); + }); + }; +} diff --git a/app/soapbox/features/admin/components/report.js b/app/soapbox/features/admin/components/report.js index ddbdb6f51..886e34a08 100644 --- a/app/soapbox/features/admin/components/report.js +++ b/app/soapbox/features/admin/components/report.js @@ -5,9 +5,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import Avatar from 'soapbox/components/avatar'; import Button from 'soapbox/components/button'; -import StatusContent from 'soapbox/components/status_content'; 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 snackbar from 'soapbox/actions/snackbar'; import { openModal } from 'soapbox/actions/modal'; @@ -120,7 +120,7 @@ class Report extends ImmutablePureComponent { expanded={accordionExpanded} onToggle={this.handleAccordionToggle} > - {statuses.map(status => )} + {statuses.map(status => )} )} diff --git a/app/soapbox/features/admin/components/report_status.js b/app/soapbox/features/admin/components/report_status.js new file mode 100644 index 000000000..50e7ce1ec --- /dev/null +++ b/app/soapbox/features/admin/components/report_status.js @@ -0,0 +1,68 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +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'; + +const messages = defineMessages({ + 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' }, +}); + +export default @connect() +@injectIntl +class ReportStatus extends ImmutablePureComponent { + + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + report: ImmutablePropTypes.map, + }; + + makeMenu = () => { + const { intl, status } = this.props; + + return [{ + text: intl.formatMessage(messages.deleteStatus, { acct: `@${status.getIn(['account', 'acct'])}` }), + action: this.handleDeleteStatus, + }]; + } + + 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(); + }, + })); + } + + render() { + const { status } = this.props; + const menu = this.makeMenu(); + + return ( +
+ +
+ +
+
+ ); + } + +} diff --git a/app/soapbox/selectors/index.js b/app/soapbox/selectors/index.js index d36839d6e..949c7a63d 100644 --- a/app/soapbox/selectors/index.js +++ b/app/soapbox/selectors/index.js @@ -177,11 +177,15 @@ export const makeGetChat = () => { }; export const makeGetReport = () => { + const getStatus = makeGetStatus(); + return createSelector( [ (state, id) => state.getIn(['admin', 'reports', id]), (state, id) => state.getIn(['admin', 'reports', id, 'statuses']).map( - statusId => state.getIn(['statuses', statusId])), + statusId => state.getIn(['statuses', statusId])) + .filter(s => s) + .map(s => getStatus(state, s.toJS())), ], (report, statuses) => { diff --git a/app/styles/components/admin.scss b/app/styles/components/admin.scss index ba29ef826..50bda569f 100644 --- a/app/styles/components/admin.scss +++ b/app/styles/components/admin.scss @@ -166,14 +166,25 @@ font-weight: normal !important; margin-bottom: 0 !important; } + } + + &__status { + display: flex; + border-bottom: 1px solid var(--accent-color--med); + padding: 10px 0; + + &:last-child { + border: 0; + } .status__content { - border-bottom: 1px solid var(--accent-color--med); - padding: 10px 0; + flex: 1; + padding: 0; + } - &:last-child { - border: 0; - } + &-actions { + padding: 3px 10px; + margin-left: auto; } } }