mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 04:10:06 -05:00
playing with AI import
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
||||
import {ref} from "vue";
|
||||
import {getCookie} from "@/utils/cookie";
|
||||
import {RecipeImageFromJSON, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
import {RecipeFromJSON, RecipeFromSourceFromJSON, RecipeFromSourceResponseFromJSON, RecipeImageFromJSON, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
import {ErrorMessageType, PreparedMessage, useMessageStore} from "@/stores/MessageStore";
|
||||
|
||||
/**
|
||||
@@ -76,5 +76,28 @@ export function useFileApi() {
|
||||
})
|
||||
}
|
||||
|
||||
return {fileApiLoading, createOrUpdateUserFile, updateRecipeImage}
|
||||
/**
|
||||
* uploads the given file to the image recognition endpoint
|
||||
* @param file file object to upload
|
||||
*/
|
||||
function convertImageToRecipe(file: File){
|
||||
let formData = new FormData()
|
||||
if (file != null) {
|
||||
formData.append('image', file)
|
||||
}
|
||||
|
||||
return fetch(getDjangoUrl(`api/image-to-recipe/`), {
|
||||
method: 'POST',
|
||||
headers: {'X-CSRFToken': getCookie('csrftoken')},
|
||||
body: formData
|
||||
}).then(r => {
|
||||
return r.json().then(r => {
|
||||
return RecipeFromSourceResponseFromJSON(r)
|
||||
})
|
||||
}).finally(() => {
|
||||
fileApiLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
return {fileApiLoading, createOrUpdateUserFile, updateRecipeImage, convertImageToRecipe}
|
||||
}
|
||||
@@ -7,8 +7,6 @@ models/AccessToken.ts
|
||||
models/AuthToken.ts
|
||||
models/AutoMealPlan.ts
|
||||
models/Automation.ts
|
||||
models/AutomationTypeEnum.ts
|
||||
models/BaseUnitEnum.ts
|
||||
models/BookmarkletImport.ts
|
||||
models/BookmarkletImportList.ts
|
||||
models/ConnectorConfigConfig.ts
|
||||
@@ -22,7 +20,6 @@ models/FoodInheritField.ts
|
||||
models/FoodShoppingUpdate.ts
|
||||
models/FoodSimple.ts
|
||||
models/Group.ts
|
||||
models/ImportImage.ts
|
||||
models/ImportLog.ts
|
||||
models/Ingredient.ts
|
||||
models/IngredientString.ts
|
||||
@@ -34,16 +31,6 @@ models/MealPlan.ts
|
||||
models/MealType.ts
|
||||
models/MethodEnum.ts
|
||||
models/NutritionInformation.ts
|
||||
models/OpenDataCategory.ts
|
||||
models/OpenDataConversion.ts
|
||||
models/OpenDataFood.ts
|
||||
models/OpenDataFoodProperty.ts
|
||||
models/OpenDataProperty.ts
|
||||
models/OpenDataStore.ts
|
||||
models/OpenDataStoreCategory.ts
|
||||
models/OpenDataUnit.ts
|
||||
models/OpenDataUnitTypeEnum.ts
|
||||
models/OpenDataVersion.ts
|
||||
models/PaginatedAutomationList.ts
|
||||
models/PaginatedBookmarkletImportListList.ts
|
||||
models/PaginatedCookLogList.ts
|
||||
@@ -90,13 +77,6 @@ models/PatchedInviteLink.ts
|
||||
models/PatchedKeyword.ts
|
||||
models/PatchedMealPlan.ts
|
||||
models/PatchedMealType.ts
|
||||
models/PatchedOpenDataCategory.ts
|
||||
models/PatchedOpenDataConversion.ts
|
||||
models/PatchedOpenDataFood.ts
|
||||
models/PatchedOpenDataProperty.ts
|
||||
models/PatchedOpenDataStore.ts
|
||||
models/PatchedOpenDataUnit.ts
|
||||
models/PatchedOpenDataVersion.ts
|
||||
models/PatchedProperty.ts
|
||||
models/PatchedPropertyType.ts
|
||||
models/PatchedRecipe.ts
|
||||
@@ -156,6 +136,7 @@ models/SupermarketCategoryRelation.ts
|
||||
models/Sync.ts
|
||||
models/SyncLog.ts
|
||||
models/ThemeEnum.ts
|
||||
models/TypeEnum.ts
|
||||
models/Unit.ts
|
||||
models/UnitConversion.ts
|
||||
models/User.ts
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,13 +13,13 @@
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AutomationTypeEnum } from './AutomationTypeEnum';
|
||||
import type { TypeEnum } from './TypeEnum';
|
||||
import {
|
||||
AutomationTypeEnumFromJSON,
|
||||
AutomationTypeEnumFromJSONTyped,
|
||||
AutomationTypeEnumToJSON,
|
||||
AutomationTypeEnumToJSONTyped,
|
||||
} from './AutomationTypeEnum';
|
||||
TypeEnumFromJSON,
|
||||
TypeEnumFromJSONTyped,
|
||||
TypeEnumToJSON,
|
||||
TypeEnumToJSONTyped,
|
||||
} from './TypeEnum';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,10 +35,10 @@ export interface Automation {
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {AutomationTypeEnum}
|
||||
* @type {TypeEnum}
|
||||
* @memberof Automation
|
||||
*/
|
||||
type: AutomationTypeEnum;
|
||||
type: TypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
@@ -111,7 +111,7 @@ export function AutomationFromJSONTyped(json: any, ignoreDiscriminator: boolean)
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'type': AutomationTypeEnumFromJSON(json['type']),
|
||||
'type': TypeEnumFromJSON(json['type']),
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'param1': json['param_1'] == null ? undefined : json['param_1'],
|
||||
@@ -135,7 +135,7 @@ export function AutomationToJSONTyped(value?: Omit<Automation, 'created_by'> | n
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'type': AutomationTypeEnumToJSON(value['type']),
|
||||
'type': TypeEnumToJSON(value['type']),
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'param_1': value['param1'],
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AutomationTypeEnum } from './AutomationTypeEnum';
|
||||
import type { TypeEnum } from './TypeEnum';
|
||||
import {
|
||||
AutomationTypeEnumFromJSON,
|
||||
AutomationTypeEnumFromJSONTyped,
|
||||
AutomationTypeEnumToJSON,
|
||||
AutomationTypeEnumToJSONTyped,
|
||||
} from './AutomationTypeEnum';
|
||||
TypeEnumFromJSON,
|
||||
TypeEnumFromJSONTyped,
|
||||
TypeEnumToJSON,
|
||||
TypeEnumToJSONTyped,
|
||||
} from './TypeEnum';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,10 +35,10 @@ export interface PatchedAutomation {
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {AutomationTypeEnum}
|
||||
* @type {TypeEnum}
|
||||
* @memberof PatchedAutomation
|
||||
*/
|
||||
type?: AutomationTypeEnum;
|
||||
type?: TypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
@@ -109,7 +109,7 @@ export function PatchedAutomationFromJSONTyped(json: any, ignoreDiscriminator: b
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'type': json['type'] == null ? undefined : AutomationTypeEnumFromJSON(json['type']),
|
||||
'type': json['type'] == null ? undefined : TypeEnumFromJSON(json['type']),
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'param1': json['param_1'] == null ? undefined : json['param_1'],
|
||||
@@ -133,7 +133,7 @@ export function PatchedAutomationToJSONTyped(value?: Omit<PatchedAutomation, 'cr
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'type': AutomationTypeEnumToJSON(value['type']),
|
||||
'type': TypeEnumToJSON(value['type']),
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'param_1': value['param1'],
|
||||
|
||||
@@ -4,8 +4,6 @@ export * from './AccessToken';
|
||||
export * from './AuthToken';
|
||||
export * from './AutoMealPlan';
|
||||
export * from './Automation';
|
||||
export * from './AutomationTypeEnum';
|
||||
export * from './BaseUnitEnum';
|
||||
export * from './BookmarkletImport';
|
||||
export * from './BookmarkletImportList';
|
||||
export * from './ConnectorConfigConfig';
|
||||
@@ -19,7 +17,6 @@ export * from './FoodInheritField';
|
||||
export * from './FoodShoppingUpdate';
|
||||
export * from './FoodSimple';
|
||||
export * from './Group';
|
||||
export * from './ImportImage';
|
||||
export * from './ImportLog';
|
||||
export * from './Ingredient';
|
||||
export * from './IngredientString';
|
||||
@@ -31,16 +28,6 @@ export * from './MealPlan';
|
||||
export * from './MealType';
|
||||
export * from './MethodEnum';
|
||||
export * from './NutritionInformation';
|
||||
export * from './OpenDataCategory';
|
||||
export * from './OpenDataConversion';
|
||||
export * from './OpenDataFood';
|
||||
export * from './OpenDataFoodProperty';
|
||||
export * from './OpenDataProperty';
|
||||
export * from './OpenDataStore';
|
||||
export * from './OpenDataStoreCategory';
|
||||
export * from './OpenDataUnit';
|
||||
export * from './OpenDataUnitTypeEnum';
|
||||
export * from './OpenDataVersion';
|
||||
export * from './PaginatedAutomationList';
|
||||
export * from './PaginatedBookmarkletImportListList';
|
||||
export * from './PaginatedCookLogList';
|
||||
@@ -87,13 +74,6 @@ export * from './PatchedInviteLink';
|
||||
export * from './PatchedKeyword';
|
||||
export * from './PatchedMealPlan';
|
||||
export * from './PatchedMealType';
|
||||
export * from './PatchedOpenDataCategory';
|
||||
export * from './PatchedOpenDataConversion';
|
||||
export * from './PatchedOpenDataFood';
|
||||
export * from './PatchedOpenDataProperty';
|
||||
export * from './PatchedOpenDataStore';
|
||||
export * from './PatchedOpenDataUnit';
|
||||
export * from './PatchedOpenDataVersion';
|
||||
export * from './PatchedProperty';
|
||||
export * from './PatchedPropertyType';
|
||||
export * from './PatchedRecipe';
|
||||
@@ -153,6 +133,7 @@ export * from './SupermarketCategoryRelation';
|
||||
export * from './Sync';
|
||||
export * from './SyncLog';
|
||||
export * from './ThemeEnum';
|
||||
export * from './TypeEnum';
|
||||
export * from './Unit';
|
||||
export * from './UnitConversion';
|
||||
export * from './User';
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
</template>
|
||||
</v-text-field>
|
||||
|
||||
<v-file-input v-model="image" :label="$t('Image')" @click="uploadAndConvertImage()">
|
||||
<template #append>
|
||||
<v-btn>AI Import</v-btn>
|
||||
</template>
|
||||
</v-file-input>
|
||||
|
||||
<!-- <v-textarea :placeholder="$t('paste_json')"></v-textarea> -->
|
||||
|
||||
<v-alert variant="tonal" v-if="importResponse.duplicates && importResponse.duplicates.length > 0">
|
||||
@@ -220,13 +226,17 @@ import {useDisplay} from "vuetify";
|
||||
|
||||
const {mobile} = useDisplay()
|
||||
const router = useRouter()
|
||||
const {updateRecipeImage, fileApiLoading} = useFileApi()
|
||||
const {updateRecipeImage, convertImageToRecipe, fileApiLoading} = useFileApi()
|
||||
|
||||
const stepper = ref("1")
|
||||
const dialog = ref(false)
|
||||
const loading = ref(false)
|
||||
const importUrl = ref("")
|
||||
|
||||
|
||||
|
||||
const image = ref<null|File>(null)
|
||||
|
||||
const importResponse = ref({} as RecipeFromSourceResponse)
|
||||
const keywordSelect = ref<null | SourceImportKeyword>(null)
|
||||
const editingIngredient = ref({} as SourceImportIngredient)
|
||||
@@ -246,6 +256,14 @@ function loadRecipeFromUrl() {
|
||||
})
|
||||
}
|
||||
|
||||
function uploadAndConvertImage(){
|
||||
if(image.value != null){
|
||||
convertImageToRecipe(image.value).then(r => {
|
||||
importResponse.value = r
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create recipe in database
|
||||
*/
|
||||
|
||||
@@ -12,66 +12,43 @@
|
||||
<model-edit-dialog model="MealPlan" v-model="dialog" :item="defaultItem" :activator="activator"></model-edit-dialog>
|
||||
</v-btn>
|
||||
|
||||
<v-divider></v-divider>
|
||||
<template v-if="false">
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<vue-draggable v-model="items1" group="test" handle=".drag-handle">
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
<v-text-field density="compact"></v-text-field>
|
||||
|
||||
<v-card v-for="i in items1" class="mt-1">
|
||||
<v-card-text>
|
||||
<v-icon icon="$dragHandle" class="drag-handle"></v-icon>
|
||||
{{ i.name }}
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<model-select model="Food" density="compact"></model-select>
|
||||
|
||||
</vue-draggable>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<vue-draggable v-model="items2" group="test" handle=".drag-handle" empty-insert-threshold="25">
|
||||
<v-card v-for="i in items2" class="mt-1">
|
||||
<v-card-text>
|
||||
<v-icon icon="$dragHandle" class="drag-handle"></v-icon>
|
||||
{{ i.name }}
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</vue-draggable>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
|
||||
<v-text-field density="comfortable"></v-text-field>
|
||||
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
<v-text-field density="compact"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
|
||||
</v-col>
|
||||
<v-col>
|
||||
<model-select model="Food" density="compact"></model-select>
|
||||
<model-select model="Food" density="comfortable"></model-select>
|
||||
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
<model-select model="Food"></model-select>
|
||||
<v-text-field></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
|
||||
<v-text-field density="comfortable"></v-text-field>
|
||||
<model-select model="Food"></model-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-col>
|
||||
<v-col>
|
||||
|
||||
<model-select model="Food" density="comfortable"></model-select>
|
||||
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-5">
|
||||
<v-col>
|
||||
<model-select model="Food"></model-select>
|
||||
<v-text-field></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
|
||||
<model-select model="Food"></model-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
|
||||
</template>
|
||||
@@ -85,8 +62,11 @@ import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
||||
import {DateTime} from "luxon";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
import {VueDraggable} from "vue-draggable-plus";
|
||||
import {useFileApi} from "@/composables/useFileApi";
|
||||
|
||||
const image = ref(File)
|
||||
const {convertImageToRecipe, fileApiLoading} = useFileApi()
|
||||
|
||||
const image = ref<null|File>(null)
|
||||
const response = ref('')
|
||||
|
||||
const dialog = ref(false)
|
||||
@@ -96,55 +76,11 @@ const defaultItem = ref({
|
||||
fromDate: DateTime.now().plus({day: 2}).toJSDate()
|
||||
} as MealPlan)
|
||||
|
||||
const items2 = ref([])
|
||||
const items1 = ref([
|
||||
{
|
||||
"name": "Jean",
|
||||
"id": "2"
|
||||
},
|
||||
{
|
||||
"name": "Johanna-2",
|
||||
"id": "3-2"
|
||||
},
|
||||
{
|
||||
"name": "Joao-2",
|
||||
"id": "1-2"
|
||||
},
|
||||
{
|
||||
"name": "Juan",
|
||||
"id": "4"
|
||||
},
|
||||
{
|
||||
"name": "Joao",
|
||||
"id": "1"
|
||||
},
|
||||
{
|
||||
"name": "Jean-2",
|
||||
"id": "2-2"
|
||||
},
|
||||
{
|
||||
"name": "Johanna",
|
||||
"id": "3"
|
||||
},
|
||||
{
|
||||
"name": "Juan-2",
|
||||
"id": "4-2"
|
||||
}
|
||||
])
|
||||
|
||||
function imageToRecipe() {
|
||||
const api = new ApiApi()
|
||||
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(image.value)
|
||||
|
||||
api.apiImageToRecipeCreate({image: image.value}).then(r => {
|
||||
console.log(r)
|
||||
response.value = r
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
response.value = err
|
||||
})
|
||||
if(image.value != null){
|
||||
convertImageToRecipe(image.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user