diff --git a/client/actions/events/api.ts b/client/actions/events/api.ts index a09157b4c..0d44dff41 100644 --- a/client/actions/events/api.ts +++ b/client/actions/events/api.ts @@ -671,7 +671,7 @@ const fetchEventTemplates = () => (dispatch, getState, {api}) => { }); }; -const createEventTemplate = (item) => (dispatch, getState, {api, modal, notify}) => { +const createEventTemplate = (item: IEventItem) => (dispatch, getState, {api, modal, notify}) => { modal.prompt(gettext('Template name')).then((templateName) => { api('events_template').query({ where: { @@ -686,21 +686,23 @@ const createEventTemplate = (item) => (dispatch, getState, {api, modal, notify}) api('events_template').save({ template_name: templateName, based_on_event: item._id, - embedded_planning: item.associated_plannings.map((planning) => ({ - coverages: planning.coverages.map((coverage) => ({ - coverage_id: coverage.coverage_id, - g2_content_type: coverage.planning.g2_content_type, - desk: coverage.assigned_to.desk, - user: coverage.assigned_to.user, - language: coverage.planning.language, - news_coverage_status: coverage.news_coverage_status.qcode, - scheduled: coverage.planning.scheduled, - genre: coverage.planning.genre?.qcode, - slugline: coverage.planning.slugline, - ednote: coverage.planning.ednote, - internal_note: coverage.planning.internal_note, + data: { + embedded_planning: item.associated_plannings.map((planning) => ({ + coverages: planning.coverages.map((coverage) => ({ + coverage_id: coverage.coverage_id, + g2_content_type: coverage.planning.g2_content_type, + desk: coverage.assigned_to.desk, + user: coverage.assigned_to.user, + language: coverage.planning.language, + news_coverage_status: coverage.news_coverage_status.qcode, + scheduled: coverage.planning.scheduled, + genre: coverage.planning.genre?.qcode, + slugline: coverage.planning.slugline, + ednote: coverage.planning.ednote, + internal_note: coverage.planning.internal_note, + })), })), - })) + }, }) .then(() => { dispatch(fetchEventTemplates()); diff --git a/client/actions/main.ts b/client/actions/main.ts index dbd5c1aca..5d9982d0a 100644 --- a/client/actions/main.ts +++ b/client/actions/main.ts @@ -17,6 +17,7 @@ import { IWebsocketMessageData, ITEM_TYPE, IEventTemplate, + IEventItem, } from '../interfaces'; import { @@ -176,42 +177,44 @@ const createNew = (itemType, item = null, updateUrl = true, modal = false) => ( }, 'create', updateUrl, modal) ); -function getEventsAssociatedItems(template: IEventTemplate) { - return template.data.embedded_planning.map((embedded) => ({ - _id: generateTempId(), - slugline: template.data.slugline, - language: template.data.language, - coverages: embedded.coverages.map((coverage) => ({ - coverage_id: coverage.coverage_id, - planning: { - g2_content_type: coverage.g2_content_type, - scheduled: coverage.scheduled, - language: coverage.language, - genre: coverage.genre ? {qcode: coverage.genre} : undefined, - slugline: coverage.slugline, - ednote: coverage.ednote, - internal_note: coverage.internal_note, - }, - assigned_to: { - desk: coverage.desk, - user: coverage.user, - }, - news_coverage_status: { - qcode: coverage.news_coverage_status, - }, - })), - })); +function getEventsAssociatedItems(template: IEventTemplate): IEventItem['associated_plannings'] | [] { + const embeddedPlanning = template.data?.embedded_planning; + + return embeddedPlanning + ? embeddedPlanning.map((embedded) => ({ + _id: generateTempId(), + slugline: template.data?.slugline, + language: template.data?.language, + coverages: embedded.coverages.map((coverage) => ({ + coverage_id: coverage.coverage_id, + planning: { + g2_content_type: coverage.g2_content_type, + scheduled: coverage.scheduled, + language: coverage.language, + genre: coverage.genre ? {qcode: coverage.genre} : undefined, + slugline: coverage.slugline, + ednote: coverage.ednote, + internal_note: coverage.internal_note, + }, + assigned_to: { + desk: coverage.desk, + user: coverage.user, + }, + news_coverage_status: { + qcode: coverage.news_coverage_status, + }, + })), + })) + : []; } function createEventFromTemplate(template: IEventTemplate) { - const embeddedPlanning = template.data?.embedded_planning || []; - return self.createNew(ITEM_TYPE.EVENT, { ...template.data, dates: { tz: template.data.dates?.tz }, - associated_plannings: embeddedPlanning ? self.getEventsAssociatedItems(template) : [] + associated_plannings: self.getEventsAssociatedItems(template) }); } diff --git a/server/planning/events/events_template.py b/server/planning/events/events_template.py index 857d21b20..5a093e422 100644 --- a/server/planning/events/events_template.py +++ b/server/planning/events/events_template.py @@ -19,6 +19,7 @@ from superdesk.utils import ListCursor from planning.common import DUPLICATE_EVENT_IGNORED_FIELDS from apps.archive.common import get_user +from .events_schema import events_schema logger = logging.getLogger(__name__) @@ -31,7 +32,6 @@ class EventsTemplateResource(Resource): endpoint_name = "events_template" resource_methods = ["GET", "POST"] item_methods = ["GET", "DELETE", "PATCH", "PUT"] - allow_unknown = True privileges = { "GET": "planning_event_management", "POST": "planning_event_templates", @@ -39,50 +39,6 @@ class EventsTemplateResource(Resource): "PATCH": "planning_event_templates", "PUT": "planning_event_templates", } - _event_fields = { - "slugline": {"type": "string", "required": False, "readonly": True}, - "name": {"type": "string", "required": False, "readonly": True}, - "definition_short": {"type": "string", "required": False, "readonly": True}, - "definition_long": {"type": "string", "required": False, "readonly": True}, - "internal_note": {"type": "string", "required": False, "readonly": True}, - "ednote": {"type": "string", "required": False, "readonly": True}, - "links": {"type": "list", "readonly": True}, - "occur_status": { - "type": "dict", - "allow_unknown": True, - "schema": { - "qcode": {"type": "string"}, - "name": {"type": "string"}, - "label": {"type": "string"}, - }, - "readonly": True, - }, - "files": { - "type": "list", - "schema": Resource.rel("events_files"), - "readonly": True, - }, - "calendars": { - "type": "list", - "schema": { - "type": "dict", - "allow_unknown": True, - "schema": { - "qcode": {"type": "string"}, - "name": {"type": "string"}, - "is_active": {"type": "boolean"}, - }, - }, - "readonly": True, - }, - "location": {"type": "list", "schema": {"type": "dict"}, "readonly": True}, - "event_contact_info": { - "type": "list", - "schema": Resource.rel("contacts"), - "readonly": True, - }, - "subject": {"type": "list", "schema": {"type": "dict"}, "readonly": True}, - } schema = { "template_name": { "type": "string", @@ -96,7 +52,7 @@ class EventsTemplateResource(Resource): embeddable=False, required=True, ), - "data": {"type": "dict", "schema": _event_fields, "allow_unknown": True}, + "data": {"type": "dict", "schema": events_schema}, } @@ -163,9 +119,7 @@ def _get_event(_id): def _fill_event_template(self, doc): event = self._get_event(doc["based_on_event"]) - doc["data"] = event.copy() - if doc.get("embedded_planning"): - doc["data"].setdefault("embedded_planning", doc.pop("embedded_planning")) + doc["data"].update(event.copy()) for field in DUPLICATE_EVENT_IGNORED_FIELDS: doc["data"].pop(field, None)