mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-04 05:39:00 -05:00
tweaks and changes
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
@@ -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'],
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user