Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NutritionScore Calculation Details HTML Template #3503

Merged
merged 4 commits into from
Jun 5, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpanfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ requires 'experimental'; # libexperimental-perl
requires 'Apache2::Request'; # libapache2-request-perl
requires 'Digest::MD5'; # libdigest-md5-perl
requires 'Time::Local'; # libtime-local-perl
requires 'Template','3.008'; # libtemplate-perl

# Probably not available as Debian packages
requires 'MongoDB', '>= 2.2.1, < 2.3'; # libmongodb-perl has an older version
Expand Down
5 changes: 5 additions & 0 deletions docker/backend-dev/conf/po-foreground.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ then
ln -sf /opt/product-opener/packager-codes /mnt/podata/packager-codes
fi

if [ ! -e /mnt/podata/templates ]
then
ln -sf /opt/product-opener/templates /mnt/podata/templates
fi

perl -I/opt/product-opener/lib -I/opt/perl/local/lib/perl5 /opt/product-opener/scripts/build_lang.pl
chown -R www-data:www-data /mnt/podata
chown -R www-data:www-data /opt/product-opener/html/images/products
Expand Down
3 changes: 2 additions & 1 deletion docker/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ RUN set -x \
libapache2-request-perl \
libdigest-md5-perl \
libtime-local-perl \
libdbd-pg-perl
libdbd-pg-perl \
libtemplate-perl

# Stage for installing/compiling cpanfile dependencies
FROM modperl AS builder
Expand Down
149 changes: 86 additions & 63 deletions lib/ProductOpener/Display.pm
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ use Storable qw(freeze);
use Digest::MD5 qw(md5_hex);
use boolean;
use Excel::Writer::XLSX;
use Template;

use Log::Any '$log', default_adapter => 'Stderr';

Expand Down Expand Up @@ -8634,79 +8635,101 @@ the rounded value according to the Nutri-Score rules, and the corresponding poin
sub display_nutriscore_calculation_details($) {

my $nutriscore_data_ref = shift;

my $html = '<p><a data-dropdown="nutriscore_drop" aria-controls="nutriscore_drop" aria-expanded="false">' . lang("nutriscore_calculation_details") . " &raquo;</a><p>"
. '<div id="nutriscore_drop" data-dropdown-content class="f-dropdown content large" aria-hidden="true" tabindex="-1">';

if ($nutriscore_data_ref->{is_beverage}) {
$html .= "<p>" . lang("nutriscore_is_beverage") . "</p>";
}
else {
$html .= "<p>" . lang("nutriscore_is_not_beverage") . "</p>";
}

if ($nutriscore_data_ref->{is_fat}) {
$html .= "<p>" . lang("nutriscore_proteins_is_added_fat") . "</p>";
}

my @points = (
["positive", ["proteins", "fiber", "fruits_vegetables_nuts_colza_walnut_olive_oils"]],
["negative", ["energy", "sugars", "saturated_fat", "sodium"]],
);

foreach my $points_ref (@points) {

$html .= "<p><strong>" . lang("nutriscore_" . $points_ref->[0] . "_points") . lang("sep") . ": "
. $nutriscore_data_ref->{$points_ref->[0] . "_points"} . "</strong></p><ul>";

foreach my $nutrient (@{$points_ref->[1]}) {

my $nutrient_threshold_id = $nutrient;

if ((defined $nutriscore_data_ref->{is_beverage}) and ($nutriscore_data_ref->{is_beverage})
and (defined $points_thresholds{$nutrient_threshold_id . "_beverages"})) {
$nutrient_threshold_id .= "_beverages";
}
if (($nutriscore_data_ref->{is_fat}) and ($nutrient eq "saturated_fat")) {
$nutrient = "saturated_fat_ratio";
$nutrient_threshold_id = "saturated_fat_ratio";
}

$html .= "<li><strong>" . lang("nutriscore_points_for_" . $nutrient) . lang("sep") . ": "
. $nutriscore_data_ref->{$nutrient . "_points"} . "&nbsp;</strong>/&nbsp;" . scalar(@{$points_thresholds{$nutrient_threshold_id}}) . lang("points")
. " (" . lang("nutriscore_source_value") . lang("sep") . ": " . $nutriscore_data_ref->{$nutrient} . ", "
. lang("nutriscore_rounded_value") . lang("sep") . ": " . $nutriscore_data_ref->{$nutrient . "_value"} . ")" . "</li>";
}

$html .= "</ul>";
}


# Select message that explains the reason why the proteins points have been counted or not

my $nutriscore_protein_info;
if ($nutriscore_data_ref->{negative_points} < 11) {
$html .= "<p>" . lang("nutriscore_proteins_negative_points_less_than_11") . "</p>";
$nutriscore_protein_info = lang("nutriscore_proteins_negative_points_less_than_11");
}
elsif ((defined $nutriscore_data_ref->{is_cheese}) and ($nutriscore_data_ref->{is_cheese})) {
$html .= "<p>" . lang("nutriscore_proteins_is_cheese") . "</p>";
$nutriscore_protein_info = lang("nutriscore_proteins_is_cheese");
}
elsif ((((defined $nutriscore_data_ref->{is_beverage}) and ($nutriscore_data_ref->{is_beverage}))
and ($nutriscore_data_ref->{fruits_vegetables_nuts_colza_walnut_olive_oils_points} == 10))
or (((not defined $nutriscore_data_ref->{is_beverage}) or (not $nutriscore_data_ref->{is_beverage}))
or (((not defined $nutriscore_data_ref->{is_beverage}) or (not $nutriscore_data_ref->{is_beverage}))
and ($nutriscore_data_ref->{fruits_vegetables_nuts_colza_walnut_olive_oils_points} == 5)) ) {
$html .= "<p>" . lang("nutriscore_proteins_maximum_fruits_points") . "</p>";

$nutriscore_protein_info = lang("nutriscore_proteins_maximum_fruits_points");
}
else {
$html .= "<p>" . lang("nutriscore_proteins_negative_points_greater_or_equal_to_11") . "</p>";
}

$html .= "<p><strong>" . lang("nutriscore_score") . lang("sep"). ": " . ($nutriscore_data_ref->{score})
. "</strong> (" . $nutriscore_data_ref->{negative_points} . " - " . $nutriscore_data_ref->{positive_points} . ")<p>";

$html .= "<p><strong>" . lang("nutriscore_grade") . lang("sep"). ": " . uc($nutriscore_data_ref->{grade}) . "</strong></p>";

$html .= "</div>";

$nutriscore_protein_info = lang("nutriscore_proteins_negative_points_greater_or_equal_to_11");
}

# Generate a data structure that we will pass to the template engine

my $template_data_ref = {

lang => \&lang,

is_beverage => $nutriscore_data_ref->{is_beverage},
is_fat => $nutriscore_data_ref->{is_fat},

nutriscore_protein_info => $nutriscore_protein_info,

score => $nutriscore_data_ref->{score},
grade => uc($nutriscore_data_ref->{grade}),
positive_points => $nutriscore_data_ref->{positive_points},
negative_points => $nutriscore_data_ref->{negative_points},

# Details of positive and negative points, filled dynamically below
# as the nutrients and thresholds are different for some products (beverages and fats)
points_groups => []
};

my %points_groups = (
"positive" => ["proteins", "fiber", "fruits_vegetables_nuts_colza_walnut_olive_oils"],
"negative" => ["energy", "sugars", "saturated_fat", "sodium"],
);

foreach my $type ("positive", "negative") {

# Initiate a data structure for the points of the group

my $points_group_ref = {
type => $type,
points => $nutriscore_data_ref->{$type . "_points"},
nutrients => [],
};

# Add the nutrients for the group
foreach my $nutrient (@{$points_groups{$type}}) {

my $nutrient_threshold_id = $nutrient;

if ((defined $nutriscore_data_ref->{is_beverage}) and ($nutriscore_data_ref->{is_beverage})
and (defined $points_thresholds{$nutrient_threshold_id . "_beverages"})) {
$nutrient_threshold_id .= "_beverages";
}
if (($nutriscore_data_ref->{is_fat}) and ($nutrient eq "saturated_fat")) {
$nutrient = "saturated_fat_ratio";
$nutrient_threshold_id = "saturated_fat_ratio";
}
push @{$points_group_ref->{nutrients}}, {
id => $nutrient,
points => $nutriscore_data_ref->{$nutrient . "_points"},
maximum => scalar(@{$points_thresholds{$nutrient_threshold_id}}),
value => $nutriscore_data_ref->{$nutrient},
rounded => $nutriscore_data_ref->{$nutrient . "_value"},
};
}

push @{$template_data_ref->{points_groups}}, $points_group_ref;
}
# Nutrition Score Calculation Template
my $config = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
my $config = {
my $config = {

Also, aren't these config we can use for every template? Can't we put them outside of the sub?

INCLUDE_PATH => $data_root . '/templates',
INTERPOLATE => 1,
EVAL_PERL => 1,
};

my $tt = Template->new($config);

my $html;
$tt->process('nutrition_score.tt', $template_data_ref, \$html) || return "template error: " . $tt->error();

return $html;
}

}

sub display_nutrient_levels($) {

Expand Down
41 changes: 41 additions & 0 deletions templates/nutrition_score.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

VaiTon marked this conversation as resolved.
Show resolved Hide resolved
<p>
<a data-dropdown="nutriscore_drop" aria-controls="nutriscore_drop" aria-expanded="false"> [% lang('nutriscore_calculation_details') %] &raquo</a>
</p>
<div id="nutriscore_drop" data-dropdown-content class="f-dropdown content large" aria-hidden="true" tabindex="-1">

[% IF is_beverage %]
<p> [% lang('nutriscore_is_beverage') %] </p>
[% ELSE %]
<p> [% lang('nutriscore_is_not_beverage') %] </p>
[% END %]
[% IF is_fat %]
<p> [% lang('nutriscore_proteins_is_added_fat') %] </p>
[% END %]

[% FOREACH group IN points_groups %]

<p>
<strong> [% lang("nutriscore_" _ group.type _ "_points") %][% lang('sep') %]: [% group.points %] </strong>
</p>

<ul>
[% FOREACH nutrient IN group.nutrients %]
<li>
<strong> [% lang("nutriscore_points_for_" _ nutrient.id) %][% lang('sep') %]: [% nutrient.points %]&nbsp</strong>
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
/&nbsp [% nutrient.maximum %][% lang("points") %] ([% lang("nutriscore_source_value") %][% lang("sep") %]: [% nutrient.value %],
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
[% lang('nutriscore_rounded_value') %][% lang('sep') %]: [% nutrient.rounded %])
</li>
[% END %]
</ul>

[% END %]

<p>[% nutriscore_protein_info %] </p>
<p>
<strong> [% lang('nutriscore_score') %][% lang('sep') %]: [% score %] </strong> (
[% negative_points %] - [% positive_points %])
</p>
<p><strong> [% lang('nutriscore_grade') %][% lang('sep') %]: [% grade %] </strong></p>

</div>
VaiTon marked this conversation as resolved.
Show resolved Hide resolved