tweaks and changes

This commit is contained in:
vabene1111
2025-04-02 09:01:52 +02:00
parent 838ce6615b
commit b18a1d0110
16 changed files with 195 additions and 1879 deletions

View File

@@ -3,9 +3,9 @@
<v-app-bar color="tandoor" flat density="comfortable" v-if="!useUserPreferenceStore().isAuthenticated">
</v-app-bar>
<v-app-bar color="tandoor" flat density="comfortable" v-if="useUserPreferenceStore().isAuthenticated">
<v-app-bar :color="useUserPreferenceStore().userSettings.navBgColor" flat density="comfortable" v-if="useUserPreferenceStore().isAuthenticated">
<router-link :to="{ name: 'view_home', params: {} }">
<v-img src="../../assets/brand_logo.svg" width="140px" class="ms-2"></v-img>
<v-img src="../../assets/brand_logo.svg" width="140px" class="ms-2" v-if="useUserPreferenceStore().userSettings.navShowLogo"></v-img>
</router-link>
<v-spacer></v-spacer>
<global-search-dialog></global-search-dialog>

View File

@@ -1,6 +1,7 @@
<template>
<slot name="activator">
<v-btn @click="dialog = true" variant="plain" density="default" :icon="mobile">
<v-btn @click="dialog = true" variant="plain" icon="fa-solid fa-search" class="mr-1 fa-fw" v-if="mobile"></v-btn>
<v-btn @click="dialog = true" variant="plain" v-else>
<v-icon icon="fa-solid fa-search" class="mr-1 fa-fw"></v-icon>
<span class="d-none d-sm-block">{{ $t('Search') }}</span>
<v-chip size="x-small" variant="tonal" class="d-none d-md-flex ml-1" label>{{ $t('Ctrl+K') }}</v-chip>

View File

@@ -15,6 +15,9 @@
<v-label>{{$t('Nav_Color')}}</v-label>
<v-color-picker v-model="useUserPreferenceStore().userSettings.navBgColor" mode="hex" :modes="['hex']" show-swatches :swatches="[['#ddbf86'],['#b98766'],['#b55e4f'],['#82aa8b'],['#385f84']]"></v-color-picker>
<v-select :label="$t('Theme')" class="mt-4" v-model="useUserPreferenceStore().userSettings.theme" :items="[{title: 'Tandoor', value: 'TANDOOR'}, {title: 'Tandoor Dark', value: 'TANDOOR_DARK'}, ]">
</v-select>
<v-checkbox :label="$t('Show_Logo')" :hint="$t('Show_Logo_Help')" persistent-hint v-model="useUserPreferenceStore().userSettings.navShowLogo"></v-checkbox>
<v-checkbox :label="$t('Sticky_Nav')" :hint="$t('Sticky_Nav_Help')" persistent-hint v-model="useUserPreferenceStore().userSettings.navSticky"></v-checkbox>

View File

@@ -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
@@ -35,16 +33,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
@@ -91,13 +79,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
@@ -157,6 +138,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

View File

@@ -13,12 +13,12 @@
*/
import { mapValues } from '../runtime';
import type { AutomationTypeEnum } from './AutomationTypeEnum';
import type { TypeEnum } from './TypeEnum';
import {
AutomationTypeEnumFromJSON,
AutomationTypeEnumFromJSONTyped,
AutomationTypeEnumToJSON,
} from './AutomationTypeEnum';
TypeEnumFromJSON,
TypeEnumFromJSONTyped,
TypeEnumToJSON,
} from './TypeEnum';
/**
*
@@ -34,10 +34,10 @@ export interface Automation {
id?: number;
/**
*
* @type {AutomationTypeEnum}
* @type {TypeEnum}
* @memberof Automation
*/
type: AutomationTypeEnum;
type: TypeEnum;
/**
*
* @type {string}
@@ -108,7 +108,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'],
@@ -127,7 +127,7 @@ export function AutomationToJSON(value?: Omit<Automation, 'createdBy'> | null):
return {
'id': value['id'],
'type': AutomationTypeEnumToJSON(value['type']),
'type': TypeEnumToJSON(value['type']),
'name': value['name'],
'description': value['description'],
'param_1': value['param1'],

View File

@@ -13,12 +13,12 @@
*/
import { mapValues } from '../runtime';
import type { AutomationTypeEnum } from './AutomationTypeEnum';
import type { TypeEnum } from './TypeEnum';
import {
AutomationTypeEnumFromJSON,
AutomationTypeEnumFromJSONTyped,
AutomationTypeEnumToJSON,
} from './AutomationTypeEnum';
TypeEnumFromJSON,
TypeEnumFromJSONTyped,
TypeEnumToJSON,
} from './TypeEnum';
/**
*
@@ -34,10 +34,10 @@ export interface PatchedAutomation {
id?: number;
/**
*
* @type {AutomationTypeEnum}
* @type {TypeEnum}
* @memberof PatchedAutomation
*/
type?: AutomationTypeEnum;
type?: TypeEnum;
/**
*
* @type {string}
@@ -106,7 +106,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'],
@@ -125,7 +125,7 @@ export function PatchedAutomationToJSON(value?: Omit<PatchedAutomation, 'created
return {
'id': value['id'],
'type': AutomationTypeEnumToJSON(value['type']),
'type': TypeEnumToJSON(value['type']),
'name': value['name'],
'description': value['description'],
'param_1': value['param1'],

View File

@@ -38,6 +38,12 @@ export interface RecipeFromSourceResponse {
* @memberof RecipeFromSourceResponse
*/
recipe?: SourceImportRecipe;
/**
*
* @type {number}
* @memberof RecipeFromSourceResponse
*/
recipeId?: number;
/**
*
* @type {Array<string>}
@@ -82,6 +88,7 @@ export function RecipeFromSourceResponseFromJSONTyped(json: any, ignoreDiscrimin
return {
'recipe': json['recipe'] == null ? undefined : SourceImportRecipeFromJSON(json['recipe']),
'recipeId': json['recipe_id'] == null ? undefined : json['recipe_id'],
'images': json['images'] == null ? undefined : json['images'],
'error': json['error'] == null ? undefined : json['error'],
'msg': json['msg'] == null ? undefined : json['msg'],
@@ -96,6 +103,7 @@ export function RecipeFromSourceResponseToJSON(value?: RecipeFromSourceResponse
return {
'recipe': SourceImportRecipeToJSON(value['recipe']),
'recipe_id': value['recipeId'],
'images': value['images'],
'error': value['error'],
'msg': value['msg'],

View File

@@ -44,7 +44,7 @@ export type TypeEnum = typeof TypeEnum[keyof typeof TypeEnum];
export function instanceOfTypeEnum(value: any): boolean {
for (const key in TypeEnum) {
if (Object.prototype.hasOwnProperty.call(TypeEnum, key)) {
if (TypeEnum[key as keyof typeof TypeEnum] === value) {
if (TypeEnum[key] === value) {
return true;
}
}
@@ -64,7 +64,3 @@ export function TypeEnumToJSON(value?: TypeEnum | null): any {
return value as any;
}
export function TypeEnumToJSONTyped(value: any, ignoreDiscriminator: boolean): TypeEnum {
return value as TypeEnum;
}

View File

@@ -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';
@@ -32,16 +30,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';
@@ -88,13 +76,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';
@@ -154,6 +135,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';

View File

@@ -115,19 +115,30 @@
<!-- ------------ -->
<v-stepper-window-item value="url">
<v-text-field :label="$t('Website') + ' (https://...)'" v-model="importUrl" v-if="importType == 'url'" :loading="loading"></v-text-field>
<v-text-field :label="$t('Website') + ' (https://...)'" v-model="importUrl" v-if="importType == 'url'" :loading="loading" autofocus
@keydown.enter="loadRecipeFromUrl({url: importUrl})"></v-text-field>
<v-file-input v-model="image" :label="$t('Image')" v-if="importType == 'ai'" :loading="loading"></v-file-input>
<v-textarea v-model="sourceImportText" label="JSON/HTML" :loading="loading" v-if="importType == 'source'" :hint="$t('SourceImportHelp')" persistent-hint></v-textarea>
<v-textarea v-model="sourceImportText" label="JSON/HTML" :loading="loading" v-if="importType == 'source'" :hint="$t('SourceImportHelp')"
persistent-hint autofocus @keydown.enter="loadRecipeFromUrl({data: sourceImportText})"></v-textarea>
<v-alert v-if="importResponse.error" :title="$t('Error')" :text="importResponse.msg" color="warning">
</v-alert>
<v-stepper-actions>
<template #prev>
<v-btn @click="stepper = 'type'">{{ $t('Back') }}</v-btn>
</template>
<template #next>
<v-btn @click="loadRecipeFromUrl({url: importUrl})" v-if="importType == 'url'" :disabled="importUrl == ''" :loading="loading">{{ $t('Load') }}</v-btn>
<v-btn @click="loadRecipeFromUrl({data: sourceImportText})" v-if="importType == 'source'" :disabled="sourceImportText == ''" :loading="loading">{{ $t('Load') }}</v-btn>
<v-btn @click="loadRecipeFromUrl({url: importUrl})" v-if="importType == 'url'" :disabled="importUrl == ''" :loading="loading">{{
$t('Load')
}}
</v-btn>
<v-btn @click="loadRecipeFromUrl({data: sourceImportText})" v-if="importType == 'source'" :disabled="sourceImportText == ''"
:loading="loading">{{ $t('Load') }}
</v-btn>
<v-btn @click="uploadAndConvertImage()" v-if="importType == 'ai'" :disabled="image == null" :loading="loading">{{ $t('Load') }}</v-btn>
</template>
</v-stepper-actions>
@@ -387,13 +398,15 @@
<!-- Bookmarklet -->
<!-- ------------ -->
<v-stepper-window-item value="bookmarklet">
{{$t('BookmarkletImportSubtitle')}}
{{ $t('BookmarkletImportSubtitle') }}
<ol>
<li>1. {{$t('BookmarkletHelp1')}}</li>
<li> <v-btn :href="bookmarkletContent" color="primary">{{$t('ImportIntoTandoor')}}</v-btn></li>
<li>2. {{$t('BookmarkletHelp2')}}</li>
<li>3. {{$t('BookmarkletHelp3')}}</li>
<li>1. {{ $t('BookmarkletHelp1') }}</li>
<li>
<v-btn :href="bookmarkletContent" color="primary">{{ $t('ImportIntoTandoor') }}</v-btn>
</li>
<li>2. {{ $t('BookmarkletHelp2') }}</li>
<li>3. {{ $t('BookmarkletHelp3') }}</li>
</ol>
<v-stepper-actions>
@@ -499,7 +512,14 @@ onMounted(() => {
function loadRecipeFromUrl(recipeFromSourceRequest: RecipeFromSource) {
let api = new ApiApi()
loading.value = true
importResponse.value = {} as RecipeFromSourceResponse
api.apiRecipeFromSourceCreate({recipeFromSource: recipeFromSourceRequest}).then(r => {
if (r.recipeId != null) {
router.push({name: 'RecipeViewPage', params: {id: r.recipeId}})
return
}
importResponse.value = r
if (importResponse.value.duplicates && importResponse.value.duplicates.length > 0) {
@@ -508,7 +528,13 @@ function loadRecipeFromUrl(recipeFromSourceRequest: RecipeFromSource) {
stepper.value = 'image_chooser'
}
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
err.response.json().then(r => {
if (r.error) {
importResponse.value = r
} else {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, r)
}
})
}).finally(() => {
loading.value = false
})

View File

@@ -5,6 +5,7 @@ import {ApiApi, ServerSettings, Space, Supermarket, UserPreference, UserSpace} f
import {ShoppingGroupingOptions} from "@/types/Shopping";
import {computed, ComputedRef, ref} from "vue";
import {DeviceSettings} from "@/types/settings";
import {useTheme} from "vuetify";
const DEVICE_SETTINGS_KEY = 'TANDOOR_DEVICE_SETTINGS'
const USER_PREFERENCE_KEY = 'TANDOOR_USER_PREFERENCE'
@@ -43,6 +44,8 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
*/
let isAuthenticated = ref(false)
let theme = useTheme()
/**
* holds the active user space if there is one or null if not
*/
@@ -66,6 +69,7 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
if (r.length == 1) {
userSettings.value = r[0]
isAuthenticated.value = true
updateTheme()
} else {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, r)
}
@@ -84,6 +88,7 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
api.apiUserPreferencePartialUpdate({user: userSettings.value.user.id!, patchedUserPreference: userSettings.value}).then(r => {
userSettings.value = r
updateTheme()
useMessageStore().addPreparedMessage(PreparedMessage.UPDATE_SUCCESS)
}).catch(err => {
useMessageStore().addError(ErrorMessageType.UPDATE_ERROR, err)
@@ -196,12 +201,24 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
}
}
/**
* applies user settings regarding themes/styling
*/
function updateTheme() {
if (userSettings.value.theme == 'TANDOOR') {
theme.global.name.value = 'light'
} else if (userSettings.value.theme == 'TANDOOR_DARK') {
theme.global.name.value = 'dark'
}
}
// always load settings on first initialization of store
loadUserSettings()
loadServerSettings()
loadActiveSpace()
loadUserSpaces()
loadSpaces()
updateTheme()
return {
deviceSettings,
@@ -216,7 +233,8 @@ export const useUserPreferenceStore = defineStore('user_preference_store', () =>
loadServerSettings,
updateUserSettings,
switchSpace,
resetDeviceSettings
resetDeviceSettings,
updateTheme,
}
})