diff --git a/html/js/display-tag.js b/html/js/display-tag.js index a4ebc7e1e9753..39dd8a91ac332 100644 --- a/html/js/display-tag.js +++ b/html/js/display-tag.js @@ -115,14 +115,26 @@ function displayPointers(pointers) { var markers = []; for (var i = 0; i < pointers.length; ++i) { var pointer = pointers[i]; - var marker = new L.marker(pointer); + var coordinates; + + // If pointer is an array, it just contains (lat, lng) geo coordinates + if (Array.isArray(pointer)) { + coordinates = pointer; + } + // Otherwise we have a structured object + // e.g. from a map element of a knowledge panel + else { + coordinates = [ pointer.geo.lat, pointer.geo.lng ]; + } + + var marker = new L.marker(coordinates); markers.push(marker); } if (markers.length > 0) { L.featureGroup(markers).addTo(actualMap); fitBoundsToAllLayers(actualMap); - actualMap.setZoom(10); + actualMap.setZoom(8); } }); } diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index e6095d0f211b0..434bc69247934 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -402,7 +402,11 @@ sub process_template($$$) { }; $template_data_ref->{sprintf} = sub($$) { return sprintf ($_[0], $_[1]); - }; + }; + + $template_data_ref->{encode_json} = sub($) { + return JSON::PP->new->utf8->canonical->encode($_[0]); + }; return($tt->process($template_filename, $template_data_ref, $result_content_ref)); } diff --git a/lib/ProductOpener/KnowledgePanels.pm b/lib/ProductOpener/KnowledgePanels.pm index f69403ed52a90..f5f9f587d7ff3 100644 --- a/lib/ProductOpener/KnowledgePanels.pm +++ b/lib/ProductOpener/KnowledgePanels.pm @@ -124,8 +124,8 @@ sub create_knowledge_panels($$$$) { $product_ref->{"knowledge_panels_" . $target_lc} = {}; # Test panel to test the start of the API - - if ($product_ref->{code} eq "3017620422003") { + # Disabled, kept as reference when we create a "Do you know" panel + if ($product_ref->{code} eq "3017620422003--disabled") { my $test_panel_ref = { parent_panel_id => "root", @@ -165,6 +165,10 @@ sub create_knowledge_panels($$$$) { create_ecoscore_panel($product_ref, $target_lc, $target_cc); create_environment_card_panel($product_ref, $target_lc, $target_cc); + + # Create the root panel that contains the panels we want to show directly on the product page + create_panel_from_json_template("root", "api/knowledge-panels/root.tt.json", + {}, $product_ref, $target_lc, $target_cc); } @@ -525,11 +529,80 @@ sub create_environment_card_panel($$$) { # Tell the environment card template to include packaging recycling panel $panel_data_ref->{packaging_recycling} = 1; - + + # Create panel for manufacturing place + $panel_data_ref->{manufacturing_place} = create_manufacturing_place_panel($product_ref, $target_lc, $target_cc); + + # Origins of ingredients for the environment card + create_panel_from_json_template("origins_of_ingredients", "api/knowledge-panels/environment/origins_of_ingredients.tt.json", + $panel_data_ref, $product_ref, $target_lc, $target_cc); # Create the environment_card panel create_panel_from_json_template("environment_card", "api/knowledge-panels/environment/environment_card.tt.json", $panel_data_ref, $product_ref, $target_lc, $target_cc); } + +=head2 create_manufacturing_place_panel ( $product_ref, $target_lc, $target_cc ) + +Creates a knowledge panel when we know the location of the manufacturing place, +usually through a packaging code. + +=head3 Arguments + +=head4 product reference $product_ref + +Loaded from the MongoDB database, Storable files, or the OFF API. + +=head4 language code $target_lc + +Returned attributes contain both data and strings intended to be displayed to users. +This parameter sets the desired language for the user facing strings. + +=head4 country code $target_cc + +The Eco-Score depends on the country of the consumer (as the transport bonus/malus depends on it) + +=head3 Return value + +1 to indicate that the panel has been created +0 to indicate that the panel was not created (if we don't have enough data for the product) + +=cut + +sub create_manufacturing_place_panel($$$) { + + my $product_ref = shift; + my $target_lc = shift; + my $target_cc = shift; + + $log->debug("create_manufacturing_place_panel", { code => $product_ref->{code} }) if $log->is_debug(); + + # Go through the product packaging codes, keep the first one with associated geo coordinates + if (defined $product_ref->{emb_codes_tags}) { + foreach my $packager_code_tagid (@{$product_ref->{emb_codes_tags}}) { + # we will create a panel for the first known location + if (exists $packager_codes{$packager_code_tagid}) { + $log->debug("packager code found for the canon_tagid", { cc => $packager_codes{$packager_code_tagid}{cc} }) if $log->is_debug(); + my ($lat, $lng) = get_packager_code_coordinates($packager_code_tagid); + if ((defined $lat) and (defined $lng)) { + + my $panel_data_ref = { + packager_code_data => $packager_codes{$packager_code_tagid}, + lat => $lat + 0.0, + lng => $lng + 0.0, + }; + + create_panel_from_json_template("manufacturing_place", "api/knowledge-panels/environment/manufacturing_place.tt.json", + $panel_data_ref, $product_ref, $target_lc, $target_cc); + + return 1; + } + } + } + } + + return 0; +} + 1; diff --git a/templates/api/knowledge-panels/environment/carbon_footprint.tt.json b/templates/api/knowledge-panels/environment/carbon_footprint.tt.json index 4391a7b9cc352..aa7b82977be14 100644 --- a/templates/api/knowledge-panels/environment/carbon_footprint.tt.json +++ b/templates/api/knowledge-panels/environment/carbon_footprint.tt.json @@ -2,12 +2,11 @@ [% SET co2_100g = product.ecoscore_data.agribalyse.co2_total / 10 %] [% SET driving_100g = co2_100g * 100 / 19.3 %] { - "parent_panel_id": "root", - "type" : "score", "level" :"info", "topics": [ "environment" ], + "expanded": false, [% IF driving_100g >= 3 %] "evaluation": "bad", [% ELSIF driving_100g >= 1.5 %] diff --git a/templates/api/knowledge-panels/environment/ecoscore/agribalyse.tt.json b/templates/api/knowledge-panels/environment/ecoscore/agribalyse.tt.json index 64a772af79ee1..81ff4cabb9e94 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/agribalyse.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/agribalyse.tt.json @@ -1,14 +1,13 @@ { - "parent_panel_id": "ecoscore", - "type" : "score", "level" :"info", - "grade": "[% panel.agribalyse_grade %]", "topics": [ "environment" ], "title_element": { "title": "[% lang('average_impact_of_the_category') %][% sep %]: [% panel.agribalyse_grade FILTER upper %] (Score: [% panel.agribalyse_score %]/100)", - "subtitle": "[% lang('categories_s') FILTER ucfirst %][% sep %]: [% panel.agribalyse_category_name %]" + "subtitle": "[% lang('categories_s') FILTER ucfirst %][% sep %]: [% panel.agribalyse_category_name %]", + "type": "grade", + "grade": "[% panel.agribalyse_grade %]", }, "elements": [ { diff --git a/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json b/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json index b5400f2806740..28ebd6bbd6bc8 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json @@ -1,14 +1,13 @@ { - "parent_panel_id": "root", - "type": "score", "level": "info", - "grade": "[% panel.grade %]", "topics": [ "environment" ], "title_element": { "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-[% panel.grade %].svg", "title": "[% panel.title %]", + "type": "grade", + "grade": "[% panel.grade %]", }, "elements": [ { diff --git a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json index a66c55ca0fbd4..e898f3aa284da 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json @@ -1,20 +1,19 @@ { - "parent_panel_id": "root", - "type": "score", "level": "info", - "grade": "unknown", "topics": [ "environment" ], "title_element": { "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-unknown.svg", "title": "[% lang("attribute_ecoscore_unknown_title") %] - [% lang("attribute_ecoscore_unknown_description_short") %]", + "type": "grade", + "grade": "unknown", }, "elements": [ { "element_type": "text", "text_element": { - "text_type": "summary", + "type": "summary", "html": "We could not compute the Eco-Score of this product as it is missing some data, could you help complete it?" } }, diff --git a/templates/api/knowledge-panels/environment/ecoscore/origins_of_ingredients.tt.json b/templates/api/knowledge-panels/environment/ecoscore/origins_of_ingredients.tt.json index 199c9fa54947e..0e6c0bf7b022d 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/origins_of_ingredients.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/origins_of_ingredients.tt.json @@ -1,6 +1,4 @@ { - "parent_panel_id": "ecoscore", - "type" : "score", "level" :"info", "topics": [ "environment" @@ -18,7 +16,7 @@ { "element_type": "text", "text_element": { - "text_type": "warning", + "type": "warning", "html": ` [% lang('ecoscore_ingredients_not_indicated') %]

[% lang('ecoscore_please_add_the_ingredients') %]

@@ -64,7 +62,6 @@ "element_type": "table", "table_element": { "id": "ecoscore_origins_of_ingredients_table", - "table_type": "percents", "title": "[% lang('ecoscore_origins_of_ingredients') %]", "columns": [ { diff --git a/templates/api/knowledge-panels/environment/ecoscore/packaging.tt.json b/templates/api/knowledge-panels/environment/ecoscore/packaging.tt.json index 06ac47ce3629d..1f2339b74581f 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/packaging.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/packaging.tt.json @@ -1,6 +1,4 @@ { - "parent_panel_id": "ecoscore", - "type" : "score", "level" :"info", "topics": [ "environment" @@ -48,7 +46,6 @@ "element_type": "table", "table_element": { "id": "ecoscore_packaging_components", - "type": "table", "title": "[% lang('packaging_parts') %]", "columns": [ { diff --git a/templates/api/knowledge-panels/environment/ecoscore/production_system.tt.json b/templates/api/knowledge-panels/environment/ecoscore/production_system.tt.json index d4e5483b63a24..ef541dac7e052 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/production_system.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/production_system.tt.json @@ -1,6 +1,4 @@ { - "parent_panel_id": "ecoscore", - "type" : "score", "level" :"info", "topics": [ "environment" diff --git a/templates/api/knowledge-panels/environment/ecoscore/threatened_species.tt.json b/templates/api/knowledge-panels/environment/ecoscore/threatened_species.tt.json index d04f3840f3dcd..c87bbd30b1bfc 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/threatened_species.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/threatened_species.tt.json @@ -1,6 +1,4 @@ { - "parent_panel_id": "ecoscore", - "type" : "score", "level" :"info", "topics": [ "environment" @@ -17,7 +15,7 @@ { "element_type": "text", "text_element": { - "text_type": "summary", + "type": "summary", "html": ` [% lang('ecoscore_ingredients_unknown') %] [% lang('ecoscore_edit_for_more_precise_ecoscore') %]

@@ -39,7 +37,7 @@ { "element_type": "text", "text_element": { - "text_type": "summary", + "type": "summary", "html": `

[% lang('contains_palm_oil') %]

[% lang('contains_palm_oil_description') %]

diff --git a/templates/api/knowledge-panels/environment/ecoscore/total.tt.json b/templates/api/knowledge-panels/environment/ecoscore/total.tt.json index c804d64730be5..27ee1c3c9ace6 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/total.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/total.tt.json @@ -1,15 +1,14 @@ [% SET sum_of_bonuses_and_maluses = product.ecoscore_data.adjustments.production_system.value + product.ecoscore_data.adjustments.packaging.value + product.ecoscore_data.adjustments.threatened_species.value + product.ecoscore_data.adjustments.origins_of_ingredients.value %] { - "parent_panel_id": "root", - "type": "score", "level": "info", - "grade": "[% panel.grade %]", "topics": [ "environment" ], "title_element": { "title": "Impact for this product: [% panel.grade FILTER upper %] (Score: [% panel.score %]/100)", "subtitle": "[% lang("front_alt") %][% sep %]: [% product_name_brand_quantity(product) %]", + "type": "grade", + "grade": "[% panel.grade %]", }, "elements": [ { diff --git a/templates/api/knowledge-panels/environment/environment_card.tt.json b/templates/api/knowledge-panels/environment/environment_card.tt.json index 0875da5bcf4fe..a12011d8e9ec0 100644 --- a/templates/api/knowledge-panels/environment/environment_card.tt.json +++ b/templates/api/knowledge-panels/environment/environment_card.tt.json @@ -1,7 +1,6 @@ { - "parent_panel_id": "root", - "level": "info", "type": "card", + "expanded": true, "topics": [ "environment" ], @@ -34,7 +33,17 @@ ], }, }, - [% END %] + [% END %] + { + "element_type": "panel_group", + "panel_group_element": { + "title": "[% lang('ecoscore_transportation') %]", + "panel_ids": [ + [% IF panel.manufacturing_place %]"manufacturing_place",[% END %] + "origins_of_ingredients", + ], + }, + }, [% IF panel.palm_oil %] { "element_type": "panel_group", diff --git a/templates/api/knowledge-panels/environment/label.tt.json b/templates/api/knowledge-panels/environment/label.tt.json index eec3b23908f2f..e513bb7e6613c 100644 --- a/templates/api/knowledge-panels/environment/label.tt.json +++ b/templates/api/knowledge-panels/environment/label.tt.json @@ -1,5 +1,4 @@ { - "parent_panel_id": "ecoscore", "level" :"info", "topics": [ "environment" diff --git a/templates/api/knowledge-panels/environment/manufacturing_place.tt.json b/templates/api/knowledge-panels/environment/manufacturing_place.tt.json new file mode 100644 index 0000000000000..4578ad86adecc --- /dev/null +++ b/templates/api/knowledge-panels/environment/manufacturing_place.tt.json @@ -0,0 +1,37 @@ +{ + "level" :"info", + "topics": [ + "environment" + ], + "evaluation": "neutral", + "expanded": true, + "title_element": { + "title": "[% lang('manufacturing_places_s') FILTER ucfirst %]", + [% IF panel.packager_code_data.cc == 'fr' %] + "subtitle": "[% panel.packager_code_data.commune %] - [% display_taxonomy_tag('countries', 'en:france') %]", + [% ELSIF panel.packager_code_data.cc == 'ch' %] + "subtitle": "[% panel.packager_code_data.full_address %]", + [% ELSIF panel.packager_code_data.cc == 'es' %] + "subtitle": "[% panel.packager_code_data.provincia_localidad %]", + [% ELSIF panel.packager_code_data.cc == 'uk' %] + "subtitle": "[% panel.packager_code_data.district %]", + [% END %] + "icon_url": "[% static_subdomain %]/images/icons/dist/transportation.svg", + "icon_color_from_evaluation": true, + }, + "elements": [ + { + "element_type": "map", + "map_element": { + "pointers": [ + { + "geo": { + "lat": [% panel.lat %], + "lng": [% panel.lng %], + } + } + ] + } + }, + ] +} diff --git a/templates/api/knowledge-panels/environment/origins_of_ingredients.tt.json b/templates/api/knowledge-panels/environment/origins_of_ingredients.tt.json new file mode 100644 index 0000000000000..eaef0564b8258 --- /dev/null +++ b/templates/api/knowledge-panels/environment/origins_of_ingredients.tt.json @@ -0,0 +1,107 @@ +{ + "level" :"info", + "topics": [ + "environment" + ], + "expanded": false, +[% IF product.ecoscore_data.adjustments.origins_of_ingredients.warning == "origins_are_100_percent_unknown" %] + "evaluation": "unknown", + "title_element": { + "title": "[% lang('ecoscore_origins_of_ingredients') %]", + "subtitle": "[% lang('ecoscore_origins_of_ingredients_missing_information') %]", + "icon_color_from_evaluation": true, + "icon_url": "[% static_subdomain %]/images/icons/dist/public.svg", + }, + "elements": [ + { + "element_type": "text", + "text_element": { + "type": "warning", + "html": ` + [% lang('ecoscore_ingredients_not_indicated') %]

+ [% lang('ecoscore_please_add_the_ingredients') %]

+ [% lang('ecoscore_platform_prompt_ecoscore_modal') %] + ` + } + }, +[% ELSE %] + [% IF product.ecoscore_data.adjustments.origins_of_ingredients.value <= 0 %] + "evaluation": "bad", + "title_element": { + "subtitle": "[% lang('ecoscore_origins_of_ingredients_impact_high') %]", + [% ELSIF product.ecoscore_data.adjustments.origins_of_ingredients.value <= 15 %] + "evaluation": "average", + "title_element": { + "subtitle": "[% lang('ecoscore_origins_of_ingredients_impact_medium') %]", + [% ELSE %] + "evaluation": "good", + "title_element": { + "subtitle": "[% lang('ecoscore_origins_of_ingredients_impact_low') %]", + [% END %] + "title": "[% lang('ecoscore_origins_of_ingredients') %]", + "icon_color_from_evaluation": true, + "icon_url": "[% static_subdomain %]/images/icons/dist/public.svg", + }, + "elements": [ + { + "element_type": "table", + "table_element": { + "id": "ecoscore_origins_of_ingredients_table", + "table_type": "percents", + "title": "[% lang('ecoscore_origins_of_ingredients') %]", + "columns": [ + { + "text": "[% lang('origin') %]", + "type": "text", + }, + { + "text": "[% lang('percent_of_ingredients') %]", + "type": "percent", + }, + { + "text": "[% lang('ecoscore_impact') %]", + "type": "text", + } + ], + "rows": [ + [% FOREACH origin IN product.ecoscore_data.adjustments.origins_of_ingredients.aggregated_origins %] + { + "values": [ + { + "text": "[% display_taxonomy_tag("origins",origin.origin) %]", + }, + { + "text": "[% round(origin.percent) %] %", + "percent": [% round(origin.percent) %], + // EPI bonus goes from -5 to 5 with the formula bonus = epi_score / 10 - 5 + // Transportation bonus goes from 0 to 15 with the formula bonus = transportation_score * 0.15 + [% SET score = origin.epi_score / 10 - 5 + origin.transportation_score * 0.15 %] + [% IF score >= 15 %] + "evaluation": "good", + [% ELSIF score <= 0 %] + "evaluation": "bad", + [% ELSE %] + "evaluation": "neutral", + [% END %] + }, + { + [% IF score >= 15 %] + "text": "[% lang('low') FILTER ucfirst %]", + "evaluation": "good", + [% ELSIF score <= 0 %] + "text": "[% lang('high') FILTER ucfirst %]", + "evaluation": "bad", + [% ELSE %] + "text": "[% lang('medium') FILTER ucfirst %]", + "evaluation": "neutral", + [% END %] + } + ] + }, + [% END %] + ] + } + }, +[% END %] + ] +} diff --git a/templates/api/knowledge-panels/environment/packaging_recycling.tt.json b/templates/api/knowledge-panels/environment/packaging_recycling.tt.json index d6efad01f184f..a09b385d73387 100644 --- a/templates/api/knowledge-panels/environment/packaging_recycling.tt.json +++ b/templates/api/knowledge-panels/environment/packaging_recycling.tt.json @@ -1,4 +1,4 @@ -// +// Create a structure so that we can display the packaging components for each recycling type [% SET recycling_types = {} %] [% SET unknown = "en:unknown" %] [% IF product.packagings %] @@ -12,8 +12,6 @@ [% END %] { - "parent_panel_id": "environment_card", - "type" : "score", "level" :"info", "topics": [ "environment" @@ -22,7 +20,7 @@ "evaluation": "unknown", "title_element": { "title": "[% lang('ecoscore_packaging_missing_information') %]", - "icon_url": "[% static_subdomain %]/images/icons/dist/help.svg", + "icon_url": "[% static_subdomain %]/images/icons/dist/packaging.svg", "icon_color_from_evaluation": true, "evaluation": "neutral", }, @@ -42,19 +40,19 @@ "evaluation": "bad", "title_element": { "title": "[% lang('ecoscore_packaging_impact_high') %]", - }, [% ELSIF product.ecoscore_data.adjustments.packaging.value <= -5 %] "evaluation": "average", "title_element": { "title": "[% lang('ecoscore_packaging_impact_medium') %]", - }, [% ELSE %] "evaluation": "good", "title_element": { "title": "[% lang('ecoscore_packaging_impact_low') %]", - }, - [% END %] - "expanded": "yes", + [% END %] + "icon_url": "[% static_subdomain %]/images/icons/dist/packaging.svg", + "icon_color_from_evaluation": true, + }, + "expanded": true, "elements": [ [% FOREACH recycling_type IN ["en:recycle", "en:discard", "en:unknown"] %] [% IF recycling_types.$recycling_type.defined %] @@ -79,7 +77,11 @@ "html": ` [% FOREACH packaging IN product.packagings %] [% IF packaging.recycling == recycling_type OR (recycling_type == "en:unknown" AND NOT packaging.recycling.defined) %] - [% display_taxonomy_tag('packaging_shapes',packaging.shape) %] ([% display_taxonomy_tag('packaging_materials',packaging.material) %])
+ [% display_taxonomy_tag('packaging_shapes',packaging.shape) %] + [% IF packaging.material %] + ([% display_taxonomy_tag('packaging_materials',packaging.material) %]) + [% END %] +
[% END %] [% END %] ` diff --git a/templates/api/knowledge-panels/environment/palm_oil.tt.json b/templates/api/knowledge-panels/environment/palm_oil.tt.json index faafc3faf0d75..83f0a01fff51e 100644 --- a/templates/api/knowledge-panels/environment/palm_oil.tt.json +++ b/templates/api/knowledge-panels/environment/palm_oil.tt.json @@ -1,6 +1,4 @@ { - "parent_panel_id": "environment_card", - "type" : "score", "level" :"info", "topics": [ "environment" @@ -16,7 +14,7 @@ { "element_type": "text", "text_element": { - "text_type": "summary", + "type": "summary", "html": `

[% lang('contains_palm_oil_description') %]

` diff --git a/templates/api/knowledge-panels/root.tt.json b/templates/api/knowledge-panels/root.tt.json new file mode 100644 index 0000000000000..6b05604141057 --- /dev/null +++ b/templates/api/knowledge-panels/root.tt.json @@ -0,0 +1,12 @@ +{ + "type": "root", + "expanded": "true", + "elements": [ + { + "element_type": "panel", + "panel_element": { + "panel_id": "environment_card", + }, + }, + ], +} diff --git a/templates/web/pages/product/product_page.tt.html b/templates/web/pages/product/product_page.tt.html index 388b1a7c09531..0c6c6a4589412 100755 --- a/templates/web/pages/product/product_page.tt.html +++ b/templates/web/pages/product/product_page.tt.html @@ -228,9 +228,9 @@

[% lang('environmental_impact') %]

[% END %] [% IF environment_card_panel %] -

Environment card panel (in development):

- [% environment_card_panel %] -

End of environment card panel

+ + [% environment_card_panel %] + [% END %] [% IF ecoscore_grade %] diff --git a/templates/web/panels/panel.tt.html b/templates/web/panels/panel.tt.html index e1d631c5484bb..d8fbd82e742b1 100644 --- a/templates/web/panels/panel.tt.html +++ b/templates/web/panels/panel.tt.html @@ -6,7 +6,7 @@