Skip to content

Commit

Permalink
Show reassign on auto add to workflow, types cleanup (#2121)
Browse files Browse the repository at this point in the history
  • Loading branch information
thecalcc committed Nov 4, 2024
1 parent f844f74 commit 4914e29
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 96 deletions.
16 changes: 9 additions & 7 deletions client/components/Coverages/CoverageArrayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {isEmpty} from 'lodash';

import {
EDITOR_TYPE,
IAssignmentItem,
IAssignmentPriority,
ICoverageFormProfile,
ICoverageProvider, ICoverageScheduledUpdate, IEventItem, IFile,
Expand All @@ -22,6 +23,7 @@ import * as selectors from '../../selectors';
import {InputArray} from '../UI/Form';
import {CoverageEditor} from './CoverageEditor';
import {CoverageAddButton} from './CoverageAddButton';
import * as actions from '../../actions';


interface IProps {
Expand Down Expand Up @@ -78,12 +80,7 @@ interface IProps {
scheduledUpdate?: ICoverageScheduledUpdate,
scheduledUpdateIndex?: number
): void;
onRemoveAssignment(
coverage: IPlanningCoverageItem,
index: number,
scheduledUpdate?: ICoverageScheduledUpdate,
scheduledUpdateIndex?: number
): void;
onRemoveAssignment(assignemnt: IAssignmentItem): Promise<void>;
uploadFiles(files: Array<Array<File>>): Promise<Array<IFile>>;
notifyValidationErrors(errors: Array<string>): void;
}
Expand All @@ -106,6 +103,10 @@ const mapStateToProps = (state) => ({
defaultDesk: selectors.general.defaultDesk(state),
});

const mapDispatchToProps = (dispatch) => ({
onRemoveAssignment: (assignment) => dispatch(actions.assignments.ui.showRemoveAssignmentModal(assignment)),
});

class CoverageArrayInputComponent extends React.Component<IProps, IState> {
constructor(props) {
super(props);
Expand Down Expand Up @@ -214,6 +215,7 @@ class CoverageArrayInputComponent extends React.Component<IProps, IState> {
onChange={onChange}
addButtonText={addButtonText}
addButtonComponent={CoverageAddButton}
onRemoveAssignment={this.props.onRemoveAssignment}
addButtonProps={{
contentTypes,
defaultDesk,
Expand Down Expand Up @@ -260,4 +262,4 @@ class CoverageArrayInputComponent extends React.Component<IProps, IState> {
}
}

export const CoverageArrayInput = connect(mapStateToProps)(CoverageArrayInputComponent);
export const CoverageArrayInput = connect(mapStateToProps, mapDispatchToProps)(CoverageArrayInputComponent);
71 changes: 42 additions & 29 deletions client/components/Coverages/CoverageEditor/CoverageFormHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React from 'react';
import {connect} from 'react-redux';
import {get} from 'lodash';

import {IPlanningCoverageItem, ICoverageScheduledUpdate} from '../../../interfaces';
import {IPlanningCoverageItem, ICoverageScheduledUpdate, ILockedItems} from '../../../interfaces';
import {IArticle, IDesk, IUser} from 'superdesk-api';

import {getCreator, getItemInArrayById, gettext, planningUtils, onEventCapture} from '../../../utils';
import {getCreator, getItemInArrayById, gettext, onEventCapture} from '../../../utils';
import {Item, Border, Column, Row as ListRow} from '../../UI/List';
import {Button} from '../../UI';
import {UserAvatar} from '../../../components/UserAvatar';
import {StateLabel} from '../../StateLabel';
import * as actions from '../../../actions';
import {ASSIGNMENTS} from '../../../constants/assignments';
import * as selectors from '../../../selectors';
import {planningUtils} from '../../../utils';
import {Button} from 'superdesk-ui-framework/react';

interface IProps {
field: string;
Expand All @@ -21,7 +24,7 @@ interface IProps {
addNewsItemToPlanning?: IArticle;
onChange(field: string, value: any): void;
onFocus?(): void;
onRemoveAssignment?(): void;
onRemoveAssignment?(): Promise<void>;
setCoverageDefaultDesk(coverage: IPlanningCoverageItem | ICoverageScheduledUpdate): void;
showEditCoverageAssignmentModal(props: {
field: string;
Expand All @@ -32,6 +35,7 @@ interface IProps {
onChange(field: string, value: any): void;
setCoverageDefaultDesk(coverage: IPlanningCoverageItem | ICoverageScheduledUpdate): void;
}): void;
lockedItems: ILockedItems;
}

const mapDispatchToProps = (dispatch) => ({
Expand All @@ -40,6 +44,10 @@ const mapDispatchToProps = (dispatch) => ({
),
});

const mapStateToProps = (state) => ({
lockedItems: selectors.locks.getLockedItems(state),
});

export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
constructor(props) {
super(props);
Expand Down Expand Up @@ -69,15 +77,24 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
addNewsItemToPlanning,
onRemoveAssignment,
readOnly,
lockedItems,
} = this.props;

const userAssigned = getCreator(value, 'assigned_to.user', users);
const deskAssigned = getItemInArrayById(desks, get(value, 'assigned_to.desk'));
const coverageProvider = get(value, 'assigned_to.coverage_provider');
const assignmentState = get(value, 'assigned_to.state');
const cancelled = get(value, 'workflow_status') === 'cancelled';
const canEditAssignment = planningUtils.isCoverageDraft(value) ||
(!!addNewsItemToPlanning && !get(value, 'coverage_id') && !get(value, 'scheduled_update_id'));
const deskAssigned = getItemInArrayById(desks, value.assigned_to?.desk);
const coverageProvider = value.assigned_to?.coverage_provider;
const assignmentState = value.assigned_to?.state;
const cancelled = value.workflow_status === ASSIGNMENTS.WORKFLOW_STATE.CANCELLED;

/*
Check if:
1. This view is rendered from AddToPlanning action
2. There's an already scheduled update for the coverage
*/
const isAssignmentLocked = lockedItems?.assignment
&& value.assigned_to?.assignment_id in lockedItems.assignment;
const canEditAssignment = addNewsItemToPlanning == null && !isAssignmentLocked
&& !((value as ICoverageScheduledUpdate).scheduled_update_id);

if (!deskAssigned && (!userAssigned || !coverageProvider)) {
return (
Expand All @@ -102,11 +119,9 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
<Button
id="editAssignment"
text={gettext('Assign')}
tabIndex={0}
enterKeyIsClick
className="btn btn--primary btn--small"
onClick={this.showAssignmentModal}
autoFocus
size="small"
type="primary"
/>
</ListRow>
)}
Expand All @@ -130,7 +145,7 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
<span className="sd-list-item__text-label sd-list-item__text-label--normal">
{gettext('Desk:')}
</span>
<span name={`${field}.assigned_to.desk`}>
<span key={`${field}.assigned_to.desk`}>
{get(deskAssigned, 'name', '')}
</span>
</span>
Expand All @@ -141,7 +156,7 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
<span className="sd-list-item__text-label sd-list-item__text-label--normal">
{gettext('Assignee:')}
</span>
<span name={`${field}.assigned_to.user`}>
<span key={`${field}.assigned_to.user`}>
{get(userAssigned, 'display_name', '')}
</span>
</span>
Expand Down Expand Up @@ -173,24 +188,22 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
<ListRow>
<Button
text={gettext('Reassign')}
className="btn btn--hollow btn--small"
onClick={this.showAssignmentModal}
tabIndex={0}
enterKeyIsClick
disabled={!!addNewsItemToPlanning}
autoFocus
style="hollow"
size="small"
expand
/>
</ListRow>
{!onRemoveAssignment ? null : (
{onRemoveAssignment != null && (
<ListRow>
<Button
text={gettext('Remove')}
className="btn btn--hollow btn--small"
onClick={onRemoveAssignment}
tabIndex={0}
enterKeyIsClick
disabled={!!addNewsItemToPlanning}
autoFocus
onClick={() => {
onRemoveAssignment();
}}
style="hollow"
size="small"
expand
/>
</ListRow>
)}
Expand All @@ -202,6 +215,6 @@ export class CoverageFormHeaderComponent extends React.PureComponent<IProps> {
}

export const CoverageFormHeader = connect(
null,
mapStateToProps,
mapDispatchToProps
)(CoverageFormHeaderComponent);
2 changes: 1 addition & 1 deletion client/components/Coverages/CoverageEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ interface IProps {
onDuplicateCoverage(coverage: DeepPartial<IPlanningCoverageItem>, duplicateAs?: IG2ContentType['qcode']): void;
onCancelCoverage?(): void;
onAddCoverageToWorkflow?(): void;
onRemoveAssignment?(): void;
onRemoveAssignment?(coverage: IPlanningCoverageItem): void;
popupContainer(): void;
setCoverageDefaultDesk(): void;
onPopupOpen(): void;
Expand Down
89 changes: 35 additions & 54 deletions client/components/UI/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import {KEYCODES} from './constants';
import {onEventCapture} from './utils';


/**
* @ngdoc react
* @name Button
* @description Generic Button component
*/
interface IButtonProps {
id?: string;
className?: string;
onClick: (...args: any) => any;
icon?: string;
title?: string;
text?: string;
disabled?: boolean;
textOnly?: boolean;
hollow?: boolean;
iconOnly?: boolean;
expanded?: boolean;
color?: 'primary' | 'success' | 'warning' | 'alert' | 'highlight' | 'sd-green' | 'ui-dark' | 'default';
size?: 'small' | 'large';
tabIndex?: number;
enterKeyIsClick?: boolean;
autoFocus?: boolean;
onKeyDown?: (e: React.KeyboardEvent) => any;
refNode?: (...args: any) => any;
iconOnlyCircle?: boolean;
children?: React.ReactNode;
pullRight?: boolean;
empty?: boolean;
}

const Button = ({
disabled = false,
textOnly = false,
hollow = false,
expanded = false,
enterKeyIsClick = false,
autoFocus = false,
iconOnlyCircle = false,
pullRight = false,
empty = false,
className,
onClick,
icon,
id,
title,
text,
disabled,
textOnly,
hollow,
expanded,
color,
size,
iconOnly,
tabIndex,
enterKeyIsClick,
autoFocus,
refNode,
onKeyDown,
iconOnlyCircle,
children,
pullRight,
empty,
...props
}) => {
}: IButtonProps) => {
const handeKeyDown = (event) => {
if (event.keyCode === KEYCODES.ENTER) {
onEventCapture(event);
Expand Down Expand Up @@ -82,42 +101,4 @@ const Button = ({
);
};

Button.propTypes = {
id: PropTypes.string,
className: PropTypes.string,
onClick: PropTypes.func.isRequired,
icon: PropTypes.string,
title: PropTypes.string,
text: PropTypes.string,
disabled: PropTypes.bool,
textOnly: PropTypes.bool,
hollow: PropTypes.bool,
iconOnly: PropTypes.bool,
expanded: PropTypes.bool,
color: PropTypes.oneOf(['primary', 'success', 'warning', 'alert', 'highlight', 'sd-green', 'ui-dark', 'default']),
size: PropTypes.oneOf(['small', 'large']),
tabIndex: PropTypes.number,
enterKeyIsClick: PropTypes.bool,
autoFocus: PropTypes.bool,
onKeyDown: PropTypes.func,
refNode: PropTypes.func,
iconOnlyCircle: PropTypes.bool,
children: PropTypes.node,
pullRight: PropTypes.bool,
empty: PropTypes.bool,
};

Button.defaultProps = {
disabled: false,
textOnly: false,
hollow: false,
iconOnly: false,
expanded: false,
enterKeyIsClick: false,
autoFocus: false,
iconOnlyCircle: false,
pullRight: false,
empty: false,
};

export default Button;
28 changes: 26 additions & 2 deletions client/components/UI/Form/InputArray/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ import {Button} from '../../';
import {Row, LineInput} from '../';
import './style.scss';
import {superdeskApi} from '../../../../superdeskApi';
import {planningApis} from '../../../../api';
import {
EDITOR_TYPE,
IAssignmentItem,
IG2ContentType,
IPlanningCoverageItem,
IPlanningNewsCoverageStatus,
} from 'interfaces';
import {IDesk} from 'superdesk-api';

interface IProps {
field: string;
Expand All @@ -18,7 +27,7 @@ interface IProps {
maxCount: number;
addOnly: boolean;
originalCount: number;
element: React.ComponentClass;
element: React.ComponentClass<any>;
defaultElement: any;
readOnly: boolean;
message: any;
Expand All @@ -37,8 +46,19 @@ interface IProps {
errors: {[key: string]: any};
showErrors: boolean;
testId?: string;

onRemoveAssignment: (assignment: IAssignmentItem) => Promise<void>;
getRef?(field: string, value: any): React.RefObject<any>;
popupContainer(): HTMLElement;
onPopupOpen(): void;
onPopupClose(): void;
setCoverageDefaultDesk(coverage: IPlanningCoverageItem): void;
contentTypes: Array<IG2ContentType>;
defaultDesk: IDesk;
newsCoverageStatus: Array<IPlanningNewsCoverageStatus>;
navigation: any;
openCoverageIds: Array<string>;
preferredCoverageDesks: {[key: string]: string};
editorType: EDITOR_TYPE;
}

export class InputArray extends React.PureComponent<IProps> {
Expand Down Expand Up @@ -153,6 +173,10 @@ export class InputArray extends React.PureComponent<IProps> {
{(value || []).map((val, index) => (
<Component
{...props}
onRemoveAssignment={(val) =>
planningApis.assignments.getById(val.assigned_to.assignment_id)
.then((assignment) => this.props.onRemoveAssignment(assignment))
}
key={index}
ref={this.props.getRef == null ? null : this.props.getRef(field, val)}
testId={`${testId}[${index}]`}
Expand Down
Loading

0 comments on commit 4914e29

Please sign in to comment.