playing with FDC search integration

This commit is contained in:
vabene1111
2025-03-20 22:09:44 +01:00
parent c36eaf934f
commit dea4fa000e
30 changed files with 344 additions and 38 deletions

View File

@@ -0,0 +1,43 @@
<template>
<v-dialog max-width="900" v-model="dialog">
<v-card>
<v-closable-card-title :title="$t('Search')" icon="$search" v-model="dialog"></v-closable-card-title>
<v-card-text>
<v-text-field v-model="query">
<template #append>
<v-btn icon="$search" @click="fdcSearch()"></v-btn>
</template>
</v-text-field>
<v-list>
<v-list-item v-for="f in fdcQueryResults?.foods">{{ f}}</v-list-item>
</v-list>
</v-card-text>
</v-card>
</v-dialog>
</template>
<script setup lang="ts">
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import {ref} from "vue";
import {ApiApi, FdcQuery} from "@/openapi";
const dialog = defineModel<boolean>({required: true})
const query = ref("")
const fdcQueryResults = ref<undefined|FdcQuery>(undefined)
function fdcSearch(){
let api = new ApiApi()
api.apiFdcSearchRetrieve({query: query.value}).then(r => {
fdcQueryResults.value = r
})
}
</script>
<style scoped>
</style>

View File

@@ -262,6 +262,7 @@
"Print": "",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "",

View File

@@ -255,6 +255,7 @@
"Print": "Печат",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Защитен",

View File

@@ -311,6 +311,7 @@
"Profile": "",
"Properties": "Egenskaber",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Egenskab",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -333,7 +333,7 @@
"Properties": "Eigenschaften",
"PropertiesFoodHelp": "Eigenschaften können für Rezepte und Lebensmittel erfasst werden. Eigenschaften von Lebensmitteln werden entsprechend der Menge für das Rezept ausgerechnet und überschreiben die Rezepteigenschaften. ",
"Properties_Food_Amount": "Eigenschaften: Lebensmittelmenge",
"Properties_Food_Unit": "Nährwert Einheit",
"Properties_Food_Unit": "Eigenschaft Einheit",
"Property": "Eigenschaft",
"PropertyType": "Eigenschafts Typ",
"Property_Editor": "Eigenschaften bearbeiten",

View File

@@ -303,6 +303,7 @@
"Profile": "",
"Properties": "Ιδιότητες",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Ιδιότητα",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -329,6 +329,7 @@
"Profile": "",
"Properties": "Propiedades",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Propiedad",
"PropertyType": "",
"Property_Editor": "Editor de Propiedades",

View File

@@ -197,6 +197,7 @@
"Print": "Tulosta",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Proteins": "Proteiinit",

View File

@@ -305,6 +305,7 @@
"Profile": "",
"Properties": "Tulajdonságok",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Tulajdonság",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -143,6 +143,7 @@
"Print": "Տպել",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Proteins": "",

View File

@@ -282,6 +282,7 @@
"Private_Recipe_Help": "Resep hanya diperlihatkan kepada Anda dan orang-orang yang dibagikan resep tersebut.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Terlindung",

View File

@@ -290,6 +290,7 @@
"Private_Recipe_Help": "La ricetta viene mostrata solo a te e a chi l'hai condivisa.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Protetto",

View File

@@ -309,6 +309,7 @@
"Profile": "",
"Properties": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -301,6 +301,7 @@
"Profile": "",
"Properties": "Egenskaper",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Egenskap",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -305,6 +305,7 @@
"Profile": "",
"Properties": "Eigenschappen",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"Property": "Eigenschap",
"PropertyType": "",
"Property_Editor": "",

View File

@@ -252,6 +252,7 @@
"Private_Recipe_Help": "A receita só é mostrada ás pessoas com que foi partilhada.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Protegido",

View File

@@ -294,6 +294,7 @@
"Private_Recipe_Help": "Rețeta este arătată doar ție și oamenilor cu care este împărtășită.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Protejat",

View File

@@ -238,6 +238,7 @@
"Print": "Распечатать",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Защищено",

View File

@@ -233,6 +233,7 @@
"Private_Recipe_Help": "Recept je prikazan samo vam in osebam, s katerimi ga delite.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Proteins": "Beljakovine",

View File

@@ -270,6 +270,7 @@
"Private_Recipe_Help": "Рецепт показаний тільки Вам і тими з ким ви поділилися їм.",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Protected": "Захищено",

View File

@@ -118,6 +118,7 @@
"Print": "",
"Profile": "",
"PropertiesFoodHelp": "",
"Properties_Food_Unit": "",
"PropertyType": "",
"Property_Editor": "",
"Proteins": "",

View File

@@ -17,6 +17,8 @@ models/CustomFilter.ts
models/DefaultPageEnum.ts
models/DeleteEnum.ts
models/ExportLog.ts
models/FdcQuery.ts
models/FdcQueryFoods.ts
models/Food.ts
models/FoodInheritField.ts
models/FoodShoppingUpdate.ts

View File

@@ -23,6 +23,7 @@ import type {
CookLog,
CustomFilter,
ExportLog,
FdcQuery,
Food,
FoodInheritField,
FoodShoppingUpdate,
@@ -165,6 +166,8 @@ import {
CustomFilterToJSON,
ExportLogFromJSON,
ExportLogToJSON,
FdcQueryFromJSON,
FdcQueryToJSON,
FoodFromJSON,
FoodToJSON,
FoodInheritFieldFromJSON,
@@ -609,6 +612,11 @@ export interface ApiExportLogUpdateRequest {
exportLog: Omit<ExportLog, 'createdBy'|'createdAt'>;
}
export interface ApiFdcSearchRetrieveRequest {
dataType?: Array<string>;
query?: string;
}
export interface ApiFoodCreateRequest {
food: Omit<Food, 'shopping'|'parent'|'numchild'|'fullName'|'substituteOnhand'>;
}
@@ -684,7 +692,7 @@ export interface ApiImageToRecipeCreateRequest {
image: string;
}
export interface ApiImageToRecipeCreate2Request {
export interface ApiImportCreateRequest {
image: string;
}
@@ -3462,6 +3470,42 @@ export class ApiApi extends runtime.BaseAPI {
return await response.value();
}
/**
*/
async apiFdcSearchRetrieveRaw(requestParameters: ApiFdcSearchRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<FdcQuery>> {
const queryParameters: any = {};
if (requestParameters['dataType'] != null) {
queryParameters['dataType'] = requestParameters['dataType'];
}
if (requestParameters['query'] != null) {
queryParameters['query'] = requestParameters['query'];
}
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.apiKey) {
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
}
const response = await this.request({
path: `/api/fdc-search/`,
method: 'GET',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.JSONApiResponse(response, (jsonValue) => FdcQueryFromJSON(jsonValue));
}
/**
*/
async apiFdcSearchRetrieve(requestParameters: ApiFdcSearchRetrieveRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<FdcQuery> {
const response = await this.apiFdcSearchRetrieveRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* logs request counts to redis cache total/per user/
*/
@@ -4165,7 +4209,7 @@ export class ApiApi extends runtime.BaseAPI {
}
const response = await this.request({
path: `/api/image-to-recipe`,
path: `/api/image-to-recipe/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
@@ -4184,11 +4228,11 @@ export class ApiApi extends runtime.BaseAPI {
/**
*/
async apiImageToRecipeCreate2Raw(requestParameters: ApiImageToRecipeCreate2Request, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RecipeFromSourceResponse>> {
async apiImportCreateRaw(requestParameters: ApiImportCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<RecipeFromSourceResponse>> {
if (requestParameters['image'] == null) {
throw new runtime.RequiredError(
'image',
'Required parameter "image" was null or undefined when calling apiImageToRecipeCreate2().'
'Required parameter "image" was null or undefined when calling apiImportCreate().'
);
}
@@ -4219,7 +4263,7 @@ export class ApiApi extends runtime.BaseAPI {
}
const response = await this.request({
path: `/api/image-to-recipe/`,
path: `/api/import/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
@@ -4231,40 +4275,11 @@ export class ApiApi extends runtime.BaseAPI {
/**
*/
async apiImageToRecipeCreate2(requestParameters: ApiImageToRecipeCreate2Request, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RecipeFromSourceResponse> {
const response = await this.apiImageToRecipeCreate2Raw(requestParameters, initOverrides);
async apiImportCreate(requestParameters: ApiImportCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<RecipeFromSourceResponse> {
const response = await this.apiImportCreateRaw(requestParameters, initOverrides);
return await response.value();
}
/**
* function to handle files passed by application importer
*/
async apiImportCreateRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
const queryParameters: any = {};
const headerParameters: runtime.HTTPHeaders = {};
if (this.configuration && this.configuration.apiKey) {
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
}
const response = await this.request({
path: `/api/import/`,
method: 'POST',
headers: headerParameters,
query: queryParameters,
}, initOverrides);
return new runtime.VoidApiResponse(response);
}
/**
* function to handle files passed by application importer
*/
async apiImportCreate(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
await this.apiImportCreateRaw(initOverrides);
}
/**
* logs request counts to redis cache total/per user/
*/

View File

@@ -0,0 +1,95 @@
/* tslint:disable */
/* eslint-disable */
/**
* Tandoor
* Tandoor API Docs
*
* The version of the OpenAPI document: 0.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
import type { FdcQueryFoods } from './FdcQueryFoods';
import {
FdcQueryFoodsFromJSON,
FdcQueryFoodsFromJSONTyped,
FdcQueryFoodsToJSON,
} from './FdcQueryFoods';
/**
*
* @export
* @interface FdcQuery
*/
export interface FdcQuery {
/**
*
* @type {number}
* @memberof FdcQuery
*/
totalHits: number;
/**
*
* @type {number}
* @memberof FdcQuery
*/
currentPage: number;
/**
*
* @type {number}
* @memberof FdcQuery
*/
totalPages: number;
/**
*
* @type {Array<FdcQueryFoods>}
* @memberof FdcQuery
*/
foods: Array<FdcQueryFoods>;
}
/**
* Check if a given object implements the FdcQuery interface.
*/
export function instanceOfFdcQuery(value: object): value is FdcQuery {
if (!('totalHits' in value) || value['totalHits'] === undefined) return false;
if (!('currentPage' in value) || value['currentPage'] === undefined) return false;
if (!('totalPages' in value) || value['totalPages'] === undefined) return false;
if (!('foods' in value) || value['foods'] === undefined) return false;
return true;
}
export function FdcQueryFromJSON(json: any): FdcQuery {
return FdcQueryFromJSONTyped(json, false);
}
export function FdcQueryFromJSONTyped(json: any, ignoreDiscriminator: boolean): FdcQuery {
if (json == null) {
return json;
}
return {
'totalHits': json['totalHits'],
'currentPage': json['currentPage'],
'totalPages': json['totalPages'],
'foods': ((json['foods'] as Array<any>).map(FdcQueryFoodsFromJSON)),
};
}
export function FdcQueryToJSON(value?: FdcQuery | null): any {
if (value == null) {
return value;
}
return {
'totalHits': value['totalHits'],
'currentPage': value['currentPage'],
'totalPages': value['totalPages'],
'foods': ((value['foods'] as Array<any>).map(FdcQueryFoodsToJSON)),
};
}

View File

@@ -0,0 +1,79 @@
/* tslint:disable */
/* eslint-disable */
/**
* Tandoor
* Tandoor API Docs
*
* The version of the OpenAPI document: 0.0.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
import { mapValues } from '../runtime';
/**
*
* @export
* @interface FdcQueryFoods
*/
export interface FdcQueryFoods {
/**
*
* @type {number}
* @memberof FdcQueryFoods
*/
fdcId: number;
/**
*
* @type {string}
* @memberof FdcQueryFoods
*/
description: string;
/**
*
* @type {string}
* @memberof FdcQueryFoods
*/
dataType: string;
}
/**
* Check if a given object implements the FdcQueryFoods interface.
*/
export function instanceOfFdcQueryFoods(value: object): value is FdcQueryFoods {
if (!('fdcId' in value) || value['fdcId'] === undefined) return false;
if (!('description' in value) || value['description'] === undefined) return false;
if (!('dataType' in value) || value['dataType'] === undefined) return false;
return true;
}
export function FdcQueryFoodsFromJSON(json: any): FdcQueryFoods {
return FdcQueryFoodsFromJSONTyped(json, false);
}
export function FdcQueryFoodsFromJSONTyped(json: any, ignoreDiscriminator: boolean): FdcQueryFoods {
if (json == null) {
return json;
}
return {
'fdcId': json['fdcId'],
'description': json['description'],
'dataType': json['dataType'],
};
}
export function FdcQueryFoodsToJSON(value?: FdcQueryFoods | null): any {
if (value == null) {
return value;
}
return {
'fdcId': value['fdcId'],
'description': value['description'],
'dataType': value['dataType'],
};
}

View File

@@ -14,6 +14,8 @@ export * from './CustomFilter';
export * from './DefaultPageEnum';
export * from './DeleteEnum';
export * from './ExportLog';
export * from './FdcQuery';
export * from './FdcQueryFoods';
export * from './Food';
export * from './FoodInheritField';
export * from './FoodShoppingUpdate';

View File

@@ -117,6 +117,9 @@
</v-col>
</v-row>
<v-btn @click="fdcDialog = true">OpenSearch</v-btn>
<fdc-search-dialog v-model="fdcDialog"></fdc-search-dialog>
</v-container>
<v-dialog v-model="dialog" max-width="600">
@@ -153,6 +156,7 @@ import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
import VClosableCardTitle from "@/components/dialogs/VClosableCardTitle.vue";
import {useUrlSearchParams} from "@vueuse/core";
import BtnCopy from "@/components/buttons/BtnCopy.vue";
import FdcSearchDialog from "@/components/dialogs/FdcSearchDialog.vue";
const params = useUrlSearchParams('history', {})
@@ -168,6 +172,8 @@ const calculatorFromNumerator = ref(250)
const calculatorFromDenominator = ref(500)
const calculatorToDenominator = ref(100)
const fdcDialog = ref(false)
const recipe = ref<undefined | Recipe>()
const propertyTypes = ref([] as PropertyType[])
const foods = ref(new Map<number, Food & { loading?: boolean }>())