diff --git a/frontend/components/Domain/Cookbook/CookbookEditor.vue b/frontend/components/Domain/Cookbook/CookbookEditor.vue
index 5598fcb1d..aa58714e2 100644
--- a/frontend/components/Domain/Cookbook/CookbookEditor.vue
+++ b/frontend/components/Domain/Cookbook/CookbookEditor.vue
@@ -83,6 +83,11 @@ const fieldDefs: FieldDefinition[] = [
label: i18n.t("household.households"),
type: Organizer.Household,
},
+ {
+ name: "user_id",
+ label: i18n.t("user.users"),
+ type: Organizer.User,
+ },
{
name: "created_at",
label: i18n.t("general.date-created"),
diff --git a/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue b/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue
index 3d8fb76d6..eed1ec2df 100644
--- a/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue
+++ b/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue
@@ -106,6 +106,11 @@ const fieldDefs: FieldDefinition[] = [
label: i18n.t("household.households"),
type: Organizer.Household,
},
+ {
+ name: "user_id",
+ label: i18n.t("user.users"),
+ type: Organizer.User,
+ },
{
name: "last_made",
label: i18n.t("general.last-made"),
diff --git a/frontend/components/Domain/QueryFilterBuilder.vue b/frontend/components/Domain/QueryFilterBuilder.vue
index aececb2f9..8bdb2b948 100644
--- a/frontend/components/Domain/QueryFilterBuilder.vue
+++ b/frontend/components/Domain/QueryFilterBuilder.vue
@@ -1,283 +1,297 @@
-
+
-
-
+
-
+
-
-
+ {{ $globals.icons.arrowUpDown }}
+
+
+
+
+
+
-
- {{ $globals.icons.arrowUpDown }}
-
-
-
-
+
+ {{ item.raw.label }}
+
+
+
+
+
+
+
+
-
-
-
- {{ item.raw.label }}
-
-
-
-
-
-
+
+ {{ item.raw }}
+
+
+
+
+
+
+
+
-
-
-
- {{ item.raw }}
-
-
-
-
-
-
+
+ {{ item.raw.label }}
+
+
+
+
+
+
+
+
-
-
-
- {{ item.raw.label }}
-
-
-
-
-
-
+
+ {{ item.raw.label }}
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- {{ item.raw.label }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setFieldValue(field, index, val ? val.toISOString().slice(0, 10) : '')"
+
+
-
-
+ setFieldValue(field, index, val ? val.toISOString().slice(0, 10) : '')"
/>
-
-
-
-
-
-
-
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+ setFieldOrganizers(field, index, (val || []) as OrganizerBase[])"
+ />
+
+
+
+
+
-
-
-
- {{ item.raw }}
-
-
-
-
-
-
-
-
-
-
-
+
+
+ {{ item.raw }}
+
+
+
+
+
+
+
+
+
+
+
-
+
{
- const baseColMaxWidth = 55;
+ const multiple = fields.value.length > 1;
+ const adv = state.showAdvanced;
+
return {
col: {
- class: "d-flex justify-center align-end field-col pa-1",
+ class: "d-flex justify-center align-end py-0",
},
select: {
textClass: "d-flex justify-center text-center",
},
items: {
icon: {
- cols: 1,
+ cols: (_index: number) => 2,
+ sm: (_index: number) => 1,
style: "width: fit-content;",
},
leftParens: {
- cols: state.showAdvanced ? 1 : 0,
- style: `min-width: ${state.showAdvanced ? baseColMaxWidth : 0}px;`,
+ cols: (index: number) => (adv ? (index === 0 ? 2 : 0) : 0),
+ sm: (_index: number) => (adv ? 1 : 0),
},
logicalOperator: {
- cols: 1,
- style: `min-width: ${baseColMaxWidth}px;`,
+ cols: (_index: number) => 0,
+ sm: (_index: number) => (multiple ? 1 : 0),
},
fieldName: {
- cols: state.showAdvanced ? 2 : 3,
- style: `min-width: ${state.showAdvanced ? baseColMaxWidth * 2 : baseColMaxWidth * 3}px;`,
+ cols: (index: number) => {
+ if (adv) return index === 0 ? 8 : 12;
+ return index === 0 ? 10 : 12;
+ },
+ sm: (_index: number) => (adv ? 2 : 3),
},
relationalOperator: {
- cols: 2,
- style: `min-width: ${baseColMaxWidth * 2}px;`,
+ cols: (_index: number) => 12,
+ sm: (_index: number) => 2,
},
fieldValue: {
- cols: state.showAdvanced ? 3 : 4,
- style: `min-width: ${state.showAdvanced ? baseColMaxWidth * 2 : baseColMaxWidth * 3}px;`,
+ cols: (index: number) => {
+ const last = index === fields.value.length - 1;
+ if (adv) return last ? 8 : 10;
+ return last ? 10 : 12;
+ },
+ sm: (_index: number) => (adv ? 3 : 4),
},
rightParens: {
- cols: state.showAdvanced ? 1 : 0,
- style: `min-width: ${state.showAdvanced ? baseColMaxWidth : 0}px;`,
+ cols: (index: number) => (adv ? (index === fields.value.length - 1 ? 2 : 0) : 0),
+ sm: (_index: number) => (adv ? 1 : 0),
},
fieldActions: {
- cols: 1,
- style: `min-width: ${baseColMaxWidth}px;`,
+ cols: (index: number) => (index === fields.value.length - 1 ? 2 : 0),
+ sm: (_index: number) => 1,
},
},
};
@@ -651,5 +677,14 @@ const config = computed(() => {
diff --git a/frontend/components/Domain/Recipe/RecipeOrganizerSelector.vue b/frontend/components/Domain/Recipe/RecipeOrganizerSelector.vue
index 8b63e1bc1..f07da4d4c 100644
--- a/frontend/components/Domain/Recipe/RecipeOrganizerSelector.vue
+++ b/frontend/components/Domain/Recipe/RecipeOrganizerSelector.vue
@@ -8,14 +8,15 @@
:label="label"
chips
closable-chips
- item-title="name"
+ :item-title="itemTitle"
+ item-value="name"
multiple
:variant="variant"
:prepend-inner-icon="icon"
:append-icon="showAdd ? $globals.icons.create : undefined"
return-object
auto-select-first
- class="pa-0"
+ class="pa-0 ma-0"
@update:model-value="resetSearchInput"
@click:append="dialog = true"
>
@@ -33,7 +34,6 @@
{{ item.value }}
-
;
- returnObject?: boolean;
showAdd?: boolean;
showLabel?: boolean;
showIcon?: boolean;
@@ -67,7 +68,6 @@ interface Props {
const props = withDefaults(defineProps(), {
inputAttrs: () => ({}),
- returnObject: true,
showAdd: true,
showLabel: true,
showIcon: true,
@@ -80,7 +80,7 @@ const selected = defineModel<(
| RecipeCategory
| RecipeTool
| IngredientFood
- | string
+ | UserSummary
)[] | undefined>({ required: true });
onMounted(() => {
@@ -108,6 +108,8 @@ const label = computed(() => {
return i18n.t("general.foods");
case Organizer.Household:
return i18n.t("household.households");
+ case Organizer.User:
+ return i18n.t("user.users");
default:
return i18n.t("general.organizer");
}
@@ -129,11 +131,19 @@ const icon = computed(() => {
return $globals.icons.foods;
case Organizer.Household:
return $globals.icons.household;
+ case Organizer.User:
+ return $globals.icons.user;
default:
return $globals.icons.tags;
}
});
+const itemTitle = computed(() =>
+ props.selectorType === Organizer.User
+ ? (i: any) => i?.fullName ?? i?.name ?? ""
+ : "name",
+);
+
// ===========================================================================
// Store & Items Setup
@@ -143,28 +153,19 @@ const storeMap = {
[Organizer.Tool]: useToolStore(),
[Organizer.Food]: useFoodStore(),
[Organizer.Household]: useHouseholdStore(),
+ [Organizer.User]: useUserStore(),
};
-const store = computed(() => {
+const activeStore = computed(() => {
const { store } = storeMap[props.selectorType];
return store.value;
});
-const items = computed(() => {
- if (!props.returnObject) {
- return store.value.map(item => item.name);
- }
- return store.value;
+const items = computed(() => {
+ const list = (activeStore.value as unknown as any[]) ?? [];
+ return list;
});
-function removeByIndex(index: number) {
- if (selected.value === undefined) {
- return;
- }
- const newSelected = selected.value.filter((_, i) => i !== index);
- selected.value = [...newSelected];
-}
-
function appendCreated(item: any) {
if (selected.value === undefined) {
return;
diff --git a/frontend/composables/use-query-filter-builder.ts b/frontend/composables/use-query-filter-builder.ts
index 1b206d3b4..c811d66ae 100644
--- a/frontend/composables/use-query-filter-builder.ts
+++ b/frontend/composables/use-query-filter-builder.ts
@@ -168,6 +168,7 @@ export function useQueryFilterBuilder() {
|| type === Organizer.Tool
|| type === Organizer.Food
|| type === Organizer.Household
+ || type === Organizer.User
);
};
diff --git a/frontend/lib/api/types/non-generated.ts b/frontend/lib/api/types/non-generated.ts
index d320f7a38..81b81325d 100644
--- a/frontend/lib/api/types/non-generated.ts
+++ b/frontend/lib/api/types/non-generated.ts
@@ -29,7 +29,8 @@ export type RecipeOrganizer
| "tags"
| "tools"
| "foods"
- | "households";
+ | "households"
+ | "users";
export enum Organizer {
Category = "categories",
@@ -37,4 +38,5 @@ export enum Organizer {
Tool = "tools",
Food = "foods",
Household = "households",
+ User = "users",
}
diff --git a/frontend/pages/g/[groupSlug]/recipes/finder/index.vue b/frontend/pages/g/[groupSlug]/recipes/finder/index.vue
index 43903a8f8..2e208d008 100644
--- a/frontend/pages/g/[groupSlug]/recipes/finder/index.vue
+++ b/frontend/pages/g/[groupSlug]/recipes/finder/index.vue
@@ -76,13 +76,15 @@
can-confirm
@confirm="saveQueryFilter"
>
- queryFilterEditorValue = value"
- @input-j-s-o-n="(value) => queryFilterEditorValueJSON = value"
- />
+
+ queryFilterEditorValue = value"
+ @input-j-s-o-n="(value) => queryFilterEditorValueJSON = value"
+ />
+