refactor(frontend): 💄 Imrove UI for parser

This commit is contained in:
hay-kot 2021-08-29 17:09:08 -08:00
parent f78eb4ec39
commit 0b27e8af45
4 changed files with 102 additions and 31 deletions

View File

@ -59,9 +59,6 @@
<RecipeIngredientFoodDialog class="mx-2" block small /> <RecipeIngredientFoodDialog class="mx-2" block small />
</template> </template>
</v-autocomplete> </v-autocomplete>
<template v-if="!checkForFood(value.food)">
'{{ value.food && value.food !== "" ? value.food.name : null }}' does not exists. Would you like to create it?
</template>
</v-col> </v-col>
<v-col sm="12" md="" cols="12"> <v-col sm="12" md="" cols="12">
<v-text-field v-model="value.note" hide-details dense solo class="mx-1" placeholder="Notes"> <v-text-field v-model="value.note" hide-details dense solo class="mx-1" placeholder="Notes">
@ -95,7 +92,6 @@ import RecipeIngredientFoodDialog from "./RecipeIngredientFoodDialog.vue";
import { useFoods } from "~/composables/use-recipe-foods"; import { useFoods } from "~/composables/use-recipe-foods";
import { useUnits } from "~/composables/use-recipe-units"; import { useUnits } from "~/composables/use-recipe-units";
import { validators } from "~/composables/use-validators"; import { validators } from "~/composables/use-validators";
import { RecipeIngredientFood } from "~/types/api-types/recipe";
export default defineComponent({ export default defineComponent({
components: { RecipeIngredientUnitDialog, RecipeIngredientFoodDialog }, components: { RecipeIngredientUnitDialog, RecipeIngredientFoodDialog },
@ -119,20 +115,6 @@ export default defineComponent({
showTitle: false, showTitle: false,
}); });
function checkForUnit(unit: RecipeIngredientFood) {
if (units.value && unit?.name) {
return units.value.some((u) => u.name === unit.name);
}
return false;
}
function checkForFood(food: RecipeIngredientFood) {
if (foods.value && food?.name) {
return foods.value.some((f) => f.name === food.name);
}
return false;
}
function toggleTitle() { function toggleTitle() {
if (value.title) { if (value.title) {
state.showTitle = false; state.showTitle = false;
@ -151,8 +133,6 @@ export default defineComponent({
units, units,
...toRefs(state), ...toRefs(state),
toggleTitle, toggleTitle,
checkForUnit,
checkForFood,
}; };
}, },
}); });

View File

@ -10,7 +10,10 @@
</v-btn> </v-btn>
</template> </template>
<v-card width="400"> <v-card width="400">
<v-card-title class="mb-1 pb-0"> Warning Experimental </v-card-title> <v-card-title class="mb-1 pb-0">
<v-icon left color="warning"> {{ $globals.icons.alert }}</v-icon> Experimental
</v-card-title>
<v-divider class="mx-2"> </v-divider>
<v-card-text> <v-card-text>
Mealie can use natural language processing to attempt to parse and create units, and foods for your Recipe Mealie can use natural language processing to attempt to parse and create units, and foods for your Recipe
ingredients. This is experimental and may not work as expected. If you choose to not use the parsed results ingredients. This is experimental and may not work as expected. If you choose to not use the parsed results
@ -29,10 +32,32 @@
</v-menu> </v-menu>
<BaseDialog ref="domParsedDataDialog" width="100%"> <BaseDialog ref="domParsedDataDialog" width="100%">
<v-card-text> <v-card-text>
<div v-for="(ing, index) in parsedData.ingredient" :key="index"> <v-expansion-panels v-model="panels" multiple>
<div class="ml-10 text-body-1" :class="index > 0 ? 'mt-4' : null">{{ ingredients[index].note }}</div> <v-expansion-panel v-for="(ing, index) in parsedData.ingredient" :key="index">
<RecipeIngredientEditor :value="ing" /> <v-expansion-panel-header class="my-0 py-0">
</div> <div class="text-body-1">
<span>
<v-icon v-if="errors[index].foodError" color="warning">
{{ $globals.icons.close }}
</v-icon>
<v-icon v-else color="success">
{{ $globals.icons.check }}
</v-icon>
</span>
{{ ingredients[index].note }}
</div>
</v-expansion-panel-header>
<v-expansion-panel-content class="pb-0 mb-0">
<RecipeIngredientEditor v-model="parsedData.ingredient[index]" />
<v-card-actions>
<v-spacer></v-spacer>
<BaseButton v-if="errors[index].foodError" color="warning" small @click="createFood(ing.food, index)">
{{ errors[index].foodErrorMessage }}
</BaseButton>
</v-card-actions>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</v-card-text> </v-card-text>
</BaseDialog> </BaseDialog>
</div> </div>
@ -42,7 +67,18 @@
import { defineComponent, ref } from "@nuxtjs/composition-api"; import { defineComponent, ref } from "@nuxtjs/composition-api";
import RecipeIngredientEditor from "./RecipeIngredientEditor.vue"; import RecipeIngredientEditor from "./RecipeIngredientEditor.vue";
import { useApiSingleton } from "~/composables/use-api"; import { useApiSingleton } from "~/composables/use-api";
import { RecipeIngredient } from "~/types/api-types/recipe"; import { RecipeIngredient, RecipeIngredientUnit } from "~/types/api-types/recipe";
import { useFoods } from "~/composables/use-recipe-foods";
import { useUnits } from "~/composables/use-recipe-units";
import { Food } from "~/api/class-interfaces/recipe-foods";
interface Error {
ingredientIndex: number;
unitError: Boolean;
unitErrorMessage: string;
foodError: Boolean;
foodErrorMessage: string;
}
export default defineComponent({ export default defineComponent({
components: { components: {
@ -60,8 +96,36 @@ export default defineComponent({
const parsedData = ref<any>([]); const parsedData = ref<any>([]);
const { foods, workingFoodData, actions } = useFoods();
const { units } = useUnits();
const domParsedDataDialog = ref(null); const domParsedDataDialog = ref(null);
const panels = ref<number[]>([]);
const errors = ref<Error[]>([]);
function checkForUnit(unit: RecipeIngredientUnit) {
if (units.value && unit?.name) {
return units.value.some((u) => u.name === unit.name);
}
return false;
}
function checkForFood(food: Food) {
if (foods.value && food?.name) {
return foods.value.some((f) => f.name === food.name);
}
return false;
}
async function createFood(food: Food, index: number) {
workingFoodData.name = food.name;
parsedData.value[index] = await actions.createOne();
errors.value[index].foodError = false;
}
async function parseIngredients() { async function parseIngredients() {
// @ts-ignore -> No idea what it's talking about // @ts-ignore -> No idea what it's talking about
const ingredientNotes = ingredients.map((ing: RecipeIngredient) => ing.note); const ingredientNotes = ingredients.map((ing: RecipeIngredient) => ing.note);
@ -73,12 +137,38 @@ export default defineComponent({
domParsedDataDialog.value.open(); domParsedDataDialog.value.open();
console.log(data); console.log(data);
parsedData.value = data; parsedData.value = data;
}
console.log("ingredientNotes", ingredientNotes); // @ts-ignore
errors.value = data.ingredient.map((ing, index: number) => {
const unitError = !checkForUnit(ing.unit);
const foodError = !checkForFood(ing.food);
let unitErrorMessage = "";
let foodErrorMessage = "";
if (unitError || foodError) {
if (unitError) {
unitErrorMessage = `Create missing unit '${ing.unit.name || "No unit"}'`;
}
if (foodError) {
panels.value.push(index);
foodErrorMessage = `Create missing food '${ing.food.name || "No food"}'?`;
}
}
return {
ingredientIndex: index,
unitError,
unitErrorMessage,
foodError,
foodErrorMessage,
};
});
}
} }
return { api, parseIngredients, parsedData, domParsedDataDialog }; return { api, parseIngredients, parsedData, domParsedDataDialog, panels, errors, createFood };
}, },
}); });
</script> </script>

View File

@ -48,6 +48,7 @@ export const useFoods = function () {
const { data } = await api.foods.createOne(workingFoodData); const { data } = await api.foods.createOne(workingFoodData);
if (data && foodStore?.value) { if (data && foodStore?.value) {
foodStore.value.push(data); foodStore.value.push(data);
return data;
} else { } else {
this.refreshAll(); this.refreshAll();
} }

View File

@ -250,7 +250,7 @@ export default {
secondary: "#973542", secondary: "#973542",
success: "#43A047", success: "#43A047",
info: "#1976d2", info: "#1976d2",
warning: "#FF4081", warning: "#FF6D00",
error: "#EF5350", error: "#EF5350",
}, },
light: { light: {
@ -259,7 +259,7 @@ export default {
secondary: "#973542", secondary: "#973542",
success: "#43A047", success: "#43A047",
info: "#1976d2", info: "#1976d2",
warning: "#FF4081", warning: "#FF6D00",
error: "#EF5350", error: "#EF5350",
}, },
}, },