From 3e99800840ca2169eea7cbe55d92fb21e6587fb1 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Tue, 5 Sep 2023 18:52:54 +0530 Subject: [PATCH 01/12] Add new key 'planning_auto_publish in the schema' --- server/planning/content_profiles/profiles/event.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server/planning/content_profiles/profiles/event.py b/server/planning/content_profiles/profiles/event.py index 3cc043e52..44f77860a 100644 --- a/server/planning/content_profiles/profiles/event.py +++ b/server/planning/content_profiles/profiles/event.py @@ -46,6 +46,7 @@ class EventSchema(BaseSchema): custom_vocabularies = schema.ListField() related_plannings = schema.ListField() related_plannings.schema["read_only"] = False + related_plannings.schema["planning_auto_publish"] = False registration_details = TextField(field_type="multi_line") invitation_details = TextField(field_type="multi_line") accreditation_info = TextField(field_type="single_line") From 0b07b9e7b59dc33b823439b850a8df85ea22f519 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Tue, 5 Sep 2023 18:55:12 +0530 Subject: [PATCH 02/12] add new toggle and register new config --- .../ContentProfiles/FieldTab/FieldEditor.tsx | 2 ++ client/components/fields/resources/profiles.ts | 11 +++++++++++ client/interfaces.ts | 1 + 3 files changed, 14 insertions(+) diff --git a/client/components/ContentProfiles/FieldTab/FieldEditor.tsx b/client/components/ContentProfiles/FieldTab/FieldEditor.tsx index 2657c7769..5a7792438 100644 --- a/client/components/ContentProfiles/FieldTab/FieldEditor.tsx +++ b/client/components/ContentProfiles/FieldTab/FieldEditor.tsx @@ -87,6 +87,7 @@ export class FieldEditor extends React.Component { const fieldProps = { 'schema.required': {enabled: !(this.props.disableRequired || this.props.systemRequired)}, 'schema.read_only': {enabled: this.props.item.name === 'related_plannings'}, + 'schema.planning_auto_publish': {enabled: this.props.item.name === 'related_plannings'}, 'schema.field_type': {enabled: fieldType != null}, 'schema.minlength': {enabled: !disableMinMax}, 'schema.maxlength': {enabled: !disableMinMax}, @@ -187,6 +188,7 @@ export class FieldEditor extends React.Component { 'schema.multilingual': {enabled: true, index: 11}, 'schema.languages': {enabled: true, index: 12}, 'schema.default_language': {enabled: true, index: 13}, + 'schema.planning_auto_publish': {enabled: true, index: 14}, }, { item: this.props.item, diff --git a/client/components/fields/resources/profiles.ts b/client/components/fields/resources/profiles.ts index 3f77bcfc2..ee63a0336 100644 --- a/client/components/fields/resources/profiles.ts +++ b/client/components/fields/resources/profiles.ts @@ -34,6 +34,17 @@ registerEditorField( true ); +registerEditorField( + 'schema.planning_auto_publish', + EditorFieldCheckbox, + () => ({ + label: superdeskApi.localization.gettext('Planning Auto Publish'), + field: 'schema.planning_auto_publish', + }), + null, + true +); + registerEditorField( 'schema.format_options', SelectEditor3FormattingOptions, diff --git a/client/interfaces.ts b/client/interfaces.ts index 7560afbc6..7cc056169 100644 --- a/client/interfaces.ts +++ b/client/interfaces.ts @@ -983,6 +983,7 @@ export interface IProfileSchemaTypeList extends IBaseProfileSchemaType<'list'> { schema?: {[key: string]: any}; mandatory_in_list?: {[key: string]: any}; vocabularies?: Array; + planning_auto_publish?:boolean; } export interface IProfileSchemaTypeInteger extends IBaseProfileSchemaType<'integer'> {} From b6653f7fdeeff398786b548410d076f37ddc368e Mon Sep 17 00:00:00 2001 From: devketanpro Date: Wed, 6 Sep 2023 00:18:22 +0530 Subject: [PATCH 03/12] add logic to post associate planning item based on new config --- server/planning/events/events_post.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/server/planning/events/events_post.py b/server/planning/events/events_post.py index 5ed1c5de0..a3c34eadd 100644 --- a/server/planning/events/events_post.py +++ b/server/planning/events/events_post.py @@ -203,13 +203,22 @@ def publish_event(self, event, version): logger.error("Failed to save planning version for event item id {}".format(event["_id"])) def post_related_plannings(self, plannings, new_post_state): - # Check to see if we are un-posting, we need to unpost it's planning item - if new_post_state != POST_STATE.CANCELLED: - return - planning_post_service = get_resource_service("planning_post") planning_spike_service = get_resource_service("planning_spike") + event_profile_schema = get_resource_service("planning_types").find_one(req=None, name="event").get("schema", {}) docs = [] + if new_post_state != POST_STATE.CANCELLED: + if event_profile_schema.get("related_plannings", {}).get("planning_auto_publish"): + docs = [ + { + "planning": planning[config.ID_FIELD], + "etag": planning.get("etag"), + "pubstatus": POST_STATE.USABLE, + } + for planning in plannings + ] + planning_post_service.post(docs) + return for planning in plannings: if not planning.get("pubstatus") and planning.get("state") in [ WORKFLOW_STATE.INGESTED, From fcd5e2506a84e3adbda4b6d6e69d65ba80ed9c95 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Wed, 6 Sep 2023 15:32:01 +0530 Subject: [PATCH 04/12] ignore related_planning.planning_auto_publish attribute from schema validation --- server/planning/validate/planning_validate.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/planning/validate/planning_validate.py b/server/planning/validate/planning_validate.py index 1d801571c..5f57aa1ea 100644 --- a/server/planning/validate/planning_validate.py +++ b/server/planning/validate/planning_validate.py @@ -78,6 +78,12 @@ def _validate_read_only(self, read_only, field, value): # Ignore this profile as it's for the front-end editor pass + def _validate_planning_auto_publish(self, planning_auto_publish, field, value): + """ + {'type': 'boolean', 'nullable': True} + """ + pass + class PlanningValidateResource(Resource): endpoint_name = "planning_validator" From f4d26bbd22afc69dc61b7fbd227faa98a391df73 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Thu, 7 Sep 2023 15:16:45 +0530 Subject: [PATCH 05/12] update label name --- client/components/fields/resources/profiles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/components/fields/resources/profiles.ts b/client/components/fields/resources/profiles.ts index ee63a0336..c45e62830 100644 --- a/client/components/fields/resources/profiles.ts +++ b/client/components/fields/resources/profiles.ts @@ -38,7 +38,7 @@ registerEditorField( 'schema.planning_auto_publish', EditorFieldCheckbox, () => ({ - label: superdeskApi.localization.gettext('Planning Auto Publish'), + label: superdeskApi.localization.gettext('Post planning items with Event'), field: 'schema.planning_auto_publish', }), null, From a1271466aea137ffe36862ab38c41649d22be80c Mon Sep 17 00:00:00 2001 From: devketanpro Date: Fri, 8 Sep 2023 18:26:33 +0530 Subject: [PATCH 06/12] add new params and handle the case to prevent planning from publish --- client/api/editor/item_events.ts | 4 ++++ client/interfaces.ts | 2 ++ server/planning/events/events_post.py | 3 ++- server/planning/planning/planning.py | 3 +++ server/planning/planning/planning_post.py | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/api/editor/item_events.ts b/client/api/editor/item_events.ts index 7650b735c..4f218234f 100644 --- a/client/api/editor/item_events.ts +++ b/client/api/editor/item_events.ts @@ -137,6 +137,10 @@ export function getEventsInstance(type: EDITOR_TYPE): IEditorAPI['item']['events return; } + if (updates && original?.version == original?.posted_version) { + original['version'] = original?.version ? original['version'] + 1 : 1; + } + plans[index] = { ...original, ...updates, diff --git a/client/interfaces.ts b/client/interfaces.ts index 7cc056169..214e45232 100644 --- a/client/interfaces.ts +++ b/client/interfaces.ts @@ -706,6 +706,8 @@ export interface IPlanningItem extends IBaseRestApiResponse { reason: string; _time_to_be_confirmed: boolean; _cancelAllCoverage: boolean; + version:number; + posted_version:number; // Used when showing Associated Planning item for Events _agendas: Array; diff --git a/server/planning/events/events_post.py b/server/planning/events/events_post.py index a3c34eadd..3aaf9f122 100644 --- a/server/planning/events/events_post.py +++ b/server/planning/events/events_post.py @@ -215,8 +215,9 @@ def post_related_plannings(self, plannings, new_post_state): "etag": planning.get("etag"), "pubstatus": POST_STATE.USABLE, } - for planning in plannings + for planning in plannings if planning.get("version") != planning.get("posted_version") ] + if len(docs) > 0: planning_post_service.post(docs) return for planning in plannings: diff --git a/server/planning/planning/planning.py b/server/planning/planning/planning.py index 248607bb3..cf941caaa 100644 --- a/server/planning/planning/planning.py +++ b/server/planning/planning/planning.py @@ -1653,6 +1653,9 @@ def duplicate_xmp_file(self, coverage): TO_BE_CONFIRMED_FIELD: TO_BE_CONFIRMED_FIELD_SCHEMA, "_type": {"type": "string", "mapping": None}, "extra": metadata_schema["extra"], + # Added fields for post planning item with events + "posted_version" : {"type": "number", "nullable": False}, + "version" : {"type": "number", "default": 1}, } # end planning_schema diff --git a/server/planning/planning/planning_post.py b/server/planning/planning/planning_post.py index a380aa2e3..8cfe7961e 100644 --- a/server/planning/planning/planning_post.py +++ b/server/planning/planning/planning_post.py @@ -125,6 +125,7 @@ def post_planning(self, plan, new_post_state, assignments_to_delete): updates = { "state": get_item_post_state(plan, new_post_state), "pubstatus": new_post_state, + "posted_version": plan.get("version") } if updates["state"] in [WORKFLOW_STATE.SCHEDULED, WORKFLOW_STATE.KILLED]: updates["state_reason"] = None From eb6af2593ecfbaa27dceeaccee99b9c140dd0e2a Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 15:10:01 +0530 Subject: [PATCH 07/12] revert changes --- client/api/editor/item_events.ts | 4 ---- client/interfaces.ts | 2 -- 2 files changed, 6 deletions(-) diff --git a/client/api/editor/item_events.ts b/client/api/editor/item_events.ts index 4f218234f..7650b735c 100644 --- a/client/api/editor/item_events.ts +++ b/client/api/editor/item_events.ts @@ -137,10 +137,6 @@ export function getEventsInstance(type: EDITOR_TYPE): IEditorAPI['item']['events return; } - if (updates && original?.version == original?.posted_version) { - original['version'] = original?.version ? original['version'] + 1 : 1; - } - plans[index] = { ...original, ...updates, diff --git a/client/interfaces.ts b/client/interfaces.ts index 214e45232..7cc056169 100644 --- a/client/interfaces.ts +++ b/client/interfaces.ts @@ -706,8 +706,6 @@ export interface IPlanningItem extends IBaseRestApiResponse { reason: string; _time_to_be_confirmed: boolean; _cancelAllCoverage: boolean; - version:number; - posted_version:number; // Used when showing Associated Planning item for Events _agendas: Array; From df2667dc719db82bf1c106f49fc20d1baa93c3dc Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 15:12:29 +0530 Subject: [PATCH 08/12] update logic for published related planning item --- server/planning/events/events_post.py | 3 ++- server/planning/planning/planning.py | 3 +-- server/planning/planning/planning_post.py | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/planning/events/events_post.py b/server/planning/events/events_post.py index 3aaf9f122..41e6264a0 100644 --- a/server/planning/events/events_post.py +++ b/server/planning/events/events_post.py @@ -215,7 +215,8 @@ def post_related_plannings(self, plannings, new_post_state): "etag": planning.get("etag"), "pubstatus": POST_STATE.USABLE, } - for planning in plannings if planning.get("version") != planning.get("posted_version") + for planning in plannings + if not planning.get("versionposted") ] if len(docs) > 0: planning_post_service.post(docs) diff --git a/server/planning/planning/planning.py b/server/planning/planning/planning.py index cf941caaa..a7c8af5ca 100644 --- a/server/planning/planning/planning.py +++ b/server/planning/planning/planning.py @@ -1654,8 +1654,7 @@ def duplicate_xmp_file(self, coverage): "_type": {"type": "string", "mapping": None}, "extra": metadata_schema["extra"], # Added fields for post planning item with events - "posted_version" : {"type": "number", "nullable": False}, - "version" : {"type": "number", "default": 1}, + "versionposted": {"type": "datetime", "nullable": False}, } # end planning_schema diff --git a/server/planning/planning/planning_post.py b/server/planning/planning/planning_post.py index 8cfe7961e..8df559cd1 100644 --- a/server/planning/planning/planning_post.py +++ b/server/planning/planning/planning_post.py @@ -14,6 +14,7 @@ from superdesk.resource import Resource from superdesk.services import BaseService from superdesk.notification import push_notification +from superdesk.utc import utcnow from copy import deepcopy import logging @@ -125,7 +126,7 @@ def post_planning(self, plan, new_post_state, assignments_to_delete): updates = { "state": get_item_post_state(plan, new_post_state), "pubstatus": new_post_state, - "posted_version": plan.get("version") + "versionposted": utcnow(), } if updates["state"] in [WORKFLOW_STATE.SCHEDULED, WORKFLOW_STATE.KILLED]: updates["state_reason"] = None From 57fa0df5423ed2732a1fb8b61a6f8cbee28a0a18 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 15:14:27 +0530 Subject: [PATCH 09/12] remove unwanted code --- server/planning/planning/planning.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server/planning/planning/planning.py b/server/planning/planning/planning.py index a7c8af5ca..19a882240 100644 --- a/server/planning/planning/planning.py +++ b/server/planning/planning/planning.py @@ -1653,7 +1653,6 @@ def duplicate_xmp_file(self, coverage): TO_BE_CONFIRMED_FIELD: TO_BE_CONFIRMED_FIELD_SCHEMA, "_type": {"type": "string", "mapping": None}, "extra": metadata_schema["extra"], - # Added fields for post planning item with events "versionposted": {"type": "datetime", "nullable": False}, } # end planning_schema From 9cbf9351e9e7df90cc99205d3e3726ce29c99aae Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 17:10:08 +0530 Subject: [PATCH 10/12] add testcases --- server/planning/events/events_tests.py | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/server/planning/events/events_tests.py b/server/planning/events/events_tests.py index c6ce0dbb9..2e12aa4c6 100644 --- a/server/planning/events/events_tests.py +++ b/server/planning/events/events_tests.py @@ -426,3 +426,112 @@ def generate_recurring_events(num_events): ) days += 1 return events + +class EventsRelatedPlanningAutoPublish(TestCase): + def test_planning_item_is_published_with_events(self): + with self.app.app_context(): + events_service = get_resource_service("events") + planning_service = get_resource_service("planning") + event = { + "type": "event", + "_id": "123", + "occur_status": { + "qcode": "eocstat:eos5", + "name": "Planned, occurs certainly", + "label": "Planned, occurs certainly", + }, + "dates": { + "start": datetime(2099, 11, 21, 11, 00, 00, tzinfo=pytz.UTC), + "end": datetime(2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC), + "tz": "Asia/Calcutta", + }, + "calendars": [], + "state": "draft", + "language": "en", + "languages": ["en"], + "place": [], + "_time_to_be_confirmed": False, + "name": "Demo ", + "update_method": "single", + } + event_id = events_service.post([event]) + planning = { + "planning_date": datetime(2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC), + "name": "Demo 1", + "place": [], + "language": "en", + "type": "planning", + "agendas": [], + "languages": ["en"], + "user": "12234553", + "event_item": event_id[0], + "coverages": [ + { + "coverage_id": "urn:newsml:localhost:5000:2023-09-08T17:40:56.290922:e264a179-5b1a-4b52-b73b-332660848cae", + "planning": { + "scheduled": datetime( + 2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC + ), + "g2_content_type": "text", + "language": "en", + "genre": "None", + }, + "news_coverage_status": { + "qcode": "ncostat:int", + "name": "coverage intended", + "label": "Planned", + }, + "workflow_status": "draft", + "assigned_to": {}, + "firstcreated": datetime(2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC), + } + ], + } + planning_id = planning_service.post([planning]) + schema = { + "language": { + "languages": ["en", "de"], + "default_language": "en", + "multilingual": True, + "required": True, + }, + "name": {"multilingual": True}, + "slugline": {"multilingual": True}, + "definition_short": {"multilingual": True}, + "related_plannings": {"planning_auto_publish": True}, + } + self.app.data.insert( + "planning_types", + [ + { + "_id": "event", + "name": "event", + "editor": { + "language": {"enabled": True}, + "related_plannings": {"enabled": True}, + }, + "schema": schema, + } + ], + ) + get_resource_service("events_post").post( + [ + { + "event": event_id[0], + "pubstatus": "usable", + "update_method": "single", + } + ] + ) + + + event_item = events_service.find_one(req = None, _id = event_id[0]) + self.assertEqual(len([event_item]), 1) + self.assertEqual(event_item.get("state"), "scheduled") + + planning_item = planning_service.find_one(req= None, _id = planning_id[0]) + self.assertEqual(len([planning_item]), 1) + self.assertEqual(planning_item.get("state"), "scheduled") + self.assertEqual(planning_item.get("versionposted"), utcnow()) + + From 31e6694689568312c1ade0261dbbcbc3d28e84bd Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 17:11:01 +0530 Subject: [PATCH 11/12] refactore code via black --- server/planning/events/events_tests.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/server/planning/events/events_tests.py b/server/planning/events/events_tests.py index 2e12aa4c6..ceaa38164 100644 --- a/server/planning/events/events_tests.py +++ b/server/planning/events/events_tests.py @@ -427,6 +427,7 @@ def generate_recurring_events(num_events): days += 1 return events + class EventsRelatedPlanningAutoPublish(TestCase): def test_planning_item_is_published_with_events(self): with self.app.app_context(): @@ -469,9 +470,7 @@ def test_planning_item_is_published_with_events(self): { "coverage_id": "urn:newsml:localhost:5000:2023-09-08T17:40:56.290922:e264a179-5b1a-4b52-b73b-332660848cae", "planning": { - "scheduled": datetime( - 2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC - ), + "scheduled": datetime(2099, 11, 21, 12, 00, 00, tzinfo=pytz.UTC), "g2_content_type": "text", "language": "en", "genre": "None", @@ -524,14 +523,11 @@ def test_planning_item_is_published_with_events(self): ] ) - - event_item = events_service.find_one(req = None, _id = event_id[0]) + event_item = events_service.find_one(req=None, _id=event_id[0]) self.assertEqual(len([event_item]), 1) self.assertEqual(event_item.get("state"), "scheduled") - planning_item = planning_service.find_one(req= None, _id = planning_id[0]) + planning_item = planning_service.find_one(req=None, _id=planning_id[0]) self.assertEqual(len([planning_item]), 1) self.assertEqual(planning_item.get("state"), "scheduled") self.assertEqual(planning_item.get("versionposted"), utcnow()) - - From 07de55303ffc227cbc395cb56c05a9628de4a933 Mon Sep 17 00:00:00 2001 From: devketanpro Date: Mon, 11 Sep 2023 18:06:34 +0530 Subject: [PATCH 12/12] refactore code --- client/interfaces.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/interfaces.ts b/client/interfaces.ts index 7cc056169..d07679a52 100644 --- a/client/interfaces.ts +++ b/client/interfaces.ts @@ -983,7 +983,7 @@ export interface IProfileSchemaTypeList extends IBaseProfileSchemaType<'list'> { schema?: {[key: string]: any}; mandatory_in_list?: {[key: string]: any}; vocabularies?: Array; - planning_auto_publish?:boolean; + planning_auto_publish?: boolean; } export interface IProfileSchemaTypeInteger extends IBaseProfileSchemaType<'integer'> {}