diff --git a/frontend/src/components/DomainSelector.vue b/frontend/src/components/DomainSelector.vue index c0ea828..e2cb112 100644 --- a/frontend/src/components/DomainSelector.vue +++ b/frontend/src/components/DomainSelector.vue @@ -22,7 +22,9 @@ const userStore = useAuthStore(); .q-btn.disabled.customized-disabled-btn { opacity: 1 !important; cursor: default !important; - + .q-icon.q-btn-dropdown__arrow { + display: none; + } * { cursor: default !important; } diff --git a/frontend/src/components/ShareDomain/RoleLabel.vue b/frontend/src/components/ShareDomain/RoleLabel.vue index 7f694de..8e84303 100644 --- a/frontend/src/components/ShareDomain/RoleLabel.vue +++ b/frontend/src/components/ShareDomain/RoleLabel.vue @@ -1,11 +1,15 @@ diff --git a/frontend/src/components/ShareDomain/ShareDomainDialog.vue b/frontend/src/components/ShareDomain/ShareDomainDialog.vue index 0cd5f55..54d4327 100644 --- a/frontend/src/components/ShareDomain/ShareDomainDialog.vue +++ b/frontend/src/components/ShareDomain/ShareDomainDialog.vue @@ -37,7 +37,7 @@ {{scope.opt.fullName}} {{scope.opt.email}} -
+
@@ -47,7 +47,7 @@ @@ -72,15 +72,19 @@ import { ref, watch, onMounted } from 'vue'; import { IDomainOwnerDisplay } from '../../types/DomainTypes'; import { IUser, IUserDisplay } from '../../types/UserTypes'; import { api } from 'boot/axios'; +import { useAuthStore } from 'stores/useAuthStore'; import SharingUserList from 'components/ShareDomain/SharingUserList.vue'; import RoleLabel from 'components/ShareDomain/RoleLabel.vue'; import { Dialog } from 'quasar' +const authStore = useAuthStore(); + interface Props { modelValue: boolean; domain: IDomainOwnerDisplay; dialogTitle: string; userListTitle: string; + hideSelf: boolean; shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise; removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise; getSharedApi: (domain: IDomainOwnerDisplay) => Promise; @@ -186,28 +190,43 @@ const removeShareTo = async (user: IUserDisplayWithShareRole) => { loading.value = true; user.isRemoving = true; await props.removeSharedApi(user, props.domain); + if (isCurrentDomain()) { + await authStore.loadCurrentDomain(); + } await loadShared(); loading.value = false; }; +const isCurrentDomain = () => { + return props.domain.id === authStore.currentDomain.id; +} + const loadShared = async () => { loading.value = true; sharedUsersIdSet.clear(); + if(props.hideSelf) { + sharedUsersIdSet.add((Number)(authStore.userId)); + } + const { data } = await props.getSharedApi(props.domain); - sharedUsers.value = data.data.map((item: IUser) => { + + sharedUsers.value = data.data.reduce((arr: IUserDisplayWithShareRole[], 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; + if(!sharedUsersIdSet.has(val.id)) { + sharedUsersIdSet.add(val.id); + // for sort + if (isOwner(val.id)) { + val.role = 2; + } else if (isManager(val.id)) { + val.role = 1; + } else { + val.role = 0; + } + arr.push(val); } - return val; - }).reverse().sort((a: IUserDisplayWithShareRole, b: IUserDisplayWithShareRole) => b.role - a.role); + return arr; + }, []).sort((a: IUserDisplayWithShareRole, b: IUserDisplayWithShareRole) => b.role - a.role); canSharedUsers.value = allUsers.value.filter((item) => !sharedUsersIdSet.has(item.id)); canSharedUserFilteredOptions.value = canSharedUsers.value; diff --git a/frontend/src/components/ShareDomain/ShareManageDialog.vue b/frontend/src/components/ShareDomain/ShareManageDialog.vue index 8455ec7..b2a7045 100644 --- a/frontend/src/components/ShareDomain/ShareManageDialog.vue +++ b/frontend/src/components/ShareDomain/ShareManageDialog.vue @@ -7,6 +7,7 @@ :remove-shared-api="removeSharedApi" :get-shared-api="getSharedApi" :model-value="modelValue" + hide-self @update:modelValue="updateModelValue" @close="close" /> diff --git a/frontend/src/components/TableActionMenu.vue b/frontend/src/components/TableActionMenu.vue index 9e40f53..5d7a6ce 100644 --- a/frontend/src/components/TableActionMenu.vue +++ b/frontend/src/components/TableActionMenu.vue @@ -3,11 +3,15 @@ @@ -23,6 +27,8 @@ import { IDomainOwnerDisplay } from '../types/DomainTypes'; interface Action { label: string; icon?: string; + tooltip?: string|((row: IDomainOwnerDisplay) => string); + disable?: boolean|((row: IDomainOwnerDisplay) => boolean); action: (row: any) => void|Promise; class?: string; } @@ -54,6 +60,10 @@ export default { methods: { isAction(item: MenuItem): item is Action { return !('separator' in item); + }, + + isFunction(item: any): item is ((row: IDomainOwnerDisplay) => boolean|string) { + return typeof item === 'function'; } } }; diff --git a/frontend/src/components/UserInfoButton.vue b/frontend/src/components/UserInfoButton.vue new file mode 100644 index 0000000..ac98544 --- /dev/null +++ b/frontend/src/components/UserInfoButton.vue @@ -0,0 +1,27 @@ + + diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 9ad772c..925bcd7 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -8,7 +8,7 @@ V{{ version }} - + @@ -37,6 +37,7 @@ import { computed, onMounted, reactive } from 'vue'; import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue'; import DomainSelector from 'components/DomainSelector.vue'; +import UserInfoButton from 'components/UserInfoButton.vue'; import { useAuthStore } from 'stores/useAuthStore'; import { useRoute } from 'vue-router'; diff --git a/frontend/src/pages/AppVersionManagement.vue b/frontend/src/pages/AppVersionManagement.vue index f053ad9..04faafe 100644 --- a/frontend/src/pages/AppVersionManagement.vue +++ b/frontend/src/pages/AppVersionManagement.vue @@ -47,8 +47,7 @@ @@ -119,7 +118,7 @@ const confirmDialog = ref(false); const deleteUserLoading = ref(false); const actionList = ref([ - { label: 'プル', icon: 'flag', action: changeVersion }, + { label: '回復する', icon: 'flag', action: changeVersion }, // { label: 'プレビュー', icon: 'visibility', action: toVersionHistoryPage }, // { separator: true }, // { label: '削除', icon: 'delete_outline', class: 'text-red', action: removeRow }, diff --git a/frontend/src/pages/TenantDomain.vue b/frontend/src/pages/TenantDomain.vue index 80a235e..04d2be8 100644 --- a/frontend/src/pages/TenantDomain.vue +++ b/frontend/src/pages/TenantDomain.vue @@ -31,6 +31,13 @@ + + @@ -165,10 +167,6 @@ const isActive = computed(() => (id: number) => { return id == activeDomainId.value; }); -const isNotOwner = computed(() => (ownerId: string) => { - return ownerId !== authStore.userId; -}); - const getDomain = async (userId? : string) => { rowIds.clear(); const resp = await api.get(`api/defaultdomain`); diff --git a/frontend/src/stores/useAuthStore.ts b/frontend/src/stores/useAuthStore.ts index 6187b7d..f45296c 100644 --- a/frontend/src/stores/useAuthStore.ts +++ b/frontend/src/stores/useAuthStore.ts @@ -8,6 +8,7 @@ import { useAppStore } from './useAppStore'; interface UserInfo { firstName: string; lastName: string; + fullName: string; email: string; } @@ -60,7 +61,7 @@ export const useAuthStore = defineStore('auth', { this.userId = tokenJson.sub; this.permissions = (tokenJson as any).permissions==='ALL' ? 'admin': 'user'; api.defaults.headers['Authorization'] = 'Bearer ' + this.token; - this.currentDomain = await this.getCurrentDomain(); + await this.loadCurrentDomain(); this.userInfo = await this.getUserInfo(); router.push(this.returnUrl || '/'); return true; @@ -69,10 +70,10 @@ export const useAuthStore = defineStore('auth', { return false; } }, - async getCurrentDomain(): Promise { + async loadCurrentDomain() { const resp = await api.get(`api/defaultdomain`); const activedomain = resp?.data?.data; - return { + this.currentDomain = { id: activedomain?.id, domainName: activedomain?.name, kintoneUrl: activedomain?.url, @@ -83,6 +84,7 @@ export const useAuthStore = defineStore('auth', { return { firstName: resp.first_name, lastName: resp.last_name, + fullName: resp.last_name + ' ' + resp.first_name, email: resp.email, } },