mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-19 13:19:41 +02:00
fix: user & household creation (#5699)
This commit is contained in:
parent
40d2ac9a6b
commit
9cfc54b1f5
4 changed files with 131 additions and 206 deletions
|
@ -45,28 +45,11 @@ export const useGroupSelf = function () {
|
||||||
export const useGroups = function () {
|
export const useGroups = function () {
|
||||||
const api = useUserApi();
|
const api = useUserApi();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const groups = ref<GroupSummary[] | null>(null);
|
||||||
|
|
||||||
function getAllGroups() {
|
async function getAllGroups() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const asyncKey = String(Date.now());
|
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" });
|
||||||
const { data: groups } = useAsyncData(asyncKey, async () => {
|
|
||||||
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" }); ;
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
return data.items;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
loading.value = false;
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshAllGroups() {
|
|
||||||
loading.value = true;
|
|
||||||
const { data } = await api.groups.getAll(1, -1, { orderBy: "name", orderDirection: "asc" }); ;
|
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
groups.value = data.items;
|
groups.value = data.items;
|
||||||
|
@ -78,11 +61,15 @@ export const useGroups = function () {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function refreshAllGroups() {
|
||||||
|
await getAllGroups();
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteGroup(id: string | number) {
|
async function deleteGroup(id: string | number) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await api.groups.deleteOne(id);
|
const { data } = await api.groups.deleteOne(id);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
refreshAllGroups();
|
await refreshAllGroups();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +80,13 @@ export const useGroups = function () {
|
||||||
if (data && groups.value) {
|
if (data && groups.value) {
|
||||||
groups.value.push(data);
|
groups.value.push(data);
|
||||||
}
|
}
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = getAllGroups();
|
// Initialize data on first call
|
||||||
|
if (!groups.value) {
|
||||||
|
getAllGroups();
|
||||||
|
}
|
||||||
|
|
||||||
return { groups, getAllGroups, refreshAllGroups, deleteGroup, createGroup };
|
return { groups, getAllGroups, refreshAllGroups, deleteGroup, createGroup };
|
||||||
};
|
};
|
||||||
|
|
|
@ -48,29 +48,12 @@ export const useHouseholdSelf = function () {
|
||||||
export const useAdminHouseholds = function () {
|
export const useAdminHouseholds = function () {
|
||||||
const api = useAdminApi();
|
const api = useAdminApi();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const households = ref<HouseholdInDB[] | null>(null);
|
||||||
|
|
||||||
function getAllHouseholds() {
|
async function getAllHouseholds() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const asyncKey = String(Date.now());
|
|
||||||
const { data: households } = useAsyncData(asyncKey, async () => {
|
|
||||||
const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" });
|
const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" });
|
||||||
|
|
||||||
if (data) {
|
|
||||||
return data.items;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
loading.value = false;
|
|
||||||
return households;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshAllHouseholds() {
|
|
||||||
loading.value = true;
|
|
||||||
const { data } = await api.households.getAll(1, -1, { orderBy: "name, group.name", orderDirection: "asc" }); ;
|
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
households.value = data.items;
|
households.value = data.items;
|
||||||
}
|
}
|
||||||
|
@ -81,11 +64,15 @@ export const useAdminHouseholds = function () {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function refreshAllHouseholds() {
|
||||||
|
await getAllHouseholds();
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteHousehold(id: string | number) {
|
async function deleteHousehold(id: string | number) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await api.households.deleteOne(id);
|
const { data } = await api.households.deleteOne(id);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
refreshAllHouseholds();
|
await refreshAllHouseholds();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +83,9 @@ export const useAdminHouseholds = function () {
|
||||||
if (data && households.value) {
|
if (data && households.value) {
|
||||||
households.value.push(data);
|
households.value.push(data);
|
||||||
}
|
}
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const households = getAllHouseholds();
|
|
||||||
function useHouseholdsInGroup(groupIdRef: Ref<string>) {
|
function useHouseholdsInGroup(groupIdRef: Ref<string>) {
|
||||||
return computed(
|
return computed(
|
||||||
() => {
|
() => {
|
||||||
|
@ -109,6 +96,10 @@ export const useAdminHouseholds = function () {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!households.value) {
|
||||||
|
getAllHouseholds();
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
households,
|
households,
|
||||||
useHouseholdsInGroup,
|
useHouseholdsInGroup,
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
:items="groups"
|
:items="groups"
|
||||||
item-title="name"
|
item-title="name"
|
||||||
item-value="id"
|
item-value="id"
|
||||||
:return-object="false"
|
|
||||||
variant="filled"
|
variant="filled"
|
||||||
:label="$t('household.household-group')"
|
:label="$t('household.household-group')"
|
||||||
:rules="[validators.required]"
|
:rules="[validators.required]"
|
||||||
|
@ -94,10 +93,7 @@
|
||||||
icon
|
icon
|
||||||
color="error"
|
color="error"
|
||||||
variant="text"
|
variant="text"
|
||||||
@click.stop="
|
@click.stop="confirmDialog = true; deleteTarget = item.id"
|
||||||
confirmDialog = true;
|
|
||||||
deleteTarget = +item.id;
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<v-icon>
|
<v-icon>
|
||||||
{{ $globals.icons.delete }}
|
{{ $globals.icons.delete }}
|
||||||
|
@ -114,7 +110,7 @@
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { fieldTypes } from "~/composables/forms";
|
import { fieldTypes } from "~/composables/forms";
|
||||||
import { useGroups } from "~/composables/use-groups";
|
import { useGroups } from "~/composables/use-groups";
|
||||||
import { useAdminHouseholds } from "~/composables/use-households";
|
import { useAdminHouseholds } from "~/composables/use-households";
|
||||||
|
@ -122,30 +118,28 @@ import { validators } from "~/composables/use-validators";
|
||||||
import type { HouseholdInDB } from "~/lib/api/types/household";
|
import type { HouseholdInDB } from "~/lib/api/types/household";
|
||||||
import type { VForm } from "~/types/auto-forms";
|
import type { VForm } from "~/types/auto-forms";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
definePageMeta({
|
||||||
setup() {
|
|
||||||
definePageMeta({
|
|
||||||
layout: "admin",
|
layout: "admin",
|
||||||
});
|
});
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
|
|
||||||
// Set page title
|
useSeoMeta({
|
||||||
useSeoMeta({
|
|
||||||
title: i18n.t("household.manage-households"),
|
title: i18n.t("household.manage-households"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { groups } = useGroups();
|
const { groups } = useGroups();
|
||||||
const { households, refreshAllHouseholds, deleteHousehold, createHousehold } = useAdminHouseholds();
|
const { households, deleteHousehold, createHousehold } = useAdminHouseholds();
|
||||||
const refNewHouseholdForm = ref<VForm | null>(null);
|
|
||||||
|
|
||||||
const state = reactive({
|
const refNewHouseholdForm = ref<VForm | null>(null);
|
||||||
createDialog: false,
|
|
||||||
confirmDialog: false,
|
const createDialog = ref(false);
|
||||||
loading: false,
|
const confirmDialog = ref(false);
|
||||||
deleteTarget: 0,
|
const deleteTarget = ref<string>("");
|
||||||
search: "",
|
const search = ref("");
|
||||||
headers: [
|
const updateMode = ref(false);
|
||||||
|
|
||||||
|
const headers = [
|
||||||
{
|
{
|
||||||
title: i18n.t("household.household"),
|
title: i18n.t("household.household"),
|
||||||
align: "start",
|
align: "start",
|
||||||
|
@ -157,9 +151,9 @@ export default defineNuxtComponent({
|
||||||
{ title: i18n.t("user.total-users"), value: "users" },
|
{ title: i18n.t("user.total-users"), value: "users" },
|
||||||
{ title: i18n.t("user.webhooks-enabled"), value: "webhookEnable" },
|
{ title: i18n.t("user.webhooks-enabled"), value: "webhookEnable" },
|
||||||
{ title: i18n.t("general.delete"), value: "actions" },
|
{ title: i18n.t("general.delete"), value: "actions" },
|
||||||
],
|
];
|
||||||
updateMode: false,
|
|
||||||
createHouseholdForm: {
|
const createHouseholdForm = reactive({
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: i18n.t("household.household-name"),
|
label: i18n.t("household.household-name"),
|
||||||
|
@ -172,42 +166,25 @@ export default defineNuxtComponent({
|
||||||
groupId: "",
|
groupId: "",
|
||||||
name: "",
|
name: "",
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
|
||||||
function openDialog() {
|
function openDialog() {
|
||||||
state.createDialog = true;
|
createDialog.value = true;
|
||||||
state.createHouseholdForm.data.name = "";
|
createHouseholdForm.data.name = "";
|
||||||
state.createHouseholdForm.data.groupId = "";
|
createHouseholdForm.data.groupId = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
function handleRowClick(item: HouseholdInDB) {
|
function handleRowClick(item: HouseholdInDB) {
|
||||||
router.push(`/admin/manage/households/${item.id}`);
|
router.push(`/admin/manage/households/${item.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleCreateSubmit() {
|
async function handleCreateSubmit() {
|
||||||
if (!refNewHouseholdForm.value?.validate()) {
|
if (!refNewHouseholdForm.value?.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
createDialog.value = false;
|
||||||
state.createDialog = false;
|
await createHousehold(createHouseholdForm.data);
|
||||||
await createHousehold(state.createHouseholdForm.data);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(state),
|
|
||||||
refNewHouseholdForm,
|
|
||||||
groups,
|
|
||||||
households,
|
|
||||||
validators,
|
|
||||||
refreshAllHouseholds,
|
|
||||||
deleteHousehold,
|
|
||||||
handleCreateSubmit,
|
|
||||||
openDialog,
|
|
||||||
handleRowClick,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -21,26 +21,23 @@
|
||||||
<v-card variant="outlined">
|
<v-card variant="outlined">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-select
|
<v-select
|
||||||
v-if="groups"
|
v-model="selectedGroup"
|
||||||
v-model="selectedGroupId"
|
:items="groups || []"
|
||||||
:items="groups"
|
|
||||||
item-title="name"
|
item-title="name"
|
||||||
item-value="id"
|
return-object
|
||||||
:return-object="false"
|
|
||||||
variant="filled"
|
variant="filled"
|
||||||
:label="$t('group.user-group')"
|
:label="$t('group.user-group')"
|
||||||
:rules="[validators.required]"
|
:rules="[validators.required]"
|
||||||
/>
|
/>
|
||||||
<v-select
|
<v-select
|
||||||
v-model="newUserData.household"
|
v-model="newUserData.household"
|
||||||
:disabled="!selectedGroupId"
|
:disabled="!selectedGroup"
|
||||||
:items="households"
|
:items="households"
|
||||||
item-title="name"
|
item-title="name"
|
||||||
item-value="name"
|
item-value="name"
|
||||||
:return-object="false"
|
|
||||||
variant="filled"
|
variant="filled"
|
||||||
:label="$t('household.user-household')"
|
:label="$t('household.user-household')"
|
||||||
:hint="selectedGroupId ? '' : $t('group.you-must-select-a-group-before-selecting-a-household')"
|
:hint="selectedGroup ? '' : $t('group.you-must-select-a-group-before-selecting-a-household')"
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:rules="[validators.required]"
|
:rules="[validators.required]"
|
||||||
/>
|
/>
|
||||||
|
@ -60,46 +57,33 @@
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import { useAdminApi } from "~/composables/api";
|
import { useAdminApi } from "~/composables/api";
|
||||||
import { useGroups } from "~/composables/use-groups";
|
import { useGroups } from "~/composables/use-groups";
|
||||||
import { useAdminHouseholds } from "~/composables/use-households";
|
|
||||||
import { useUserForm } from "~/composables/use-users";
|
import { useUserForm } from "~/composables/use-users";
|
||||||
import { validators } from "~/composables/use-validators";
|
import { validators } from "~/composables/use-validators";
|
||||||
import type { UserIn } from "~/lib/api/types/user";
|
import type { GroupInDB, UserIn } from "~/lib/api/types/user";
|
||||||
import type { VForm } from "~/types/auto-forms";
|
import type { VForm } from "~/types/auto-forms";
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
definePageMeta({
|
||||||
setup() {
|
|
||||||
definePageMeta({
|
|
||||||
layout: "admin",
|
layout: "admin",
|
||||||
});
|
});
|
||||||
|
const { userForm } = useUserForm();
|
||||||
|
const { groups } = useGroups();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const { userForm } = useUserForm();
|
const refNewUserForm = ref<VForm | null>(null);
|
||||||
const { groups } = useGroups();
|
const adminApi = useAdminApi();
|
||||||
const { useHouseholdsInGroup } = useAdminHouseholds();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// ==============================================
|
const selectedGroup = ref<GroupInDB | undefined>(undefined);
|
||||||
// New User Form
|
const households = computed(() => selectedGroup.value?.households || []);
|
||||||
|
|
||||||
const refNewUserForm = ref<VForm | null>(null);
|
const newUserData = ref({
|
||||||
|
|
||||||
const adminApi = useAdminApi();
|
|
||||||
|
|
||||||
const selectedGroupId = ref<string>("");
|
|
||||||
const households = useHouseholdsInGroup(selectedGroupId);
|
|
||||||
|
|
||||||
const selectedGroup = computed(() => {
|
|
||||||
return groups.value?.find(group => group.id === selectedGroupId.value);
|
|
||||||
});
|
|
||||||
const state = reactive({
|
|
||||||
newUserData: {
|
|
||||||
username: "",
|
username: "",
|
||||||
fullName: "",
|
fullName: "",
|
||||||
email: "",
|
email: "",
|
||||||
admin: false,
|
admin: false,
|
||||||
group: selectedGroup.value?.name || "",
|
group: computed(() => selectedGroup.value?.name || ""),
|
||||||
household: "",
|
household: "",
|
||||||
advanced: false,
|
advanced: false,
|
||||||
canInvite: false,
|
canInvite: false,
|
||||||
|
@ -107,35 +91,17 @@ export default defineNuxtComponent({
|
||||||
canOrganize: false,
|
canOrganize: false,
|
||||||
password: "",
|
password: "",
|
||||||
authMethod: "Mealie",
|
authMethod: "Mealie",
|
||||||
},
|
});
|
||||||
});
|
|
||||||
watch(selectedGroup, (newGroup) => {
|
|
||||||
state.newUserData.group = newGroup?.name || "";
|
|
||||||
state.newUserData.household = "";
|
|
||||||
});
|
|
||||||
|
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
if (!refNewUserForm.value?.validate()) return;
|
if (!refNewUserForm.value?.validate()) return;
|
||||||
|
|
||||||
const { response } = await adminApi.users.createOne(state.newUserData as UserIn);
|
const { response } = await adminApi.users.createOne(newUserData.value as UserIn);
|
||||||
|
|
||||||
if (response?.status === 201) {
|
if (response?.status === 201) {
|
||||||
router.push("/admin/manage/users");
|
router.push("/admin/manage/users");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
...toRefs(state),
|
|
||||||
userForm,
|
|
||||||
refNewUserForm,
|
|
||||||
handleSubmit,
|
|
||||||
groups,
|
|
||||||
selectedGroupId,
|
|
||||||
households,
|
|
||||||
validators,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue