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

Make nutrition table visible in the menu #1111

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 8 additions & 1 deletion src/components/ResponsiveAppBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,14 @@ const pages = [
},
],
},
{
url: "nutrition",
translationKey: "menu.nutritions",
desktopOnly: true,
},
{ translationKey: "menu.manage" },
{ url: "insights", translationKey: "menu.insights", devModeOnly: true },
{ url: "dashboard", translationKey: "menu.dashboard" },
// { url: "nutriscore", translationKey: "menu.nutriscore", devModeOnly: true },
{ url: "settings", translationKey: "menu.settings", mobileOnly: true },
];

Expand Down Expand Up @@ -139,6 +143,9 @@ const ResponsiveAppBar = () => {
if (page.mobileOnly) {
return !isDesktop;
}
if (page.desktopOnly) {
return isDesktop;
}
return true;
};

Expand Down
78 changes: 30 additions & 48 deletions src/i18n/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"countries": "Countries",
"view": "View",
"edit": "Edit",
"remaining": "Remaining: {{count}}",
"hide_images": "Hide images (faster loading)",
"display_images": "Display images",
"annotations": "Annotations",
Expand Down Expand Up @@ -129,7 +130,7 @@
"logos-deep-search": "Infinite annotation",
"manage": "Manage",
"insights": "Insights",
"nutritions": "Nutrition facts",
"nutritions": "Nutrition",
"settings": "Settings",
"eco-score": "Eco-score",
"dashboard": "Logos dashboard",
Expand Down Expand Up @@ -247,7 +248,7 @@
"Open_Food_Facts_wiki": "Open Food Facts wiki (en)",
"Translators": "Translators",
"Partners": "Partners",
"Open_Beauty_Facts": "Open Beauty Facts - Cosmetics",
"Open_Beauty_Facts": "Open Beauty Facts - cosmetics",
"text2": "A collaborative, free and open database of food products from around the world."
},
"helper": {
Expand Down Expand Up @@ -313,53 +314,34 @@
"close": "Close"
},
"nutrition": {
"instructions": {
"cropTheTable": "Crop the image to simplify your annotation",
"verifyNutrimentDetected": "Indicate if the nutriment detected is correct",
"selectMissingNutriments": "Add missing nutriments (you can click even if the word has no box)",
"selectValue": "Select the nutritional value of: "
},
"steps": {
"1": "Crop",
"2": "Special values",
"3": "Nutriments Selection",
"4": "Values Selection"
},
"loading": "Loading...",
"unknown_brand": "Brand Unknown",
"value_missing": "You forgot to input a value.",
"next": "Next step",
"prev": "Prev step",
"skip": "Skip this product",
"validate": "Validate Table",
"unselect_picture": "No nutrition info",
"basis": "data for: ",
"servingSize": "serving size",
"value": "Value",
"unit": "Unit",
"nutriments": {
"nutriment_energy-kj": "Energy (kJ)",
"nutriment_energy-kcal": "Energy (kCal)",
"nutriment_fat": "Fat",
"nutriment_saturated-fat": "Saturated fat",
"nutriment_carbohydrates": "Carbohydrates",
"nutriment_sugars": "Sugar",
"nutriment_proteins": "Protein content",
"nutriment_fiber": "Fibres",
"nutriment_salt": "Salt",
"nutriment_sodium": "Sodium"
"table_partialy_filled": "Table with already some data",
"display_off_values": "Display values from OpenFoodFacts",
"nutrients": "Nutrients",
"serving_size": "Serving size",
"add_nutrient": "-- add nutrient --",
"validate_100g": "Validate (100g)",
"validate_serving": "Validate (serving)",
"skip": "Skip",
"invalid_image": "Invalid image",
"pictures": {
"picture_date": "Photo uploaded",
"selected_as_nutrients": "Selected as nutriment image ✅",
"not_selected_as_nutrients": "Not selected as nutriment ❌"
},
"history": {
"title": "Session History",
"status": "status",
"product name": "product name",
"view": "view page",
"edit": "edit page",
"SKIP": "ignored",
"VALIDATED": "edited",
"WRONG_IMAGE": "unselected picture",
"close": "close",
"open": "open history"
"instructions": {
"open_button": "Open instructions",
"title": "How to use the interface",
"chose_between_empty_and_partially_filled": "You can chose between products for which OpenFoodFacts (OFF) has no data about the nutrients. Or product with partially filled nutrient table.",
"picture_date_is_display": "The date of the picture is displayed on top of it. Allowing you to check if it's a recent one.",
"nutriments_from_off_are_displayed": "You can display data that are already present in the OFF database. They will appear under the inputs:",
"green_for_same": "With <1>green</1> for those matching with the input value.",
"orange_for_empty": "With <1>orange</1> for those with empty input value.",
"red_for_different": "With <1>red</1> for those with different input value.",
"indicate_not_provided_value": "Empty inputs are ignored. If fibers are not present in the table, you can put \"-\" to specify the value is not available.",
"validate_one_column": "Once you've verified one column, you can validate. It's useless to fill both columns. The data base only save one of them. The second one is computed by using proportionality.",
"skip_button": "If you don't know how to deal with an image, or you just don't want to do it, press \"skip\". Other user will be able to handle it.",
"invalid_image_button": "If the pictures is not a nutritional table, press \"Invalid image\" to remove it from the list of the images to verify",
"close": "Close"
}
},
"notfound": {
Expand Down
76 changes: 29 additions & 47 deletions src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"countries": "Countries",
"view": "View",
"edit": "Edit",
"remaining": "Remaining: {{count}}",
"hide_images": "Hide images (faster loading)",
"display_images": "Display images",
"annotations": "Annotations",
Expand Down Expand Up @@ -129,7 +130,7 @@
"logos-deep-search": "Infinite annotation",
"manage": "Manage",
"insights": "Insights",
"nutritions": "Nutrition facts",
"nutritions": "Nutrition",
"settings": "Settings",
"eco-score": "Eco-score",
"dashboard": "Logos dashboard",
Expand Down Expand Up @@ -313,53 +314,34 @@
"close": "Close"
},
"nutrition": {
"instructions": {
"cropTheTable": "Crop the image to simplify your annotation",
"verifyNutrimentDetected": "Indicate if the nutriment detected is correct",
"selectMissingNutriments": "Add missing nutriments (you can click even if the word has no box)",
"selectValue": "Select the nutritional value of: "
},
"steps": {
"1": "Crop",
"2": "Special values",
"3": "Nutriments Selection",
"4": "Values Selection"
},
"loading": "Loading...",
"unknown_brand": "Brand Unknown",
"value_missing": "You forgot to input a value.",
"next": "Next step",
"prev": "Prev step",
"skip": "Skip this product",
"validate": "Validate Table",
"unselect_picture": "No nutrition info",
"basis": "data for: ",
"servingSize": "serving size",
"value": "Value",
"unit": "Unit",
"nutriments": {
"nutriment_energy-kj": "Energy (kJ)",
"nutriment_energy-kcal": "Energy (kCal)",
"nutriment_fat": "Fat",
"nutriment_saturated-fat": "Saturated fat",
"nutriment_carbohydrates": "Carbohydrates",
"nutriment_sugars": "Sugar",
"nutriment_proteins": "Protein content",
"nutriment_fiber": "Fibres",
"nutriment_salt": "Salt",
"nutriment_sodium": "Sodium"
"table_partialy_filled": "Table with already some data",
"display_off_values": "Display values from OpenFoodFacts",
"nutrients": "Nutrients",
"serving_size": "Serving size",
"add_nutrient": "-- add nutrient --",
"validate_100g": "Validate (100g)",
"validate_serving": "Validate (serving)",
"skip": "Skip",
"invalid_image": "Invalid image",
"pictures": {
"picture_date": "Photo uploaded",
"selected_as_nutrients": "Selected as nutriment image ✅",
"not_selected_as_nutrients": "Not selected as nutriment ❌"
},
"history": {
"title": "Session History",
"status": "status",
"product name": "product name",
"view": "view page",
"edit": "edit page",
"SKIP": "ignored",
"VALIDATED": "edited",
"WRONG_IMAGE": "unselected picture",
"close": "close",
"open": "open history"
"instructions": {
"open_button": "Open instructions",
"title": "How to use the interface",
"chose_between_empty_and_partially_filled": "You can chose between products for which OpenFoodFacts (OFF) has no data about the nutrients. Or product with partially filled nutrient table.",
"picture_date_is_display": "The date of the picture is displayed on top of it. Allowing you to check if it's a recent one.",
"nutriments_from_off_are_displayed": "You can display data that are already present in the OFF database. They will appear under the inputs:",
"green_for_same": "With <1>green</1> for those matching with the input value.",
"orange_for_empty": "With <1>orange</1> for those with empty input value.",
"red_for_different": "With <1>red</1> for those with different input value.",
"indicate_not_provided_value": "Empty inputs are ignored. If fibers are not present in the table, you can put \"-\" to specify the value is not available.",
"validate_one_column": "Once you've verified one column, you can validate. It's useless to fill both columns. The data base only save one of them. The second one is computed by using proportionality.",
"skip_button": "If you don't know how to deal with an image, or you just don't want to do it, press \"skip\". Other user will be able to handle it.",
"invalid_image_button": "If the pictures is not a nutritional table, press \"Invalid image\" to remove it from the list of the images to verify",
"close": "Close"
}
},
"notfound": {
Expand Down
56 changes: 26 additions & 30 deletions src/pages/nutrition/Instructions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogTitle from "@mui/material/DialogTitle";
import Typography from "@mui/material/Typography";
import { Trans, useTranslation } from "react-i18next";

export default function Instructions() {
const { t } = useTranslation();
const [open, setOpen] = React.useState(false);

const handleClickOpen = () => {
Expand All @@ -27,7 +29,7 @@ export default function Instructions() {
onClick={handleClickOpen}
sx={{ margin: 2 }}
>
Instructions
{t("nutrition.instructions.open_button")}
</Button>
<Dialog
open={open}
Expand All @@ -36,61 +38,55 @@ export default function Instructions() {
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
Comment utiliser cette interface
{t("nutrition.instructions.title")}
</DialogTitle>
<DialogContent sx={{ "& p": { marginBottom: 2 } }}>
<DialogContentText component="div" id="alert-dialog-description">
<Typography>
Avec les checkbox du haut, vous pouvez choisir entre traiter des
tableux de produit sans tableau nutritionel. Ou traiter des
produits pour lequels robotoof à trouver des nutriments en plus.
{t(
"nutrition.instructions.chose_between_empty_and_partially_filled",
)}
</Typography>
<Typography>
La date de la photo est affichée au dessus de la photo.
{t("nutrition.instructions.picture_date_is_display")}
</Typography>
<Typography>
Les nutriments déjà associé au produit sont affiché en petit sous
les inputs.
{t("nutrition.instructions.nutriments_from_off_are_displayed")}
<ol>
<li>
En <span style={{ color: "green" }}>vert</span> pour ceux qui
matchent avec la valeur du champ
<Trans i18nKey="nutrition.instructions.green_for_same">
With <span style={{ color: "green" }}>green</span> for those
matching with the input value.
</Trans>
</li>
<li>
En <span style={{ color: "orange" }}>orange</span> si le champ
est vide
<Trans i18nKey="nutrition.instructions.orange_for_empty">
With <span style={{ color: "orange" }}>orange</span> for
those with empty input value.
</Trans>
</li>
<li>
En <span style={{ color: "red" }}>rouge</span> si le champ est
différent de la valeur connue.
<Trans i18nKey="nutrition.instructions.red_for_different">
With <span style={{ color: "red" }}>red</span> for those
with different input value.
</Trans>
</li>
</ol>
La valeur "-" indique une valeur abscente du tableau nutritionel.
Particulierement utile pour les fibres qui sont souvent abscente.
{t("nutrition.instructions.indicate_not_provided_value")}
</Typography>
<Typography>
Quand une colone a été vérifiée (celle pour 100g ou celle par
portion) il ne vous reste plus qu'à la valider pour passer à la
suite. Innutil de remplir les deux colones. Une seul des deux peut
être enregistrée par OFF.
{t("nutrition.instructions.validate_one_column")}
</Typography>

<ul>
<li>
Le bouton "skip" passe à la suite. quelqu'un d'autre s'en
chargera.
</li>
<li>
Le bouton "invalid image" indique que la photo ne correspond pas
à un tableau nutritionel, et supprime la question pour tout le
monde.
</li>
<li>{t("nutrition.instructions.skip_button")}</li>
<li>{t("nutrition.instructions.invalid_image_button")}</li>
</ul>
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} autoFocus>
Fermer
{t("nutrition.instructions.close")}
</Button>
</DialogActions>
</Dialog>
Expand Down
6 changes: 5 additions & 1 deletion src/pages/nutrition/LinksToProduct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export default function LinkToProduct(
>
{t("questions.edit")}
</Button>
<Typography sx={{ ml: "auto" }}>Restant: {count}</Typography>
<Typography sx={{ ml: "auto" }}>
{t("questions.remaining", {
count,
})}
</Typography>
</Stack>
);
}
8 changes: 5 additions & 3 deletions src/pages/nutrition/PictureSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TransformWrapper,
} from "react-zoom-pan-pinch";
import { OFF_IMAGE_URL } from "../../const";
import { useTranslation } from "react-i18next";

interface PictureSectionProps {
isLoading?: boolean;
Expand All @@ -20,6 +21,7 @@ interface PictureSectionProps {
}

export default function PictureSection(props: PictureSectionProps) {
const { t } = useTranslation();
const { isLoading, insight, product, apiRef } = props;

const [rotationIndex, setRotationIndex] = React.useState(0);
Expand All @@ -46,7 +48,7 @@ export default function PictureSection(props: PictureSectionProps) {
return (
<React.Fragment>
<p>
Photo upload:{" "}
{`${t("nutrition.pictures.picture_date")}: `}
{imageTimestamp
? new Date(imageTimestamp * 1000).toLocaleDateString(undefined, {
day: "2-digit",
Expand All @@ -57,8 +59,8 @@ export default function PictureSection(props: PictureSectionProps) {
</p>
<p>
{selectedImagesIds.includes(imageId)
? `Selected as nutriment image ✅`
: `Not selected as nutriment ❌`}
? t("nutrition.pictures.selected_as_nutrients")
: t("nutrition.pictures.not_selected_as_nutrients")}
</p>
<IconButton onClick={() => setRotationIndex((p) => p - 1)}>
<RotateLeftIcon />
Expand Down
Loading
Loading