Add share manage dialog
This commit is contained in:
19
frontend/src/components/ShareDomain/RoleLabel.vue
Normal file
19
frontend/src/components/ShareDomain/RoleLabel.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<q-badge v-if="isOwner" color="purple">所有者</q-badge>
|
||||
<q-badge v-else-if="isManager" color="primary">管理者</q-badge>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||
|
||||
interface Props {
|
||||
user: { id: number };
|
||||
domain: IDomainOwnerDisplay;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const isOwner = computed(() => props.user.id === props.domain.owner.id);
|
||||
const isManager = computed(() => props.user.id === props.domain.owner.id); // TODO
|
||||
</script>
|
||||
@@ -2,7 +2,7 @@
|
||||
<q-dialog :auto-close="false" :model-value="visible" persistent bordered>
|
||||
<q-card class="dialog-content" >
|
||||
<q-toolbar class="bg-grey-4">
|
||||
<q-toolbar-title>「{{domain.name}}」のドメイン利用権限設定</q-toolbar-title>
|
||||
<q-toolbar-title>{{ dialogTitle }}</q-toolbar-title>
|
||||
<q-btn flat round dense icon="close" @click="close" />
|
||||
</q-toolbar>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<template v-slot:selected-item="scope">
|
||||
<span v-if="canSharedUserFilter">
|
||||
{{ canSharedUserFilter.fullName }} ({{ canSharedUserFilter.email }})
|
||||
<q-badge v-if="isOwner(scope.opt.id)" color="purple">所有者</q-badge>
|
||||
<role-label :domain="domain" :user="scope.opt"></role-label>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -38,18 +38,17 @@
|
||||
<q-item-section>{{scope.opt.email}}</q-item-section>
|
||||
<q-item-section side>
|
||||
<div style="width: 4em;">
|
||||
<q-badge v-if="isOwner(scope.opt.id)" color="purple">所有者</q-badge>
|
||||
<role-label :domain="domain" :user="scope.opt"></role-label>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
|
||||
<sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" title="ドメイン利用権限を持つユーザー">
|
||||
<sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" :title="userListTitle">
|
||||
<template v-slot:body-cell-role="{ row }">
|
||||
<q-td>
|
||||
<q-badge v-if="row.role == 2" color="purple">所有者</q-badge>
|
||||
<!-- <q-badge v-else-if="row.id === domain.owner.id" color="primary">管理者</q-badge> -->
|
||||
<role-label :domain="domain" :user="row"></role-label>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
@@ -74,16 +73,22 @@ import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||
import { IUser, IUserDisplay } from '../../types/UserTypes';
|
||||
import { api } from 'boot/axios';
|
||||
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
|
||||
import RoleLabel from 'components/ShareDomain/RoleLabel.vue';
|
||||
import { Dialog } from 'quasar'
|
||||
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
domain: IDomainOwnerDisplay;
|
||||
dialogTitle: string;
|
||||
userListTitle: string;
|
||||
shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
||||
removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
|
||||
getSharedApi: (domain: IDomainOwnerDisplay) => Promise<any>;
|
||||
}
|
||||
|
||||
interface IUserDisplayWithShareRole extends IUserDisplay {
|
||||
isRemoving: boolean;
|
||||
role: number; // 2: 所有者,1: 管理者, 0: 利用者
|
||||
role: number;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
@@ -126,6 +131,9 @@ watch(
|
||||
loading.value = false;
|
||||
addLoading.value = false;
|
||||
if (newValue) {
|
||||
if (Object.keys(allUsers.value).length == 0) {
|
||||
await getUsers();
|
||||
}
|
||||
await loadShared();
|
||||
}
|
||||
}
|
||||
@@ -167,10 +175,7 @@ const close = () => {
|
||||
const shareTo = async (user: IUserDisplayWithShareRole) => {
|
||||
addLoading.value = true;
|
||||
loading.value = true;
|
||||
await api.post(`api/userdomain`, {
|
||||
'userid': user.id,
|
||||
'domainid': props.domain.id
|
||||
})
|
||||
await props.shareApi(user, props.domain);
|
||||
await loadShared();
|
||||
canSharedUserFilter.value = undefined;
|
||||
loading.value = false;
|
||||
@@ -180,7 +185,7 @@ const shareTo = async (user: IUserDisplayWithShareRole) => {
|
||||
const removeShareTo = async (user: IUserDisplayWithShareRole) => {
|
||||
loading.value = true;
|
||||
user.isRemoving = true;
|
||||
await api.delete(`api/domain/${props.domain.id}/${user.id}`)
|
||||
await props.removeSharedApi(user, props.domain);
|
||||
await loadShared();
|
||||
loading.value = false;
|
||||
};
|
||||
@@ -189,10 +194,18 @@ const loadShared = async () => {
|
||||
loading.value = true;
|
||||
sharedUsersIdSet.clear();
|
||||
|
||||
const { data } = await api.get(`/api/domainshareduser/${props.domain.id}`);
|
||||
const { data } = await props.getSharedApi(props.domain);
|
||||
sharedUsers.value = data.data.map((item: IUser) => {
|
||||
const val = itemToDisplay(item);
|
||||
sharedUsersIdSet.add(val.id);
|
||||
// for sort
|
||||
if (isOwner(item.id)) {
|
||||
val.role = 2;
|
||||
} else if (isManager(item.id)) {
|
||||
val.role = 1;
|
||||
} else {
|
||||
val.role = 0;
|
||||
}
|
||||
return val;
|
||||
}).reverse().sort((a: IUserDisplayWithShareRole, b: IUserDisplayWithShareRole) => b.role - a.role);
|
||||
|
||||
@@ -202,24 +215,21 @@ const loadShared = async () => {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getUsers();
|
||||
})
|
||||
function isOwner(userId: number) {
|
||||
return userId === props.domain?.owner?.id
|
||||
}
|
||||
|
||||
function isManager(userId: number) {
|
||||
return false // TODO
|
||||
}
|
||||
|
||||
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.data.map(itemToDisplay);
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
function isOwner(userId: number) {
|
||||
return userId === props.domain.owner.id
|
||||
}
|
||||
|
||||
const itemToDisplay = (item: IUser) => {
|
||||
return {
|
||||
id: item.id,
|
||||
@@ -230,9 +240,10 @@ const itemToDisplay = (item: IUser) => {
|
||||
email: item.email,
|
||||
isSuperuser: item.is_superuser,
|
||||
isActive: item.is_active,
|
||||
role: isOwner(item.id) ? 2 : 0, // TODO
|
||||
role: 0,
|
||||
} as IUserDisplayWithShareRole
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
56
frontend/src/components/ShareDomain/ShareManageDialog.vue
Normal file
56
frontend/src/components/ShareDomain/ShareManageDialog.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<share-domain-dialog
|
||||
:dialogTitle="`「${domain.name}」のドメイン管理権限設定`"
|
||||
userListTitle="ドメイン管理権限を持つユーザー"
|
||||
:domain="domain"
|
||||
:share-api="shareApi"
|
||||
:remove-shared-api="removeSharedApi"
|
||||
:get-shared-api="getSharedApi"
|
||||
:model-value="modelValue"
|
||||
@update:modelValue="updateModelValue"
|
||||
@close="close"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits } from 'vue';
|
||||
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
|
||||
import { IUserDisplay } from '../../types/UserTypes';
|
||||
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
domain: IDomainOwnerDisplay;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
||||
return api.post(`api/managedomain`, {
|
||||
userid: user.id,
|
||||
domainid: domain.id,
|
||||
});
|
||||
}
|
||||
|
||||
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
||||
return api.delete(`api/managedomain/${domain.id}/${user.id}`);
|
||||
}
|
||||
|
||||
async function getSharedApi(domain: IDomainOwnerDisplay) {
|
||||
return api.get(`/api/managedomainuser/${domain.id}`);
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void;
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
const updateModelValue = (value: boolean) => {
|
||||
emit('update:modelValue', value);
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
emit('close');
|
||||
};
|
||||
</script>
|
||||
56
frontend/src/components/ShareDomain/ShareUsageDialog.vue
Normal file
56
frontend/src/components/ShareDomain/ShareUsageDialog.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<share-domain-dialog
|
||||
:dialogTitle="`「${domain.name}」のドメイン利用権限設定`"
|
||||
userListTitle="ドメイン利用権限を持つユーザー"
|
||||
:domain="domain"
|
||||
:share-api="shareApi"
|
||||
:remove-shared-api="removeSharedApi"
|
||||
:get-shared-api="getSharedApi"
|
||||
:model-value="modelValue"
|
||||
@update:modelValue="updateModelValue"
|
||||
@close="close"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits } from 'vue';
|
||||
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
|
||||
import { IUserDisplay } from '../../types/UserTypes';
|
||||
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
interface Props {
|
||||
modelValue: boolean;
|
||||
domain: IDomainOwnerDisplay;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
||||
return api.post(`api/userdomain`, {
|
||||
userid: user.id,
|
||||
domainid: domain.id,
|
||||
});
|
||||
}
|
||||
|
||||
async function removeSharedApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
|
||||
return api.delete(`api/domain/${domain.id}/${user.id}`);
|
||||
}
|
||||
|
||||
async function getSharedApi(domain: IDomainOwnerDisplay) {
|
||||
return api.get(`/api/domainshareduser/${domain.id}`);
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void;
|
||||
(e: 'close'): void;
|
||||
}>();
|
||||
|
||||
const updateModelValue = (value: boolean) => {
|
||||
emit('update:modelValue', value);
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
emit('close');
|
||||
};
|
||||
</script>
|
||||
@@ -44,7 +44,7 @@ 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 },
|
||||
{ name: 'role', label: '権限', field: 'role', align: 'left', sortable: true },
|
||||
{ name: 'role', label: '', field: 'role', align: 'left', sortable: false },
|
||||
{ name: 'actions', label: '', field: 'actions', sortable: false },
|
||||
];
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<!-- -1 loading -->
|
||||
<q-card-section v-if="deleteLoadingState == -1" class="row items-center">
|
||||
<q-spinner color="primary" size="2em"/>
|
||||
<span class="q-ml-sm">ドメイン利用権限を確認中</span>
|
||||
<span class="q-ml-sm">ドメイン利用/管理権限を確認中</span>
|
||||
</q-card-section>
|
||||
<!-- > 0 can't delete -->
|
||||
<q-card-section v-else-if="deleteLoadingState > 0" class="row items-center">
|
||||
@@ -131,14 +131,15 @@
|
||||
<q-card-actions align="right">
|
||||
<q-btn flat label="キャンセル" color="primary" v-close-popup />
|
||||
<!-- > 0 can't delete -->
|
||||
<q-btn v-if="deleteLoadingState > 0" label="実行" color="primary" v-close-popup @click="openShareDg(editId)" />
|
||||
<q-btn v-if="deleteLoadingState > 0" label="実行" color="primary" v-close-popup @click="openShareDg(SHARE_MANAGE, editId)" />
|
||||
<!-- 0/-2 can delete -->
|
||||
<q-btn flat v-else label="OK" :disabled="deleteLoadingState == -1" :loading="deleteLoadingState == -2" color="primary" @click="deleteDomain()" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
|
||||
<share-domain-dialog v-model="shareDg" :domain="shareDomain" @close="closeShareDg()" />
|
||||
<share-usage-dialog v-model="shareDg" :domain="shareDomain" @close="shareDg = false" />
|
||||
<share-manage-dialog v-model="shareManageDg" :domain="shareDomain" @close="shareManageDg = false" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -147,7 +148,8 @@
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { api } from 'boot/axios';
|
||||
import { useAuthStore } from 'stores/useAuthStore';
|
||||
import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue';
|
||||
import ShareUsageDialog from 'components/ShareDomain/ShareUsageDialog.vue';
|
||||
import ShareManageDialog from 'components/ShareDomain/ShareManageDialog.vue';
|
||||
import TableActionMenu from 'components/TableActionMenu.vue';
|
||||
import { IDomain, IDomainDisplay, IDomainOwnerDisplay, IDomainSubmit } from '../types/DomainTypes';
|
||||
|
||||
@@ -196,6 +198,7 @@ const domainActive = ref(true);
|
||||
const isCreate = ref(true);
|
||||
let editId = ref(0);
|
||||
const shareDg = ref(false);
|
||||
const shareManageDg = ref(false);
|
||||
const shareDomain = ref<IDomainOwnerDisplay>({} as IDomainOwnerDisplay);
|
||||
|
||||
const activeOptions = [
|
||||
@@ -219,9 +222,13 @@ const activeFilterUpdate = (option: {value: number}) => {
|
||||
}
|
||||
}
|
||||
|
||||
const SHARE_USE = 'use';
|
||||
const SHARE_MANAGE = 'manage';
|
||||
|
||||
const actionList = [
|
||||
{ label: '編集', icon: 'edit_note', action: editRow },
|
||||
{ label: '利用権限設定', icon: 'person_add_alt', action: openShareDg },
|
||||
{ label: '利用権限設定', icon: 'person_add_alt', action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_USE, row)} },
|
||||
{ label: '管理権限設定', icon: 'add_moderator', action: (row: IDomainOwnerDisplay) => {openShareDg(SHARE_MANAGE, row)} },
|
||||
{ separator: true },
|
||||
{ label: '削除', icon: 'delete_outline', class: 'text-red', action: removeRow },
|
||||
];
|
||||
@@ -340,18 +347,18 @@ const onSubmit = () => {
|
||||
})
|
||||
}
|
||||
|
||||
function openShareDg(row: IDomainOwnerDisplay|number) {
|
||||
function openShareDg(type: typeof SHARE_MANAGE|typeof SHARE_USE, row: IDomainOwnerDisplay|number) {
|
||||
if (typeof row === 'number') {
|
||||
row = rows.value.find(item => item.id === row) as IDomainOwnerDisplay;
|
||||
}
|
||||
shareDomain.value = row ;
|
||||
shareDg.value = true;
|
||||
shareDomain.value = row;
|
||||
if (type === SHARE_USE) {
|
||||
shareDg.value = true;
|
||||
} else if (type === SHARE_MANAGE) {
|
||||
shareManageDg.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
function closeShareDg() {
|
||||
shareDg.value = false;
|
||||
}
|
||||
|
||||
const onReset = () => {
|
||||
name.value = '';
|
||||
url.value = '';
|
||||
|
||||
@@ -112,7 +112,10 @@ const addUserDomainFinished = async (val: string) => {
|
||||
const selected = addDomainRef.value.selected;
|
||||
if (val == 'OK' && selected.length > 0) {
|
||||
addUserDomainLoading.value = true;
|
||||
const { data } = await api.post(`api/domain/${authStore.userId}?domainid=${selected[0].id}`)
|
||||
const { data } = await api.post(`api/userdomain`, {
|
||||
userid: authStore.userId,
|
||||
domainid: selected[0].id,
|
||||
});
|
||||
if (rows.value.length === 0 && data.data) {
|
||||
const domain = data.data;
|
||||
await authStore.setCurrentDomain({
|
||||
|
||||
Reference in New Issue
Block a user