Skip to content

Commit

Permalink
Merge branch 'develop' into feature/multiple-events-in-planning
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaskikutis committed Nov 7, 2024
2 parents 14db5a6 + abe10c5 commit 8e68f6e
Show file tree
Hide file tree
Showing 26 changed files with 753 additions and 448 deletions.
4 changes: 2 additions & 2 deletions client/actions/assignments/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as actions from '../';
import {ASSIGNMENTS, ALL_DESKS, SORT_DIRECTION} from '../../constants';
import planningUtils from '../../utils/planning';
import {getErrorMessage, isExistingItem, gettext} from '../../utils';
import planning from '../planning';
import planningActions from '../planning/api';
import {assignmentsViewRequiresArchiveItems} from '../../components/Assignments/AssignmentItem/fields';

const setBaseQuery = ({must = []}) => ({
Expand Down Expand Up @@ -415,7 +415,7 @@ const receiveAssignmentHistory = (items) => ({
* @param {object} assignment - The Assignment to load items for
*/
const loadPlanningAndEvent = (assignment) => (dispatch) =>
dispatch(planning.api.fetchById(assignment.planning_item));
dispatch(planningActions.fetchById(assignment.planning_item));

/**
* Loads the Archive items that are linked to the provided Assignment list
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
import {superdeskApi} from '../../../superdeskApi';
import * as selectors from '../../../selectors';
import * as actions from '../../../actions';
import planningActions from '../../../actions/planning/api';

import {assignmentUtils, eventUtils, planningUtils, getFileDownloadURL} from '../../../utils';
import {ASSIGNMENTS, WORKSPACE} from '../../../constants';

Expand Down Expand Up @@ -262,7 +264,7 @@ const mapDispatchToProps = (dispatch) => ({
removeAssignment: (assignment) => dispatch(actions.assignments.ui.showRemoveAssignmentModal(assignment)),
openArchivePreview: (assignment) => dispatch(actions.assignments.ui.openArchivePreview(assignment)),
fetchEventFiles: (event) => dispatch(actions.events.api.fetchEventFiles(event)),
fetchPlanningFiles: (planning) => dispatch(actions.planning.api.fetchPlanningFiles(planning)),
fetchPlanningFiles: (planning) => dispatch(planningActions.fetchPlanningFiles(planning)),
});

export const AssignmentPreviewContainer = connect<IStateProps, IDispatchProps>(
Expand Down
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
4 changes: 3 additions & 1 deletion client/components/Coverages/CoverageIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,15 @@ export function getAvatarForCoverage(

return placeholder;
} else {
const statusDotColor = planningUtils.getNewsCoverageStatusDotColor(coverage);

const avatar: Omit<IPropsAvatar, 'size'> = {
initials: getUserInitials(user.display_name),
imageUrl: user.picture_url,
displayName: user.display_name,
icon: icon,
customContent: getCustomAvatarContent(user),
statusDot: {color: planningUtils.getNewsCoverageStatusDotColor(coverage)},
statusDot: statusDotColor != null ? {color: statusDotColor} : null,
};

return avatar;
Expand Down
7 changes: 4 additions & 3 deletions client/components/Planning/PlanningEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {planningUtils, eventUtils, lockUtils} from '../../../utils';
import {EditorForm} from '../../Editor/EditorForm';
import {PlanningEditorHeader} from './PlanningEditorHeader';
import {COVERAGES} from '../../../constants';
import planningActions from '../../../actions/planning/api';

interface IProps {
original?: IPlanningItem;
Expand Down Expand Up @@ -99,9 +100,9 @@ const mapStateToProps = (state) => ({

const mapDispatchToProps = (dispatch) => ({
fetchEventFiles: (event) => dispatch(actions.events.api.fetchEventFiles(event)),
fetchPlanningFiles: (planning) => dispatch(actions.planning.api.fetchPlanningFiles(planning)),
uploadFiles: (files) => dispatch(actions.planning.api.uploadFiles({files: files})),
removeFile: (file) => dispatch(actions.planning.api.removeFile(file)),
fetchPlanningFiles: (planning) => dispatch(planningActions.fetchPlanningFiles(planning)),
uploadFiles: (files) => dispatch(planningActions.uploadFiles({files: files})),
removeFile: (file) => dispatch(planningActions.removeFile(file)),
setCoverageDefaultDesk: (coverage) => dispatch(actions.users.setCoverageDefaultDesk(coverage)),
setCoverageAddAdvancedMode: (advancedMode) => dispatch(actions.users.setCoverageAddAdvancedMode(advancedMode)),
});
Expand Down
3 changes: 2 additions & 1 deletion client/components/Planning/PlanningPreviewContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {eventUtils, getCreator, getFileDownloadURL} from '../../utils';
import {getUserInterfaceLanguageFromCV} from '../../utils/users';
import * as selectors from '../../selectors';
import * as actions from '../../actions';
import planningActions from '../../actions/planning/api';

import {
AuditInformation,
Expand Down Expand Up @@ -83,7 +84,7 @@ const mapStateToProps = (state, ownProps): IReduxProps => ({
const mapDispatchToProps = (dispatch): IDispatchProps => ({
onEditEvent: (event) => dispatch(actions.main.openForEdit(event)),
fetchEventFiles: (event) => dispatch(actions.events.api.fetchEventFiles(event)),
fetchPlanningFiles: (planning) => dispatch(actions.planning.api.fetchPlanningFiles(planning)),
fetchPlanningFiles: (planning) => dispatch(planningActions.fetchPlanningFiles(planning)),
});

export class PlanningPreviewContentComponent extends React.PureComponent<IProps> {
Expand Down
Loading

0 comments on commit 8e68f6e

Please sign in to comment.