diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index a22257e61f3f1..c32fd06e23a95 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -99,6 +99,7 @@ BEGIN $styles $header $bodyabout + $debug_template $original_subdomain $subdomain @@ -296,6 +297,7 @@ sub init() $header = ''; $bodyabout = ''; $admin = 0; + $debug_template = undef; my $r = shift; @@ -558,7 +560,7 @@ sub analyze_request($) # first check and set parameters in the query string - foreach my $parameter ('api_version', 'blame', 'fields', 'rev', 'json', 'jsonp', 'jqm','xml', 'nocache', 'filter', 'limit', 'translate', 'stats', 'status', 'missing_property') { + foreach my $parameter ('api_version', 'blame', 'fields', 'rev', 'json', 'jsonp', 'jqm','xml', 'nocache', 'filter', 'limit', 'translate', 'stats', 'status', 'missing_property', 'debug_template') { if ($request_ref->{query_string} =~ /(\&|\?)$parameter=([^\&]+)/) { @@ -572,6 +574,11 @@ sub analyze_request($) if ($parameter eq "fields") { $request_ref->{$parameter} =~ s/\%2C/,/g; } + + if ($parameter eq "debug_template") { + # Use a global variable so that we can access it in functions that do not have $request_ref as a parameter + $debug_template = $request_ref->{$parameter}; + } $log->debug("parameter $parameter was set from query string: " . $request_ref->{$parameter}, { parameter => $parameter, value => $request_ref->{$parameter} }) if $log->is_debug(); } @@ -8030,7 +8037,9 @@ HTML if (defined $categories_nutriments_ref) { foreach my $cid (@{$product_ref->{categories_tags}}) { + if ((defined $categories_nutriments_ref->{$cid}) and (defined $categories_nutriments_ref->{$cid}{stats})) { + push @comparisons, { id => $cid, name => display_taxonomy_tag($lc,'categories', $cid), @@ -8749,6 +8758,8 @@ sub display_nutriscore_calculation_details($) { push @{$template_data_ref->{points_groups}}, $points_group_ref; } + # Nutrition Score Calculation Template + my $html; $tt->process('nutriscore_details.tt.html', $template_data_ref, \$html) || return "template error: " . $tt->error(); @@ -9023,12 +9034,36 @@ sub display_nutrition_table($$) { my $comparisons_ref = shift; my $html = ''; - + + # This function populates a data structure that is used by the template to display the nutrition facts table + my $template_data_ref = { + lang => \&lang, + + tables => [ + { + id => "nutrition", + header => { + name => lang('nutrition_data_table'), + columns => [], + }, + rows => [], + }, + { + id => "ecological", + header => { + name => lang('ecological_data_table'), + columns => [], + }, + rows => [], + }, + ], + + carbon_footprint => [], + }; + my @cols; - - my %col_name = ( - ); + my %col_name = (); my @displayed_product_types = (); my %displayed_product_types = (); @@ -9044,7 +9079,6 @@ sub display_nutrition_table($$) { } - foreach my $product_type (@displayed_product_types) { my $nutrition_data_per = "nutrition_data" . "_" . $product_type . "per"; @@ -9105,27 +9139,26 @@ sub display_nutrition_table($$) { '90' => 'stats', 'max' => 'stats', ); - - + # Comparisons with other products, categories, recommended daily values etc. if ((defined $comparisons_ref) and (scalar @$comparisons_ref > 0)) { - $html .= "

" . lang("nutrition_data_comparison_with_categories") . "

"; - - + # Add a comparisons array to the template data structure + + $template_data_ref->{comparisons} = []; my $i = 0; foreach my $comparison_ref (@$comparisons_ref) { - my $colid = "compare_" . $i; + my $col_id = "compare_" . $i; - push @cols, $colid; - $col_class{$colid} = $colid; - $col_name{$colid} = $comparison_ref->{name}; + push @cols, $col_id; + $col_class{$col_id} = $col_id; + $col_name{$col_id} = $comparison_ref->{name}; - $log->debug("displaying nutrition table comparison column", { colid => $colid, id => $comparison_ref->{id}, name => $comparison_ref->{name} }) if $log->is_debug(); + $log->debug("displaying nutrition table comparison column", { colid => $col_id, id => $comparison_ref->{id}, name => $comparison_ref->{name} }) if $log->is_debug(); my $checked = 0; if (defined $comparison_ref->{show}) { @@ -9133,7 +9166,7 @@ sub display_nutrition_table($$) { } else { $styles .= < $comparison_ref->{name} -HTML -; - if (defined $comparison_ref->{count}) { - $html .= " {link}\">(" . $comparison_ref->{count} . " " . lang("products") . ")"; - } - $html .= "
"; + push @{$template_data_ref->{comparisons}}, { + col_id => $col_id, + checked => $checked, + name => $comparison_ref->{name}, + link => $comparison_ref->{link}, + count => $comparison_ref->{count}, + }; $i++; } - $html .= < - - - - - -HTML -; - - $html .= "

→ " . lang("nutrition_data_comparison_with_categories_note") . "

"; - # \$( ".show_comparison" ).button(); @@ -9186,6 +9206,7 @@ HTML } ); + \$(".show_comparison").change(function () { if (\$(this).prop('checked')) { \$("." + \$(this).attr("id")).show(); @@ -9211,11 +9232,10 @@ JS } if ($product_ref->{id} ne 'search') { - - $html .= "
" . "
"; + + # Show checkbox to display/hide stats for the category + + $template_data_ref->{category_stats} = 1; $initjs .= < - - -HTML -. lang("nutrition_data_table") . < -HTML -; - - foreach my $col (@cols) { - my $col_class = ''; - if (defined $col_class{$col}) { - $col_class = ' ' . $col_class{$col} ; + push (@{$template_data_ref->{tables}[$i]{header}{columns}}, { + col_id => $col, + class => $col_class{$col}, + name => $col_name{$col}, + }); } - my $col_name = $col_name{$col}; - - $html .= '' . $col_name . ''; - $empty_cols .= ""; } - - $html .= < - - -HTML -; + + # Tables body columns defined $product_ref->{nutriments} or $product_ref->{nutriments} = {}; @@ -9307,6 +9312,9 @@ HTML push @nutriments, "fruits-vegetables-nuts-estimate-from-ingredients-"; } } + + my $decf = get_decimal_formatter($lc); + my $perf = get_percent_formatter($lc, 0); foreach my $nutriment (@nutriments) { @@ -9316,7 +9324,7 @@ HTML $nid =~ s/-$//g; next if $nid eq 'sodium'; - + my $class = 'main'; my $prefix = ''; @@ -9347,7 +9355,7 @@ HTML } } - my $label = ''; + my $name; # display nutrition score only when the country is matching @@ -9357,31 +9365,20 @@ HTML $shown = 0; } else { - $label = <${prefix}$Nutriments{$nid}{$lang} -HTML -; + $name = '' . $prefix.$Nutriments{$nid}{$lang} . ''; } } - elsif ((exists $Nutriments{$nid}) and (exists $Nutriments{$nid}{$lang})) { - $label = <${prefix}$Nutriments{$nid}{$lang} -HTML -; + elsif ((exists $Nutriments{$nid}) and (exists $Nutriments{$nid}{$lang})) { + $name = $prefix . $Nutriments{$nid}{$lang}; + } elsif ((exists $Nutriments{$nid}) and (exists $Nutriments{$nid}{en})) { - $label = <${prefix}$Nutriments{$nid}{en} -HTML -; + $name = $prefix . $Nutriments{$nid}{en}; + } elsif (defined $product_ref->{nutriments}{$nid . "_label"}) { - my $label_value = $product_ref->{nutriments}{$nid . "_label"}; - $label = <$label_value -HTML -; + $name = $product_ref->{nutriments}{$nid . "_label"}; } my $unit = 'g'; @@ -9394,21 +9391,33 @@ HTML $unit = $product_ref->{nutriments}{$nid . "_unit"}; } - my $values = ''; - - my $values2 = ''; + my $values; + my $values2; + + my @columns; + my @extra_row_columns; + my @ecological_impact_columns; - my $decf = get_decimal_formatter($lc); - my $perf = get_percent_formatter($lc, 0); foreach my $col (@cols) { - + + $values = ''; # Value for row + $values2 = ''; # Value for extra row (e.g. after the row for salt, we add an extra row for sodium) my $col_class = ''; + my $percent = ''; + + my $rdfa = ''; # RDFA property for row + my $rdfa2 = ''; # RDFA property for extra row + + my $col_type; + if (defined $col_class{$col}) { $col_class = ' ' . $col_class{$col} ; } if ($col =~ /compare_(.*)/) { #comparisons + $col_type = "comparison"; + my $comparison_ref = $comparisons_ref->[$1]; my $value = ""; @@ -9429,9 +9438,9 @@ HTML # 0.045 g 0.0449 g - my $value_unit = "$value $unit"; + $values = "$value $unit"; if ((not defined $comparison_ref->{nutriments}{$nid . "_100g"}) or ($comparison_ref->{nutriments}{$nid . "_100g"} eq '')) { - $value_unit = '?'; + $values = '?'; } elsif (($nid eq "energy") or ($nid eq "energy-from-fat")) { # Use the actual value in kcal if we have it @@ -9443,11 +9452,12 @@ HTML else { $value_in_kcal = g_to_unit($comparison_ref->{nutriments}{$nid . "_100g"}, 'kcal'); } - $value_unit .= "
(" . sprintf("%d", $value_in_kcal) . ' kcal)'; + $values .= "
(" . sprintf("%d", $value_in_kcal) . ' kcal)'; } - my $percent = $comparison_ref->{nutriments}{"${nid}_100g_%"}; + $percent = $comparison_ref->{nutriments}{"${nid}_100g_%"}; if ((defined $percent) and ($percent ne '')) { + my $percent_numeric_value = $percent; $percent = $perf->format($percent / 100.0); # issue 2273 - minus signs are rendered with different characters in different locales, e.g. Finnish @@ -9455,32 +9465,25 @@ HTML if ($percent_numeric_value > 0 ) { $percent = "+" . $percent; } - $value_unit = '' . $percent . ''; } else { $percent = ""; } - - $values .= "$value_unit"; - + if ($nid eq 'sodium') { if ((not defined $comparison_ref->{nutriments}{$nid . "_100g"}) or ($comparison_ref->{nutriments}{$nid . "_100g"} eq '')) { - $values2 .= "?"; + $values2 .= '?'; } else { - $values2 .= "" - . '' . $percent . '' - . '' . ""; + $values2 .= ($decf->format(g_to_unit($comparison_ref->{nutriments}{$nid . "_100g"} * 2.5, $unit))) . " " . $unit; } } if ($nid eq 'salt') { if ((not defined $comparison_ref->{nutriments}{$nid . "_100g"}) or ($comparison_ref->{nutriments}{$nid . "_100g"} eq '')) { - $values2 .= "?"; + $values2 .= '?'; } else { - $values2 .= "" - . '' . $percent . '' - . '' . ""; + $values2 .= ($decf->format(g_to_unit($comparison_ref->{nutriments}{$nid . "_100g"} / 2.5, $unit))) . " " . $unit; } } @@ -9501,17 +9504,14 @@ HTML my $nutriscore_grade = compute_nutriscore_grade($product_ref->{nutriments}{$nid . "_100g"}, is_beverage_for_nutrition_score($product_ref), is_water_for_nutrition_score($product_ref)); - $values2 .= "" - . uc ($nutriscore_grade) - . ""; + + $values2 .= uc ($nutriscore_grade); } } - } else { - + $col_type = "normal"; my $value_unit = ""; - my $rdfa = ''; # Nutriscore: per serving = per 100g if (($nid =~ /(nutrition-score(-\w\w)?)/)) { @@ -9569,18 +9569,17 @@ HTML if (exists $product_ref->{nutriments}{"salt" . "_$col"}) { $salt = $product_ref->{nutriments}{"salt" . "_$col"}; } - my $property = ''; if (defined $salt) { $salt = $decf->format(g_to_unit($salt, $unit)); if ($col eq '100g') { - $property = "property=\"food:saltEquivalentPer100g\" content=\"$salt\""; + $rdfa2 = "property=\"food:saltEquivalentPer100g\" content=\"$salt\""; } $salt .= " " . $unit; } else { $salt = "?"; } - $values2 .= "" . $salt . ""; + $values2 .= $salt; } elsif ($nid eq 'salt') { my $sodium; @@ -9590,18 +9589,17 @@ HTML if (exists $product_ref->{nutriments}{"sodium". "_$col"}) { $sodium = $product_ref->{nutriments}{"sodium". "_$col"}; } - my $property = ''; if (defined $sodium) { $sodium = $decf->format(g_to_unit($sodium, $unit)); if ($col eq '100g') { - $property = "property=\"food:sodiumEquivalentPer100g\" content=\"$sodium\""; + $rdfa2 = "property=\"food:sodiumEquivalentPer100g\" content=\"$sodium\""; } $sodium .= " " . $unit; } else { $sodium = "?"; } - $values2 .= "" . $sodium . ""; + $values2 .= $sodium ; } elsif ($nid eq 'nutrition-score-fr') { # We need to know the category in order to select the right thresholds for the nutrition grades @@ -9618,20 +9616,14 @@ HTML if (defined $product_ref->{categories_tags}) { - if ($col eq "std") { - $values2 .= ""; - } - else { + if ($col ne "std") { + my $nutriscore_grade = compute_nutriscore_grade($product_ref->{nutriments}{$nid . "_$col"}, is_beverage_for_nutrition_score($product_ref), is_water_for_nutrition_score($product_ref)); - $values2 .= "" - . uc ($nutriscore_grade) # ! prepared - . ""; + + $values2 .= uc ($nutriscore_grade); } } - else { - $values2 .= ""; - } } elsif ($col eq $product_ref->{nutrition_data_per}) { # % DV ? @@ -9647,85 +9639,103 @@ HTML $rdfa = " property=\"food:$property\" content=\"" . $product_ref->{nutriments}{$nid . "_$col"} . "\""; } - - $values .= "$value_unit"; + $values .= $value_unit; } + + if (($nid eq 'carbon-footprint') or ($nid eq 'carbon-footprint-from-meat-or-fish')){ + push (@ecological_impact_columns, { + value => $values, + class => $col_class, + percent => $percent, + type => $col_type, + }); + } + + push (@columns, { + value => $values, + rdfa => $rdfa, + class => $col_class, + percent => $percent, + type => $col_type, + }); + + push (@extra_row_columns, { + value => $values2, + rdfa => $rdfa2, + class => $col_class, + percent => $percent, + type => $col_type, + }); } + if ($shown) { - my $input = < -$label -$values - -HTML -; + if (($nid ne 'carbon-footprint') and ($nid ne 'carbon-footprint-from-meat-or-fish')) { - if (($nid eq 'sodium') and ($values2 ne '')) { - $input .= < - -HTML -. lang("salt_equivalent") . < -$values2 - -HTML -; - } + push @{$template_data_ref->{tables}[0]{rows}}, { + nid => $nid, + class => $class, + name => $name, + columns => \@columns, + }; - if (($nid eq 'salt') and ($values2 ne '')) { - $input .= < - -HTML -. $Nutriments{sodium}{$lang} . < -$values2 - -HTML -; - } + if (($nid eq 'sodium') and ($values2 ne '')) { - if (($nid eq 'nutrition-score-fr') and ($values2 ne '')) { - $input .= < - -HTML -. "Nutri-Score" . < -$values2 - -HTML -; - } + push @{$template_data_ref->{tables}[0]{rows}}, { + name => lang("salt_equivalent"), + nid => "salt_equivalent", + class => "sub", + columns => \@extra_row_columns, + }; + } - if (not $shown) { - #print STDERR "nutrition_table - nid: $nid - shown: $shown \n"; - } - elsif (($nid eq 'carbon-footprint') or ($nid eq 'carbon-footprint-from-meat-or-fish')) { + if (($nid eq 'salt') and ($values2 ne '')) { - $html2 .= <$Lang{ecological_data_table}{$lang}$empty_cols -HTML - . $input; + push @{$template_data_ref->{tables}[0]{rows}}, { + name => $Nutriments{sodium}{$lang}, + nid => "sodium", + class => "sub", + columns => \@extra_row_columns, + }; + } - } - else { - $html .= $input; - } + if (($nid eq 'nutrition-score-fr') and ($values2 ne '')) { + push @{$template_data_ref->{tables}[0]{rows}}, { + name => "Nutri-Score", + nid => "nutriscore", + class => "sub", + columns => \@extra_row_columns, + }; + } + } + + else { + + push @{$template_data_ref->{tables}[1]->{rows}}, { + nid => $nid, + class => $class, + name => $name, + columns => \@ecological_impact_columns, + }; + } + } + } + + # Remove the ecological table if we have no rows + + if (scalar @{$template_data_ref->{tables}[1]->{rows}} == 0) { + pop @{$template_data_ref->{tables}}; } - $html .= < - -HTML -; + $tt->process('nutrition_facts_table.tt.html', $template_data_ref, \$html) || return "template error: " . $tt->error(); - return $html; + if ((defined $debug_template) + and ($debug_template eq "nutrition_facts_table")) { + $html .= "
" . Dumper($template_data_ref) . "
"; + } + return $html; } diff --git a/templates/nutrition_facts_table.tt.html b/templates/nutrition_facts_table.tt.html new file mode 100644 index 0000000000000..42fb8dd4adfcd --- /dev/null +++ b/templates/nutrition_facts_table.tt.html @@ -0,0 +1,90 @@ + +[% IF comparisons.defined %] + + +

[% lang('nutrition_data_comparison_with_categories') %]

+ + + [% FOREACH comparison IN comparisons %] + + + + [% IF comparison.count.defined %] + ([% comparison.count %] [% lang('products') %]) + [% END %] + +
+ + [% END %] + +[% END %] + +
+ + + + + +

→ [% lang('nutrition_data_comparison_with_categories_note') %]

+ + +[% IF category_stats.defined %] + +
+ + [% lang('show_category_stats') %] + +
+ +[% END %] + +[% FOREACH table IN tables %] + + + + + + + + [% FOREACH column IN table.header.columns %] + + [% END %] + + + + + + [% FOREACH row IN table.rows %] + + + + + [% FOREACH column IN row.columns %] + [% IF column.type == 'normal' %] + + [% ELSE %] + + [% END %] + [% END %] + + + [% END %] + + +
[% table.header.name %][% column.name %]
+ [% row.name %] + + [% column.value %] + + [% column.percent %] + +
+ +[% END %]