287 lines
9.8 KiB
Vue
287 lines
9.8 KiB
Vue
<template>
|
||
<div class="q-pa-md">
|
||
<div class="q-gutter-sm row items-start">
|
||
<q-breadcrumbs>
|
||
<q-breadcrumbs-el icon="domain" label="ドメイン管理" />
|
||
</q-breadcrumbs>
|
||
</div>
|
||
<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 == currentDomainId" 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>
|
||
|
||
<q-dialog :model-value="show" persistent>
|
||
<q-card style="min-width: 36em">
|
||
<q-form class="q-gutter-md" @submit="onSubmit" autocomplete="off">
|
||
<q-card-section>
|
||
<div class="text-h6 q-ma-sm">Kintone Account</div>
|
||
</q-card-section>
|
||
|
||
<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を入力してください']" />
|
||
|
||
<q-input filled v-model="kintoneuser" label="ログイン名 *" hint="Kintoneのログイン名を入力してください" lazy-rules
|
||
:rules="[val => val && val.length > 0 || 'Kintoneのログイン名を入力してください']" autocomplete="new-password" />
|
||
|
||
<q-input v-if="isCreate" v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'"
|
||
hint="パスワード" label="パスワード" :disable="!isCreate" lazy-rules
|
||
:rules="[val => val && val.length > 0 || 'Please type something']" autocomplete="new-password">
|
||
<template v-slot:append>
|
||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||
@click="isPwd = !isPwd" />
|
||
</template>
|
||
</q-input>
|
||
|
||
<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="domainActive" />
|
||
</q-item-section>
|
||
</q-item>
|
||
|
||
<div class="q-gutter-y-md" v-if="!isCreate">
|
||
<q-separator />
|
||
|
||
<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="resetPsw" @update:model-value="updateResetPsw" />
|
||
</q-item-section>
|
||
</q-item>
|
||
|
||
<q-input v-model="kintonepwd" filled :type="isPwd ? 'password' : 'text'" hint="パスワードを入力してください"
|
||
label="パスワード" :disable="!resetPsw" lazy-rules
|
||
:rules="[val => val && val.length > 0 || 'Please type something']" autocomplete="new-password">
|
||
<template v-slot:append>
|
||
<q-icon :name="isPwd ? 'visibility_off' : 'visibility'" class="cursor-pointer"
|
||
@click="isPwd = !isPwd" />
|
||
</template>
|
||
</q-input>
|
||
<!-- <q-btn label="asdf"/> -->
|
||
</div>
|
||
</div>
|
||
|
||
</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 label="キャンセル" type="cancel" color="primary" flat class="q-ml-sm" @click="closeDg()" />
|
||
</q-card-actions>
|
||
</q-form>
|
||
</q-card>
|
||
|
||
</q-dialog>
|
||
|
||
<q-dialog v-model="confirm" persistent>
|
||
<q-card>
|
||
<q-card-section class="row items-center">
|
||
<q-icon name="warning" color="warning" 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-card-actions>
|
||
</q-card>
|
||
</q-dialog>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
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';
|
||
|
||
const authStore = useAuthStore();
|
||
const domainStore = useDomainStore();
|
||
const inactiveRowClass = (row: IDomainDisplay) => 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: 'name', label: '環境名', field: 'name', align: 'left', 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: 'actions', label: '操作', field: 'actions' }
|
||
];
|
||
|
||
const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||
const loading = ref(false);
|
||
const filter = ref('');
|
||
const rows = ref<IDomainDisplay[]>([]);
|
||
const show = ref(false);
|
||
const confirm = ref(false);
|
||
const resetPsw = ref(false);
|
||
|
||
const currentDomainId = computed(() => authStore.currentDomain.id);
|
||
const tenantid = ref(authStore.currentDomain.id);
|
||
const name = ref('');
|
||
const url = ref('');
|
||
const isPwd = ref(true);
|
||
const kintoneuser = ref('');
|
||
const kintonepwd = ref('');
|
||
const kintonepwdBK = ref('');
|
||
const domainActive = ref(true);
|
||
const isCreate = ref(true);
|
||
let editId = ref(0);
|
||
let ownerid = ref('');
|
||
|
||
const getDomain = async () => {
|
||
loading.value = true;
|
||
const { data } = await api.get<{data:IDomain[]}>(`api/domains`);
|
||
rows.value = data.data.map((item) => {
|
||
return {
|
||
id: item.id,
|
||
tenantid: item.tenantid,
|
||
domainActive: item.is_active,
|
||
name: item.name,
|
||
url: item.url,
|
||
user: item.kintoneuser,
|
||
password: item.kintonepwd,
|
||
}
|
||
});
|
||
loading.value = false;
|
||
}
|
||
|
||
onMounted(async () => {
|
||
await getDomain();
|
||
})
|
||
|
||
// emulate fetching data from server
|
||
const addRow = () => {
|
||
// editId.value
|
||
onReset();
|
||
show.value = true;
|
||
}
|
||
|
||
const removeRow = (row: IDomainDisplay) => {
|
||
confirm.value = true;
|
||
editId.value = row.id;
|
||
}
|
||
|
||
const deleteDomain = () => {
|
||
api.delete(`api/domain/${editId.value}`).then(() => {
|
||
getDomain();
|
||
// authStore.setCurrentDomain();
|
||
})
|
||
editId.value = 0; // set in removeRow()
|
||
};
|
||
|
||
const editRow = (row) => {
|
||
isCreate.value = false
|
||
editId.value = row.id;
|
||
tenantid.value = row.tenantid;
|
||
name.value = row.name;
|
||
url.value = row.url;
|
||
kintoneuser.value = row.user;
|
||
kintonepwd.value = row.password;
|
||
domainActive.value = row.domainActive;
|
||
isPwd.value = true;
|
||
show.value = true;
|
||
};
|
||
|
||
const updateResetPsw = (value: boolean) => {
|
||
if (value === true) {
|
||
kintonepwd.value = ''
|
||
isPwd.value = true
|
||
} else {
|
||
kintonepwd.value = kintonepwdBK.value
|
||
}
|
||
}
|
||
|
||
const closeDg = () => {
|
||
show.value = false;
|
||
onReset();
|
||
}
|
||
|
||
const onSubmit = () => {
|
||
const method = editId.value !== 0 ? 'put' : 'post';
|
||
const param: IDomainSubmit = {
|
||
'id': editId.value,
|
||
'tenantid': tenantid.value,
|
||
'name': name.value,
|
||
'url': url.value,
|
||
'kintoneuser': kintoneuser.value,
|
||
'kintonepwd': ((isCreate.value && editId.value == 0) || resetPsw.value) ? kintonepwd.value : '',
|
||
'is_active': domainActive.value,
|
||
'ownerid': authStore.userId || ''
|
||
}
|
||
// for search: api.put(`api/domain`)、api.post(`api/domain`)
|
||
api[method].apply(api, [`api/domain`, param]).then(() => {
|
||
getDomain();
|
||
domainStore.loadUserDomains();
|
||
closeDg();
|
||
onReset();
|
||
})
|
||
}
|
||
|
||
const onReset = () => {
|
||
name.value = '';
|
||
url.value = '';
|
||
kintoneuser.value = '';
|
||
kintonepwd.value = '';
|
||
isPwd.value = true;
|
||
editId.value = 0;
|
||
ownerid.value = '';
|
||
isCreate.value = true;
|
||
domainActive.value = true;
|
||
resetPsw.value = false
|
||
}
|
||
</script>
|
||
<style lang="scss">
|
||
.q-table td.inactive-row {
|
||
color: #aaa;
|
||
}
|
||
</style>
|