source merge
This commit is contained in:
@@ -16,6 +16,11 @@
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<template v-slot:body-cell-name="prop">
|
||||
<q-td :props="prop">
|
||||
<q-btn flat dense :label="prop.row.name" @click="toEditFlowPage(prop.row)" ></q-btn>
|
||||
</q-td>
|
||||
</template>
|
||||
<template v-slot:body-cell-url="prop">
|
||||
<q-td :props="prop">
|
||||
<a :href="prop.row.url" target="_blank" :title="prop.row.name" >
|
||||
@@ -25,11 +30,31 @@
|
||||
</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="toEditFlowPage(p.row)" />
|
||||
<q-btn disabled flat color="primary" padding="xs" size="1em" icon="history" @click="showHistory(p.row)" />
|
||||
<q-btn disabled flat color="negative" padding="xs" size="1em" icon="delete_outline" @click="removeRow(p.row)" />
|
||||
</q-btn-group>
|
||||
<q-btn flat padding="xs" round size="1em" icon="more_vert">
|
||||
<q-menu >
|
||||
<q-list dense style="min-width: 100px">
|
||||
<q-item clickable v-close-popup @click="toEditFlowPage(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="account_tree" />
|
||||
</q-item-section>
|
||||
<q-item-section>設定</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="showHistory(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="history" />
|
||||
</q-item-section>
|
||||
<q-item-section>履歴</q-item-section>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
<q-item class="text-red" clickable v-close-popup @click="removeRow(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="delete_outline" />
|
||||
</q-item-section>
|
||||
<q-item-section>削除</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
</template>
|
||||
</q-table>
|
||||
@@ -49,6 +74,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, reactive } from 'vue';
|
||||
import { useQuasar } from 'quasar'
|
||||
import { api } from 'boot/axios';
|
||||
import { useAuthStore } from 'stores/useAuthStore';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
@@ -78,7 +104,7 @@ const columns = [
|
||||
{ name: 'user', label: '最後更新者', field: 'user', align: 'left', sortable: true},
|
||||
{ name: 'updatetime', label: '最後更新日', field: 'updatetime', align: 'left', sortable: true},
|
||||
{ name: 'version', label: 'バージョン', field: 'version', align: 'left', sortable: true, sort: numberStringSorting },
|
||||
{ name: 'actions', label: '操作', field: 'actions' }
|
||||
{ name: 'actions', label: '', field: 'actions' }
|
||||
];
|
||||
|
||||
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||||
@@ -87,6 +113,7 @@ const filter = ref('');
|
||||
const rows = ref<IAppDisplay[]>([]);
|
||||
const rowIds = new Set<string>();
|
||||
|
||||
const $q = useQuasar()
|
||||
const store = useFlowEditorStore();
|
||||
const appDialog = ref();
|
||||
const showSelectApp=ref(false);
|
||||
@@ -95,12 +122,21 @@ const isAdding = ref(false);
|
||||
const getApps = async () => {
|
||||
loading.value = true;
|
||||
rowIds.clear();
|
||||
const result = await api.get('api/apps');
|
||||
rows.value = result.data.map((item: IManagedApp) => {
|
||||
rowIds.add(item.appid);
|
||||
return appToAppDisplay(item)
|
||||
}).sort((a: IAppDisplay, b: IAppDisplay) => a.sortId - b.sortId); // set default order
|
||||
loading.value = false;
|
||||
try {
|
||||
const { data } = await api.get('api/apps');
|
||||
rows.value = data.data.map((item: IManagedApp) => {
|
||||
rowIds.add(item.appid);
|
||||
return appToAppDisplay(item)
|
||||
}).sort((a: IAppDisplay, b: IAppDisplay) => a.sortId - b.sortId); // set default order
|
||||
} catch (error) {
|
||||
$q.notify({
|
||||
icon: 'error',
|
||||
color: 'negative',
|
||||
message: 'アプリ一覧の読み込みに失敗しました'
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -17,9 +17,15 @@
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-name="p">
|
||||
<q-td class="flex justify-between items-center" :props="p">
|
||||
{{ p.row.name }}
|
||||
<template v-slot:header-cell-active="p">
|
||||
<q-th auto-width :props="p">
|
||||
<q-select class="filter-header" v-model="activeFilter" :options="activeOptions" @update:model-value="activeFilterUpdate" borderless
|
||||
dense options-dense hide-bottom-space/>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-active="p">
|
||||
<q-td auto-width :props="p">
|
||||
<q-badge v-if="!p.row.domainActive" color="grey">未使用</q-badge>
|
||||
<q-badge v-if="p.row.id == currentDomainId" color="primary">既定</q-badge>
|
||||
</q-td>
|
||||
@@ -27,10 +33,31 @@
|
||||
|
||||
<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-btn flat padding="xs" round size="1em" icon="more_vert">
|
||||
<q-menu >
|
||||
<q-list dense style="min-width: 100px">
|
||||
<q-item clickable v-close-popup @click="editRow(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="edit_note" />
|
||||
</q-item-section>
|
||||
<q-item-section>編集</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="openShareDg(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="person_add_alt" />
|
||||
</q-item-section>
|
||||
<q-item-section>共有</q-item-section>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
<q-item class="text-red" clickable v-close-popup @click="removeRow(p.row)">
|
||||
<q-item-section>
|
||||
<q-icon size="1.2em" name="delete_outline" />
|
||||
</q-item-section>
|
||||
<q-item-section>削除</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
@@ -46,15 +73,11 @@
|
||||
<q-card-section class="q-pt-none q-mt-none">
|
||||
<div class="q-gutter-lg">
|
||||
|
||||
|
||||
<q-input filled v-model="tenantid" label="テナントID" hint="テナントIDを入力してください。" lazy-rules
|
||||
:rules="[val => val && val.length > 0 || 'テナントIDを入力してください。']" />
|
||||
|
||||
<q-input filled v-model="name" label="環境名 *" hint="kintoneの環境名を入力してください" lazy-rules
|
||||
:rules="[val => val && val.length > 0 || 'kintoneの環境名を入力してください。']" />
|
||||
|
||||
<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
|
||||
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
||||
@@ -103,7 +126,7 @@
|
||||
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary q-mb-md q-mx-sm">
|
||||
<q-btn label="保存" type="submit" color="primary" />
|
||||
<q-btn :loading="addEditLoading" label="保存" type="submit" color="primary" />
|
||||
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
@@ -113,18 +136,29 @@
|
||||
|
||||
<q-dialog v-model="confirm" persistent>
|
||||
<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" />
|
||||
<span class="q-ml-sm">削除してもよろしいですか?</span>
|
||||
</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-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>
|
||||
</q-dialog>
|
||||
|
||||
<share-domain-dialog v-model="shareDg" :domain="shareDomain" @close="closeShareDg()" />
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -133,39 +167,49 @@ 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 },
|
||||
{
|
||||
name: 'tenantid',
|
||||
required: true,
|
||||
label: 'テナントID',
|
||||
field: 'tenantid',
|
||||
align: 'left',
|
||||
sortable: true,
|
||||
classes: inactiveRowClass
|
||||
},
|
||||
// {
|
||||
// name: 'tenantid',
|
||||
// required: true,
|
||||
// label: 'テナントID',
|
||||
// field: 'tenantid',
|
||||
// align: 'left',
|
||||
// sortable: true,
|
||||
// classes: inactiveRowClass
|
||||
// },
|
||||
{ name: 'name', label: '環境名', field: 'name', align: 'left', sortable: true, classes: inactiveRowClass },
|
||||
{ name: 'active', label: 'x', align: 'left', field: 'domainActive', classes: inactiveRowClass },
|
||||
{ name: 'url', label: 'URL', field: 'url', align: 'left', sortable: true, 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<number>(-1); // -1: loading, 0: allow, > 0: user count
|
||||
|
||||
const filter = ref('');
|
||||
const rows = ref<IDomainDisplay[]>([]);
|
||||
const rows = ref<IDomainOwnerDisplay[]>([]);
|
||||
const show = ref(false);
|
||||
const confirm = ref(false);
|
||||
const resetPsw = ref(false);
|
||||
|
||||
const activeOptions = ['全データ', '启用', '未启用']
|
||||
const activeFilter = ref('全データ');
|
||||
|
||||
|
||||
const currentDomainId = computed(() => authStore.currentDomain.id);
|
||||
const tenantid = ref(authStore.currentDomain.id);
|
||||
// const tenantid = ref(authStore.currentDomain.id);
|
||||
const name = ref('');
|
||||
const url = ref('');
|
||||
const isPwd = ref(true);
|
||||
@@ -175,9 +219,24 @@ 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<IDomainOwnerDisplay>();
|
||||
|
||||
const getDomain = async () => {
|
||||
const activeFilterUpdate = (selected) => {
|
||||
switch (selected) {
|
||||
case '启用':
|
||||
getDomain((row) => row.domainActive)
|
||||
break;
|
||||
case '未启用':
|
||||
getDomain((row) => !row.domainActive)
|
||||
break;
|
||||
default:
|
||||
getDomain()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const getDomain = async (filter = () => true) => {
|
||||
loading.value = true;
|
||||
const { data } = await api.get<{data:IDomain[]}>(`api/domains`);
|
||||
rows.value = data.data.map((item) => {
|
||||
@@ -189,8 +248,18 @@ 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,
|
||||
}
|
||||
}
|
||||
});
|
||||
}).filter(filter);
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -205,23 +274,31 @@ 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) => {
|
||||
isCreate.value = false
|
||||
editId.value = row.id;
|
||||
tenantid.value = row.tenantid;
|
||||
// tenantid.value = row.tenantid;
|
||||
name.value = row.name;
|
||||
url.value = row.url;
|
||||
kintoneuser.value = row.user;
|
||||
@@ -246,10 +323,11 @@ const closeDg = () => {
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
addEditLoading.value = true;
|
||||
const method = editId.value !== 0 ? 'put' : 'post';
|
||||
const param: IDomainSubmit = {
|
||||
'id': editId.value,
|
||||
'tenantid': tenantid.value,
|
||||
'tenantid': '1', // TODO: テナントIDを取得する
|
||||
'name': name.value,
|
||||
'url': url.value,
|
||||
'kintoneuser': kintoneuser.value,
|
||||
@@ -258,14 +336,31 @@ const onSubmit = () => {
|
||||
'ownerid': authStore.userId || ''
|
||||
}
|
||||
// for search: api.put(`api/domain`)、api.post(`api/domain`)
|
||||
api[method].apply(api, [`api/domain`, param]).then(() => {
|
||||
api[method].apply(api, [`api/domain`, param]).then(async (resp: any) => {
|
||||
const res = resp.data;
|
||||
if (res.data.id === currentDomainId.value && !res.data.is_active) {
|
||||
await authStore.setCurrentDomain();
|
||||
}
|
||||
getDomain();
|
||||
domainStore.loadUserDomains();
|
||||
closeDg();
|
||||
onReset();
|
||||
addEditLoading.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
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,14 +368,25 @@ const onReset = () => {
|
||||
kintonepwd.value = '';
|
||||
isPwd.value = true;
|
||||
editId.value = 0;
|
||||
ownerid.value = '';
|
||||
isCreate.value = true;
|
||||
domainActive.value = true;
|
||||
resetPsw.value = false
|
||||
addEditLoading.value = false;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.filter-header .q-field__native {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.filter-header .q-icon {
|
||||
width: 12px;
|
||||
}
|
||||
.q-table td.inactive-row {
|
||||
color: #aaa;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
.q-table tr > td.inactive-row:last-child {
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,23 +6,14 @@
|
||||
<q-breadcrumbs-el icon="assignment_ind" label="ドメイン適用" />
|
||||
</q-breadcrumbs>
|
||||
</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">
|
||||
|
||||
<template v-slot:top>
|
||||
|
||||
<q-btn class="q-mx-none" color="primary" label="追加" @click="clickAddDomain()" />
|
||||
|
||||
<q-space />
|
||||
<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">
|
||||
<template v-slot:append>
|
||||
<q-icon name="search" />
|
||||
@@ -38,69 +29,25 @@
|
||||
|
||||
<template v-slot:item="props">
|
||||
<div class="q-pa-sm">
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<div class="q-table__grid-item-row">
|
||||
<div class="q-table__grid-item-title">Domain</div>
|
||||
<div class="q-table__grid-item-value">{{ props.row.name }}</div>
|
||||
</div>
|
||||
<div class="q-table__grid-item-row">
|
||||
<div class="q-table__grid-item-title">URL</div>
|
||||
<div class="q-table__grid-item-value" style="width: 22rem;">{{ props.row.url }}</div>
|
||||
</div>
|
||||
<div class="q-table__grid-item-row">
|
||||
<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>
|
||||
<domain-card :item="props.row" :active-id="activeDomainId">
|
||||
<template v-slot:actions>
|
||||
<q-card-actions align="right">
|
||||
<q-chip class="no-border" v-if="isActive(props.row.id)" outline color="primary" text-color="white" icon="done">
|
||||
既定
|
||||
</q-chip>
|
||||
<q-btn flat v-else :loading="activeDomainLoadingId === props.row.id" :disable="deleteDomainLoadingId === props.row.id" @click="activeDomain(props.row)">既定にする</q-btn>
|
||||
<q-btn flat :disable="isNotOwner(props.row.owner.id) || activeDomainLoadingId === props.row.id" :text-color="isNotOwner(props.row.owner.id)?'grey':''" :loading="deleteDomainLoadingId === props.row.id" @click="clickDeleteConfirm(props.row)">削除</q-btn>
|
||||
</q-card-actions>
|
||||
</template>
|
||||
</domain-card>
|
||||
</div>
|
||||
</template>
|
||||
</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>
|
||||
</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-card>
|
||||
<q-card-section class="row items-center">
|
||||
@@ -123,33 +70,29 @@
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
import { useAuthStore } from 'stores/useAuthStore';
|
||||
import { useDomainStore } from 'stores/useDomainStore';
|
||||
import { IDomainOwnerDisplay } from '../types/DomainTypes';
|
||||
|
||||
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 rows = ref<IDomainOwnerDisplay[]>([]);
|
||||
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 = [
|
||||
{ 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' },
|
||||
{ name: 'active', field: 'active' }
|
||||
{ name: 'kintoneuser', label: 'User', field: 'user', sortable: true },
|
||||
];
|
||||
const userDomainTableFilter = ref();
|
||||
|
||||
const currentUserName = ref('');
|
||||
const useOtherUser = ref(false);
|
||||
const otherUserId = ref('');
|
||||
|
||||
let editId = ref(0);
|
||||
|
||||
const showAddDomainDg = ref(false);
|
||||
@@ -164,22 +107,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);
|
||||
@@ -190,26 +135,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);
|
||||
@@ -218,52 +162,58 @@ 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/activedomain`);
|
||||
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) => {
|
||||
rows.value = domains.sort((a, b) => a.id - b.id).reduce((acc, item) => {
|
||||
rowIds.add(item.id);
|
||||
return { id: item.id, name: item.name, url: item.url, kintoneuser: item.kintoneuser, kintonepwd: item.kintonepwd }
|
||||
});
|
||||
loading.value = false;
|
||||
if (item.is_active) {
|
||||
acc.push({
|
||||
id: item.id,
|
||||
tenantid: item.tenantid,
|
||||
domainActive: item.is_active,
|
||||
name: item.name,
|
||||
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,
|
||||
}
|
||||
})
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
currentUserName.value = authStore.userInfo.email
|
||||
initLoading.value = true;
|
||||
await getDomain();
|
||||
initLoading.value = false;
|
||||
})
|
||||
|
||||
</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">
|
||||
<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 || 'ユーザーの氏名を入力してください。']" />
|
||||
|
||||
<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 || 'ユーザーの苗字を入力してください']" />
|
||||
|
||||
<q-input filled type="email" v-model="email" label="電子メール *" hint="電子メール、ログインとしても使用" lazy-rules
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
</q-card-section>
|
||||
<q-card-actions align="right" class="text-primary q-mb-md q-mx-sm">
|
||||
<q-btn label="保存" type="submit" color="primary" />
|
||||
<q-btn :loading="addEditLoading" label="保存" type="submit" color="primary" />
|
||||
<q-btn label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
||||
</q-card-actions>
|
||||
</q-form>
|
||||
@@ -158,8 +158,8 @@ import { api } from 'boot/axios';
|
||||
|
||||
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 },
|
||||
{ name: 'status', label: '状況', field: 'status', align: 'left' },
|
||||
{ name: 'actions', label: '操作', field: 'actions' }
|
||||
@@ -168,6 +168,7 @@ const columns = [
|
||||
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||||
|
||||
const loading = ref(false);
|
||||
const addEditLoading = ref(false);
|
||||
const filter = ref('');
|
||||
const statusFilter = ref('全データ');
|
||||
const rows = ref([]);
|
||||
@@ -189,7 +190,7 @@ let editId = ref(0);
|
||||
const getUsers = async (filter = () => true) => {
|
||||
loading.value = true;
|
||||
const result = await api.get(`api/v1/users`);
|
||||
rows.value = result.data.map((item) => {
|
||||
rows.value = result.data.data.map((item) => {
|
||||
return { id: item.id, firstName: item.first_name, lastName: item.last_name, email: item.email, isSuperuser: item.is_superuser, isActive: item.is_active }
|
||||
}).filter(filter);
|
||||
loading.value = false;
|
||||
@@ -260,6 +261,7 @@ const closeDg = () => {
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
addEditLoading.value = true;
|
||||
if (editId.value !== 0) {
|
||||
api.put(`api/v1/users/${editId.value}`, {
|
||||
'first_name': firstName.value,
|
||||
@@ -302,6 +304,7 @@ const onReset = () => {
|
||||
isPwd.value = true;
|
||||
editId.value = 0;
|
||||
isCreate.value = true;
|
||||
resetPsw.value = false
|
||||
resetPsw.value = false;
|
||||
addEditLoading.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user