diff --git a/client/components/Coverages/CoverageEditor/index.tsx b/client/components/Coverages/CoverageEditor/index.tsx index 883eb8f69..2a4f247d6 100644 --- a/client/components/Coverages/CoverageEditor/index.tsx +++ b/client/components/Coverages/CoverageEditor/index.tsx @@ -1,5 +1,6 @@ import React from 'react'; import {get} from 'lodash'; +import {connect} from 'react-redux'; import { EDITOR_TYPE, @@ -25,8 +26,9 @@ import {getUserInterfaceLanguageFromCV} from '../../../utils/users'; import {getRelatedEventIdsForPlanning} from '../../../utils/planning'; import {planningApi} from '../../../superdeskApi'; import {planningApis} from '../../../api'; +import * as selectors from '../../../selectors'; -interface IProps { +interface IOwnProps { testId?: string; field: string; value: IPlanningCoverageItem; @@ -69,6 +71,12 @@ interface IProps { onPopupClose(): void; } +interface IReduxStateProps { + defaultDesk: IDesk | undefined; +} + +type IProps = IOwnProps & IReduxStateProps; + function duplicateCoverage( { planning, @@ -99,19 +107,75 @@ function duplicateCoverage( return coverages; } -export class CoverageEditor extends React.PureComponent { +function assignCoverageToDefaultDesk(coverage: DeepPartial, defaultDesk: IDesk) { + if (!Object.keys(coverage.assigned_to ?? {}).length) { + coverage.assigned_to = {desk: defaultDesk._id}; + } else { + // TODO: Fix IDesk['members'] type in client-core + // @ts-ignore + const deskMembers = (defaultDesk?.members ?? []).map((m) => m.user); + + coverage.assigned_to.desk = defaultDesk._id; + + // If the user does not belong to default desk, remove the user + if (coverage.assigned_to.user && !deskMembers.includes(coverage.assigned_to.user)) { + coverage.assigned_to.user = null; + } + } +} + +export class CoverageEditorComponent extends React.PureComponent { collapseBox: React.RefObject; constructor(props) { super(props); this.collapseBox = React.createRef(); + this.onChange = this.onChange.bind(this); } scrollInView() { this.collapseBox.current?.scrollInView(true); } + onChange(field, value) { + let valueToUpdate = value; + + if (field.match(/^coverages\[/)) { + const {newsCoverageStatus} = this.props; + const coverage = value; + + // If there is an assignment and coverage status not planned, + // change it to 'planned' + if (newsCoverageStatus.length > 0 && + coverage?.news_coverage_status?.qcode !== newsCoverageStatus[0].qcode && + coverage?.assigned_to?.desk != null + ) { + valueToUpdate = { + ...coverage, + news_coverage_status: this.props.newsCoverageStatus[0], + }; + } + + if (field.match(/g2_content_type$/) && + value === 'text' && + this.props.defaultDesk?._id != null + ) { + const coverageStr = field.substr(0, field.indexOf('.')); + let existingCoverage: IPlanningCoverageItem = {...get(this.props, `diff.${coverageStr}`)}; + + if (existingCoverage?.assigned_to?.desk !== this.props.defaultDesk._id) { + existingCoverage.planning.g2_content_type = value; + assignCoverageToDefaultDesk(existingCoverage, this.props.defaultDesk); + this.props.onChange(coverageStr, existingCoverage); + return; + } + } + } + + this.props.onChange(field, valueToUpdate); + } + render() { const { diff, @@ -124,7 +188,6 @@ export class CoverageEditor extends React.PureComponent { contentTypes, genres, newsCoverageStatus, - onChange, coverageProviders, priorities, keywords, @@ -139,9 +202,12 @@ export class CoverageEditor extends React.PureComponent { openCoverageIds, testId, includeScheduledUpdates, + onChange: __unused, // destructure to avoid it being present in "...props" ...props } = this.props; + const {onChange} = this; + // Coverage item actions let itemActions = []; @@ -156,7 +222,7 @@ export class CoverageEditor extends React.PureComponent { label: gettext('Duplicate'), icon: 'icon-copy', callback: () => { - this.props.onChange( + onChange( fieldOfArray, duplicateCoverage({ planning: diff, @@ -179,7 +245,7 @@ export class CoverageEditor extends React.PureComponent { language ), callback: () => { - this.props.onChange( + onChange( fieldOfArray, duplicateCoverage({ planning: diff, @@ -199,7 +265,7 @@ export class CoverageEditor extends React.PureComponent { callback: () => { planningApis.coverages.cancelCoverage(this.props.coverages, value) .then((nextCoverages) => { - this.props.onChange(fieldOfArray, nextCoverages); + onChange(fieldOfArray, nextCoverages); }); }, }); @@ -211,7 +277,7 @@ export class CoverageEditor extends React.PureComponent { label: gettext('Add to workflow'), icon: 'icon-assign', callback: () => { - this.props.onChange( + onChange( fieldOfArray, planningApis.planning.coverages.addCoverageToWorkflow(this.props.coverages, value) ); @@ -325,3 +391,14 @@ export class CoverageEditor extends React.PureComponent { ); } } + +function mapStateToProps(state: IPlanningAppState): IReduxStateProps { + return { + defaultDesk: selectors.general.defaultDesk(state), + }; +} + + +export const CoverageEditor = connect( + mapStateToProps, +)(CoverageEditorComponent); diff --git a/client/components/Planning/PlanningEditor/index.tsx b/client/components/Planning/PlanningEditor/index.tsx index 8e160047b..b60710957 100644 --- a/client/components/Planning/PlanningEditor/index.tsx +++ b/client/components/Planning/PlanningEditor/index.tsx @@ -249,41 +249,7 @@ class PlanningEditorComponent extends React.Component { } onCoverageChange(field: string, value: any, planningFormEdited: boolean = true) { - let valueToUpdate = value; - - if (field.match(/^coverages\[/)) { - const {newsCoverageStatus} = this.props; - const coverage = value as IPlanningCoverageItem; - - // If there is an assignment and coverage status not planned, - // change it to 'planned' - if (newsCoverageStatus.length > 0 && - coverage?.news_coverage_status?.qcode !== newsCoverageStatus[0].qcode && - coverage?.assigned_to?.desk != null - ) { - valueToUpdate = { - ...coverage, - news_coverage_status: this.props.newsCoverageStatus[0], - }; - } - - if (field.match(/g2_content_type$/) && - value === 'text' && - this.props.defaultDesk?._id != null - ) { - const coverageStr = field.substr(0, field.indexOf('.')); - let existingCoverage = {...get(this.props, `diff.${coverageStr}`)}; - - if (get(existingCoverage, 'assigned_to.desk') !== this.props.defaultDesk._id) { - existingCoverage.planning.g2_content_type = value; - this.assignCoverageToDefaultDesk(existingCoverage); - this.props.onChangeHandler(coverageStr, existingCoverage); - return; - } - } - } - - this.props.onChangeHandler(field, valueToUpdate, planningFormEdited); + this.props.onChangeHandler(field, value, planningFormEdited); if (field === 'coverages') { // Flush the autosave so the Redux Store get's updated with the @@ -307,23 +273,6 @@ class PlanningEditorComponent extends React.Component { this.props.onChangeHandler('_time_to_be_confirmed', true); } - assignCoverageToDefaultDesk(coverage: DeepPartial) { - if (!Object.keys(coverage.assigned_to ?? {}).length) { - coverage.assigned_to = {desk: this.props.defaultDesk._id}; - } else { - // TODO: Fix IDesk['members'] type in client-core - // @ts-ignore - const deskMembers = (this.props.defaultDesk?.members ?? []).map((m) => m.user); - - coverage.assigned_to.desk = this.props.defaultDesk._id; - - // If the user does not belong to default desk, remove the user - if (coverage.assigned_to.user && !deskMembers.includes(coverage.assigned_to.user)) { - coverage.assigned_to.user = null; - } - } - } - renderHeader() { return !this.props.itemExists ? null : (