Merge branch 'scheduled-post-validations' into 'develop'
Scheduled statuses validation Closes #663 and #659 See merge request soapbox-pub/soapbox-fe!563
This commit is contained in:
commit
86a90112a1
4 changed files with 23 additions and 6 deletions
|
@ -15,6 +15,7 @@ import { getFeatures } from 'soapbox/utils/features';
|
||||||
import { uploadMedia } from './media';
|
import { uploadMedia } from './media';
|
||||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||||
import { createStatus } from './statuses';
|
import { createStatus } from './statuses';
|
||||||
|
import snackbar from 'soapbox/actions/snackbar';
|
||||||
|
|
||||||
let cancelFetchComposeSuggestionsAccounts;
|
let cancelFetchComposeSuggestionsAccounts;
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ export const COMPOSE_SCHEDULE_REMOVE = 'COMPOSE_SCHEDULE_REMOVE';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
||||||
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
||||||
|
scheduleError: { id: 'compose.invalid_schedule', defaultMessage: 'You must schedule a post at least 5 minutes out.' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1);
|
const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1);
|
||||||
|
@ -170,6 +172,15 @@ const needsDescriptions = state => {
|
||||||
return missingDescriptionModal && hasMissing;
|
return missingDescriptionModal && hasMissing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validateSchedule = state => {
|
||||||
|
const schedule = state.getIn(['compose', 'schedule']);
|
||||||
|
if (!schedule) return true;
|
||||||
|
|
||||||
|
const fiveMinutesFromNow = new Date(new Date().getTime() + 300000);
|
||||||
|
|
||||||
|
return schedule.getTime() > fiveMinutesFromNow.getTime();
|
||||||
|
};
|
||||||
|
|
||||||
export function submitCompose(routerHistory, force = false) {
|
export function submitCompose(routerHistory, force = false) {
|
||||||
return function(dispatch, getState) {
|
return function(dispatch, getState) {
|
||||||
if (!isLoggedIn(getState)) return;
|
if (!isLoggedIn(getState)) return;
|
||||||
|
@ -178,6 +189,11 @@ export function submitCompose(routerHistory, force = false) {
|
||||||
const status = state.getIn(['compose', 'text'], '');
|
const status = state.getIn(['compose', 'text'], '');
|
||||||
const media = state.getIn(['compose', 'media_attachments']);
|
const media = state.getIn(['compose', 'media_attachments']);
|
||||||
|
|
||||||
|
if (!validateSchedule(state)) {
|
||||||
|
dispatch(snackbar.error(messages.scheduleError));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!status || !status.length) && media.size === 0) {
|
if ((!status || !status.length) && media.size === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import DatePicker from 'react-datepicker';
|
||||||
import 'react-datepicker/dist/react-datepicker.css';
|
import 'react-datepicker/dist/react-datepicker.css';
|
||||||
import IconButton from 'soapbox/components/icon_button';
|
import IconButton from 'soapbox/components/icon_button';
|
||||||
import { removeSchedule } from 'soapbox/actions/compose';
|
import { removeSchedule } from 'soapbox/actions/compose';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
schedule: { id: 'schedule.post_time', defaultMessage: 'Post Date/Time' },
|
schedule: { id: 'schedule.post_time', defaultMessage: 'Post Date/Time' },
|
||||||
|
@ -66,7 +67,7 @@ class ScheduleForm extends React.Component {
|
||||||
const { intl, scheduledAt } = this.props;
|
const { intl, scheduledAt } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='datepicker'>
|
<div className={classNames('datepicker', { 'datepicker--error': !this.isFiveMinutesFromNow(scheduledAt) })}>
|
||||||
<div className='datepicker__hint'>
|
<div className='datepicker__hint'>
|
||||||
<FormattedMessage id='datepicker.hint' defaultMessage='Scheduled to post at…' />
|
<FormattedMessage id='datepicker.hint' defaultMessage='Scheduled to post at…' />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -84,10 +84,6 @@ const initialPoll = ImmutableMap({
|
||||||
multiple: false,
|
multiple: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialSchedule = new Date();
|
|
||||||
initialSchedule.setDate(initialSchedule.getDate() - 1);
|
|
||||||
|
|
||||||
|
|
||||||
function statusToTextMentions(state, status, account) {
|
function statusToTextMentions(state, status, account) {
|
||||||
const author = status.getIn(['account', 'acct']);
|
const author = status.getIn(['account', 'acct']);
|
||||||
const mentions = status.get('mentions', []).map(m => m.get('acct'));
|
const mentions = status.get('mentions', []).map(m => m.get('acct'));
|
||||||
|
@ -407,7 +403,7 @@ export default function compose(state = initialState, action) {
|
||||||
case COMPOSE_POLL_REMOVE:
|
case COMPOSE_POLL_REMOVE:
|
||||||
return state.set('poll', null);
|
return state.set('poll', null);
|
||||||
case COMPOSE_SCHEDULE_ADD:
|
case COMPOSE_SCHEDULE_ADD:
|
||||||
return state.set('schedule', initialSchedule);
|
return state.set('schedule', new Date());
|
||||||
case COMPOSE_SCHEDULE_SET:
|
case COMPOSE_SCHEDULE_SET:
|
||||||
return state.set('schedule', action.date);
|
return state.set('schedule', action.date);
|
||||||
case COMPOSE_SCHEDULE_REMOVE:
|
case COMPOSE_SCHEDULE_REMOVE:
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
&__cancel {
|
&__cancel {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--error .react-datepicker__input-container {
|
||||||
|
border-color: $error-red !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.datepicker .react-datepicker {
|
.datepicker .react-datepicker {
|
||||||
|
|
Loading…
Reference in a new issue