Merge branch 'dev3' of https://dev.azure.com/alicorn-dev/KintoneAppBuilder/_git/KintoneAppBuilder into dev3
This commit is contained in:
@@ -33,10 +33,10 @@ export default {
|
|||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true, classes: inactiveRowClass },
|
{ 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: 'left', label: 'ドメイン', field: 'name', sortable: true, classes: inactiveRowClass },
|
||||||
{ name: 'name', align: 'center', label: 'ドメイン', field: 'name', sortable: true, classes: inactiveRowClass },
|
{ name: 'url', label: 'URL', field: 'url',align: 'left', sortable: true, classes: inactiveRowClass },
|
||||||
{ name: 'url', label: 'URL', field: 'url', sortable: true, classes: inactiveRowClass },
|
{ name: 'user', label: 'アカウント', field: 'user',align: 'left', classes: inactiveRowClass },
|
||||||
{ name: 'user', label: 'アカウント', field: 'user', classes: inactiveRowClass }
|
{ name: 'owner', label: '所有者', field: row => row.owner.fullName, align: 'left', classes: inactiveRowClass },
|
||||||
]
|
]
|
||||||
const rows = reactive([]);
|
const rows = reactive([]);
|
||||||
|
|
||||||
@@ -51,6 +51,16 @@ export default {
|
|||||||
name: data.name,
|
name: data.name,
|
||||||
url: data.url,
|
url: data.url,
|
||||||
user: data.kintoneuser,
|
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)) {
|
if (props.filterInitRowsFunc && !props.filterInitRowsFunc(item)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
191
frontend/src/components/ShareDomain/ShareDomainDialog.vue
Normal file
191
frontend/src/components/ShareDomain/ShareDomainDialog.vue
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
<template>
|
||||||
|
<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-btn flat round dense icon="close" @click="close" />
|
||||||
|
</q-toolbar>
|
||||||
|
|
||||||
|
<q-card-section class="q-mx-md " >
|
||||||
|
<q-select
|
||||||
|
class="q-mt-md"
|
||||||
|
:disable="loading"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model="canSharedUserFilter"
|
||||||
|
use-input
|
||||||
|
input-debounce="0"
|
||||||
|
:options="canSharedUserFilteredOptions"
|
||||||
|
clearable
|
||||||
|
:placeholder="canSharedUserFilter ? '' : '共有するユーザーを選択'"
|
||||||
|
@filter="filterFn"
|
||||||
|
:display-value="canSharedUserFilter?`${canSharedUserFilter.fullName} (${canSharedUserFilter.email})`:''">
|
||||||
|
|
||||||
|
<template v-slot:after>
|
||||||
|
<q-btn :disable="!canSharedUserFilter" :loading="addLoading" label="共有する" color="primary" @click="shareTo(canSharedUserFilter as IUserDisplay)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:option="scope">
|
||||||
|
<q-item v-bind="scope.itemProps">
|
||||||
|
<q-item-section avatar>{{scope.opt.id}}</q-item-section>
|
||||||
|
<q-item-section>{{scope.opt.fullName}}</q-item-section>
|
||||||
|
<q-item-section>{{scope.opt.email}}</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
<sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" title="現在の共有ユーザー">
|
||||||
|
<template v-slot:actions="{ row }">
|
||||||
|
<q-btn flat color="primary" padding="xs" size="1em" :loading="row.id == removingUser?.id" icon="person_off" @click="removeShareTo(row)" />
|
||||||
|
</template>
|
||||||
|
</sharing-user-list>
|
||||||
|
</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 { IDomainOwnerDisplay } from '../../types/DomainTypes';
|
||||||
|
import { IUser, IUserDisplay } from '../../types/UserTypes';
|
||||||
|
import { api } from 'boot/axios';
|
||||||
|
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modelValue: boolean;
|
||||||
|
domain: IDomainOwnerDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:modelValue', value: boolean): void;
|
||||||
|
(e: 'close'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const addLoading = ref(false);
|
||||||
|
const removingUser = ref<IUserDisplay>();
|
||||||
|
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[]>([]);
|
||||||
|
const canSharedUserFilter = ref<IUserDisplay>();
|
||||||
|
const canSharedUserFilteredOptions = ref<IUserDisplay[]>([]);
|
||||||
|
|
||||||
|
const filterFn = (val:string, update: (cb: () => void) => void) => {
|
||||||
|
update(() => {
|
||||||
|
if (val === '') {
|
||||||
|
canSharedUserFilteredOptions.value = canSharedUsers.value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const needle = val.toLowerCase();
|
||||||
|
canSharedUserFilteredOptions.value = canSharedUsers.value.filter(v =>
|
||||||
|
v.email.toLowerCase().indexOf(needle) > -1 || v.fullNameSearch.toLowerCase().indexOf(needle) > -1);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
async (newValue) => {
|
||||||
|
visible.value = newValue;
|
||||||
|
sharedUsers.value = [];
|
||||||
|
canSharedUserFilter.value = undefined
|
||||||
|
if (newValue) {
|
||||||
|
await loadShared();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => visible.value,
|
||||||
|
(newValue) => {
|
||||||
|
emit('update:modelValue', newValue);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const shareTo = async (user: IUserDisplay) => {
|
||||||
|
addLoading.value = true;
|
||||||
|
loading.value = true;
|
||||||
|
await api.post(`api/domain/${user.id}?domainid=${props.domain.id}`)
|
||||||
|
await loadShared();
|
||||||
|
canSharedUserFilter.value = undefined;
|
||||||
|
loading.value = false;
|
||||||
|
addLoading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeShareTo = async (user: IUserDisplay) => {
|
||||||
|
removingUser.value = user;
|
||||||
|
loading.value = true;
|
||||||
|
await api.delete(`api/domain/${props.domain.id}/${user.id}`)
|
||||||
|
await loadShared();
|
||||||
|
loading.value = false;
|
||||||
|
removingUser.value = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
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));
|
||||||
|
canSharedUserFilteredOptions.value = canSharedUsers.value;
|
||||||
|
|
||||||
|
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,
|
||||||
|
isActive: item.is_active,
|
||||||
|
} as IUserDisplay
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.dialog-content {
|
||||||
|
width: 60vw;
|
||||||
|
max-height: 80vh;
|
||||||
|
.q-select {
|
||||||
|
min-width: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
45
frontend/src/components/ShareDomain/SharingUserList.vue
Normal file
45
frontend/src/components/ShareDomain/SharingUserList.vue
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<q-table :rows="users" :filter="filter" dense :columns="columns" row-key="id" :loading="loading" :pagination="pagination">
|
||||||
|
<template v-slot:top>
|
||||||
|
<div class="h6 text-weight-bold">{{props.title}}</div>
|
||||||
|
<q-space />
|
||||||
|
<q-input borderless dense filled debounce="300" v-model="filter" placeholder="検索">
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="search" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:body-cell-actions="props">
|
||||||
|
<q-td :props="props">
|
||||||
|
<slot name="actions" :row="props.row"></slot>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, PropType } from 'vue';
|
||||||
|
import { IUserDisplay } from '../../types/UserTypes';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
users: {
|
||||||
|
type: Array as PropType<IUserDisplay[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
title: String
|
||||||
|
});
|
||||||
|
|
||||||
|
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: 'actions', label: '', field: 'actions', sortable: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
const filter = ref('');
|
||||||
|
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 10 });
|
||||||
|
</script>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions v-if="!disableBtn" align="right" class="text-primary">
|
<q-card-actions v-if="!disableBtn" align="right" class="text-primary">
|
||||||
<q-btn flat label="確定" :loading="okBtnLoading" :v-close-popup="okBtnAutoClose" @click="CloseDialogue('OK')" />
|
<q-btn flat label="確定" :loading="okBtnLoading" :v-close-popup="okBtnAutoClose" @click="CloseDialogue('OK')" />
|
||||||
<q-btn flat label="キャンセル" v-close-popup @click="CloseDialogue('Cancel')" />
|
<q-btn flat label="キャンセル" :disable="okBtnLoading" v-close-popup @click="CloseDialogue('Cancel')" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|||||||
64
frontend/src/components/UserDomain/DomainCard.vue
Normal file
64
frontend/src/components/UserDomain/DomainCard.vue
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<q-card :class="['domain-card', small ? 'small' : '']">
|
||||||
|
<q-card-section :class="[small ? 'q-py-sm' : '']">
|
||||||
|
<div class="row items-center no-wrap">
|
||||||
|
<div class="col">
|
||||||
|
<div :class="[small ? 'text-subtitle2' : 'text-h6']">{{ item.name }} <q-icon v-if="isNotOwnerFunc(item.id)" name="account_circle" color="teal" class="q-mb-xs"></q-icon> </div>
|
||||||
|
<div :class="[small ? 'text-caption' : 'text-subtitle2']">{{ item.url }}</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div v-if="isNotOwnerFunc(item.id)" class="col-auto">
|
||||||
|
<q-icon name="account_circle" color="teal" size="2em"></q-icon>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section>
|
||||||
|
<div class="row items-center no-wrap">
|
||||||
|
<div class="col">
|
||||||
|
<div class="text-grey-7 text-caption text-weight-medium">
|
||||||
|
アカウント
|
||||||
|
</div>
|
||||||
|
<div class="smaller-font-size">{{ item.kintoneuser }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="isNotOwnerFunc(item.id)" class="col-auto">
|
||||||
|
<div class="text-grey-7 text-caption text-weight-medium">
|
||||||
|
所有者
|
||||||
|
</div>
|
||||||
|
<div class="smaller-font-size">{{ item.owner }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator v-if="$slots.actions" />
|
||||||
|
<slot name="actions" :item="item"></slot>
|
||||||
|
</q-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineProps, computed } from 'vue';
|
||||||
|
import { IDomain } from 'src/types/DomainTypes';
|
||||||
|
import { useAuthStore } from 'stores/useAuthStore';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
item: IDomain;
|
||||||
|
small: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const isNotOwnerFunc = computed(() => (ownerId: string) => {
|
||||||
|
return ownerId == authStore.userId;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.domain-card.small {
|
||||||
|
width: 18rem;
|
||||||
|
}
|
||||||
|
.domain-card {
|
||||||
|
width: 22rem;
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
|
.smaller-font-size {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,8 +9,8 @@ import { api } from 'boot/axios';
|
|||||||
const props = defineProps<{filter:string}>()
|
const props = defineProps<{filter:string}>()
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
|
{ 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 },
|
{ name: 'email', label: '電子メール', field: 'email', align: 'left', sortable: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
33
frontend/src/components/main/domainTable.vue
Normal file
33
frontend/src/components/main/domainTable.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<q-table :rows="rows" :columns="columns" row-key="id" :filter="filter" :loading="loading" :pagination="pagination">
|
||||||
|
|
||||||
|
<template v-slot:top>
|
||||||
|
<q-btn color="primary" :disable="loading" label="新規" @click="addRow" />
|
||||||
|
<q-space />
|
||||||
|
<q-input borderless dense filled debounce="300" v-model="filter" placeholder="検索">
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-icon name="search" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:body-cell-name="p">
|
||||||
|
<q-td class="flex justify-between items-center" :props="p">
|
||||||
|
{{ p.row.name }}
|
||||||
|
<q-badge v-if="!p.row.domainActive" color="grey">未启用</q-badge>
|
||||||
|
<q-badge v-if="p.row.id == currendDomainId" color="primary">現在</q-badge>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<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="edit_note" @click="editRow(p.row)" />
|
||||||
|
<q-btn flat color="negative" padding="xs" size="1em" icon="delete_outline" @click="removeRow(p.row)" />
|
||||||
|
</q-btn-group>
|
||||||
|
</q-td>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</q-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
|
|
||||||
<template v-slot:body-cell-name="p">
|
<template v-slot:body-cell-name="p">
|
||||||
<q-td class="flex justify-between items-center" :props="p">
|
<q-td class="flex justify-between items-center" :props="p">
|
||||||
{{ p.row.name }}
|
<div>
|
||||||
|
{{ p.row.name }}
|
||||||
|
<!-- <q-icon class="q-ml-xs" title="共有中です" name="people" :color="p.row.domainActive ? 'grey-8' : 'grey-4'" /> -->
|
||||||
|
</div>
|
||||||
<q-badge v-if="!p.row.domainActive" color="grey">未启用</q-badge>
|
<q-badge v-if="!p.row.domainActive" color="grey">未启用</q-badge>
|
||||||
<q-badge v-if="p.row.id == currentDomainId" color="primary">現在</q-badge>
|
<q-badge v-if="p.row.id == currentDomainId" color="primary">現在</q-badge>
|
||||||
</q-td>
|
</q-td>
|
||||||
@@ -29,6 +32,7 @@
|
|||||||
<q-td :props="p">
|
<q-td :props="p">
|
||||||
<q-btn-group flat>
|
<q-btn-group flat>
|
||||||
<q-btn flat color="primary" padding="xs" size="1em" icon="edit_note" @click="editRow(p.row)" />
|
<q-btn flat color="primary" padding="xs" size="1em" icon="edit_note" @click="editRow(p.row)" />
|
||||||
|
<q-btn flat color="primary" :disable="!p.row.domainActive" padding="xs" size="1em" icon="person_add_alt" @click="openShareDg(p.row)" />
|
||||||
<q-btn flat color="negative" padding="xs" size="1em" icon="delete_outline" @click="removeRow(p.row)" />
|
<q-btn flat color="negative" padding="xs" size="1em" icon="delete_outline" @click="removeRow(p.row)" />
|
||||||
</q-btn-group>
|
</q-btn-group>
|
||||||
</q-td>
|
</q-td>
|
||||||
@@ -50,7 +54,7 @@
|
|||||||
:rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" />
|
:rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" />
|
||||||
|
|
||||||
<q-input filled type="url" v-model.trim="url" label="Kintone url" hint="KintoneのURLを入力してください" lazy-rules
|
<q-input filled type="url" v-model.trim="url" label="Kintone url" hint="KintoneのURLを入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0, isDomain || 'KintoneのURLを入力してください']" />
|
:rules="[val => val && val.length > 0 || 'KintoneのURLを入力してください']" />
|
||||||
|
|
||||||
<q-input filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" lazy-rules
|
<q-input filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
||||||
@@ -109,18 +113,29 @@
|
|||||||
|
|
||||||
<q-dialog v-model="confirm" persistent>
|
<q-dialog v-model="confirm" persistent>
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section class="row items-center">
|
<q-card-section v-if="deleteLoadingState == -1" class="row items-center">
|
||||||
|
<q-spinner color="primary" size="2em"/>
|
||||||
|
<span class="q-ml-sm">共有ユーザーのチェック</span>
|
||||||
|
</q-card-section>
|
||||||
|
<q-card-section v-else-if="deleteLoadingState == 0" class="row items-center">
|
||||||
<q-icon name="warning" color="warning" size="2em" />
|
<q-icon name="warning" color="warning" size="2em" />
|
||||||
<span class="q-ml-sm">削除してもよろしいですか?</span>
|
<span class="q-ml-sm">削除してもよろしいですか?</span>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-card-section v-else class="row items-center">
|
||||||
|
<q-icon name="error" color="negative" size="2em" />
|
||||||
|
<span class="q-ml-sm">共有ユーザーが存在し、キャンセルする必要がある</span>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
<q-card-actions align="right">
|
<q-card-actions align="right">
|
||||||
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
<q-btn flat label="Cancel" color="primary" v-close-popup />
|
||||||
<q-btn flat label="OK" color="primary" v-close-popup @click="deleteDomain()" />
|
<q-btn v-if="deleteLoadingState > 0" label="処理に行く" color="primary" v-close-popup @click="openShareDg(editId)" />
|
||||||
|
<q-btn flat v-else label="OK" :disabled="deleteLoadingState" color="primary" v-close-popup @click="deleteDomain()" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</q-dialog>
|
</q-dialog>
|
||||||
|
|
||||||
|
<share-domain-dialog v-model="shareDg" :domain="shareDomain" @close="closeShareDg()" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -129,11 +144,12 @@ import { ref, onMounted, computed } from 'vue';
|
|||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
import { useAuthStore } from 'stores/useAuthStore';
|
import { useAuthStore } from 'stores/useAuthStore';
|
||||||
import { useDomainStore } from 'stores/useDomainStore';
|
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 authStore = useAuthStore();
|
||||||
const domainStore = useDomainStore();
|
const domainStore = useDomainStore();
|
||||||
const inactiveRowClass = (row: IDomainDisplay) => row.domainActive ? '' : 'inactive-row';
|
const inactiveRowClass = (row: IDomainOwnerDisplay) => row.domainActive ? '' : 'inactive-row';
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true, classes: inactiveRowClass },
|
{ 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: 'name', label: '環境名', field: 'name', align: 'left', sortable: true, classes: inactiveRowClass },
|
||||||
{ name: 'url', label: 'URL', field: 'url', 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: '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 pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const addEditLoading = ref(false);
|
const addEditLoading = ref(false);
|
||||||
|
const deleteLoadingState = ref<number>(-1); // -1: loading, 0: allow, > 0: user count
|
||||||
|
|
||||||
const filter = ref('');
|
const filter = ref('');
|
||||||
const rows = ref<IDomainDisplay[]>([]);
|
const rows = ref<IDomainOwnerDisplay[]>([]);
|
||||||
const show = ref(false);
|
const show = ref(false);
|
||||||
const confirm = ref(false);
|
const confirm = ref(false);
|
||||||
const resetPsw = ref(false);
|
const resetPsw = ref(false);
|
||||||
@@ -173,7 +191,8 @@ const kintonepwdBK = ref('');
|
|||||||
const domainActive = ref(true);
|
const domainActive = ref(true);
|
||||||
const isCreate = ref(true);
|
const isCreate = ref(true);
|
||||||
let editId = ref(0);
|
let editId = ref(0);
|
||||||
let ownerid = ref('');
|
const shareDg = ref(false);
|
||||||
|
const shareDomain = ref<IDomainOwnerDisplay>();
|
||||||
|
|
||||||
const getDomain = async () => {
|
const getDomain = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@@ -187,6 +206,16 @@ const getDomain = async () => {
|
|||||||
url: item.url,
|
url: item.url,
|
||||||
user: item.kintoneuser,
|
user: item.kintoneuser,
|
||||||
password: item.kintonepwd,
|
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;
|
loading.value = false;
|
||||||
@@ -203,17 +232,25 @@ const addRow = () => {
|
|||||||
show.value = true;
|
show.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeRow = (row: IDomainDisplay) => {
|
const removeRow = async (row: IDomainOwnerDisplay) => {
|
||||||
confirm.value = true;
|
confirm.value = true;
|
||||||
|
deleteLoadingState.value = -1;
|
||||||
editId.value = row.id;
|
editId.value = row.id;
|
||||||
|
|
||||||
|
const { data } = await api.get(`/api/domainshareduser/${row.id}`);
|
||||||
|
deleteLoadingState.value = data.data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteDomain = () => {
|
const deleteDomain = () => {
|
||||||
api.delete(`api/domain/${editId.value}`).then(() => {
|
api.delete(`api/domain/${editId.value}`).then(({ data }) => {
|
||||||
|
if (!data.data) {
|
||||||
|
// TODO dialog
|
||||||
|
}
|
||||||
getDomain();
|
getDomain();
|
||||||
// authStore.setCurrentDomain();
|
// authStore.setCurrentDomain();
|
||||||
})
|
})
|
||||||
editId.value = 0; // set in removeRow()
|
editId.value = 0; // set in removeRow()
|
||||||
|
deleteLoadingState.value = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const editRow = (row) => {
|
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 = () => {
|
const onReset = () => {
|
||||||
name.value = '';
|
name.value = '';
|
||||||
url.value = '';
|
url.value = '';
|
||||||
@@ -273,7 +322,6 @@ const onReset = () => {
|
|||||||
kintonepwd.value = '';
|
kintonepwd.value = '';
|
||||||
isPwd.value = true;
|
isPwd.value = true;
|
||||||
editId.value = 0;
|
editId.value = 0;
|
||||||
ownerid.value = '';
|
|
||||||
isCreate.value = true;
|
isCreate.value = true;
|
||||||
domainActive.value = true;
|
domainActive.value = true;
|
||||||
resetPsw.value = false
|
resetPsw.value = false
|
||||||
@@ -283,5 +331,6 @@ const onReset = () => {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.q-table td.inactive-row {
|
.q-table td.inactive-row {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -6,23 +6,14 @@
|
|||||||
<q-breadcrumbs-el icon="assignment_ind" label="ドメイン適用" />
|
<q-breadcrumbs-el icon="assignment_ind" label="ドメイン適用" />
|
||||||
</q-breadcrumbs>
|
</q-breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
<q-table :loading="loading" grid grid-header title="Domain" selection="single" :rows="rows" :columns="columns" row-key="name"
|
|
||||||
|
<q-table :loading="initLoading" grid grid-header title="Domain" selection="single" :rows="rows" :columns="columns" row-key="name"
|
||||||
:filter="userDomainTableFilter" virtual-scroll v-model:pagination="pagination">
|
:filter="userDomainTableFilter" virtual-scroll v-model:pagination="pagination">
|
||||||
|
|
||||||
<template v-slot:top>
|
<template v-slot:top>
|
||||||
|
|
||||||
<q-btn class="q-mx-none" color="primary" label="追加" @click="clickAddDomain()" />
|
<q-btn class="q-mx-none" color="primary" label="追加" @click="clickAddDomain()" />
|
||||||
|
|
||||||
<q-space />
|
<q-space />
|
||||||
<div class="row q-gutter-md">
|
<div class="row q-gutter-md">
|
||||||
<!-- <q-item v-if="authStore.permissions === 'admin'" tag="label" dense @click="clickSwitchUser()">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>適用するユーザ : </q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section avatar>
|
|
||||||
{{ currentUserName }}
|
|
||||||
</q-item-section>
|
|
||||||
</q-item> -->
|
|
||||||
|
|
||||||
<q-input borderless dense filled debounce="300" v-model="userDomainTableFilter" placeholder="Search">
|
<q-input borderless dense filled debounce="300" v-model="userDomainTableFilter" placeholder="Search">
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="search" />
|
<q-icon name="search" />
|
||||||
@@ -38,69 +29,25 @@
|
|||||||
|
|
||||||
<template v-slot:item="props">
|
<template v-slot:item="props">
|
||||||
<div class="q-pa-sm">
|
<div class="q-pa-sm">
|
||||||
<q-card>
|
<domain-card :item="props.row">
|
||||||
<q-card-section>
|
<template v-slot:actions>
|
||||||
<div class="q-table__grid-item-row">
|
<q-card-actions align="right">
|
||||||
<div class="q-table__grid-item-title">Domain</div>
|
<q-chip v-if="isActive(props.row.id)" outline color="teal" text-color="white" icon="done">
|
||||||
<div class="q-table__grid-item-value">{{ props.row.name }}</div>
|
既定
|
||||||
</div>
|
</q-chip>
|
||||||
<div class="q-table__grid-item-row">
|
<q-btn flat v-else :loading="activeDomainLoadingId === props.row.id" :disable="deleteDomainLoadingId === props.row.id" @click="activeDomain(props.row)">既定にする</q-btn>
|
||||||
<div class="q-table__grid-item-title">URL</div>
|
<q-btn flat :disable="isNotOwner(props.row.id) || activeDomainLoadingId === props.row.id" :text-color="isNotOwner(props.row.id)?'grey':''" :loading="deleteDomainLoadingId === props.row.id" @click="clickDeleteConfirm(props.row)">削除</q-btn>
|
||||||
<div class="q-table__grid-item-value" style="width: 22rem;">{{ props.row.url }}</div>
|
</q-card-actions>
|
||||||
</div>
|
</template>
|
||||||
<div class="q-table__grid-item-row">
|
</domain-card>
|
||||||
<div class="q-table__grid-item-title">Account</div>
|
|
||||||
<div class="q-table__grid-item-value">{{ props.row.kintoneuser }}</div>
|
|
||||||
</div>
|
|
||||||
</q-card-section>
|
|
||||||
<q-separator />
|
|
||||||
<q-card-actions align="right">
|
|
||||||
<div style="width: 98%;">
|
|
||||||
<div class="row items-center justify-between">
|
|
||||||
<div class="q-table__grid-item-value"
|
|
||||||
:class="isActive(props.row.id) ? 'text-positive' : 'text-negative'">{{
|
|
||||||
isActive(props.row.id)?'既定':'' }}</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<q-btn v-if="!isActive(props.row.id)" flat
|
|
||||||
@click="activeDomain(props.row)">既定にする</q-btn>
|
|
||||||
<q-btn flat @click="clickDeleteConfirm(props.row)">削除</q-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
|
|
||||||
<show-dialog v-model:visible="showAddDomainDg" name="ドメイン" @close="addUserDomainFinished">
|
<show-dialog v-model:visible="showAddDomainDg" name="ドメイン" @close="addUserDomainFinished" :ok-btn-loading="addUserDomainLoading" :ok-btn-auto-close="false">
|
||||||
<domain-select ref="addDomainRef" name="ドメイン" type="single" :filterInitRowsFunc="filterAddDgInitRows"></domain-select>
|
<domain-select ref="addDomainRef" name="ドメイン" type="single" :filterInitRowsFunc="filterAddDgInitRows"></domain-select>
|
||||||
</show-dialog>
|
</show-dialog>
|
||||||
|
|
||||||
<show-dialog v-model:visible="showSwitchUserDd" name="ドメイン" minWidth="35vw" @close="switchUserFinished">
|
|
||||||
<template v-slot:toolbar>
|
|
||||||
<q-input dense placeholder="検索" v-model="switchUserFilter">
|
|
||||||
<template v-slot:append>
|
|
||||||
<q-icon name="search" />
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</template>
|
|
||||||
<div class="q-gutter-md">
|
|
||||||
<q-item tag="label" class="q-pl-sm q-pr-none q-py-xs">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>他のユーザーを選択する</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-toggle v-model="useOtherUser" />
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<div v-if="useOtherUser">
|
|
||||||
<user-list ref="switchUserRef" name="ドメイン" :filter="switchUserFilter" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</show-dialog>
|
|
||||||
|
|
||||||
<q-dialog v-model="showDeleteConfirm" persistent>
|
<q-dialog v-model="showDeleteConfirm" persistent>
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section class="row items-center">
|
<q-card-section class="row items-center">
|
||||||
@@ -123,32 +70,28 @@
|
|||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import { api } from 'boot/axios';
|
import { api } from 'boot/axios';
|
||||||
import { useAuthStore } from 'stores/useAuthStore';
|
import { useAuthStore } from 'stores/useAuthStore';
|
||||||
import { useDomainStore } from 'stores/useDomainStore';
|
|
||||||
|
|
||||||
import ShowDialog from 'components/ShowDialog.vue';
|
import ShowDialog from 'components/ShowDialog.vue';
|
||||||
|
import DomainCard from 'components/UserDomain/DomainCard.vue';
|
||||||
import DomainSelect from 'components/DomainSelect.vue';
|
import DomainSelect from 'components/DomainSelect.vue';
|
||||||
import UserList from 'components/UserList.vue';
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const domainStore = useDomainStore();
|
|
||||||
const pagination = ref({ sortBy: 'id', rowsPerPage: 0 });
|
const pagination = ref({ sortBy: 'id', rowsPerPage: 0 });
|
||||||
const rows = ref([] as any[]);
|
const rows = ref([] as any[]);
|
||||||
const rowIds = new Set<string>();
|
const rowIds = new Set<string>();
|
||||||
const loading = ref(true);
|
const initLoading = ref(true);
|
||||||
|
const addUserDomainLoading = ref(false);
|
||||||
|
const activeDomainLoadingId = ref<number|undefined>(undefined);
|
||||||
|
const deleteDomainLoadingId = ref<number|undefined>(undefined);
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id' },
|
{ name: 'id' },
|
||||||
{ name: 'name', required: true, label: 'Name', align: 'left', field: 'name', sortable: true },
|
{ name: 'name', required: true, label: 'Name', align: 'left', field: 'name', sortable: true },
|
||||||
{ name: 'url', align: 'center', label: 'Domain', field: 'url', sortable: true },
|
{ name: 'url', align: 'center', label: 'Domain', field: 'url', sortable: true },
|
||||||
{ name: 'kintoneuser', label: 'User', field: 'kintoneuser', sortable: true },
|
{ name: 'kintoneuser', label: 'User', field: 'kintoneuser', sortable: true },
|
||||||
{ name: 'kintonepwd' },
|
|
||||||
];
|
];
|
||||||
const userDomainTableFilter = ref();
|
const userDomainTableFilter = ref();
|
||||||
|
|
||||||
const currentUserName = ref('');
|
|
||||||
const useOtherUser = ref(false);
|
|
||||||
const otherUserId = ref('');
|
|
||||||
|
|
||||||
let editId = ref(0);
|
let editId = ref(0);
|
||||||
|
|
||||||
const showAddDomainDg = ref(false);
|
const showAddDomainDg = ref(false);
|
||||||
@@ -163,22 +106,24 @@ const clickAddDomain = () => {
|
|||||||
showAddDomainDg.value = true;
|
showAddDomainDg.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const addUserDomainFinished = (val: string) => {
|
const addUserDomainFinished = async (val: string) => {
|
||||||
|
showAddDomainDg.value = true;
|
||||||
const selected = addDomainRef.value.selected;
|
const selected = addDomainRef.value.selected;
|
||||||
if (val == 'OK' && selected.length > 0) {
|
if (val == 'OK' && selected.length > 0) {
|
||||||
api.post(`api/domain/${useOtherUser.value ? otherUserId.value : authStore.userId}?domainid=${selected[0].id}`)
|
addUserDomainLoading.value = true;
|
||||||
.then(async ({ data }) => {
|
const { data } = await api.post(`api/domain/${authStore.userId}?domainid=${selected[0].id}`)
|
||||||
if (rows.value.length === 0 && data.data) {
|
if (rows.value.length === 0 && data.data) {
|
||||||
const domain = data.data;
|
const domain = data.data;
|
||||||
await authStore.setCurrentDomain({
|
await authStore.setCurrentDomain({
|
||||||
id: domain.id,
|
id: domain.id,
|
||||||
kintoneUrl: domain.url,
|
kintoneUrl: domain.url,
|
||||||
domainName: domain.name
|
domainName: domain.name
|
||||||
});
|
|
||||||
}
|
|
||||||
getDomain(useOtherUser.value ? otherUserId.value : undefined);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
await getDomain();
|
||||||
}
|
}
|
||||||
|
addUserDomainLoading.value = false;
|
||||||
|
showAddDomainDg.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const showDeleteConfirm = ref(false);
|
const showDeleteConfirm = ref(false);
|
||||||
@@ -189,26 +134,25 @@ const clickDeleteConfirm = (row: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deleteDomainFinished = async () => {
|
const deleteDomainFinished = async () => {
|
||||||
await api.delete(`api/domain/${editId.value}/${useOtherUser.value ? otherUserId.value : authStore.userId}`).then(({ data }) => {
|
deleteDomainLoadingId.value = editId.value;
|
||||||
if (data.msg == 'OK' && authStore.currentDomain.id === editId.value) {
|
const { data } = await api.delete(`api/domain/${editId.value}/${authStore.userId}`)
|
||||||
authStore.setCurrentDomain();
|
if (data.msg == 'OK' && authStore.currentDomain.id === editId.value) {
|
||||||
}
|
authStore.setCurrentDomain();
|
||||||
getDomain(useOtherUser.value ? otherUserId.value : undefined);
|
}
|
||||||
})
|
|
||||||
editId.value = 0;
|
editId.value = 0;
|
||||||
|
await getDomain();
|
||||||
|
deleteDomainLoadingId.value = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const activeDomain = async (domain: any) => {
|
const activeDomain = async (domain: any) => {
|
||||||
if (useOtherUser.value) {
|
activeDomainLoadingId.value = domain.id;
|
||||||
// TODO
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await authStore.setCurrentDomain({
|
await authStore.setCurrentDomain({
|
||||||
id: domain.id,
|
id: domain.id,
|
||||||
kintoneUrl: domain.url,
|
kintoneUrl: domain.url,
|
||||||
domainName: domain.name
|
domainName: domain.name
|
||||||
});
|
});
|
||||||
getDomain();
|
await getDomain();
|
||||||
|
activeDomainLoadingId.value = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
let activeDomainId = ref(0);
|
let activeDomainId = ref(0);
|
||||||
@@ -217,52 +161,43 @@ const isActive = computed(() => (id: number) => {
|
|||||||
return id == activeDomainId.value;
|
return id == activeDomainId.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isNotOwner = computed(() => (ownerId: string) => {
|
||||||
const showSwitchUserDd = ref(false);
|
return ownerId == authStore.userId;
|
||||||
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 getDomain = async (userId? : string) => {
|
const getDomain = async (userId? : string) => {
|
||||||
loading.value = true;
|
|
||||||
rowIds.clear();
|
rowIds.clear();
|
||||||
if (useOtherUser.value) {
|
|
||||||
// TODO
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const resp = await api.get(`api/defaultdomain`);
|
const resp = await api.get(`api/defaultdomain`);
|
||||||
activeDomainId.value = resp?.data?.data?.id;
|
activeDomainId.value = resp?.data?.data?.id;
|
||||||
const domainResult = userId ? await api.get(`api/domain?userId=${userId}`) : await api.get(`api/domain`);
|
const domainResult = userId ? await api.get(`api/domain?userId=${userId}`) : await api.get(`api/domain`);
|
||||||
const domains = domainResult.data as any[];
|
const domains = domainResult.data as any[];
|
||||||
rows.value = domains.map((item) => {
|
rows.value = domains.map((item) => {
|
||||||
rowIds.add(item.id);
|
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 () => {
|
onMounted(async () => {
|
||||||
currentUserName.value = authStore.userInfo.email
|
initLoading.value = true;
|
||||||
await getDomain();
|
await getDomain();
|
||||||
|
initLoading.value = false;
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.domain-card {
|
||||||
|
width: 22rem;
|
||||||
|
word-break: break-word;
|
||||||
|
|
||||||
|
.smaller-font-size {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -65,10 +65,10 @@
|
|||||||
<q-card-section class="q-pt-none q-mt-none">
|
<q-card-section class="q-pt-none q-mt-none">
|
||||||
<div class="q-gutter-lg">
|
<div class="q-gutter-lg">
|
||||||
|
|
||||||
<q-input filled v-model="firstName" label="氏名 *" hint="ユーザーの氏名を入力してください" lazy-rules
|
<q-input filled v-model="lastName" label="氏名 *" hint="ユーザーの氏名を入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'ユーザーの氏名を入力してください。']" />
|
:rules="[val => val && val.length > 0 || 'ユーザーの氏名を入力してください。']" />
|
||||||
|
|
||||||
<q-input filled v-model="lastName" label="苗字 *" hint="ユーザーの苗字を入力してください" lazy-rules
|
<q-input filled v-model="firstName" label="苗字 *" hint="ユーザーの苗字を入力してください" lazy-rules
|
||||||
:rules="[val => val && val.length > 0 || 'ユーザーの苗字を入力してください']" />
|
:rules="[val => val && val.length > 0 || 'ユーザーの苗字を入力してください']" />
|
||||||
|
|
||||||
<q-input filled type="email" v-model="email" label="電子メール *" hint="電子メール、ログインとしても使用" lazy-rules
|
<q-input filled type="email" v-model="email" label="電子メール *" hint="電子メール、ログインとしても使用" lazy-rules
|
||||||
@@ -158,8 +158,8 @@ import { api } from 'boot/axios';
|
|||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: 'id', label: 'ID', field: 'id', align: 'left', sortable: true },
|
{ 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 },
|
{ name: 'email', label: '電子メール', field: 'email', align: 'left', sortable: true },
|
||||||
{ name: 'status', label: '状況', field: 'status', align: 'left' },
|
{ name: 'status', label: '状況', field: 'status', align: 'left' },
|
||||||
{ name: 'actions', label: '操作', field: 'actions' }
|
{ name: 'actions', label: '操作', field: 'actions' }
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { IDomain } from './ActionTypes';
|
import { IUser, IUserDisplay } from './UserTypes';
|
||||||
import { IUser } from './UserTypes';
|
|
||||||
|
|
||||||
export interface IDomainInfo {
|
export interface IDomainInfo {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -32,4 +31,8 @@ export interface IDomainDisplay {
|
|||||||
user: string;
|
user: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
domainActive: boolean;
|
domainActive: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDomainOwnerDisplay extends IDomainDisplay {
|
||||||
|
owner: IUserDisplay
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,24 @@
|
|||||||
export interface IUser {
|
export interface IUser {
|
||||||
|
id: number;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
last_name: string;
|
last_name: string;
|
||||||
email: string;
|
email: string;
|
||||||
is_active: boolean,
|
is_active: boolean,
|
||||||
is_superuser: boolean,
|
is_superuser: boolean,
|
||||||
roles: string[]
|
roles: object[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IUserDisplay {
|
||||||
|
id: number;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
fullName: string;
|
||||||
|
fullNameSearch: string;
|
||||||
|
email: string;
|
||||||
|
isActive: boolean,
|
||||||
|
isSuperuser: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUserRolesDisplay extends IUserDisplay {
|
||||||
|
roles: object[]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user