From b1dc195a0ecce7994c80f24bceb35ff10dc5f241 Mon Sep 17 00:00:00 2001 From: EEA Jenkins <2368628+eea-jenkins@users.noreply.github.com> Date: Mon, 21 Oct 2024 19:44:05 +0300 Subject: [PATCH 1/8] Back to devel --- docs/HISTORY.txt | 3 +++ eea/api/dataconnector/version.txt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index 258f66b..e741ab0 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -1,6 +1,9 @@ Changelog ========= +10.7-dev0 - (unreleased) +--------------------------- + 10.6 - (2024-10-21) --------------------------- * Change: Add embed_content block serializer diff --git a/eea/api/dataconnector/version.txt b/eea/api/dataconnector/version.txt index 12c0281..724c962 100644 --- a/eea/api/dataconnector/version.txt +++ b/eea/api/dataconnector/version.txt @@ -1 +1 @@ -10.6 +10.7-dev0 From 3463e7bf44425e0c015bb8aad00f94bc5c1883ae Mon Sep 17 00:00:00 2001 From: Miu Razvan Date: Thu, 24 Oct 2024 18:02:17 +0300 Subject: [PATCH 2/8] improvments --- eea/api/dataconnector/api/visualization.py | 8 +- eea/api/dataconnector/browser/blocks.py | 501 +++++++++------------ 2 files changed, 219 insertions(+), 290 deletions(-) diff --git a/eea/api/dataconnector/api/visualization.py b/eea/api/dataconnector/api/visualization.py index cabcce0..356076b 100644 --- a/eea/api/dataconnector/api/visualization.py +++ b/eea/api/dataconnector/api/visualization.py @@ -23,9 +23,9 @@ def reply(self): return { "visualization": { - **getMetadata(serializer=serializer), + **getMetadata(doc_json=serializer), **getVisualization( - serializer=serializer, + doc_json=serializer, layout=False ) } @@ -50,9 +50,9 @@ def reply(self): return { "visualization": { - **getMetadata(serializer=serializer), + **getMetadata(doc_json=serializer), **getVisualization( - serializer=serializer + doc_json=serializer ) } } diff --git a/eea/api/dataconnector/browser/blocks.py b/eea/api/dataconnector/browser/blocks.py index b952e70..48da44a 100644 --- a/eea/api/dataconnector/browser/blocks.py +++ b/eea/api/dataconnector/browser/blocks.py @@ -81,28 +81,12 @@ def getUid(context, link, retry=True): return uid -def getUrlUid(self, value, field): +def getMetadata(doc_json): """ - Get URL and UID based on the provided value and field. - - :param value: The input value. - :param field: The field to extract the URL from in the value. - - :return: A tuple containing the URL and UID. - """ - - url = value.get(field) - uid = getUid(self.context, url) - url = uid_to_url(url) - return url, uid - - -def getMetadata(serializer): - """ - Extract metadata information from a serializer. + Extract metadata information from a doc_json. Parameters: - - serializer: The serializer providing metadata information. + - doc_json: The doc_json providing metadata information. Returns: - dict: A dictionary containing metadata information with @@ -117,21 +101,21 @@ def getMetadata(serializer): - "figure_note": Additional notes related to the figure. The function retrieves metadata information from the provided - serializer and returns it as a dictionary. If a specific metadata - field is not present in the serializer, the corresponding key in + doc_json and returns it as a dictionary. If a specific metadata + field is not present in the doc_json, the corresponding key in the dictionary will have a value of None. """ return { - "@id": serializer.get("@id"), - "title": serializer.get("title"), - "description": serializer.get("description"), - "publisher": serializer.get("publisher"), - "geo_coverage": serializer.get("geo_coverage"), - "temporal_coverage": serializer.get("temporal_coverage"), - "other_organisations": serializer.get("other_organisations"), - "data_provenance": serializer.get("data_provenance"), - "figure_note": serializer.get("figure_note") + "@id": doc_json.get("@id"), + "title": doc_json.get("title"), + "description": doc_json.get("description"), + "publisher": doc_json.get("publisher"), + "geo_coverage": doc_json.get("geo_coverage"), + "temporal_coverage": doc_json.get("temporal_coverage"), + "other_organisations": doc_json.get("other_organisations"), + "data_provenance": doc_json.get("data_provenance"), + "figure_note": doc_json.get("figure_note") } @@ -157,12 +141,12 @@ def getVisualizationLayout(chartData): return chartData -def getVisualization(serializer, layout=True): +def getVisualization(doc_json, layout=True): """ - Extract visualization information from a serializer. + Extract visualization information from a doc_json. Parameters: - - serializer: The serializer providing visualization information. + - doc_json: The doc_json providing visualization information. - layout (bool, optional): If True, apply layout adjustments to the visualization data. Defaults to True. @@ -174,13 +158,13 @@ def getVisualization(serializer, layout=True): Returns None if the visualization information is not present. The function retrieves visualization information from the provided - serializer, including chart data and provider URL. If layout is set + doc_json, including chart data and provider URL. If layout is set to True (default), it applies layout adjustments to the chart data using the getVisualizationLayout function. If visualization information is not present, the function returns None. """ - visualization = serializer.get("visualization", None) + visualization = doc_json.get("visualization", None) if not visualization: return {} @@ -216,10 +200,88 @@ def getVisualization(serializer, layout=True): @implementer(IBlockFieldSerializationTransformer) @adapter(IBlocks, IBrowserRequest) -class EmbedContentSerializationTransformer: - """Embed content serialization""" +class EmbedingBlockSerializationTransformer: + """Embeding block serialization""" order = 9999 + block_type = "unknown" + title = 'content' + state = {} + error = None + initialized = False + + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, value): + return value + + def init(self, value): + """Init""" + self.state = {} + self.initialized = True + url = self.get_url(value) + + if not url: + return + + self.state["url"] = url + self.state["uid"] = getUid(self.context, self.state["url"]) + self.state["doc"] = self.get_doc() + self.state["doc_json"] = self.get_doc_json() + + if not self.state["doc_json"]: + return + + self.state["properties"] = { + **getMetadata(self.state["doc_json"]), + "@type": self.state["doc_json"].get("@type"), + "UID": self.state["doc_json"].get("UID") + } + + def get_url(self, value): + """Get url""" + if not value: + return None + return value.get("url") or value.get("vis_url") or value.get( + "tableau_vis_url") + + def get_doc(self): + """Get doc""" + url = self.state["url"] + uid = self.state["uid"] + try: + return api.content.get(UID=uid) + except Unauthorized: + self.error = "Apologies, it seems this " + getLinkHTML( + url, self.title) + " has not been published yet." + + except Forbidden: + self.error = "Apologies, it seems you do not have " + \ + "permissions to see this " + getLinkHTML(url, self.title) + \ + "." + + def get_doc_json(self): + """Get document json""" + doc = self.state["doc"] + if not doc: + return None + serializer = queryMultiAdapter( + (doc, self.request), ISerializeToJson) + if not serializer: + return None + return serializer( + version=self.request.get("version")) + + def get_error(self): + """Get error""" + + +class EmbedContentSerializationTransformer( + EmbedingBlockSerializationTransformer): + """Embed content serialization""" + block_type = "embed_content" def __init__(self, context, request): @@ -227,8 +289,31 @@ def __init__(self, context, request): self.request = request def __call__(self, value): - properties = value.get("properties", {}) - content_type = properties.get('@type', None) + if not self.initialized: + self.init(value) + + url = self.state.get("url") + doc_json = self.state.get("doc_json") + + if not url: + return value + + if self.error: + return { + **value, + "error": self.error + } + + if not doc_json: + return { + **value, + "error": "Apologies, it seems this " + getLinkHTML( + url, self.title) + " does not exist." + } + + value["properties"] = self.state["properties"] + + content_type = value["properties"].get('@type', None) block_type = 'none' if content_type == 'visualization': @@ -249,90 +334,51 @@ def __call__(self, value): return new_value -@implementer(IBlockFieldSerializationTransformer) -@adapter(IBlocks, IBrowserRequest) -class EmbedVisualizationSerializationTransformer: +class EmbedVisualizationSerializationTransformer( + EmbedingBlockSerializationTransformer): """Embed visualization serialization""" order = 9999 block_type = "embed_visualization" + title = "Chart (Interactive)" def __init__(self, context, request): self.context = context self.request = request def __call__(self, value): - vis_url, uid = getUrlUid(self, value, 'vis_url') - if not uid: - vis_url, uid = getUrlUid(self, value, 'url') - - if 'visualization' in value: - del value['visualization'] + if not self.initialized: + self.init(value) - if not uid: - return value + url = uid_to_url(self.state.get("url")) + doc_json = self.state.get("doc_json") - doc = None + value["vis_url"] = url - try: - doc = api.content.get(UID=uid) - except Unauthorized: + if self.error: return { - **value, "vis_url": vis_url, + **value, "visualization": { - "error": - "Apologies, it seems this " + - getLinkHTML(vis_url, 'Chart (Interactive)') + - " has not been published yet." + "error": self.error } } - except Forbidden: - return { - **value, "vis_url": vis_url, - "visualization": { - "error": - "Apologies, it seems you do not have " + - "permissions to see this " + - getLinkHTML(vis_url, 'Chart (Interactive)') + "." - } - } - - doc_serializer = self._get_doc_serializer(doc) - if doc_serializer: - use_data_sources = value.get('use_data_sources', True) - return { - **value, "vis_url": vis_url, - "visualization": { - **getVisualization(serializer=doc_serializer, - layout=use_data_sources), - **getMetadata(doc_serializer), - } - } - return {**value, "vis_url": uid_to_url(value.get('vis_url'))} - - def _get_doc_serializer(self, doc): - """ - Get a serializer for the given document. + if 'visualization' in value: + del value['visualization'] - This method queries for a JSON serializer adapter for the provided - document and request. If a serializer is found, it is instantiated - with the version from the request and returned. + if not doc_json: + return value - :param doc: The document for which to get a serializer. - :type doc: object + use_data_sources = value.get('use_data_sources', True) - :return: An instantiated JSON serializer if available, or None if - not found. - :rtype: object or None - """ - if doc: - doc_serializer = queryMultiAdapter( - (doc, self.request), ISerializeToJson) - if doc_serializer: - return doc_serializer( - version=self.request.get("version")) - return None + return { + **value, + "visualization": { + **getVisualization(doc_json=doc_json, + layout=use_data_sources), + **getMetadata(doc_json), + } + } @implementer(IBlockFieldDeserializationTransformer) @@ -356,91 +402,49 @@ def __call__(self, value): return value -@implementer(IBlockFieldSerializationTransformer) -@adapter(IBlocks, IBrowserRequest) -class EmbedTableauVisualizationSerializationTransformer: +class EmbedTableauVisualizationSerializationTransformer(( + EmbedingBlockSerializationTransformer)): """Embed tableau visualization serialization""" order = 9999 block_type = "embed_tableau_visualization" + title = "Dashboard" def __init__(self, context, request): self.context = context self.request = request def __call__(self, value): - tableau_vis_url, uid = getUrlUid(self, value, 'tableau_vis_url') - if not uid: - tableau_vis_url, uid = getUrlUid(self, value, 'url') - - if 'tableau_visualization' in value: - del value['tableau_visualization'] + if not self.initialized: + self.init(value) - if not uid: - return value + url = uid_to_url(self.state.get("url")) + doc_json = self.state.get("doc_json") - doc = None + value["tableau_vis_url"] = url - try: - doc = api.content.get(UID=uid) - except Unauthorized: + if self.error: return { - **value, "tableau_vis_url": tableau_vis_url, - "tableau_visualization": { - "error": - "Apologies, it seems this " + - getLinkHTML(tableau_vis_url, 'Dashboard') + - " has not been published yet." - } - } - except Forbidden: - return { - **value, "tableau_vis_url": tableau_vis_url, - "tableau_visualization": { - "error": - "Apologies, it seems you do not have " + - "permissions to see this " + - getLinkHTML(tableau_vis_url, 'Dashboard') + "." + **value, + "visualization": { + "error": self.error } } - doc_serializer = self._get_doc_serializer(doc) - if doc_serializer: - return { - **value, "tableau_vis_url": tableau_vis_url, - "tableau_visualization": { - **doc_serializer.get('tableau_visualization', {}), - **getMetadata(doc_serializer), - } - } + if 'tableau_visualization' in value: + del value['tableau_visualization'] + + if not doc_json: + return value + return { **value, - "tableau_vis_url": tableau_vis_url, + "tableau_visualization": { + **doc_json.get('tableau_visualization', {}), + **getMetadata(doc_json), + } } - def _get_doc_serializer(self, doc): - """ - Get a serializer for the given document. - - This method queries for a JSON serializer adapter for the provided - document and request. If a serializer is found, it is instantiated - with the version from the request and returned. - - :param doc: The document for which to get a serializer. - :type doc: object - - :return: An instantiated JSON serializer if available, or None if - not found. - :rtype: object or None - """ - if doc: - doc_serializer = queryMultiAdapter( - (doc, self.request), ISerializeToJson) - if doc_serializer: - return doc_serializer( - version=self.request.get("version")) - return None - @implementer(IBlockFieldDeserializationTransformer) @adapter(IBlocks, IBrowserRequest) @@ -463,91 +467,49 @@ def __call__(self, value): return value -@implementer(IBlockFieldSerializationTransformer) -@adapter(IBlocks, IBrowserRequest) -class EmbedEEAMapBlockSerializationTransformer: +class EmbedEEAMapBlockSerializationTransformer( + EmbedingBlockSerializationTransformer): """Embed eea map block serializer""" order = 9999 block_type = "embed_eea_map_block" + title = "Map (Simple)" def __init__(self, context, request): self.context = context self.request = request def __call__(self, value): - vis_url, uid = getUrlUid(self, value, 'vis_url') - if not uid: - vis_url, uid = getUrlUid(self, value, 'url') + if not self.initialized: + self.init(value) - if 'map_visualization_data' in value: - del value['map_visualization_data'] - - if not uid: - return value + url = uid_to_url(self.state.get("url")) + doc_json = self.state.get("doc_json") - doc = None + value["vis_url"] = url - try: - doc = api.content.get(UID=uid) - except Unauthorized: - return { - **value, "tableau_vis_url": vis_url, - "map_visualization_data": { - "error": - "Apologies, it seems this " + - getLinkHTML(vis_url, 'Map (Simple)') + - " has not been published yet." - } - } - except Forbidden: + if self.error: return { - **value, "tableau_vis_url": vis_url, - "map_visualization_data": { - "error": - "Apologies, it seems you do not have " + - "permissions to see this " + - getLinkHTML(vis_url, 'Map (Simple)') + "." + **value, + "visualization": { + "error": self.error } } - doc_serializer = self._get_doc_serializer(doc) - if doc_serializer: - return { - **value, "vis_url": vis_url, - "map_visualization_data": { - **doc_serializer.get('map_visualization_data', {}), - **getMetadata(doc_serializer), - } - } + if 'map_visualization_data' in value: + del value['map_visualization_data'] + + if not doc_json: + return value + return { **value, - "vis_url": vis_url, + "map_visualization_data": { + **doc_json.get('map_visualization_data', {}), + **getMetadata(doc_json), + } } - def _get_doc_serializer(self, doc): - """ - Get a serializer for the given document. - - This method queries for a JSON serializer adapter for the provided - document and request. If a serializer is found, it is instantiated - with the version from the request and returned. - - :param doc: The document for which to get a serializer. - :type doc: object - - :return: An instantiated JSON serializer if available, or None if - not found. - :rtype: object or None - """ - if doc: - doc_serializer = queryMultiAdapter( - (doc, self.request), ISerializeToJson) - if doc_serializer: - return doc_serializer( - version=self.request.get("version")) - return None - @implementer(IBlockFieldDeserializationTransformer) @adapter(IBlocks, IBrowserRequest) @@ -570,80 +532,47 @@ def __call__(self, value): return value -@implementer(IBlockFieldSerializationTransformer) -@adapter(IBlocks, IBrowserRequest) -class EmbedMapsSerializationTransformer: +class EmbedMapsSerializationTransformer( + EmbedingBlockSerializationTransformer): """Embed maps serializer""" order = 9999 block_type = "embed_maps" + title = "Map (Interactive)" def __init__(self, context, request): self.context = context self.request = request def __call__(self, value): - url, uid = getUrlUid(self, value, 'url') + if not self.initialized: + self.init(value) - if 'maps' in value: - del value['maps'] + url = uid_to_url(self.state.get("url")) + doc_json = self.state.get("doc_json") - if not uid: - return value + value["url"] = url - try: - doc = api.content.get(UID=uid) - except Unauthorized: - return { - **value, "maps": { - "error": - "Apologies, it seems this " + - getLinkHTML(url, 'Map (Interactive)') + - " has not been published yet." - } - } - except Forbidden: + if self.error: return { - **value, "maps": { - "error": - "Apologies, it seems you do not have " + - "permissions to see this " + - getLinkHTML(url, 'Map (Interactive)') + "." + **value, + "visualization": { + "error": self.error } } - doc_serializer = self._get_doc_serializer(doc) - if doc_serializer: - return { - **value, "maps": { - **doc_serializer.get('maps', {}), - **getMetadata(doc_serializer), - } - } - return value + if 'maps' in value: + del value['maps'] + + if not doc_json: + return value - def _get_doc_serializer(self, doc): - """ - Get a serializer for the given document. - - This method queries for a JSON serializer adapter for the provided - document and request. If a serializer is found, it is instantiated - with the version from the request and returned. - - :param doc: The document for which to get a serializer. - :type doc: object - - :return: An instantiated JSON serializer if available, or None if - not found. - :rtype: object or None - """ - if doc: - doc_serializer = queryMultiAdapter( - (doc, self.request), ISerializeToJson) - if doc_serializer: - return doc_serializer( - version=self.request.get("version")) - return None + return { + **value, "maps": { + **doc_json.get('maps', {}), + **getMetadata(doc_json), + } + } @implementer(IBlockFieldDeserializationTransformer) From 24b2ca36085480ebcc4d218562d701cee6b7370b Mon Sep 17 00:00:00 2001 From: Miu Razvan Date: Thu, 24 Oct 2024 18:06:14 +0300 Subject: [PATCH 3/8] update --- eea/api/dataconnector/browser/blocks.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/eea/api/dataconnector/browser/blocks.py b/eea/api/dataconnector/browser/blocks.py index 48da44a..c2c791c 100644 --- a/eea/api/dataconnector/browser/blocks.py +++ b/eea/api/dataconnector/browser/blocks.py @@ -210,10 +210,6 @@ class EmbedingBlockSerializationTransformer: error = None initialized = False - def __init__(self, context, request): - self.context = context - self.request = request - def __call__(self, value): return value From 5ca9423d2f56a27c644b4d3af52bfaf627c6941e Mon Sep 17 00:00:00 2001 From: Miu Razvan Date: Thu, 24 Oct 2024 18:08:58 +0300 Subject: [PATCH 4/8] update --- eea/api/dataconnector/browser/blocks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eea/api/dataconnector/browser/blocks.py b/eea/api/dataconnector/browser/blocks.py index c2c791c..db0bc5f 100644 --- a/eea/api/dataconnector/browser/blocks.py +++ b/eea/api/dataconnector/browser/blocks.py @@ -252,11 +252,13 @@ def get_doc(self): except Unauthorized: self.error = "Apologies, it seems this " + getLinkHTML( url, self.title) + " has not been published yet." + return None except Forbidden: self.error = "Apologies, it seems you do not have " + \ "permissions to see this " + getLinkHTML(url, self.title) + \ "." + return None def get_doc_json(self): """Get document json""" From ba07ced0167e0d3dfbe69b3ba1e788e7395590fa Mon Sep 17 00:00:00 2001 From: EEA Jenkins Date: Thu, 24 Oct 2024 18:15:15 +0300 Subject: [PATCH 5/8] Updated version to 10.7 --- eea/api/dataconnector/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eea/api/dataconnector/version.txt b/eea/api/dataconnector/version.txt index 724c962..4e74f9f 100644 --- a/eea/api/dataconnector/version.txt +++ b/eea/api/dataconnector/version.txt @@ -1 +1 @@ -10.7-dev0 +10.7 From f6f0aea823858f10068c258c1fae47e2431e45d6 Mon Sep 17 00:00:00 2001 From: EEA Jenkins Date: Thu, 24 Oct 2024 18:15:17 +0300 Subject: [PATCH 6/8] Updated changelog - removed develop information --- docs/HISTORY.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index e741ab0..a4a2955 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -1,8 +1,10 @@ Changelog ========= -10.7-dev0 - (unreleased) +10.7 - (2024-10-24) --------------------------- +* Change: improvments + [razvanMiu] 10.6 - (2024-10-21) --------------------------- From 57561e149020c11881d939865e428b03206bd22a Mon Sep 17 00:00:00 2001 From: Miu Razvan Date: Thu, 24 Oct 2024 18:36:22 +0300 Subject: [PATCH 7/8] Add embed_content deserializer --- eea/api/dataconnector/browser/blocks.py | 19 +++++++++++++++++++ eea/api/dataconnector/browser/configure.zcml | 3 +++ 2 files changed, 22 insertions(+) diff --git a/eea/api/dataconnector/browser/blocks.py b/eea/api/dataconnector/browser/blocks.py index db0bc5f..8f158b5 100644 --- a/eea/api/dataconnector/browser/blocks.py +++ b/eea/api/dataconnector/browser/blocks.py @@ -332,6 +332,25 @@ def __call__(self, value): return new_value +@implementer(IBlockFieldDeserializationTransformer) +@adapter(IBlocks, IBrowserRequest) +class EmbedContentDeserializationTransformer: + """Embed content deserialization""" + + order = 9999 + block_type = "embed_content" + + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self, value): + return { + "@type": value.get("@type"), + "url": value.get("url") + } + + class EmbedVisualizationSerializationTransformer( EmbedingBlockSerializationTransformer): """Embed visualization serialization""" diff --git a/eea/api/dataconnector/browser/configure.zcml b/eea/api/dataconnector/browser/configure.zcml index 2f20dc8..9547e58 100644 --- a/eea/api/dataconnector/browser/configure.zcml +++ b/eea/api/dataconnector/browser/configure.zcml @@ -84,6 +84,9 @@ factory=".blocks.PlotlyChartSerializationTransformer" /> + From 801864f201e391412662ac739253955a61ccb5c7 Mon Sep 17 00:00:00 2001 From: alin Date: Thu, 24 Oct 2024 19:46:45 +0300 Subject: [PATCH 8/8] Release 11.0 --- docs/HISTORY.txt | 6 +++--- eea/api/dataconnector/version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index a4a2955..f5d4e5e 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -1,10 +1,10 @@ Changelog ========= -10.7 - (2024-10-24) +11.0 - (2024-10-24) --------------------------- -* Change: improvments - [razvanMiu] +* Change: Refactor Visualisation serializers + [razvanMiu - refs #274326] 10.6 - (2024-10-21) --------------------------- diff --git a/eea/api/dataconnector/version.txt b/eea/api/dataconnector/version.txt index 4e74f9f..2dbc24b 100644 --- a/eea/api/dataconnector/version.txt +++ b/eea/api/dataconnector/version.txt @@ -1 +1 @@ -10.7 +11.0