From 2939b9e49572fa458da864700e0e95ff56ac3750 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 28 Jun 2021 00:06:04 -0500 Subject: [PATCH 1/2] ScheduledStatuses: improve picker input UI --- .../compose/components/schedule_form.js | 58 ++++++++++------ .../containers/schedule_button_container.js | 2 +- .../features/scheduled_statuses/index.js | 2 +- app/styles/components/datepicker.scss | 66 ++++++++++++++++++- 4 files changed, 104 insertions(+), 24 deletions(-) diff --git a/app/soapbox/features/compose/components/schedule_form.js b/app/soapbox/features/compose/components/schedule_form.js index ad444ec95..2228946eb 100644 --- a/app/soapbox/features/compose/components/schedule_form.js +++ b/app/soapbox/features/compose/components/schedule_form.js @@ -3,20 +3,30 @@ import React from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; +import IconButton from 'soapbox/components/icon_button'; +import { removeSchedule } from 'soapbox/actions/compose'; const messages = defineMessages({ schedule: { id: 'schedule.post_time', defaultMessage: 'Post Date/Time' }, + remove: { id: 'schedule.remove', defaultMessage: 'Remove schedule' }, }); +const mapStateToProps = (state, ownProps) => ({ + schedule: state.getIn(['compose', 'schedule']), +}); + +export default @connect(mapStateToProps) +@injectIntl class ScheduleForm extends React.Component { static propTypes = { schedule: PropTypes.instanceOf(Date), intl: PropTypes.object.isRequired, onSchedule: PropTypes.func.isRequired, + dispatch: PropTypes.func, active: PropTypes.bool, }; @@ -54,33 +64,43 @@ class ScheduleForm extends React.Component { return fiveMinutesFromNow.getTime() < selectedDate.getTime(); }; + handleRemove = e => { + this.props.dispatch(removeSchedule()); + e.preventDefault(); + } + render() { if (!this.props.active || !this.state) { return null; } + const { intl } = this.props; const { schedule } = this.state; return ( - +
+
+ +
+
+ +
+ +
+
+
); } } - -const mapStateToProps = (state, ownProps) => ({ - schedule: state.getIn(['compose', 'schedule']), -}); - -export default injectIntl(connect(mapStateToProps)(ScheduleForm)); diff --git a/app/soapbox/features/compose/containers/schedule_button_container.js b/app/soapbox/features/compose/containers/schedule_button_container.js index 472155284..61c4ca99f 100644 --- a/app/soapbox/features/compose/containers/schedule_button_container.js +++ b/app/soapbox/features/compose/containers/schedule_button_container.js @@ -9,7 +9,7 @@ const mapStateToProps = state => ({ const mapDispatchToProps = dispatch => ({ onClick() { - dispatch((_, getState) => { + dispatch((dispatch, getState) => { if (getState().getIn(['compose', 'schedule'])) { dispatch(removeSchedule()); } else { diff --git a/app/soapbox/features/scheduled_statuses/index.js b/app/soapbox/features/scheduled_statuses/index.js index a14022711..ea6816057 100644 --- a/app/soapbox/features/scheduled_statuses/index.js +++ b/app/soapbox/features/scheduled_statuses/index.js @@ -51,7 +51,7 @@ class ScheduledStatuses extends ImmutablePureComponent { const emptyMessage = ; return ( - + Date: Mon, 28 Jun 2021 00:36:44 -0500 Subject: [PATCH 2/2] ScheduledStatuses: refactor ScheduleForm, display "Schedule" button in Composer, fixes #660 --- .../compose/components/compose_form.js | 5 ++++ .../compose/components/schedule_form.js | 26 +++++-------------- .../containers/compose_form_container.js | 2 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/app/soapbox/features/compose/components/compose_form.js b/app/soapbox/features/compose/components/compose_form.js index 42d2cd826..c6a17b2c2 100644 --- a/app/soapbox/features/compose/components/compose_form.js +++ b/app/soapbox/features/compose/components/compose_form.js @@ -35,6 +35,7 @@ const messages = defineMessages({ spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' }, publish: { id: 'compose_form.publish', defaultMessage: 'Publish' }, publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' }, + schedule: { id: 'compose_form.schedule', defaultMessage: 'Schedule' }, }); export default @injectIntl @@ -262,6 +263,10 @@ class ComposeForm extends ImmutablePureComponent { publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish); } + if (this.props.scheduledAt) { + publishText = intl.formatMessage(messages.schedule); + } + const composeClassNames = classNames({ 'compose-form': true, 'condensed': condensed, diff --git a/app/soapbox/features/compose/components/schedule_form.js b/app/soapbox/features/compose/components/schedule_form.js index 2228946eb..bb6304a9f 100644 --- a/app/soapbox/features/compose/components/schedule_form.js +++ b/app/soapbox/features/compose/components/schedule_form.js @@ -15,7 +15,7 @@ const messages = defineMessages({ }); const mapStateToProps = (state, ownProps) => ({ - schedule: state.getIn(['compose', 'schedule']), + scheduledAt: state.getIn(['compose', 'schedule']), }); export default @connect(mapStateToProps) @@ -23,15 +23,14 @@ export default @connect(mapStateToProps) class ScheduleForm extends React.Component { static propTypes = { - schedule: PropTypes.instanceOf(Date), + scheduledAt: PropTypes.instanceOf(Date), intl: PropTypes.object.isRequired, onSchedule: PropTypes.func.isRequired, dispatch: PropTypes.func, active: PropTypes.bool, }; - setSchedule(date) { - this.setState({ schedule: date }); + setSchedule = date => { this.props.onSchedule(date); } @@ -43,16 +42,6 @@ class ScheduleForm extends React.Component { datePicker.setOpen(true); } - componentDidMount() { - this.setState({ schedule: this.props.schedule }); - } - - constructor(props) { - super(props); - - this.setSchedule = this.setSchedule.bind(this); - } - isCurrentOrFutureDate(date) { return date && new Date().setHours(0, 0, 0, 0) <= new Date(date).setHours(0, 0, 0, 0); } @@ -70,12 +59,11 @@ class ScheduleForm extends React.Component { } render() { - if (!this.props.active || !this.state) { + if (!this.props.active) { return null; } - const { intl } = this.props; - const { schedule } = this.state; + const { intl, scheduledAt } = this.props; return (
@@ -84,7 +72,7 @@ class ScheduleForm extends React.Component {
diff --git a/app/soapbox/features/compose/containers/compose_form_container.js b/app/soapbox/features/compose/containers/compose_form_container.js index dad55a041..874402b62 100644 --- a/app/soapbox/features/compose/containers/compose_form_container.js +++ b/app/soapbox/features/compose/containers/compose_form_container.js @@ -26,7 +26,7 @@ const mapStateToProps = state => ({ anyMedia: state.getIn(['compose', 'media_attachments']).size > 0, isModalOpen: state.get('modal').modalType === 'COMPOSE', maxTootChars: state.getIn(['instance', 'max_toot_chars']), - schedule: state.getIn(['instance', 'schedule']), + scheduledAt: state.getIn(['compose', 'schedule']), scheduledStatusCount: state.get('scheduled_statuses').size, });