diff --git a/frontend/src/components/DomainSelect.vue b/frontend/src/components/DomainSelect.vue index e598f57..35cae98 100644 --- a/frontend/src/components/DomainSelect.vue +++ b/frontend/src/components/DomainSelect.vue @@ -33,10 +33,10 @@ export default { const columns = [ { name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true, classes: inactiveRowClass }, - { name: 'tenantid', required: true,label: 'テナント',align: 'left',field: 'tenantid',sortable: true, classes: inactiveRowClass}, - { name: 'name', align: 'center', label: 'ドメイン', field: 'name', sortable: true, classes: inactiveRowClass }, - { name: 'url', label: 'URL', field: 'url', sortable: true, classes: inactiveRowClass }, - { name: 'user', label: 'アカウント', field: 'user', classes: inactiveRowClass } + { name: 'name', align: 'left', label: 'ドメイン', field: 'name', sortable: true, classes: inactiveRowClass }, + { name: 'url', label: 'URL', field: 'url',align: 'left', sortable: true, classes: inactiveRowClass }, + { name: 'user', label: 'アカウント', field: 'user',align: 'left', classes: inactiveRowClass }, + { name: 'owner', label: '所有者', field: row => row.owner.fullName, align: 'left', classes: inactiveRowClass }, ] const rows = reactive([]); @@ -51,6 +51,16 @@ export default { name: data.name, url: data.url, user: data.kintoneuser, + owner: { + id: data.owner.id, + firstName: data.owner.first_name, + lastName: data.owner.last_name, + fullNameSearch: (data.owner.last_name + data.owner.first_name).toLowerCase(), + fullName: data.owner.last_name + ' ' + data.owner.first_name, + email: data.owner.email, + isActive: data.owner.is_active, + isSuperuser: data.owner.is_superuser, + } } if (props.filterInitRowsFunc && !props.filterInitRowsFunc(item)) { return; diff --git a/frontend/src/components/ShareDomain/ShareDomainDialog.vue b/frontend/src/components/ShareDomain/ShareDomainDialog.vue new file mode 100644 index 0000000..09e2eff --- /dev/null +++ b/frontend/src/components/ShareDomain/ShareDomainDialog.vue @@ -0,0 +1,191 @@ + + + + + 「{{domain.name}}」のドメインを共有する + + + + + + + + + + + + + {{scope.opt.id}} + {{scope.opt.fullName}} + {{scope.opt.email}} + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src/components/ShareDomain/SharingUserList.vue b/frontend/src/components/ShareDomain/SharingUserList.vue new file mode 100644 index 0000000..8c244a5 --- /dev/null +++ b/frontend/src/components/ShareDomain/SharingUserList.vue @@ -0,0 +1,45 @@ + + + + {{props.title}} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/components/ShowDialog.vue b/frontend/src/components/ShowDialog.vue index 50641db..5f6098e 100644 --- a/frontend/src/components/ShowDialog.vue +++ b/frontend/src/components/ShowDialog.vue @@ -13,7 +13,7 @@ - + diff --git a/frontend/src/components/UserDomain/DomainCard.vue b/frontend/src/components/UserDomain/DomainCard.vue new file mode 100644 index 0000000..d43a9f1 --- /dev/null +++ b/frontend/src/components/UserDomain/DomainCard.vue @@ -0,0 +1,64 @@ + + + + + + {{ item.name }} + {{ item.url }} + + + + + + + + + アカウント + + {{ item.kintoneuser }} + + + + 所有者 + + {{ item.owner }} + + + + + + + + + + + diff --git a/frontend/src/components/UserList.vue b/frontend/src/components/UserList.vue index 64b3b35..2cca424 100644 --- a/frontend/src/components/UserList.vue +++ b/frontend/src/components/UserList.vue @@ -9,8 +9,8 @@ import { api } from 'boot/axios'; const props = defineProps<{filter:string}>() const columns = [ { name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true }, - { name: 'firstName', label: '氏名', field: 'firstName', align: 'left', sortable: true }, - { name: 'lastName', label: '苗字', field: 'lastName', align: 'left', sortable: true }, + { name: 'lastName', label: '氏名', field: 'lastName', align: 'left', sortable: true }, + { name: 'firstName', label: '苗字', field: 'firstName', align: 'left', sortable: true }, { name: 'email', label: '電子メール', field: 'email', align: 'left', sortable: true }, ]; diff --git a/frontend/src/components/main/domainTable.vue b/frontend/src/components/main/domainTable.vue new file mode 100644 index 0000000..23bf91d --- /dev/null +++ b/frontend/src/components/main/domainTable.vue @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + {{ p.row.name }} + 未启用 + 現在 + + + + + + + + + + + + + + + diff --git a/frontend/src/pages/TenantDomain.vue b/frontend/src/pages/TenantDomain.vue index 3564ff5..a0ac958 100644 --- a/frontend/src/pages/TenantDomain.vue +++ b/frontend/src/pages/TenantDomain.vue @@ -19,7 +19,10 @@ - {{ p.row.name }} + + {{ p.row.name }} + + 未启用 現在 @@ -29,6 +32,7 @@ + @@ -50,7 +54,7 @@ :rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" /> + :rules="[val => val && val.length > 0 || 'KintoneのURLを入力してください']" /> @@ -109,18 +113,29 @@ - + + + 共有ユーザーのチェック + + 削除してもよろしいですか? + + + 共有ユーザーが存在し、キャンセルする必要がある + - + + + + @@ -129,11 +144,12 @@ import { ref, onMounted, computed } from 'vue'; import { api } from 'boot/axios'; import { useAuthStore } from 'stores/useAuthStore'; import { useDomainStore } from 'stores/useDomainStore'; -import { IDomain, IDomainDisplay, IDomainSubmit } from '../types/DomainTypes'; +import ShareDomainDialog from 'components/ShareDomain/ShareDomainDialog.vue'; +import { IDomain, IDomainOwnerDisplay, IDomainSubmit } from '../types/DomainTypes'; const authStore = useAuthStore(); const domainStore = useDomainStore(); -const inactiveRowClass = (row: IDomainDisplay) => row.domainActive ? '' : 'inactive-row'; +const inactiveRowClass = (row: IDomainOwnerDisplay) => row.domainActive ? '' : 'inactive-row'; const columns = [ { name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true, classes: inactiveRowClass }, @@ -148,16 +164,18 @@ const columns = [ // }, { name: 'name', label: '環境名', field: 'name', align: 'left', sortable: true, classes: inactiveRowClass }, { name: 'url', label: 'URL', field: 'url', align: 'left', sortable: true, classes: inactiveRowClass }, - // { name: 'owner', label: '所有者', field: 'owner', align: 'left', classes: inactiveRowClass }, { name: 'user', label: 'ログイン名', field: 'user', align: 'left', classes: inactiveRowClass }, - { name: 'actions', label: '操作', field: 'actions' } + { name: 'owner', label: '所有者', field: row => row.owner.fullName, align: 'left', classes: inactiveRowClass }, + { name: 'actions', label: '操作', field: 'actions', classes: inactiveRowClass } ]; const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 }); const loading = ref(false); const addEditLoading = ref(false); +const deleteLoadingState = ref(-1); // -1: loading, 0: allow, > 0: user count + const filter = ref(''); -const rows = ref([]); +const rows = ref([]); const show = ref(false); const confirm = ref(false); const resetPsw = ref(false); @@ -173,7 +191,8 @@ const kintonepwdBK = ref(''); const domainActive = ref(true); const isCreate = ref(true); let editId = ref(0); -let ownerid = ref(''); +const shareDg = ref(false); +const shareDomain = ref(); const getDomain = async () => { loading.value = true; @@ -187,6 +206,16 @@ const getDomain = async () => { url: item.url, user: item.kintoneuser, password: item.kintonepwd, + owner: { + id: item.owner.id, + firstName: item.owner.first_name, + lastName: item.owner.last_name, + fullNameSearch: (item.owner.last_name + item.owner.first_name).toLowerCase(), + fullName: item.owner.last_name + ' ' + item.owner.first_name, + email: item.owner.email, + isActive: item.owner.is_active, + isSuperuser: item.owner.is_superuser, + } } }); loading.value = false; @@ -203,17 +232,25 @@ const addRow = () => { show.value = true; } -const removeRow = (row: IDomainDisplay) => { +const removeRow = async (row: IDomainOwnerDisplay) => { confirm.value = true; + deleteLoadingState.value = -1; editId.value = row.id; + + const { data } = await api.get(`/api/domainshareduser/${row.id}`); + deleteLoadingState.value = data.data.length; } const deleteDomain = () => { - api.delete(`api/domain/${editId.value}`).then(() => { + api.delete(`api/domain/${editId.value}`).then(({ data }) => { + if (!data.data) { + // TODO dialog + } getDomain(); // authStore.setCurrentDomain(); }) editId.value = 0; // set in removeRow() + deleteLoadingState.value = -1; }; const editRow = (row) => { @@ -266,6 +303,18 @@ const onSubmit = () => { }) } +const openShareDg = (row: IDomainOwnerDisplay|number) => { + if (typeof row === 'number') { + row = rows.value.find(item => item.id === row) as IDomainOwnerDisplay; + } + shareDomain.value = row ; + shareDg.value = true; +}; + +const closeShareDg = () => { + shareDg.value = false; +} + const onReset = () => { name.value = ''; url.value = ''; @@ -273,7 +322,6 @@ const onReset = () => { kintonepwd.value = ''; isPwd.value = true; editId.value = 0; - ownerid.value = ''; isCreate.value = true; domainActive.value = true; resetPsw.value = false @@ -283,5 +331,6 @@ const onReset = () => { \ No newline at end of file diff --git a/frontend/src/pages/UserDomain.vue b/frontend/src/pages/UserDomain.vue index 08942f3..a56fbea 100644 --- a/frontend/src/pages/UserDomain.vue +++ b/frontend/src/pages/UserDomain.vue @@ -6,23 +6,14 @@ - + - - - - @@ -38,69 +29,25 @@ - - - - Domain - {{ props.row.name }} - - - URL - {{ props.row.url }} - - - Account - {{ props.row.kintoneuser }} - - - - - - - {{ - isActive(props.row.id)?'既定':'' }} - - 既定にする - 削除 - - - - - + + + + + 既定 + + 既定にする + 削除 + + + - + - - - - - - - - - - - - 他のユーザーを選択する - - - - - - - - - - - - @@ -123,32 +70,28 @@ import { ref, onMounted, computed } from 'vue' import { api } from 'boot/axios'; import { useAuthStore } from 'stores/useAuthStore'; -import { useDomainStore } from 'stores/useDomainStore'; import ShowDialog from 'components/ShowDialog.vue'; +import DomainCard from 'components/UserDomain/DomainCard.vue'; import DomainSelect from 'components/DomainSelect.vue'; -import UserList from 'components/UserList.vue'; const authStore = useAuthStore(); -const domainStore = useDomainStore(); const pagination = ref({ sortBy: 'id', rowsPerPage: 0 }); const rows = ref([] as any[]); const rowIds = new Set(); -const loading = ref(true); +const initLoading = ref(true); +const addUserDomainLoading = ref(false); +const activeDomainLoadingId = ref(undefined); +const deleteDomainLoadingId = ref(undefined); const columns = [ { name: 'id' }, { name: 'name', required: true, label: 'Name', align: 'left', field: 'name', sortable: true }, { name: 'url', align: 'center', label: 'Domain', field: 'url', sortable: true }, { name: 'kintoneuser', label: 'User', field: 'kintoneuser', sortable: true }, - { name: 'kintonepwd' }, ]; const userDomainTableFilter = ref(); -const currentUserName = ref(''); -const useOtherUser = ref(false); -const otherUserId = ref(''); - let editId = ref(0); const showAddDomainDg = ref(false); @@ -163,22 +106,24 @@ const clickAddDomain = () => { showAddDomainDg.value = true; }; -const addUserDomainFinished = (val: string) => { +const addUserDomainFinished = async (val: string) => { + showAddDomainDg.value = true; const selected = addDomainRef.value.selected; if (val == 'OK' && selected.length > 0) { - api.post(`api/domain/${useOtherUser.value ? otherUserId.value : authStore.userId}?domainid=${selected[0].id}`) - .then(async ({ data }) => { - if (rows.value.length === 0 && data.data) { - const domain = data.data; - await authStore.setCurrentDomain({ - id: domain.id, - kintoneUrl: domain.url, - domainName: domain.name - }); - } - getDomain(useOtherUser.value ? otherUserId.value : undefined); + addUserDomainLoading.value = true; + const { data } = await api.post(`api/domain/${authStore.userId}?domainid=${selected[0].id}`) + if (rows.value.length === 0 && data.data) { + const domain = data.data; + await authStore.setCurrentDomain({ + id: domain.id, + kintoneUrl: domain.url, + domainName: domain.name }); + } + await getDomain(); } + addUserDomainLoading.value = false; + showAddDomainDg.value = false; }; const showDeleteConfirm = ref(false); @@ -189,26 +134,25 @@ const clickDeleteConfirm = (row: any) => { }; const deleteDomainFinished = async () => { - await api.delete(`api/domain/${editId.value}/${useOtherUser.value ? otherUserId.value : authStore.userId}`).then(({ data }) => { - if (data.msg == 'OK' && authStore.currentDomain.id === editId.value) { - authStore.setCurrentDomain(); - } - getDomain(useOtherUser.value ? otherUserId.value : undefined); - }) + deleteDomainLoadingId.value = editId.value; + const { data } = await api.delete(`api/domain/${editId.value}/${authStore.userId}`) + if (data.msg == 'OK' && authStore.currentDomain.id === editId.value) { + authStore.setCurrentDomain(); + } editId.value = 0; + await getDomain(); + deleteDomainLoadingId.value = undefined; }; const activeDomain = async (domain: any) => { - if (useOtherUser.value) { - // TODO - return; - } + activeDomainLoadingId.value = domain.id; await authStore.setCurrentDomain({ id: domain.id, kintoneUrl: domain.url, domainName: domain.name }); - getDomain(); + await getDomain(); + activeDomainLoadingId.value = undefined; }; let activeDomainId = ref(0); @@ -217,52 +161,43 @@ const isActive = computed(() => (id: number) => { return id == activeDomainId.value; }); - -const showSwitchUserDd = ref(false); -const switchUserRef = ref(); -const switchUserFilter = ref('') - -const clickSwitchUser = () => { - showSwitchUserDd.value = true; - useOtherUser.value = false; -}; - -const switchUserFinished = async (val: string) => { - if (val == 'OK') { - if (useOtherUser.value) { - const user = switchUserRef.value.selected[0] - currentUserName.value = user.email; - otherUserId.value = user.id - await getDomain(user.id) - } else { - currentUserName.value = authStore.userInfo.email - await getDomain(); - } - - } -}; +const isNotOwner = computed(() => (ownerId: string) => { + return ownerId == authStore.userId; +}); const getDomain = async (userId? : string) => { - loading.value = true; rowIds.clear(); - if (useOtherUser.value) { - // TODO - return; - } const resp = await api.get(`api/defaultdomain`); activeDomainId.value = resp?.data?.data?.id; const domainResult = userId ? await api.get(`api/domain?userId=${userId}`) : await api.get(`api/domain`); const domains = domainResult.data as any[]; rows.value = domains.map((item) => { rowIds.add(item.id); - return { id: item.id, name: item.name, url: item.url, kintoneuser: item.kintoneuser, kintonepwd: item.kintonepwd } + return { + id: item.id, + name: item.name, + url: item.url, + kintoneuser: item.kintoneuser, + ownerEmail: item.owner.email, + owner: item.owner.first_name + ' ' + item.owner.last_name, + } }); - loading.value = false; } onMounted(async () => { - currentUserName.value = authStore.userInfo.email + initLoading.value = true; await getDomain(); + initLoading.value = false; }) + \ No newline at end of file diff --git a/frontend/src/pages/UserManagement.vue b/frontend/src/pages/UserManagement.vue index 0b06b69..777ecd2 100644 --- a/frontend/src/pages/UserManagement.vue +++ b/frontend/src/pages/UserManagement.vue @@ -65,10 +65,10 @@ - -