Skip to content

Commit

Permalink
Merge branch 'develop' into unlink-as-coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
thecalcc committed Sep 12, 2024
2 parents 0b9d3eb + 55f1293 commit dfd0245
Show file tree
Hide file tree
Showing 35 changed files with 201 additions and 100 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ Below sections include the config options that can be defined in settings.py.
* language (includes `languages` if multilingual is enabled)
* definition_short (copies to Planning item's `Description Text`)
* priority
* PLANNING_DUPLICATE_RETAIN_ASSIGNEE_DETAILS
* Default: False (the current behavior where assignee details are removed)
* If true, the `assigned_to` field (assignee details) is retained when duplicating planning items with coverages.

### Assignments Config
* SLACK_BOT_TOKEN
Expand Down
3 changes: 2 additions & 1 deletion client/actions/agenda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {AGENDA, MODALS, EVENTS} from '../constants';
import {getErrorMessage, gettext, planningUtils} from '../utils';
import {planning, showModal, main} from './index';
import {convertStringFields} from '../utils/strings';
import planningApis from '../actions/planning/api';

const openAgenda = () => (
(dispatch) => (
Expand Down Expand Up @@ -302,7 +303,7 @@ const createPlanningFromEvent = (
newPlanningItem.agendas = newPlanningItem.agendas.concat(agendas);

return (dispatch) => (
dispatch(planning.api.save({}, newPlanningItem))
dispatch(planningApis.save({}, newPlanningItem))
);
};

Expand Down
4 changes: 2 additions & 2 deletions client/actions/assignments/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {lockUtils, assignmentUtils, gettext, isExistingItem} from '../../utils';
import * as selectors from '../../selectors';
import assignments from './index';
import main from '../main';
import planning from '../planning';
import {hideModal, showModal} from '../index';
import * as actions from '../../actions';
import planningApis from '../planning/api';

const _notifyAssignmentEdited = (assignmentId) => (
(dispatch, getState, {notify}) => {
Expand Down Expand Up @@ -191,7 +191,7 @@ const _updatePlannigRelatedToAssignment = (data) => (
return Promise.resolve();
}

dispatch(planning.api.loadPlanningByIds([data.planning]));
dispatch(planningApis.loadPlanningByIds([data.planning]));
dispatch(main.fetchItemHistory(planningItem));
}
);
Expand Down
41 changes: 23 additions & 18 deletions client/actions/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import {get, isEmpty, isEqual, isNil, omit} from 'lodash';
import moment from 'moment';

import {appConfig} from 'appConfig';
import {appConfig as config} from 'appConfig';

const appConfig = config as IPlanningConfig;

import {IUser} from 'superdesk-api';
import {planningApi, superdeskApi} from '../superdeskApi';
import {
Expand All @@ -18,6 +21,7 @@ import {
ITEM_TYPE,
IEventTemplate,
IEventItem,
IPlanningConfig,
} from '../interfaces';

import {
Expand Down Expand Up @@ -68,6 +72,7 @@ import eventsPlanningUi from './eventsPlanning/ui';
import * as selectors from '../selectors';
import {validateItem} from '../validators';
import {searchParamsToOld} from '../utils/search';
import {searchAndStore} from '../api/combined';

function openForEdit(item: IEventOrPlanningItem, updateUrl: boolean = true, modal: boolean = false) {
return (dispatch, getState) => {
Expand Down Expand Up @@ -716,7 +721,7 @@ const openIgnoreCancelSaveModal = ({
const storedItems = itemType === ITEM_TYPE.EVENT ?
selectors.events.storedEvents(getState()) :
selectors.planning.storedPlannings(getState());
const item = get(storedItems, itemId) || {};
const item = storedItems[itemId] ?? {};

if (!isExistingItem(item)) {
delete item._id;
Expand All @@ -725,19 +730,17 @@ const openIgnoreCancelSaveModal = ({
let promise = Promise.resolve(item);

if (itemType === ITEM_TYPE.EVENT && eventUtils.isEventRecurring(item)) {
const originalEvent = get(storedItems, itemId, {});

promise = dispatch(eventsApi.query({
recurrenceId: originalEvent.recurrence_id,
maxResults: appConfig.max_recurrent_events,
onlyFuture: false,
}))
.then((relatedEvents) => ({
...item,
_recurring: relatedEvents || [item],
_events: [],
_originalEvent: originalEvent,
}));
promise = searchAndStore({
recurrence_id: item.recurrence_id,
max_results: appConfig.max_recurrent_events,
only_future: false,
include_associated_planning: true,
}).then((relatedEvents) => ({
...item,
_recurring: relatedEvents.filter((item) => item.type === 'event') ?? [item],
_events: [],
_originalEvent: item,
}));
}

return promise.then((itemWithAssociatedData) => (
Expand Down Expand Up @@ -1200,8 +1203,10 @@ const openFromLockActions = () => (
if (action) {
/* get the item we're operating on */
dispatch(self.fetchById(sessionLastLock.item_id, sessionLastLock.item_type)).then((item) => {
actionUtils.getActionDispatches({dispatch: dispatch, eventOnly: false,
planningOnly: false})[action[0].actionName](item, false, false);
actionUtils.getActionDispatches({
dispatch: dispatch, eventOnly: false,
planningOnly: false
})[action[0].actionName](item, false, false);
});
}
}
Expand Down Expand Up @@ -1460,7 +1465,7 @@ function onItemUnlocked(
}));

if (getItemType(item) === ITEM_TYPE.PLANNING && selectors.general.currentWorkspace(state)
=== WORKSPACE.AUTHORING) {
=== WORKSPACE.AUTHORING) {
dispatch(self.closePreviewAndEditorForItems([item]));
}
}
Expand Down
2 changes: 1 addition & 1 deletion client/actions/planning/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ const unpost = (original, updates) => (
* Also loads all the associated contacts (if any)
* @param {array, object} plannings - An array of planning item objects
*/
const receivePlannings = (plannings) => (
const receivePlannings = (plannings): any => (
(dispatch) => {
dispatch(actions.contacts.fetchContactsFromPlanning(plannings));
dispatch({
Expand Down
3 changes: 2 additions & 1 deletion client/actions/planning/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {events, fetchAgendas} from '../index';
import main from '../main';
import {showModal, hideModal} from '../index';
import eventsPlanning from '../eventsPlanning';
import planningApis from '../planning/api';

/**
* WS Action when a new Planning item is created
Expand Down Expand Up @@ -104,7 +105,7 @@ const onPlanningLocked = (e, data) => (

const sessionId = selectors.general.session(getState()).sessionId;

return dispatch(planning.api.getPlanning(data.item, false))
return dispatch(planningApis.getPlanning(data.item, false))
.then((planInStore) => {
let plan = {
...planInStore,
Expand Down
4 changes: 1 addition & 3 deletions client/actions/planning/tests/api_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import {
restoreSinonStub,
convertEventDatesToMoment,
} from '../../../utils/testUtils';
import {createTestStore} from '../../../utils';
import {PLANNING, SPIKED_STATE, WORKFLOW_STATE} from '../../../constants';
import {PLANNING, SPIKED_STATE} from '../../../constants';
import {MAIN} from '../../../constants';
import * as selectors from '../../../selectors';
import contactsApi from '../../contacts';
import {planningApis} from '../../../api';

Expand Down
5 changes: 2 additions & 3 deletions client/actions/planning/tests/notifications_test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {planningApi} from '../../../superdeskApi';
import planningApis from '../api';
import planningApis from '../../planning/api';
import planningUi from '../ui';
import featuredPlanning from '../featuredPlanning';
import eventsPlanningUi from '../../eventsPlanning/ui';
Expand Down Expand Up @@ -197,7 +197,7 @@ describe('actions.planning.notifications', () => {
describe('onPlanningLocked', () => {
beforeEach(() => {
sinon.stub(planningApi.locks, 'setItemAsLocked').returns(undefined);
sinon.stub(planningApis, 'getPlanning').returns(Promise.resolve(data.plannings[0]));
sinon.stub(planningApis, 'getPlanning').returns(() => Promise.resolve(data.plannings[0]));
});

afterEach(() => {
Expand All @@ -219,7 +219,6 @@ describe('actions.planning.notifications', () => {
))
.then(() => {
expect(planningApi.locks.setItemAsLocked.callCount).toBe(1);
expect(planningApis.getPlanning.callCount).toBe(1);
expect(planningApis.getPlanning.args[0]).toEqual([
'p1',
false,
Expand Down
17 changes: 15 additions & 2 deletions client/api/combined.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
IEventOrPlanningItem,
} from '../interfaces';
import {IRestApiResponse} from 'superdesk-api';
import {searchRaw, searchRawGetAll, convertCommonParams, cvsToString, arrayToString} from './search';
import {searchRaw, searchRawGetAll, convertCommonParams, cvsToString, arrayToString, searchRawAndStore} from './search';
import {eventUtils, planningUtils} from '../utils';
import {planningApi} from '../superdeskApi';
import {combinedSearchProfile} from '../selectors/forms';
import {searchPlanningGetAll} from './planning';
import {searchPlanningGetAll, convertPlanningParams} from './planning';
import {searchEventsGetAll} from './events';

type IResponse = IRestApiResponse<IEventOrPlanningItem>;
Expand Down Expand Up @@ -67,6 +67,18 @@ export function searchCombinedGetAll(params: ISearchParams): Promise<Array<IEven
});
}

export function searchAndStore(params: ISearchParams) {
return searchRawAndStore<IEventOrPlanningItem>({
...convertCommonParams(params),
...convertPlanningParams(params),
repo: FILTER_TYPE.COMBINED,
}).then((res) => {
res._items.forEach(modifyItemForClient);

return res._items;
});
}

export function getEventsAndPlanning(params: ISearchParams): Promise<{
events: Array<IEventItem>;
plannings: Array<IPlanningItem>;
Expand Down Expand Up @@ -145,5 +157,6 @@ export const combined: IPlanningAPI['combined'] = {
getRecurringEventsAndPlanningItems: getRecurringEventsAndPlanningItems,
getEventsAndPlanning: getEventsAndPlanning,
getSearchProfile: getCombinedSearchProfile,
searchAndStore: searchAndStore,
};

6 changes: 3 additions & 3 deletions client/api/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {EVENTS, TEMP_ID_PREFIX} from '../constants';
import {arrayToString, convertCommonParams, cvsToString, searchRaw, searchRawGetAll} from './search';
import {eventUtils} from '../utils';
import {eventProfile, eventSearchProfile} from '../selectors/forms';
import * as actions from '../actions';
import planningApis from '../actions/planning/api';

const appConfig = config as IPlanningConfig;

Expand Down Expand Up @@ -161,7 +161,7 @@ function create(updates: Partial<IEventItem>): Promise<Array<IEventItem>> {
}).then((planningItems) => {
// Make sure to update the Redux Store with the latest Planning items
// So that the Editor can set the state with these latest items
planningApi.redux.store.dispatch<any>(actions.planning.api.receivePlannings(planningItems));
planningApi.redux.store.dispatch<any>(planningApis.receivePlannings(planningItems));

return events;
});
Expand Down Expand Up @@ -207,7 +207,7 @@ function update(original: IEventItem, updates: Partial<IEventItem>): Promise<Arr
}).then((planningItems) => {
// Make sure to update the Redux Store with the latest Planning items
// So that the Editor can set the state with these latest items
planningApi.redux.store.dispatch<any>(actions.planning.api.receivePlannings(planningItems));
planningApi.redux.store.dispatch<any>(planningApis.receivePlannings(planningItems));

return events;
});
Expand Down
10 changes: 5 additions & 5 deletions client/api/planning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import {planningProfile, planningSearchProfile} from '../selectors/forms';
import {featured} from './featured';
import {PLANNING} from '../constants';
import * as selectors from '../selectors';
import * as actions from '../actions';
import planningApis from '../actions/planning/api';

const appConfig = config as IPlanningConfig;

function convertPlanningParams(params: ISearchParams): Partial<ISearchAPIParams> {
export function convertPlanningParams(params: ISearchParams): Partial<ISearchAPIParams> {
return {
agendas: arrayToString(params.agendas),
no_agenda_assigned: params.no_agenda_assigned,
Expand Down Expand Up @@ -90,7 +90,7 @@ export function getPlanningById(
.then(modifyItemForClient)
.then((item) => {
if (saveToStore) {
dispatch<any>(actions.planning.api.receivePlannings([item]));
dispatch<any>(planningApis.receivePlannings([item]));
}

return item;
Expand Down Expand Up @@ -215,7 +215,7 @@ function bulkAddCoverageToWorkflow(planningItems: Array<IPlanningItem>): Promise

return planning.update(plan, updates)
.then((updatedPlan) => {
dispatch<any>(actions.planning.api.receivePlannings([updatedPlan]));
dispatch<any>(planningApis.receivePlannings([updatedPlan]));

return updatedPlan;
});
Expand Down Expand Up @@ -254,7 +254,7 @@ function addCoverageToWorkflow(
return planning.update(plan, updates)
.then((updatedPlan) => {
notify.success(gettext('Coverage added to workflow.'));
dispatch<any>(actions.planning.api.receivePlannings([updatedPlan]));
dispatch<any>(planningApis.receivePlannings([updatedPlan]));

return updatedPlan;
})
Expand Down
28 changes: 25 additions & 3 deletions client/api/search.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {ISearchAPIParams, ISearchParams} from '../interfaces';
import {superdeskApi} from '../superdeskApi';
import {IEventOrPlanningItem, ISearchAPIParams, ISearchParams} from '../interfaces';
import {superdeskApi, planningApi as sdPlanningApi} from '../superdeskApi';
import {IRestApiResponse} from 'superdesk-api';
import {getDateTimeElasticFormat, getTimeZoneOffset} from '../utils';
import {default as timeUtils} from '../utils/time';
import {appConfig} from 'appConfig';

import planningApi from '../actions/planning/api';
import eventsApi from '../actions/events/api';
import {partition} from 'lodash';

export function cvsToString(items?: Array<{[key: string]: any}>, field: string = 'qcode'): string {
return arrayToString(
Expand Down Expand Up @@ -51,6 +53,7 @@ export function convertCommonParams(params: ISearchParams): Partial<ISearchAPIPa
sort_field: params.sort_field,
tz_offset: params.date_filter ? getTimeZoneOffset() : null,
time_zone: timeUtils.localTimeZone(),
include_associated_planning: params.include_associated_planning,
};
}

Expand All @@ -76,6 +79,25 @@ export function searchRaw<T>(args: ISearchAPIParams): Promise<IRestApiResponse<T
);
}

export const searchRawAndStore = <T>(args: ISearchAPIParams) => {
const {dispatch} = sdPlanningApi.redux.store;

return superdeskApi.dataApi.queryRawJson<IRestApiResponse<T>>(
'events_planning_search',
excludeNullParams(args)
).then((res) => {
const [relatedPlans, events] = partition(res._items, (item: IEventOrPlanningItem) => item.type === 'planning');

if (args.include_associated_planning) {
dispatch(planningApi.receivePlannings(relatedPlans));
}

dispatch(eventsApi.receiveEvents(events));

return res;
});
};

export function searchRawGetAll<T>(args: ISearchAPIParams): Promise<Array<T>> {
const params = excludeNullParams(args);
let items: Array<T> = [];
Expand Down
1 change: 1 addition & 0 deletions client/components/ContentProfiles/FieldTab/FieldList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export class FieldList extends React.PureComponent<IProps> {
this.renderList()
) : (
<ToggleBox
variant="simple"
key={this.props.group._id}
title={getProfileGroupNameTranslated(this.props.group)}
className="toggle-box--circle toggle-box--no-line"
Expand Down
1 change: 1 addition & 0 deletions client/components/ContentProfiles/GroupTab/GroupEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export class GroupEditor extends React.PureComponent<IProps> {
</div>
{!this.props.languages?.length ? null : (
<ToggleBox
variant="simple"
title={gettext('Name Translations')}
className="toggle-box--circle"
initiallyOpen={true}
Expand Down
2 changes: 1 addition & 1 deletion client/components/Coverages/CoverageIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class CoverageIcons extends React.PureComponent<IProps> {

return (
<WithPopover
placement="bottom-end"
placement="auto-end"
zIndex={1051}
component={() => (
<div className="coverages-popup">
Expand Down
2 changes: 1 addition & 1 deletion client/components/Coverages/coverage-icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
border-radius: var(--b-radius--medium);
padding: 1.5rem;
box-shadow: var(--sd-shadow__dropdown);
max-height: 100%;
max-height: 400px;
overflow: auto;
}

Expand Down
Loading

0 comments on commit dfd0245

Please sign in to comment.