Add shared dialog

This commit is contained in:
xue jiahao
2024-12-02 16:21:23 +08:00
parent 8a3aaec8d5
commit 660ffe36c2
7 changed files with 532 additions and 35 deletions

View File

@@ -0,0 +1,186 @@
<template>
<q-dialog :auto-close="false" :model-value="visible" persistent bordered>
<q-card style="min-width: 40vw; max-width: 80vw; max-height: 95vh;" >
<q-toolbar class="bg-grey-4">
<q-toolbar-title>{{domain.name}}のドメインを共有する</q-toolbar-title>
<q-space></q-space>
<slot name="toolbar"></slot>
<q-btn flat round dense icon="close" @click="close" />
</q-toolbar>
<q-card-section>
{{ props.domain.url }}
<!-- <q-input value="props.domain.url" label="共有リンク" readonly outlined dense>
</q-input> -->
</q-card-section>
<q-card-section>
<!-- <q-select
filled
v-model="filterInput"
use-input
use-chips
multiple
input-debounce="0"
:options="filterUsers"
@filter="filterFn"
/> -->
<q-table :rows="canSharedUsers" :filter="filterUnshared" :columns="columns" row-key="id" :loading="loading" :pagination="paginationUnshared">
<template v-slot:body-cell-actions="p">
<q-td :props="p">
<q-btn-group flat>
<q-btn flat color="primary" padding="xs" size="1em" icon="add" @click="shareTo(p.row)" />
</q-btn-group>
</q-td>
</template>
<template v-slot:top-right>
<q-input borderless dense filled debounce="300" v-model="filterUnshared" placeholder="検索">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</template>
</q-table>
<!-- <q-btn flat label="共有する" @click="shareTo" /> -->
<q-table :rows="sharedUsers" :filter="filterShared" :columns="columns" row-key="id" :loading="loading" :pagination="paginationShared" >
<template v-slot:body-cell-actions="p">
<q-td :props="p">
<q-btn-group flat>
<q-btn flat color="primary" padding="xs" size="1em" icon="person_off" @click="removeShareTo(p.row)" />
</q-btn-group>
</q-td>
</template>
<template v-slot:top-right>
<q-input borderless dense filled debounce="300" v-model="filterShared" placeholder="検索">
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
</template>
</q-table>
</q-card-section>
<q-card-actions align="right" class="text-primary">
<q-btn flat label="確定" @click="close" />
<q-btn flat label="キャンセル" @click="close" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from 'vue';
import { IDomainDisplay } from '../../types/DomainTypes';
import { IUser, IUserDisplay } from '../../types/UserTypes';
import { api } from 'boot/axios';
interface Props {
modelValue: boolean;
domain: IDomainDisplay;
}
const props = defineProps<Props>();
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void;
(e: 'close'): void;
}>();
const columns = [
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
{ name: 'fullName', label: '名前', field: 'fullName', align: 'left', sortable: true },
{ name: 'email', label: '電子メール', field: 'email', align: 'left', sortable: true },
];
const paginationUnshared = ref({ sortBy: 'id', descending: true, rowsPerPage: 10 });
const filterUnshared = ref('');
const paginationShared = ref({ sortBy: 'id', descending: true, rowsPerPage: 10 });
const filterShared = ref('');
const loading = ref(true);
const visible = ref(props.modelValue);
const allUsers = ref<IUserDisplay[]>([]);
const sharedUsers = ref<IUserDisplay[]>([]);
const sharedUsersIdSet = new Set<number>();
const canSharedUsers = ref<IUserDisplay[]>([]);
watch(
() => props.modelValue,
async (newValue) => {
visible.value = newValue;
if (newValue) {
await loadShared();
}
}
);
watch(
() => visible.value,
(newValue) => {
emit('update:modelValue', newValue);
}
);
const close = () => {
emit('close');
};
const shareTo = async (user: IUserDisplay) => {
loading.value = true;
await api.post(`api/domain/${user.id}?domainid=${props.domain.id}`)
await loadShared();
loading.value = false;
}
const removeShareTo = async (user: IUserDisplay) => {
loading.value = true;
await api.delete(`api/domain/${props.domain.id}/${user.id}`)
await loadShared();
loading.value = false;
};
const loadShared = async () => {
loading.value = true;
sharedUsersIdSet.clear();
const { data } = await api.get(`/api/domainshareduser/${props.domain.id}`);
sharedUsers.value = data.data.map((item: IUser) => {
const val = itemToDisplay(item);
sharedUsersIdSet.add(val.id);
return val;
});
canSharedUsers.value = allUsers.value.filter((item) => !sharedUsersIdSet.has(item.id));
loading.value = false;
}
onMounted(async () => {
await getUsers();
})
const getUsers = async () => {
if (Object.keys(allUsers.value).length > 0) {
return;
}
loading.value = true;
const result = await api.get(`api/v1/users`);
allUsers.value = result.data.map(itemToDisplay);
loading.value = false;
}
const itemToDisplay = (item: IUser) => {
return {
id: item.id,
firstName: item.first_name,
lastName: item.last_name,
fullNameSearch: (item.last_name + item.first_name).toLowerCase(),
fullName: item.last_name + ' ' + item.first_name,
email: item.email,
isSuperuser: item.is_superuser,
roles: item.roles,
isActive: item.is_active,
} as IUserDisplay
}
</script>
<style lang="scss"></style>