vue2_frontend/src/components/todo/ListComponent.vue
2022-09-02 19:03:18 +09:00

383 lines
11 KiB
Vue

<template>
<div>
<!-- 참조: https://codesandbox.io/s/3v0m1?file=/src/components/board/BoardList.vue -->
<b-container fluid>
<b-row>
<b-col class="border">
<b-input-group>
<label class="input-group-text">
<b-form-checkbox @change="rowSelectAllToggle"
>All</b-form-checkbox
>
</label>
<b-form-select
v-model="selectedRowMode"
:options="selectedRowModes"
></b-form-select>
</b-input-group>
</b-col>
<b-col cols="4" class="border">
<b-input-group>
<label class="input-group-text">
<b-form-checkbox-group
class="d-flex flex-nowrap"
v-model="searchFields"
:options="searchFieldOptions"
></b-form-checkbox-group>
</label>
<b-form-input
v-model="search"
type="text"
placeholder="검색어"
@keydown.enter="searchClick"
></b-form-input>
<b-button @click="searchClick">검색</b-button>
</b-input-group>
</b-col>
<b-col cols="4" class="border">
<b-input-group>
<b-form-select
class="d-flex flex-nowrap"
v-model="filterDateField"
:options="filterDateFieldOptions"
></b-form-select>
<b-form-input v-model="filterDateStart" type="date"></b-form-input>
~
<b-form-input v-model="filterDateEnd" type="date"></b-form-input>
<b-button @click="dateClick">선택</b-button>
</b-input-group>
</b-col>
<b-col class="border">
<b-input-group class="justify-content-end">
<label class="input-group-text">줄수</label>
<b-form-select
v-model="perPage"
:options="perPageOptions"
@change="perPageClick"
></b-form-select>
</b-input-group>
</b-col>
</b-row>
</b-container>
<b-table
id="todoTable"
ref="todoTable"
:page="page"
:items="rows"
:fields="fields"
:per-page="perPage"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
@sort-changed="sortClick"
label-sort-asc=""
label-sort-desc=""
label-sort-clear=""
:select-mode="selectedRowMode"
selectable
@row-selected="rowSelectedToggle"
:busy="isBusy"
:sticky-header="commonTableAttributes.stickyHeader"
:no-border-collapse="commonTableAttributes.noBorderCollapse"
:striped="commonTableAttributes.striped"
:hover="commonTableAttributes.hover"
:no-local-sorting="commonTableAttributes.noLocalSorting"
:bordered="commonTableAttributes.bordered"
:dark="commonTableAttributes.dark"
:head-variant="commonTableAttributes.headVariant"
>
<!-- Column별 Filter용 -->
<template #thead-top>
<b-tr>
<b-td colspan="4"> </b-td>
<b-td variant="primary"
><b-form-select
v-model="filterIsDone"
:options="filterIsDoneFieldOptions"
@change="isDoneClick"
></b-form-select
></b-td>
<b-td></b-td>
</b-tr>
</template>
<!-- 비/선택 Row를 토글용 -->
<template #cell(rowSelect)="{ rowSelected }">
<template v-if="rowSelected">
<span aria-hidden="true">✓</span>
</template>
<template v-else>
<span aria-hidden="true">&nbsp;</span>
</template>
</template>
<!-- Row의 Index를 이용한 번호 출력 -->
<template #cell(id)="row">
<b-link ref="edit/{{row.item.id}}">
{{ total - (page * perPage + row.index) + perPage }}
</b-link>
</template>
<!-- 제목부분 출력용 -->
<template #cell(title)="row">
{{ row.item.title }}
</template>
<!-- 상세 내용 출력용 -->
<template #cell(content)="row">
<b-button size="sm" @click="row.toggleDetails" class="mr-2">
[{{ row.item.id }}] {{ row.detailsShowing ? '숨기기' : '보기' }}
</b-button>
</template>
<template #row-details="row">
<b-card>
<b-row>
<b-col v-html="row.item.content"></b-col>
</b-row>
<b-button size="sm" @click="row.toggleDetails">숨기기</b-button>
</b-card>
</template>
<!-- 데이터 로딩중 출력용 -->
<template #table-busy>
<div class="text-center text-danger my-2">
<b-spinner class="align-middle"></b-spinner>
<strong>Loading...</strong>
</div>
</template>
</b-table>
<b-container fluid>
<b-row>
<b-col>
<p>{{ selectedRows }}</p>
</b-col>
<b-col>
<b-pagination
:page="page"
:total-rows="total"
:per-page="perPage"
@page-click="pageClick"
last-number
aria-controls="todoTable"
class="justify-content-center"
>
</b-pagination>
</b-col>
<b-col>
<b-input-group class="justify-content-end">
<b-button @click="busyToggle">Toggle Busy State</b-button>
</b-input-group>
</b-col>
</b-row>
</b-container>
</div>
</template>
<script>
// 참조 : https://vuejsexamples.com/vuejs-tables-and-select-all-checkbox/
import axios from 'axios'
export default {
components: {},
data: function () {
return {
rows: [],
fields: [
{ key: 'rowSelect', label: '✓', thStyle: { width: '55px' } },
{
key: 'id',
label: '번호',
thStyle: { width: '75px' },
variant: 'primary',
sortable: true
},
{
key: 'title',
label: '제목',
sortable: true
},
{
key: 'content',
label: '내용',
sortable: true
},
{
key: 'is_done',
label: '사용여부',
thStyle: { width: '105px' },
formatter: (value) => {
const data = this.filterIsDoneFieldOptions.find(
(data) => data.value === value
)
return data ? data.text : value
},
sortable: true,
sortByFormatted: true //fomatter결과에따른 Sort가 필요시 true
},
// { key: 'updateAt', label: '수정일' },
{
key: 'createdAt',
label: '등록일',
thStyle: { width: '105px' },
formatter: (value) => {
return value.replace(
/([0-9]{4})-([0-9]{2})-([0-9]{2}).*/gi,
'$1-$2-$3'
)
},
sortable: true,
sortByFormatted: true //fomatter결과에따른 Sort가 필요시 true
}
],
total: 0,
page: process.env.VUE_APP_TABLE_DEFAULT_PAGE, // 현재 페이지
perPage: process.env.VUE_APP_TABLE_DEFAULT_PERPAGE, // 페이지당 보여줄 갯수
perPageOptions: [
{ text: '5줄', value: 5 },
{ text: '10줄', value: 10 },
{ text: '30줄', value: 30 },
{ text: '60줄', value: 60 },
{ text: '100줄', value: 100 }
],
// 속성옵션
commonTableAttributes: {
stickyHeader: '50%',
//noBorderCollapse: false,
striped: true,
hover: true,
noLocalSorting: true,
bordered: true,
dark: false,
headVariant: 'light'
},
isBusy: false,
sortBy: 'id',
sortDesc: true,
search: null,
searchFields: ['title', 'content'],
searchFieldOptions: [
{ text: '제목', value: 'title' },
{ text: '내용', value: 'content' }
],
filter: null,
filterField: null,
filterDateStart: null,
filterDateEnd: null,
filterDateField: 'createdAt',
filterDateFieldOptions: [
{ text: '수정일', value: 'updatedAt' },
{ text: '등록일', value: 'createdAt' }
],
filterIsDone: '',
filterIsDoneFieldOptions: [
{ text: '선택', value: '' },
{ text: 'YES', value: true },
{ text: 'NO', value: false }
],
selectedRows: [],
selectedRowAllToggle: false,
selectedRowMode: 'multi',
selectedRowModes: ['multi', 'single', 'range']
}
},
setup: function () {},
created: function () {},
mounted: function () {
this.getDatas()
},
unmounted() {},
methods: {
async getDatas(page = 1) {
this.isBusy = true
const results = await this.callAPI('/todo', {
params: {
page: page,
perPage: this.perPage,
sortBy: this.sortBy,
sortDesc: this.sortDesc,
searchFields: this.searchFields,
search: this.search,
filter: this.filter,
filterField: this.filterField,
filterDateStart: this.filterDateStart,
filterDateEnd: this.filterDateEnd
}
})
//console.log(JSON.stringify(results))
console.log(results)
this.total = results.total
this.perPage = results.perPage
this.page = results.page
this.sortBy = results.sortBy
this.sortDesc = results.sortDesc === 'true' ? true : false
this.rows = results.rows
this.isBusy = false
},
searchClick() {
this.getDatas()
},
pageClick(bvEvent, page) {
console.log(bvEvent)
this.getDatas(page)
// bvEvent.preventDefault()
},
perPageClick(perPage) {
this.perPage = perPage
console.log(this.perPage)
this.getDatas()
},
sortClick(event) {
console.log(event)
this.sortBy = event.sortBy
this.sortDesc = event.sortDesc
this.getDatas()
},
dateClick() {
this.filterField = this.filterDateField
this.getDatas()
},
isDoneClick() {
this.filter = this.filterIsDone
this.filterField = 'is_done'
this.getDatas()
},
busyToggle() {
this.isBusy = !this.isBusy
},
rowSelectedToggle(selectedRow) {
this.selectedRows = selectedRow
},
rowSelectAllToggle() {
if (this.selectedRowAllToggle) {
this.$refs.todoTable.clearSelected()
this.selectedRowAllToggle = false
} else {
this.$refs.todoTable.selectAllRows()
this.selectedRowAllToggle = true
}
},
// rowSelectSet(id) {
// // Rows are indexed from 0, so the third row is index 2
// this.$refs.todoTable.selectRow(id)
// },
// rowSelectUnSet(id) {
// // Rows are indexed from 0, so the third row is index 2
// this.$refs.todoTable.unselectRow(id)
// }
async callAPI(url, params) {
console.log('CallAPI..', [url, params])
axios.defaults.baseURL = process.env.VUE_APP_BACKEND_HOST
//전송 Header에 추가
const headers = {
Authorization:
'Bearer ' +
sessionStorage.getItem(process.env.VUE_APP_LOCALSTORAGE_NAME)
}
return await axios
.get(url, params, headers)
.then((response) => {
return response.status === 200 ? response.data : []
})
.catch((err) => {
console.log(err)
return []
})
}
},
computed: {}
}
</script>
<style scoped></style>