mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-05 05:25:26 +02:00
fix: QueryFilter Hydration & script setup (#5839)
This commit is contained in:
parent
d6d247f1f8
commit
eefe613aaf
5 changed files with 534 additions and 658 deletions
|
@ -44,33 +44,17 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
|
||||||
import { Organizer } from "~/lib/api/types/non-generated";
|
import { Organizer } from "~/lib/api/types/non-generated";
|
||||||
import QueryFilterBuilder from "~/components/Domain/QueryFilterBuilder.vue";
|
import QueryFilterBuilder from "~/components/Domain/QueryFilterBuilder.vue";
|
||||||
import type { FieldDefinition } from "~/composables/use-query-filter-builder";
|
import type { FieldDefinition } from "~/composables/use-query-filter-builder";
|
||||||
|
import type { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
const modelValue = defineModel<ReadCookBook>({ required: true });
|
||||||
components: { QueryFilterBuilder },
|
|
||||||
props: {
|
|
||||||
modelValue: {
|
|
||||||
type: Object as () => ReadCookBook,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
type: Object as () => any,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["update:modelValue"],
|
|
||||||
setup(props, { emit }) {
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
|
const cookbook = toRef(modelValue);
|
||||||
const cookbook = toRef(() => props.modelValue);
|
|
||||||
|
|
||||||
function handleInput(value: string | undefined) {
|
function handleInput(value: string | undefined) {
|
||||||
cookbook.value.queryFilterString = value || "";
|
cookbook.value.queryFilterString = value || "";
|
||||||
emit("update:modelValue", cookbook.value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldDefs: FieldDefinition[] = [
|
const fieldDefs: FieldDefinition[] = [
|
||||||
|
@ -110,12 +94,4 @@ export default defineNuxtComponent({
|
||||||
type: "date",
|
type: "date",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
|
||||||
cookbook,
|
|
||||||
handleInput,
|
|
||||||
fieldDefs,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<CookbookEditor
|
<CookbookEditor
|
||||||
v-model="editTarget"
|
v-model="editTarget"
|
||||||
:actions="actions"
|
|
||||||
/>
|
/>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
@ -65,7 +64,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { useLazyRecipes } from "~/composables/recipes";
|
import { useLazyRecipes } from "~/composables/recipes";
|
||||||
import RecipeCardSection from "@/components/Domain/Recipe/RecipeCardSection.vue";
|
import RecipeCardSection from "@/components/Domain/Recipe/RecipeCardSection.vue";
|
||||||
import { useCookbookStore } from "~/composables/store/use-cookbook-store";
|
import { useCookbookStore } from "~/composables/store/use-cookbook-store";
|
||||||
|
@ -74,9 +73,6 @@ import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||||
import type { RecipeCookBook } from "~/lib/api/types/cookbook";
|
import type { RecipeCookBook } from "~/lib/api/types/cookbook";
|
||||||
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
|
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
|
||||||
components: { RecipeCardSection, CookbookEditor },
|
|
||||||
setup() {
|
|
||||||
const $auth = useMealieAuth();
|
const $auth = useMealieAuth();
|
||||||
const { isOwnGroup } = useLoggedInState();
|
const { isOwnGroup } = useLoggedInState();
|
||||||
|
|
||||||
|
@ -89,7 +85,6 @@ export default defineNuxtComponent({
|
||||||
const { actions } = useCookbookStore();
|
const { actions } = useCookbookStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const tab = ref(null);
|
|
||||||
const book = getOne(slug);
|
const book = getOne(slug);
|
||||||
|
|
||||||
const isOwnHousehold = computed(() => {
|
const isOwnHousehold = computed(() => {
|
||||||
|
@ -132,23 +127,4 @@ export default defineNuxtComponent({
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: book?.value?.name || "Cookbook",
|
title: book?.value?.name || "Cookbook",
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
book,
|
|
||||||
slug,
|
|
||||||
tab,
|
|
||||||
appendRecipes,
|
|
||||||
assignSorted,
|
|
||||||
recipes,
|
|
||||||
removeRecipe,
|
|
||||||
replaceRecipes,
|
|
||||||
canEdit,
|
|
||||||
dialogStates,
|
|
||||||
editTarget,
|
|
||||||
handleEditCookbook,
|
|
||||||
editCookbook,
|
|
||||||
actions,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -163,14 +163,14 @@
|
||||||
max-width="290px"
|
max-width="290px"
|
||||||
min-width="auto"
|
min-width="auto"
|
||||||
>
|
>
|
||||||
<template #activator="{ props }">
|
<template #activator="{ props: activatorProps }">
|
||||||
<v-text-field
|
<v-text-field
|
||||||
v-model="field.value"
|
v-model="field.value"
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:prepend-icon="$globals.icons.calendar"
|
:prepend-icon="$globals.icons.calendar"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
color="primary"
|
color="primary"
|
||||||
v-bind="props"
|
v-bind="activatorProps"
|
||||||
readonly
|
readonly
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -184,53 +184,48 @@
|
||||||
</v-menu>
|
</v-menu>
|
||||||
<RecipeOrganizerSelector
|
<RecipeOrganizerSelector
|
||||||
v-else-if="field.type === Organizer.Category"
|
v-else-if="field.type === Organizer.Category"
|
||||||
:model-value="field.organizers"
|
v-model="field.organizers"
|
||||||
:selector-type="Organizer.Category"
|
:selector-type="Organizer.Category"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:show-icon="false"
|
:show-icon="false"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
@update:model-value="setOrganizerValues(field, index, $event)"
|
|
||||||
/>
|
/>
|
||||||
<RecipeOrganizerSelector
|
<RecipeOrganizerSelector
|
||||||
v-else-if="field.type === Organizer.Tag"
|
v-else-if="field.type === Organizer.Tag"
|
||||||
:model-value="field.organizers"
|
v-model="field.organizers"
|
||||||
:selector-type="Organizer.Tag"
|
:selector-type="Organizer.Tag"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:show-icon="false"
|
:show-icon="false"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
@update:model-value="setOrganizerValues(field, index, $event)"
|
|
||||||
/>
|
/>
|
||||||
<RecipeOrganizerSelector
|
<RecipeOrganizerSelector
|
||||||
v-else-if="field.type === Organizer.Tool"
|
v-else-if="field.type === Organizer.Tool"
|
||||||
:model-value="field.organizers"
|
v-model="field.organizers"
|
||||||
:selector-type="Organizer.Tool"
|
:selector-type="Organizer.Tool"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:show-icon="false"
|
:show-icon="false"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
@update:model-value="setOrganizerValues(field, index, $event)"
|
|
||||||
/>
|
/>
|
||||||
<RecipeOrganizerSelector
|
<RecipeOrganizerSelector
|
||||||
v-else-if="field.type === Organizer.Food"
|
v-else-if="field.type === Organizer.Food"
|
||||||
:model-value="field.organizers"
|
v-model="field.organizers"
|
||||||
:selector-type="Organizer.Food"
|
:selector-type="Organizer.Food"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:show-icon="false"
|
:show-icon="false"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
@update:model-value="setOrganizerValues(field, index, $event)"
|
|
||||||
/>
|
/>
|
||||||
<RecipeOrganizerSelector
|
<RecipeOrganizerSelector
|
||||||
v-else-if="field.type === Organizer.Household"
|
v-else-if="field.type === Organizer.Household"
|
||||||
:model-value="field.organizers"
|
v-model="field.organizers"
|
||||||
:selector-type="Organizer.Household"
|
:selector-type="Organizer.Household"
|
||||||
:show-add="false"
|
:show-add="false"
|
||||||
:show-label="false"
|
:show-label="false"
|
||||||
:show-icon="false"
|
:show-icon="false"
|
||||||
variant="underlined"
|
variant="underlined"
|
||||||
@update:model-value="setOrganizerValues(field, index, $event)"
|
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<!-- right parenthesis -->
|
<!-- right parenthesis -->
|
||||||
|
@ -297,7 +292,7 @@
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { VueDraggable } from "vue-draggable-plus";
|
import { VueDraggable } from "vue-draggable-plus";
|
||||||
import { useDebounceFn } from "@vueuse/core";
|
import { useDebounceFn } from "@vueuse/core";
|
||||||
import { useHouseholdSelf } from "~/composables/use-households";
|
import { useHouseholdSelf } from "~/composables/use-households";
|
||||||
|
@ -307,12 +302,7 @@ import type { LogicalOperator, QueryFilterJSON, QueryFilterJSONPart, RelationalK
|
||||||
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
||||||
import { type Field, type FieldDefinition, type FieldValue, type OrganizerBase, useQueryFilterBuilder } from "~/composables/use-query-filter-builder";
|
import { type Field, type FieldDefinition, type FieldValue, type OrganizerBase, useQueryFilterBuilder } from "~/composables/use-query-filter-builder";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
const props = defineProps({
|
||||||
components: {
|
|
||||||
VueDraggable,
|
|
||||||
RecipeOrganizerSelector,
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
fieldDefs: {
|
fieldDefs: {
|
||||||
type: Array as () => FieldDefinition[],
|
type: Array as () => FieldDefinition[],
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -321,9 +311,13 @@ export default defineNuxtComponent({
|
||||||
type: Object as () => QueryFilterJSON | null,
|
type: Object as () => QueryFilterJSON | null,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
emits: ["input", "inputJSON"],
|
|
||||||
setup(props, context) {
|
const emit = defineEmits<{
|
||||||
|
(event: "input", value: string | undefined): void;
|
||||||
|
(event: "inputJSON", value: QueryFilterJSON | undefined): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
const { household } = useHouseholdSelf();
|
const { household } = useHouseholdSelf();
|
||||||
const { logOps, relOps, buildQueryFilterString, getFieldFromFieldDef, isOrganizerType } = useQueryFilterBuilder();
|
const { logOps, relOps, buildQueryFilterString, getFieldFromFieldDef, isOrganizerType } = useQueryFilterBuilder();
|
||||||
|
|
||||||
|
@ -337,6 +331,7 @@ export default defineNuxtComponent({
|
||||||
datePickers: [] as boolean[],
|
datePickers: [] as boolean[],
|
||||||
drag: false,
|
drag: false,
|
||||||
});
|
});
|
||||||
|
const { showAdvanced, datePickers, drag } = toRefs(state);
|
||||||
|
|
||||||
const storeMap = {
|
const storeMap = {
|
||||||
[Organizer.Category]: useCategoryStore(),
|
[Organizer.Category]: useCategoryStore(),
|
||||||
|
@ -369,7 +364,7 @@ export default defineNuxtComponent({
|
||||||
id: useUid(),
|
id: useUid(),
|
||||||
});
|
});
|
||||||
state.datePickers.push(false);
|
state.datePickers.push(false);
|
||||||
};
|
}
|
||||||
|
|
||||||
function setField(index: number, fieldLabel: string) {
|
function setField(index: number, fieldLabel: string) {
|
||||||
state.datePickers[index] = false;
|
state.datePickers[index] = false;
|
||||||
|
@ -419,15 +414,10 @@ export default defineNuxtComponent({
|
||||||
fields.value[index].values = values;
|
fields.value[index].values = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setOrganizerValues(field: FieldWithId, index: number, values: OrganizerBase[]) {
|
|
||||||
setFieldValues(field, index, values.map(value => value.id.toString()));
|
|
||||||
fields.value[index].organizers = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeField(index: number) {
|
function removeField(index: number) {
|
||||||
fields.value.splice(index, 1);
|
fields.value.splice(index, 1);
|
||||||
state.datePickers.splice(index, 1);
|
state.datePickers.splice(index, 1);
|
||||||
};
|
}
|
||||||
|
|
||||||
const fieldsUpdater = useDebounceFn((/* newFields: typeof fields.value */) => {
|
const fieldsUpdater = useDebounceFn((/* newFields: typeof fields.value */) => {
|
||||||
/* newFields.forEach((field, index) => {
|
/* newFields.forEach((field, index) => {
|
||||||
|
@ -441,19 +431,17 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
state.qfValid = !!qf;
|
state.qfValid = !!qf;
|
||||||
|
|
||||||
context.emit("input", qf || undefined);
|
emit("input", qf || undefined);
|
||||||
context.emit("inputJSON", qf ? buildQueryFilterJSON() : undefined);
|
emit("inputJSON", qf ? buildQueryFilterJSON() : undefined);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
watch(fields, fieldsUpdater, { deep: true });
|
watch(fields, fieldsUpdater, { deep: true });
|
||||||
|
|
||||||
async function hydrateOrganizers(field: FieldWithId, index: number) {
|
async function hydrateOrganizers(field: FieldWithId, _index: number) {
|
||||||
if (!field.values?.length || !isOrganizerType(field.type)) {
|
if (!field.values?.length || !isOrganizerType(field.type)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
field.organizers = [];
|
|
||||||
|
|
||||||
const { store, actions } = storeMap[field.type];
|
const { store, actions } = storeMap[field.type];
|
||||||
if (!store.value.length) {
|
if (!store.value.length) {
|
||||||
await actions.refresh();
|
await actions.refresh();
|
||||||
|
@ -467,8 +455,9 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
return organizer;
|
return organizer;
|
||||||
});
|
});
|
||||||
|
|
||||||
field.organizers = organizers.filter(organizer => organizer !== undefined) as OrganizerBase[];
|
field.organizers = organizers.filter(organizer => organizer !== undefined) as OrganizerBase[];
|
||||||
setOrganizerValues(field, index, field.organizers);
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initFieldsError(error = "") {
|
function initFieldsError(error = "") {
|
||||||
|
@ -482,14 +471,15 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeFields() {
|
async function initializeFields() {
|
||||||
if (!props.initialQueryFilter?.parts?.length) {
|
if (!props.initialQueryFilter?.parts?.length) {
|
||||||
return initFieldsError();
|
return initFieldsError();
|
||||||
};
|
}
|
||||||
|
|
||||||
const initFields: FieldWithId[] = [];
|
const initFields: FieldWithId[] = [];
|
||||||
let error = false;
|
let error = false;
|
||||||
props.initialQueryFilter.parts.forEach((part: QueryFilterJSONPart, index: number) => {
|
|
||||||
|
for (const [index, part] of props.initialQueryFilter.parts.entries()) {
|
||||||
const fieldDef = props.fieldDefs.find(fieldDef => fieldDef.name === part.attributeName);
|
const fieldDef = props.fieldDefs.find(fieldDef => fieldDef.name === part.attributeName);
|
||||||
if (!fieldDef) {
|
if (!fieldDef) {
|
||||||
error = true;
|
error = true;
|
||||||
|
@ -522,7 +512,7 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOrganizerType(field.type)) {
|
if (isOrganizerType(field.type)) {
|
||||||
hydrateOrganizers(field, index);
|
await hydrateOrganizers(field, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (field.type === "boolean") {
|
else if (field.type === "boolean") {
|
||||||
|
@ -553,7 +543,7 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
initFields.push(field);
|
initFields.push(field);
|
||||||
});
|
}
|
||||||
|
|
||||||
if (initFields.length && !error) {
|
if (initFields.length && !error) {
|
||||||
fields.value = initFields;
|
fields.value = initFields;
|
||||||
|
@ -561,14 +551,16 @@ export default defineNuxtComponent({
|
||||||
else {
|
else {
|
||||||
initFieldsError();
|
initFieldsError();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
initializeFields();
|
await initializeFields();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
initFieldsError(`Error initializing fields: ${(error || "").toString()}`);
|
initFieldsError(`Error initializing fields: ${(error || "").toString()}`);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function buildQueryFilterJSON(): QueryFilterJSON {
|
function buildQueryFilterJSON(): QueryFilterJSON {
|
||||||
const parts = fields.value.map((field) => {
|
const parts = fields.value.map((field) => {
|
||||||
|
@ -643,30 +635,6 @@ export default defineNuxtComponent({
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
Organizer,
|
|
||||||
...toRefs(state),
|
|
||||||
logOps,
|
|
||||||
relOps,
|
|
||||||
config,
|
|
||||||
firstDayOfWeek,
|
|
||||||
onDragEnd,
|
|
||||||
// Fields
|
|
||||||
fields,
|
|
||||||
addField,
|
|
||||||
setField,
|
|
||||||
setLeftParenthesisValue,
|
|
||||||
setRightParenthesisValue,
|
|
||||||
setLogicalOperatorValue,
|
|
||||||
setRelationalOperatorValue,
|
|
||||||
setFieldValue,
|
|
||||||
setFieldValues,
|
|
||||||
setOrganizerValues,
|
|
||||||
removeField,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
v-model="selected"
|
v-model="selected"
|
||||||
v-bind="inputAttrs"
|
v-bind="inputAttrs"
|
||||||
v-model:search="searchInput"
|
v-model:search="searchInput"
|
||||||
:items="storeItem"
|
:items="items"
|
||||||
:label="label"
|
:label="label"
|
||||||
chips
|
chips
|
||||||
closable-chips
|
closable-chips
|
||||||
|
@ -46,67 +46,40 @@
|
||||||
</v-autocomplete>
|
</v-autocomplete>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import type { IngredientFood, RecipeCategory, RecipeTag } from "~/lib/api/types/recipe";
|
import type { IngredientFood, RecipeCategory, RecipeTag } from "~/lib/api/types/recipe";
|
||||||
import type { RecipeTool } from "~/lib/api/types/admin";
|
import type { RecipeTool } from "~/lib/api/types/admin";
|
||||||
import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated";
|
import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated";
|
||||||
import type { HouseholdSummary } from "~/lib/api/types/household";
|
import type { HouseholdSummary } from "~/lib/api/types/household";
|
||||||
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
import { useCategoryStore, useFoodStore, useHouseholdStore, useTagStore, useToolStore } from "~/composables/store";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
interface Props {
|
||||||
props: {
|
selectorType: RecipeOrganizer;
|
||||||
modelValue: {
|
inputAttrs?: Record<string, any>;
|
||||||
type: Array as () => (
|
returnObject?: boolean;
|
||||||
|
showAdd?: boolean;
|
||||||
|
showLabel?: boolean;
|
||||||
|
showIcon?: boolean;
|
||||||
|
variant?: "filled" | "underlined" | "outlined" | "plain" | "solo" | "solo-inverted" | "solo-filled";
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
inputAttrs: () => ({}),
|
||||||
|
returnObject: true,
|
||||||
|
showAdd: true,
|
||||||
|
showLabel: true,
|
||||||
|
showIcon: true,
|
||||||
|
variant: "outlined",
|
||||||
|
});
|
||||||
|
|
||||||
|
const selected = defineModel<(
|
||||||
| HouseholdSummary
|
| HouseholdSummary
|
||||||
| RecipeTag
|
| RecipeTag
|
||||||
| RecipeCategory
|
| RecipeCategory
|
||||||
| RecipeTool
|
| RecipeTool
|
||||||
| IngredientFood
|
| IngredientFood
|
||||||
| string
|
| string
|
||||||
)[] | undefined,
|
)[] | undefined>({ required: true });
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* The type of organizer to use.
|
|
||||||
*/
|
|
||||||
selectorType: {
|
|
||||||
type: String as () => RecipeOrganizer,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
inputAttrs: {
|
|
||||||
type: Object as () => Record<string, any>,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
returnObject: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
showAdd: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
showLabel: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
showIcon: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
variant: {
|
|
||||||
type: String as () => "filled" | "underlined" | "outlined" | "plain" | "solo" | "solo-inverted" | "solo-filled",
|
|
||||||
default: "outlined",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["update:modelValue"],
|
|
||||||
|
|
||||||
setup(props, context) {
|
|
||||||
const selected = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: (val) => {
|
|
||||||
context.emit("update:modelValue", val);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (selected.value === undefined) {
|
if (selected.value === undefined) {
|
||||||
|
@ -205,21 +178,6 @@ export default defineNuxtComponent({
|
||||||
function resetSearchInput() {
|
function resetSearchInput() {
|
||||||
searchInput.value = "";
|
searchInput.value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
Organizer,
|
|
||||||
appendCreated,
|
|
||||||
dialog,
|
|
||||||
storeItem: items,
|
|
||||||
label,
|
|
||||||
icon,
|
|
||||||
selected,
|
|
||||||
removeByIndex,
|
|
||||||
searchInput,
|
|
||||||
resetSearchInput,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
@cancel="deleteCreateTarget()"
|
@cancel="deleteCreateTarget()"
|
||||||
>
|
>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<CookbookEditor :key="createTargetKey" v-model="createTarget" :actions="actions" />
|
<CookbookEditor :key="createTargetKey" v-model="createTarget" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
|
||||||
|
@ -105,9 +105,7 @@
|
||||||
<v-expansion-panel-text>
|
<v-expansion-panel-text>
|
||||||
<CookbookEditor
|
<CookbookEditor
|
||||||
v-model="myCookbooks[index]"
|
v-model="myCookbooks[index]"
|
||||||
:actions="actions"
|
|
||||||
:collapsable="false"
|
:collapsable="false"
|
||||||
@delete="deleteEventHandler"
|
|
||||||
/>
|
/>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue