Skip to content

Commit

Permalink
feat: extend ingredients analysis panels with details and call for he…
Browse files Browse the repository at this point in the history
…lp (#6905)

* fix ingredients icon

* replace nutrition balance icon with existing balance icon

* feat: extend ingredients analysis panels with details and call for help - fixes #6904

* feat: extend ingredients analysis panels with details and call for help - fixes #6904

* feat: extend ingredients analysis panels with details and call for help - fixes #6904

* suggestions from code review

* keep track of unknown ingredients even if analysis status is known #6904
  • Loading branch information
stephanegigandet authored Jun 20, 2022
1 parent 3c12065 commit 8690daf
Show file tree
Hide file tree
Showing 22 changed files with 563 additions and 61 deletions.
2 changes: 1 addition & 1 deletion icons/ingredients.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion icons/nutrition.svg

This file was deleted.

48 changes: 48 additions & 0 deletions icons/off-magnifying-glass.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 56 additions & 26 deletions lib/ProductOpener/Display.pm
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ BEGIN
&data_to_display_nutriscore_and_nutrient_levels
&data_to_display_ingredients_analysis
&data_to_display_ingredients_analysis_details
&count_products
&add_params_to_query
Expand Down Expand Up @@ -10698,7 +10699,7 @@ sub display_nested_list_of_ingredients($$$) {
my $ingredients_exists = exists_taxonomy_tag("ingredients", $ingredient_ref->{id});
my $class = '';
if (not $ingredients_exists) {
$class = ' class="unknown_ingredient"';
$class = ' class="text_info unknown_ingredient"';
}

${$ingredients_text_ref} .= "<span$class>" . $ingredient_ref->{text} . "</span>";
Expand Down Expand Up @@ -10780,26 +10781,34 @@ sub display_list_of_specific_ingredients($) {
}


=head2 display_ingredients_analysis_details ( $product_ref )
=head2 data_to_display_ingredients_analysis_details ( $product_ref )
Generates HTML code with information on how the ingredient list was parsed and mapped to the ingredients taxonomy.
Generates a data structure to display the details of ingredients analysis.
The resulting data structure can be passed to a template to generate HTML or the JSON data for a knowledge panel.
=head3 Arguments
=head4 Product reference $product_ref
=head3 Return values
Reference to a data structure with needed data to display.
=cut

sub display_ingredients_analysis_details($) {
sub data_to_display_ingredients_analysis_details($) {

my $product_ref = shift;

# Do not display ingredients analysis details when we don't have ingredients

if ((not defined $product_ref->{ingredients})
or (scalar @{$product_ref->{ingredients}} == 0)) {
return "";
return undef;
}

my $template_data_ref = {
lang => \&lang,
};
my $result_data_ref = {};

my $ingredients_text = "";
my $ingredients_list = "";
Expand All @@ -10808,27 +10817,35 @@ sub display_ingredients_analysis_details($) {

my $specific_ingredients = display_list_of_specific_ingredients($product_ref);

my $unknown_ingredients_html = '';
my $unknown_ingredients_help_html = '';

if (($ingredients_text . $specific_ingredients) =~ /unknown_ingredient/) {
$template_data_ref->{unknown_ingredients} = 1;
$result_data_ref->{unknown_ingredients} = 1;
}

$styles .= <<CSS
.unknown_ingredient {
background-color:cyan;
$result_data_ref->{ingredients_text} = $ingredients_text;
$result_data_ref->{ingredients_list} = $ingredients_list;
$result_data_ref->{specific_ingredients} = $specific_ingredients;

return $result_data_ref;
}
CSS
;
}

$template_data_ref->{ingredients_text} = $ingredients_text;
$template_data_ref->{ingredients_list} = $ingredients_list;
$template_data_ref->{specific_ingredients} = $specific_ingredients;

my $html;
=head2 display_ingredients_analysis_details ( $product_ref )
process_template('web/pages/product/includes/ingredients_analysis_details.tt.html', $template_data_ref, \$html) || return "template error: " . $tt->error();
Generates HTML code with information on how the ingredient list was parsed and mapped to the ingredients taxonomy.
=cut

sub display_ingredients_analysis_details($) {

my $product_ref = shift;

my $html = "";

my $template_data_ref = data_to_display_ingredients_analysis_details($product_ref);

if (defined $template_data_ref) {
process_template('web/pages/product/includes/ingredients_analysis_details.tt.html', $template_data_ref, \$html) || return "template error: " . $tt->error();
}

return $html;
}
Expand Down Expand Up @@ -10868,10 +10885,18 @@ sub data_to_display_ingredients_analysis($) {

my $evaluation;
my $icon = "";
# $ingredients_analysis_tag is a tag like "en:palm-oil-free", "en:vegan-status-unknown", or "en:non-vegetarian"
# we will derive from it the associated property e.g. "palm_oil", "vegan", "vegetarian"
# and the tag corresponding to unknown status for the property e.g. "en:palm-oil-content-unknown", "en:vegan-status-unknown"
# so that we can display unknown ingredients for the property even if the status is different than unknown
my $property;
my $property_unknown_tag;

if ($ingredients_analysis_tag =~ /palm/) {

# Icon
# Set property and icon
$property = "palm_oil_free";
$property_unknown_tag = "en:palm-oil-content-unknown";
$icon = "palm-oil";

# Evaluation
Expand All @@ -10890,13 +10915,16 @@ sub data_to_display_ingredients_analysis($) {
}
else {

# Icon
# Set property (e.g. vegan for the tag vegan or non-vegan) and icon
if ($ingredients_analysis_tag =~ /vegan/) {
$property = "vegan";
$icon = "leaf";
}
elsif ($ingredients_analysis_tag =~ /vegetarian/) {
$property = "vegetarian";
$icon = "vegetarian";
}
$property_unknown_tag = "en:" . $property . "-status-unknown";

# Evaluation
if ($ingredients_analysis_tag =~ /^en:non-/) {
Expand Down Expand Up @@ -10927,7 +10955,9 @@ sub data_to_display_ingredients_analysis($) {
}

push @{$result_data_ref->{ingredients_analysis_tags}}, {
property => $ingredients_analysis_tag,
tag => $ingredients_analysis_tag,
property => $property,
property_unknown_tag => $property_unknown_tag,
evaluation => $evaluation,
icon => $icon,
title => display_taxonomy_tag($lc, "ingredients_analysis", $ingredients_analysis_tag),
Expand Down
28 changes: 20 additions & 8 deletions lib/ProductOpener/Ingredients.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2736,6 +2736,11 @@ sub analyze_ingredients($) {
delete $product_ref->{ingredients_analysis_tags};

my @properties = ("from_palm_oil", "vegan", "vegetarian");
my %properties_unknown_tags = (
"from_palm_oil" => "en:palm-oil-content-unknown",
"vegan" => "en:vegan-status-unknown",
"vegetarian" => "en:vegetarian-status-unknown",
);

# Structure to store the result of the ingredient analysis for each property
my $ingredients_analysis_properties_ref = {};
Expand Down Expand Up @@ -2847,10 +2852,10 @@ sub analyze_ingredients($) {
$property_value = "en:" . $from_what_with_dashes . "-free"; # en:palm-oil-free
}
else {
$property_value = "en:" . $from_what_with_dashes . "-content-unknown"; # en:palm-oil-content-unknown
$property_value = $properties_unknown_tags{$property}; # en:palm-oil-content-unknown
}
# In all cases, keep track of the unknown ingredients
$ingredients_analysis_ref->{"en:" . $from_what_with_dashes . "-content-unknown"} = $values{unknown_ingredients};
$ingredients_analysis_ref->{$properties_unknown_tags{$property}} = $values{unknown_ingredients};
}
else {
# no yes, maybe or unknown ingredients
Expand All @@ -2869,10 +2874,10 @@ sub analyze_ingredients($) {
$property_value = "en:non-" . $property ; # en:non-vegetarian
$ingredients_analysis_ref->{$property_value} = $values{no};
}
elsif (defined $values{undef}) {
elsif (defined $values{"undef"}) {
# Some ingredients were not recognized or we do not have a property value for them
$property_value = "en:" . $property . "-status-unknown"; # en:vegetarian-status-unknown
$ingredients_analysis_ref->{$property_value} = $values{undef};
$property_value = $properties_unknown_tags{$property}; # en:vegetarian-status-unknown
$ingredients_analysis_ref->{$property_value} = $values{"undef"};
}
elsif (defined $values{maybe}) {
# One maybe ingredient -> maybe for the whole product
Expand All @@ -2883,6 +2888,12 @@ sub analyze_ingredients($) {
# all ingredients known and with a value, no no or maybe value -> yes
$property_value = "en:" . $property ; # en:vegetarian
}

# In all cases, keep track of unknown ingredients so that we can display unknown ingredients
# even if some ingredients also triggered non-vegan or non-vegetarian
if (defined $values{"undef"}) {
$ingredients_analysis_ref->{$properties_unknown_tags{$property}} = $values{"undef"};
}
}

$property_value =~ s/_/-/g;
Expand Down Expand Up @@ -2928,9 +2939,10 @@ sub analyze_ingredients($) {
if (defined $ingredients_analysis_ref->{$property_value}) {
$product_ref->{ingredients_analysis}{$property_value} = $ingredients_analysis_ref->{$property_value};
}
# for palm-oil-free products, we can have a fraction of ingredients that have palm-oil-content-unknown
elsif (($property_value =~ /-free$/) and (defined $ingredients_analysis_ref->{$` . '-content-unknown'})) {
$product_ref->{ingredients_analysis}{$` . '-content-unknown'} = $ingredients_analysis_ref->{$` . '-content-unknown'};

# Also store the list of ingredients that are not recognized
if (defined $ingredients_analysis_ref->{$properties_unknown_tags{$property}}) {
$product_ref->{ingredients_analysis}{$properties_unknown_tags{$property}} = $ingredients_analysis_ref->{$properties_unknown_tags{$property}};
}
}
}
Expand Down
22 changes: 21 additions & 1 deletion lib/ProductOpener/KnowledgePanels.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1156,13 +1156,33 @@ sub create_ingredients_analysis_panel($$$) {

$log->debug("create ingredients analysis panel", { code => $product_ref->{code} }) if $log->is_debug();

# First create an ingredients analysis details sub-panel
# It will be included in the ingredients analysis panel

my $ingredients_analysis_details_data_ref = data_to_display_ingredients_analysis_details($product_ref);

# When we don't have ingredients, we don't display the ingredients analysis details
if (defined $ingredients_analysis_details_data_ref) {
create_panel_from_json_template("ingredients_analysis_details", "api/knowledge-panels/health/ingredients/ingredients_analysis_details.tt.json",
$ingredients_analysis_details_data_ref, $product_ref , $target_lc, $target_cc);

# If we have some unrecognized ingredients, create a call for help panel that will be displayed in the ingredients analysis details panel
# + the panels specific to each property (vegan, vegetarian, palm oil free)
if ($ingredients_analysis_details_data_ref->{unknown_ingredients}) {
create_panel_from_json_template("ingredients_analysis_help", "api/knowledge-panels/health/ingredients/ingredients_analysis_help.tt.json",
{}, $product_ref , $target_lc, $target_cc);
}
}

# Create the ingredients analysis panel

my $ingredients_analysis_data_ref = data_to_display_ingredients_analysis($product_ref);

if (defined $ingredients_analysis_data_ref) {

foreach my $property_panel_data_ref (@{$ingredients_analysis_data_ref->{ingredients_analysis_tags}}) {

my $property_panel_id = "ingredients_analysis_" . $property_panel_data_ref->{property};
my $property_panel_id = "ingredients_analysis_" . $property_panel_data_ref->{tag};

create_panel_from_json_template($property_panel_id, "api/knowledge-panels/health/ingredients/ingredients_analysis_property.tt.json",
$property_panel_data_ref, $product_ref, $target_lc, $target_cc);
Expand Down
29 changes: 29 additions & 0 deletions scss/_off.scss
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,35 @@ a.attribute_card:hover {
color:$grade-unknown-color;
}

.text_good {
background-color:rgba($evaluation-good-color,0.1) !important;
}

.text_average {
background-color:rgba($evaluation-average-color,0.1) !important;
}

.text_bad {
background-color:rgba($evaluation-bad-color,0.1) !important;
}

.text_info {
background-color:$info-color !important;
}

.text_warning {
background-color:$warning-color !important;
color: white;
}

.text_error {
background-color:$alert-color !important;
}





.grade_unknown {
background-color:rgba($grade-unknown-color,0.1) !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@
],
"en:palm-oil-content-unknown" : [
"fr:kangourou"
],
"en:vegan-status-unknown" : [
"fr:kangourou",
"en:brine"
],
"en:vegetarian-status-unknown" : [
"fr:kangourou",
"en:brine"
]
},
"ingredients_analysis_tags" : [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@
"en:non-vegetarian" : [
"fr:viande-de-poulet-traitee-en-salaison",
"en:chicken-meat"
],
"en:vegan-status-unknown" : [
"en:brine"
],
"en:vegetarian-status-unknown" : [
"en:brine"
]
},
"ingredients_analysis_tags" : [
Expand Down
Loading

0 comments on commit 8690daf

Please sign in to comment.