diff --git a/cgi/search.pl b/cgi/search.pl index 3d3294167add9..c393ab001e658 100755 --- a/cgi/search.pl +++ b/cgi/search.pl @@ -94,7 +94,8 @@ } my @search_fields - = qw(brands categories packaging labels origins manufacturing_places emb_codes purchase_places stores countries ingredients additives allergens traces nutrition_grades nova_groups languages creator editors states); + = qw(brands categories packaging labels origins manufacturing_places emb_codes purchase_places stores countries + ingredients additives allergens traces nutrition_grades nova_groups ecoscore languages creator editors states); $admin and push @search_fields, "lang"; @@ -109,6 +110,8 @@ allergens => 1, traces => 1, nutrition_grades => 1, + nova_groups => 1, + eco_score => 1, purchase_places => 1, stores => 1, countries => 1, @@ -322,16 +325,28 @@ $axis_labels{$nid} = display_taxonomy_tag($lc, "nutrients", "zz:$nid"); $log->debug("nutriments", {nid => $nid, value => $axis_labels{$nid}}) if $log->is_debug(); } - push @axis_values, "additives_n", "ingredients_n", "known_ingredients_n", "unknown_ingredients_n"; - push @axis_values, "fruits-vegetables-nuts-estimate-from-ingredients"; - push @axis_values, "forest_footprint"; - $axis_labels{additives_n} = lang("number_of_additives"); - $axis_labels{ingredients_n} = lang("ingredients_n_s"); - $axis_labels{known_ingredients_n} = lang("known_ingredients_n_s"); - $axis_labels{unknown_ingredients_n} = lang("unknown_ingredients_n_s"); + + my @other_search_fields = ( + "additives_n", "ingredients_n", "known_ingredients_n", "unknown_ingredients_n", + "fruits-vegetables-nuts-estimate-from-ingredients", + "forest_footprint", "product_quantity", "nova_group", 'ecoscore_score', + ); + + # Add the fields related to packaging + foreach my $material ("all", "en:plastic", "en:glass", "en:metal", "en:paper-or-cardboard", "en:unknown") { + foreach my $subfield ("weight", "weight_100g", "weight_percent") { + push @other_search_fields, "packagings_materials.$material.$subfield"; + } + } + $axis_labels{search_nutriment} = lang("search_nutriment"); $axis_labels{products_n} = lang("number_of_products"); - $axis_labels{forest_footprint} = lang("forest_footprint"); + + foreach my $field (@other_search_fields) { + my ($title, $unit, $unit2, $allow_decimals) = get_search_field_title_and_details($field); + push @axis_values, $field; + $axis_labels{$field} = $title; + } my @sorted_axis_values = ("", sort({lc($axis_labels{$a}) cmp lc($axis_labels{$b})} @axis_values)); @@ -738,13 +753,13 @@ # We want existing values for axis fields foreach my $axis ('x', 'y') { - if ( ($graph_ref->{"axis_$axis"} ne "") - and ($graph_ref->{"axis_$axis"} ne "forest_footprint") - and ($graph_ref->{"axis_$axis"} !~ /_n$/)) - { - (defined $query_ref->{"nutriments." . $graph_ref->{"axis_$axis"} . "_100g"}) - or $query_ref->{"nutriments." . $graph_ref->{"axis_$axis"} . "_100g"} = {}; - $query_ref->{"nutriments." . $graph_ref->{"axis_$axis"} . "_100g"}{'$exists'} = 1; + + if ($graph_ref->{"axis_$axis"} ne "") { + my $field = $graph_ref->{"axis_$axis"}; + # Get the field path components + my @fields = get_search_field_path_components($field); + # Convert to dot notation to get the MongoDB field + $query_ref->{join(".", @fields)} = {'$exists' => 1}; } } diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index 46aac7b8e75d1..6bc6ed536fc2a 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -76,6 +76,8 @@ BEGIN { &display_product_history &display_preferences_api &display_attribute_groups_api + &get_search_field_path_components + &get_search_field_title_and_details &search_and_display_products &search_and_export_products &search_and_graph_products @@ -5802,63 +5804,150 @@ my %nutrition_grades_colors = ( unknown => {r => 128, g => 128, b => 128}, ); -sub display_scatter_plot ($graph_ref, $products_ref) { +# Return the path (list of nodes) to the search field - my @products = @{$products_ref}; - my $count = @products; +# field name from the search form +# it can be: +# - a nutrient id like "saturated-fat" +# - a direct field like ingredients_n +# - an indirect field like packagings_materials.all.weight_100g - my $html = ''; +sub get_search_field_path_components ($field) { + my @fields; + # direct fields + if (($field =~ /_n$/) or ($field eq "product_quantity") or ($field eq "nova_group") or ($field eq "ecoscore_score")) + { + @fields = ($field); + } + # indirect fields separated with the . character + elsif ($field =~ /\./) { + @fields = split(/\./, $field); + } + # forest footprint + elsif ($field eq "forest_footprint") { + @fields = ('forest_footprint_data', 'footprint_per_kg'); + } + # we assume other fields are nutrients ids + else { + @fields = ("nutriments", $field . "_100g"); + } + return @fields; +} + +sub get_search_field_title_and_details ($field) { - my $x_allowDecimals = ''; - my $y_allowDecimals = ''; - my $x_title; - my $y_title; - my $x_unit = ''; - my $y_unit = ''; - my $x_unit2 = ''; - my $y_unit2 = ''; + my ($title, $unit, $unit2, $allow_decimals) = ('', '', '', ''); - if ($graph_ref->{axis_x} eq 'additives_n') { - $x_allowDecimals = "allowDecimals:false,\n"; - $x_title = escape_single_quote(lang("number_of_additives")); + if ($field eq 'additives_n') { + $allow_decimals = "allowDecimals:false,\n"; + $title = escape_single_quote(lang("number_of_additives")); } - elsif ($graph_ref->{axis_x} eq "forest_footprint") { - $x_allowDecimals = "allowDecimals:true,\n"; - $x_title = escape_single_quote(lang($graph_ref->{axis_x})); + elsif ($field eq "forest_footprint") { + $allow_decimals = "allowDecimals:true,\n"; + $title = escape_single_quote(lang($field)); } - elsif ($graph_ref->{axis_x} =~ /ingredients_n/) { - $x_allowDecimals = "allowDecimals:false,\n"; - $x_title = escape_single_quote(lang($graph_ref->{axis_x} . "_s")); + elsif ($field =~ /_n$/) { + $allow_decimals = "allowDecimals:false,\n"; + $title = escape_single_quote(lang($field . "_s")); } - else { - $x_title = display_taxonomy_tag($lc, "nutrients", "zz:" . $graph_ref->{axis_x}); - $x_unit - = " (" - . (get_property("nutrients", "zz:" . $graph_ref->{axis_x}, "unit:en") // 'g') . " " - . lang("nutrition_data_per_100g") . ")"; - $x_unit =~ s/\ / /g; - $x_unit2 = display_taxonomy_tag($lc, "nutrients", "zz:" . $graph_ref->{axis_x}); + elsif ($field eq "product_quantity") { + $allow_decimals = "allowDecimals:false,\n"; + $title = escape_single_quote(lang("quantity")); + $unit = ' (g)'; + $unit2 = 'g'; } - if ($graph_ref->{axis_y} eq 'additives_n') { - $y_allowDecimals = "allowDecimals:false,\n"; - $y_title = escape_single_quote(lang("number_of_additives")); + elsif ($field eq "nova_group") { + $allow_decimals = "allowDecimals:false,\n"; + $title = escape_single_quote(lang("nova_groups_s")); } - elsif ($graph_ref->{axis_y} eq "forest_footprint") { - $y_allowDecimals = "allowDecimals:true,\n"; - $y_title = escape_single_quote(lang($graph_ref->{axis_y})); + elsif ($field eq "ecoscore_score") { + $allow_decimals = "allowDecimals:false,\n"; + $title = escape_single_quote(lang("ecoscore_score")); } - elsif ($graph_ref->{axis_y} =~ /ingredients_n/) { - $y_allowDecimals = "allowDecimals:false,\n"; - $y_title = escape_single_quote(lang($graph_ref->{axis_y} . "_s")); + elsif ($field =~ /^packagings_materials\.([^.]+)\.([^.]+)$/) { + my $material = $1; + my $subfield = $2; + $title = lang("packaging") . " - "; + if ($material eq "all") { + $title .= lang("packagings_materials_all"); + } + else { + $title .= display_taxonomy_tag($lc, "packaging_materials", $material); + } + $title .= ' - ' . lang($subfield); + if ($subfield =~ /_percent$/) { + $unit = ' %'; + $unit2 = '%'; + } + elsif ($subfield =~ /_100g$/) { + $unit = ' (g/100g)'; + $unit2 = 'g/100g'; + } + else { + $unit = ' (g)'; + $unit2 = 'g'; + } } else { - $y_title = display_taxonomy_tag($lc, "nutrients", "zz:" . $graph_ref->{axis_y}); - $y_unit + $title = display_taxonomy_tag($lc, "nutrients", "zz:" . $field); + $unit2 = $title; # displayed in the tooltip + $unit = " (" - . (get_property("nutrients", "zz:" . $graph_ref->{axis_y}, "unit:en") // 'g') . " " + . (get_property("nutrients", "zz:" . $field, "unit:en") // 'g') . " " . lang("nutrition_data_per_100g") . ")"; - $y_unit =~ s/\ / /g; - $y_unit2 = display_taxonomy_tag($lc, "nutrients", "zz:" . $graph_ref->{axis_y}); + $unit =~ s/\ / /g; + } + + return ($title, $unit, $unit2, $allow_decimals); +} + +=head2 display_scatter_plot ($graph_ref, $products_ref) + +Called by search_and_graph_products() to display a scatter plot of products on 2 axis + +=head3 Arguments + +=head4 $graph_ref + +Options for the graph, set by /cgi/search.pl + +=head4 $products_ref + +List of search results from search_and_graph_products() + +=cut + +sub display_scatter_plot ($graph_ref, $products_ref) { + + my @products = @{$products_ref}; + my $count = scalar @products; + + my $html = ''; + + my %axis_details = (); + my %min = (); # Minimum for the axis, 0 except -15 for Nutri-Score score + my %fields = (); # fields path components for each axis, to use with deep_get() + + foreach my $axis ("x", "y") { + # Set the titles and details of each axis + my $field = $graph_ref->{"axis_" . $axis}; + my ($title, $unit, $unit2, $allow_decimals) = get_search_field_title_and_details($field); + $axis_details{$axis} = { + title => $title, + unit => $unit, + unit2 => $unit2, + allow_decimals => $allow_decimals, + }; + + # Set the minimum value for the axis (0 in most cases, except for Nutri-Score) + $min{$axis} = 0; + + if ($field =~ /^nutrition-score/) { + $min{$axis} = -15; + } + + # Store the field path components + $fields{$field} = [get_search_field_path_components($field)]; } my %nutriments = (); @@ -5867,122 +5956,100 @@ sub display_scatter_plot ($graph_ref, $products_ref) { my %series = (); my %series_n = (); - my %min = (); # Minimum for the axis, 0 except -15 for Nutri-Score score foreach my $product_ref (@products) { - # Keep only products that have known values for both x and y + # Gather the data for the 2 axis - if ( - ( - ( - (($graph_ref->{axis_x} eq 'additives_n') or ($graph_ref->{axis_x} =~ /ingredients_n$/)) - and (defined $product_ref->{$graph_ref->{axis_x}}) - ) - or (($graph_ref->{axis_x} eq 'forest_footprint') and (defined $product_ref->{forest_footprint_data})) - or (defined $product_ref->{nutriments}{$graph_ref->{axis_x} . "_100g"}) - and ($product_ref->{nutriments}{$graph_ref->{axis_x} . "_100g"} ne '') - ) - and ( - ( - (($graph_ref->{axis_y} eq 'additives_n') or ($graph_ref->{axis_y} =~ /ingredients_n$/)) - and (defined $product_ref->{$graph_ref->{axis_y}}) - ) - or (($graph_ref->{axis_y} eq 'forest_footprint') and (defined $product_ref->{forest_footprint_data})) - or (defined $product_ref->{nutriments}{$graph_ref->{axis_y} . "_100g"}) - and ($product_ref->{nutriments}{$graph_ref->{axis_y} . "_100g"} ne '') - ) - ) - { + my %data; - my $url = $formatted_subdomain . product_url($product_ref->{code}); + foreach my $axis ('x', 'y') { - # Identify the series id - my $seriesid = 0; - my $s = 1000000; + my $field = $graph_ref->{"axis_" . $axis}; + my $value = deep_get($product_ref, @{$fields{$field}}); - # default, organic, fairtrade, with_sweeteners - # order: organic, organic+fairtrade, organic+fairtrade+sweeteners, organic+sweeteners, fairtrade, fairtrade + sweeteners - # + # For nutrients except energy-kcal, convert to the default nutrient unit + if ((defined $value) and ($fields{$field}[0] eq "nutriments") and ($field !~ /energy-kcal/)) { + $value = g_to_unit($value, (get_property("nutrients", "zz:$field", "unit:en") // 'g')); + } - # Colors for nutrition grades - if ($graph_ref->{"series_nutrition_grades"}) { - if (defined $product_ref->{"nutrition_grade_fr"}) { - $seriesid = $product_ref->{"nutrition_grade_fr"}; - } - else { - $seriesid = 'unknown'; - } + if (defined $value) { + $value = $value + 0; # Make sure the value is a number } - else { - # Colors for labels and labels combinations - foreach my $series (@search_series) { - # Label? - if ($graph_ref->{"series_$series"}) { - if (defined lang("search_series_${series}_label")) { - if (has_tag($product_ref, "labels", 'en:' . lc($Lang{"search_series_${series}_label"}{en}))) - { - $seriesid += $s; - } - else { - } - } - if ($product_ref->{$series}) { + $data{$axis} = $value; + } + + # Keep only products that have known values for both x and y + if ((not defined $data{x}) or (not defined $data{y})) { + $log->debug("Skipping product with unknown values ", {data => \%data}) if $log->is_debug(); + next; + } + + # Add values to stats, and set min axis + foreach my $axis ('x', 'y') { + my $field = $graph_ref->{"axis_" . $axis}; + add_product_nutriment_to_stats(\%nutriments, $field, $data{$axis}); + } + + # Identify the series id + my $seriesid = 0; + # series value, we start high for first series + # and second series value will have s / 10, etc. + my $s = 1000000; + + # default, organic, fairtrade, with_sweeteners + # order: organic, organic+fairtrade, organic+fairtrade+sweeteners, organic+sweeteners, fairtrade, fairtrade + sweeteners + # + + # Colors for nutrition grades + if ($graph_ref->{"series_nutrition_grades"}) { + if (defined $product_ref->{"nutrition_grade_fr"}) { + $seriesid = $product_ref->{"nutrition_grade_fr"}; + } + else { + $seriesid = 'unknown'; + } + } + else { + # Colors for labels and labels combinations + foreach my $series (@search_series) { + # Label? + if ($graph_ref->{"series_$series"}) { + if (defined lang("search_series_${series}_label")) { + if (has_tag($product_ref, "labels", 'en:' . lc($Lang{"search_series_${series}_label"}{en}))) { $seriesid += $s; } + else { + } } - if (($series eq 'default') and ($seriesid == 0)) { + if ($product_ref->{$series}) { $seriesid += $s; } - $s = $s / 10; } - } - defined $series{$seriesid} or $series{$seriesid} = ''; - - # print STDERR "Display::search_and_graph_products: i: $i - axis_x: $graph_ref->{axis_x} - axis_y: $graph_ref->{axis_y}\n"; - - my %data; - - foreach my $axis ('x', 'y') { - my $nid = $graph_ref->{"axis_" . $axis}; + if (($series eq 'default') and ($seriesid == 0)) { + $seriesid += $s; + } + $s = $s / 10; + } + } - $min{$axis} = 0; + $series{$seriesid} = $series{$seriesid} // ''; - # number of ingredients, additives etc. (ingredients_n) - if ($nid =~ /_n$/) { - $data{$axis} = $product_ref->{$nid}; - } - elsif ($nid eq "forest_footprint") { - $data{$axis} = $product_ref->{forest_footprint_data}{footprint_per_kg}; - } - # energy-kcal is already in kcal - elsif ($nid eq 'energy-kcal') { - $data{$axis} = $product_ref->{nutriments}{"${nid}_100g"}; - } - elsif ($nid =~ /^nutrition-score/) { - $data{$axis} = $product_ref->{nutriments}{"${nid}_100g"}; - $min{$axis} = -15; - } - else { - $data{$axis} = g_to_unit($product_ref->{nutriments}{"${nid}_100g"}, - (get_property("nutrients", "zz:$nid", "unit:en") // 'g')); - } + $data{product_name} = $product_ref->{product_name}; + $data{url} = $formatted_subdomain . product_url($product_ref->{code}); + $data{img} = display_image_thumb($product_ref, 'front'); - add_product_nutriment_to_stats(\%nutriments, $nid, $product_ref->{nutriments}{"${nid}_100g"}); - } - $data{product_name} = $product_ref->{product_name}; - $data{url} = $url; - $data{img} = display_image_thumb($product_ref, 'front'); + # create data entry for series + defined $series{$seriesid} or $series{$seriesid} = ''; + $series{$seriesid} .= JSON::PP->new->encode(\%data) . ','; + # count entries / series + defined $series_n{$seriesid} or $series_n{$seriesid} = 0; + $series_n{$seriesid}++; + $i++; - defined $series{$seriesid} or $series{$seriesid} = ''; - $series{$seriesid} .= JSON::PP->new->encode(\%data) . ','; - defined $series_n{$seriesid} or $series_n{$seriesid} = 0; - $series_n{$seriesid}++; - $i++; - } } my $series_data = ''; @@ -6102,21 +6169,21 @@ JS text: '$Lang{data_source}{$lc}$sep: $formatted_subdomain' }, xAxis: { - $x_allowDecimals + $axis_details{x}{allow_decimals} min:$min{x}, title: { enabled: true, - text: '${x_title}${x_unit}' + text: '$axis_details{x}{title}$axis_details{x}{unit}' }, startOnTick: true, endOnTick: true, showLastLabel: true }, yAxis: { - $y_allowDecimals + $axis_details{y}{allow_decimals} min:$min{y}, title: { - text: '${y_title}${y_unit}' + text: '$axis_details{y}{title}$axis_details{y}{unit}' } }, tooltip: { @@ -6127,8 +6194,8 @@ JS return '' + this.point.product_name + '
' + this.point.img + '

' + '$Lang{nutrition_data_per_100g}{$lc} :' - + '
$x_title$sep: '+ this.x + ' $x_unit2' - + '
$y_title$sep: ' + this.y + ' $y_unit2'; + + '
$axis_details{x}{title}$sep: '+ this.x + ' $axis_details{x}{unit2}' + + '
$axis_details{y}{title}$sep: ' + this.y + ' $axis_details{y}{unit2}'; } }, @@ -6190,6 +6257,22 @@ HTML } +=head2 display_histogram ($graph_ref, $products_ref) + +Called by search_and_graph_products() to display an histogram of products on 1 axis + +=head3 Arguments + +=head4 $graph_ref + +Options for the graph, set by /cgi/search.pl + +=head4 $products_ref + +List of search results from search_and_graph_products() + +=cut + sub display_histogram ($graph_ref, $products_ref) { my @products = @{$products_ref}; @@ -6197,41 +6280,34 @@ sub display_histogram ($graph_ref, $products_ref) { my $html = ''; - my $x_allowDecimals = ''; - my $y_allowDecimals = ''; - my $x_title; - my $y_title; - my $x_unit = ''; - my $y_unit = ''; - my $x_unit2 = ''; - my $y_unit2 = ''; + my %axis_details = (); + my %min = (); # Minimum for the axis, 0 except -15 for Nutri-Score score - if ($graph_ref->{axis_x} eq 'additives_n') { - $x_allowDecimals = "allowDecimals:false,\n"; - $x_title = escape_single_quote(lang("number_of_additives")); - } - elsif ($graph_ref->{axis_x} eq "forest_footprint") { - $x_allowDecimals = "allowDecimals:true,\n"; - $x_title = escape_single_quote(lang($graph_ref->{axis_x})); - } - elsif ($graph_ref->{axis_x} =~ /ingredients_n$/) { - $x_allowDecimals = "allowDecimals:false,\n"; - $x_title = escape_single_quote(lang($graph_ref->{axis_x} . "_s")); - } - else { - $x_title = display_taxonomy_tag($lc, "nutrients", "zz:" . $graph_ref->{axis_x}); - $x_unit - = " (" - . (get_property("nutrients", "zz:" . $graph_ref->{axis_x}, "unit:en") // 'g') . " " - . lang("nutrition_data_per_100g") . ")"; - $x_unit =~ s/\ / /g; - $x_unit2 = (get_property("nutrients", "zz:" . $graph_ref->{axis_x}, "unit:en") // 'g'); - } + foreach my $axis ("x") { + # Set the titles and details of each axis + my $field = $graph_ref->{"axis_" . $axis}; + my ($title, $unit, $unit2, $allow_decimals) = get_search_field_title_and_details($field); + $axis_details{$axis} = { + title => $title, + unit => $unit, + unit2 => $unit2, + allow_decimals => $allow_decimals, + }; - $y_allowDecimals = "allowDecimals:false,\n"; - $y_title = escape_single_quote(lang("number_of_products")); + # Set the minimum value for the axis (0 in most cases, except for Nutri-Score) + $min{$axis} = 0; + + if ($field =~ /^nutrition-score/) { + $min{$axis} = -15; + } + } - my $nid = $graph_ref->{"axis_x"}; + $axis_details{"y"} = { + title => escape_single_quote(lang("number_of_products")), + allow_decimals => "allowDecimals:false,\n", + unit => '', + unit2 => '', + }; my $i = 0; @@ -6242,92 +6318,71 @@ sub display_histogram ($graph_ref, $products_ref) { my $min = 10000000000000; my $max = -10000000000000; + my $field = $graph_ref->{"axis_x"}; + my @fields = get_search_field_path_components($field); + foreach my $product_ref (@products) { - # Keep only products that have known values for x + my $value = deep_get($product_ref, @fields); - if ( - ( - ( - (($graph_ref->{axis_x} eq 'additives_n') or ($graph_ref->{axis_x} =~ /ingredients_n$/)) - and (defined $product_ref->{$graph_ref->{axis_x}}) - ) - or (($graph_ref->{axis_x} eq 'forest_footprint') and (defined $product_ref->{forest_footprint_data})) - or (defined $product_ref->{nutriments}{$graph_ref->{axis_x} . "_100g"}) - and ($product_ref->{nutriments}{$graph_ref->{axis_x} . "_100g"} ne '') - ) - ) - { + # For nutrients except energy-kcal, convert to the default nutrient unit + if ((defined $value) and ($fields[0] eq "nutriments") and ($field !~ /energy-kcal/)) { + $value = g_to_unit($value, (get_property("nutrients", "zz:$field", "unit:en") // 'g')); + } - # Identify the series id - my $seriesid = 0; - my $s = 1000000; + # Keep only products that have known values for both x and y + if (not defined $value) { + next; + } - # default, organic, fairtrade, with_sweeteners - # order: organic, organic+fairtrade, organic+fairtrade+sweeteners, organic+sweeteners, fairtrade, fairtrade + sweeteners - # + $value = $value + 0; # Make sure the value is a number - foreach my $series (@search_series) { - # Label? - if ($graph_ref->{"series_$series"}) { - if (defined lang("search_series_${series}_label")) { - if (has_tag($product_ref, "labels", 'en:' . lc($Lang{"search_series_${series}_label"}{en}))) { - $seriesid += $s; - } - else { - } - } + if ($value < $min) { + $min = $value; + } + if ($value > $max) { + $max = $value; + } - if ($product_ref->{$series}) { + # Identify the series id + my $seriesid = 0; + my $s = 1000000; + + # default, organic, fairtrade, with_sweeteners + # order: organic, organic+fairtrade, organic+fairtrade+sweeteners, organic+sweeteners, fairtrade, fairtrade + sweeteners + # + + foreach my $series (@search_series) { + # Label? + if ($graph_ref->{"series_$series"}) { + if (defined lang("search_series_${series}_label")) { + if (has_tag($product_ref, "labels", 'en:' . lc($Lang{"search_series_${series}_label"}{en}))) { $seriesid += $s; } + else { + } } - if (($series eq 'default') and ($seriesid == 0)) { + if ($product_ref->{$series}) { $seriesid += $s; } - $s = $s / 10; } - # print STDERR "Display::search_and_graph_products: i: $i - axis_x: $graph_ref->{axis_x} - axis_y: $graph_ref->{axis_y}\n"; - - my $value = 0; - - # number of ingredients, additives etc. (ingredients_n) - if ($nid =~ /_n$/) { - $value = $product_ref->{$nid}; - } - elsif ($nid eq "forest_footprint") { - $value = $product_ref->{forest_footprint_data}{footprint_per_kg}; - } - # energy-kcal is already in kcal - elsif ($nid eq 'energy-kcal') { - $value = $product_ref->{nutriments}{"${nid}_100g"}; - } - elsif ($nid =~ /^nutrition-score/) { - $value = $product_ref->{nutriments}{"${nid}_100g"}; - } - else { - $value = g_to_unit($product_ref->{nutriments}{"${nid}_100g"}, - (get_property("nutrients", "zz:$nid", "unit:en") // 'g')); + if (($series eq 'default') and ($seriesid == 0)) { + $seriesid += $s; } + $s = $s / 10; + } - if ($value < $min) { - $min = $value; - } - if ($value > $max) { - $max = $value; - } + push @all_values, $value; - push @all_values, $value; + defined $series{$seriesid} or $series{$seriesid} = []; + push @{$series{$seriesid}}, $value; - defined $series{$seriesid} or $series{$seriesid} = []; - push @{$series{$seriesid}}, $value; + defined $series_n{$seriesid} or $series_n{$seriesid} = 0; + $series_n{$seriesid}++; + $i++; - defined $series_n{$seriesid} or $series_n{$seriesid} = 0; - $series_n{$seriesid}++; - $i++; - } } # define intervals @@ -6349,7 +6404,7 @@ sub display_histogram ($graph_ref, $products_ref) { push @intervals, [$min, $max, "$min"]; } else { - if (($nid =~ /_n$/) or ($nid =~ /^nutrition-score/)) { + if (($field =~ /_n$/) or ($field =~ /^nutrition-score/)) { $interval = 1; $intervals = 0; for (my $j = $min; $j <= $max; $j++) { @@ -6486,7 +6541,7 @@ JS xAxis: { title: { enabled: true, - text: '${x_title}${x_unit}' + text: '$axis_details{x}{title}$axis_details{x}{unit}' }, categories: [ $categories @@ -6494,10 +6549,10 @@ JS }, yAxis: { - $y_allowDecimals + $axis_details{y}{allow_decimals} min:0, title: { - text: '${y_title}${y_unit}' + text: '$axis_details{y}{title}' }, stackLabels: { enabled: true, @@ -6508,14 +6563,14 @@ JS } }, tooltip: { - headerFormat: '${x_title} {point.key}
${x_unit}', + headerFormat: '$axis_details{x}{title} {point.key}
$axis_details{x}{unit}
', pointFormat: '' + '', footerFormat: '
{series.name}: {point.y}
Total: {point.total}', shared: true, useHTML: true, formatter: function() { - var points=''; + var points='
${x_title} ' + this.x + '
${x_unit}
'; //loop each point in this.points \$.each(this.points,function(i,point){ points+='' @@ -6607,18 +6662,13 @@ sub search_and_graph_products ($request_ref, $query_ref, $graph_ref) { } } + # Add fields for the axis foreach my $axis ('x', 'y') { - if ($graph_ref->{"axis_$axis"} ne "products_n") { - if ($graph_ref->{"axis_$axis"} eq "forest_footprint") { - $fields_ref->{"forest_footprint_data.footprint_per_kg"} = 1; - } - elsif ($graph_ref->{"axis_$axis"} =~ /_n$/) { - $fields_ref->{$graph_ref->{"axis_$axis"}} = 1; - } - else { - $fields_ref->{"nutriments." . $graph_ref->{"axis_$axis"} . "_100g"} = 1; - } - } + my $field = $graph_ref->{"axis_$axis"}; + # Get the field path components + my @fields = get_search_field_path_components($field); + # Convert to dot notation to get the MongoDB field + $fields_ref->{join(".", @fields)} = 1; } if ($graph_ref->{"series_nutrition_grades"}) { diff --git a/po/common/common.pot b/po/common/common.pot index b8ea301eee0b4..f192cf5de7cfe 100644 --- a/po/common/common.pot +++ b/po/common/common.pot @@ -6591,3 +6591,26 @@ msgctxt "relative_to_all_products" msgid "relative to all products" msgstr "relative to all products" +msgctxt "packagings_n_p" +msgid "Numbers of packaging components" +msgstr "Numbers of packaging components" + +msgctxt "packagings_n_s" +msgid "Number of packaging components" +msgstr "Number of packaging components" + +msgctxt "packagings_materials_all" +msgid "All materials" +msgstr "All materials" + +msgctxt "weight" +msgid "Weight" +msgstr "Weight" + +msgctxt "weight_100g" +msgid "Weight per 100g of product" +msgstr "Weight per 100g of product" + +msgctxt "weight_percent" +msgid "Weight percent" +msgstr "Weight percent" \ No newline at end of file diff --git a/po/common/en.po b/po/common/en.po index 85dcb121ee9c5..fea79ee0e10b9 100644 --- a/po/common/en.po +++ b/po/common/en.po @@ -6615,3 +6615,26 @@ msgctxt "relative_to_all_products" msgid "relative to all products" msgstr "relative to all products" +msgctxt "packagings_n_p" +msgid "Numbers of packaging components" +msgstr "Numbers of packaging components" + +msgctxt "packagings_n_s" +msgid "Number of packaging components" +msgstr "Number of packaging components" + +msgctxt "packagings_materials_all" +msgid "All materials" +msgstr "All materials" + +msgctxt "weight" +msgid "Weight" +msgstr "Weight" + +msgctxt "weight_100g" +msgid "Weight per 100g of product" +msgstr "Weight per 100g of product" + +msgctxt "weight_percent" +msgid "Weight percent" +msgstr "Weight percent" \ No newline at end of file
$axis_details{x}{title} ' + this.x + '
$axis_details{x}{unit}
'+point.series.name+':