Task FIlters (#149)
Set done filter based on passed params Make due date filter actually work Move filters into seperate config Merge branch 'master' into feature/task-filters Change done task filter text Make sure done tasks are always shown in table view Table view filter improvements Add done filter to table view Fix indent Add filter icon Move search and filter container Add filter for done tasks Hide done tasks by default Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/149
This commit is contained in:
parent
55afb7adc4
commit
ef01e8807e
8 changed files with 353 additions and 101 deletions
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
required: true,
|
required: false,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -52,7 +52,3 @@
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
152
src/components/lists/reusable/filters.vue
Normal file
152
src/components/lists/reusable/filters.vue
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<template>
|
||||||
|
<div class="card filters">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Show Done Tasks</label>
|
||||||
|
<div class="control">
|
||||||
|
<fancycheckbox @change="setDoneFilter" v-model="filters.done">
|
||||||
|
Show Done Tasks
|
||||||
|
</fancycheckbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Due Date</label>
|
||||||
|
<div class="control">
|
||||||
|
<flat-pickr
|
||||||
|
class="input"
|
||||||
|
:config="flatPickerConfig"
|
||||||
|
placeholder="Due Date Range"
|
||||||
|
v-model="filters.dueDate"
|
||||||
|
@on-close="setDueDateFilter"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Fancycheckbox from '../../global/fancycheckbox'
|
||||||
|
import flatPickr from 'vue-flatpickr-component'
|
||||||
|
import 'flatpickr/dist/flatpickr.css'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'filters',
|
||||||
|
components: {
|
||||||
|
Fancycheckbox,
|
||||||
|
flatPickr,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
params: {
|
||||||
|
sort_by: [],
|
||||||
|
order_by: [],
|
||||||
|
filter_by: [],
|
||||||
|
filter_value: [],
|
||||||
|
filter_comparator: [],
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
done: false,
|
||||||
|
dueDate: '',
|
||||||
|
},
|
||||||
|
flatPickerConfig: {
|
||||||
|
altFormat: 'j M Y H:i',
|
||||||
|
altInput: true,
|
||||||
|
dateFormat: 'Y-m-d H:i',
|
||||||
|
enableTime: true,
|
||||||
|
time_24hr: true,
|
||||||
|
mode: 'range',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.params = this.value
|
||||||
|
this.prepareDone()
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(newVal) {
|
||||||
|
this.$set(this, 'params', newVal)
|
||||||
|
this.prepareDone()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
change() {
|
||||||
|
this.$emit('input', this.params)
|
||||||
|
this.$emit('change', this.params)
|
||||||
|
},
|
||||||
|
prepareDone() {
|
||||||
|
// Set filters.done based on params
|
||||||
|
if(typeof this.params.filter_by !== 'undefined') {
|
||||||
|
let foundDone = false
|
||||||
|
this.params.filter_by.forEach((f, i) => {
|
||||||
|
if (f === 'done') {
|
||||||
|
foundDone = i
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (foundDone === false) {
|
||||||
|
this.filters.done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setDoneFilter() {
|
||||||
|
if (this.filters.done) {
|
||||||
|
for (const i in this.params.filter_by) {
|
||||||
|
if (this.params.filter_by[i] === 'done') {
|
||||||
|
this.params.filter_by.splice(i, 1)
|
||||||
|
this.params.filter_comparator.splice(i, 1)
|
||||||
|
this.params.filter_value.splice(i, 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.params.filter_by.push('done')
|
||||||
|
this.params.filter_comparator.push('equals')
|
||||||
|
this.params.filter_value.push('false')
|
||||||
|
}
|
||||||
|
this.change()
|
||||||
|
},
|
||||||
|
setDueDateFilter() {
|
||||||
|
// Only filter if we have a start and end due date
|
||||||
|
if (this.filters.dueDate !== '') {
|
||||||
|
|
||||||
|
const parts = this.filters.dueDate.split(' to ')
|
||||||
|
|
||||||
|
if(parts.length < 2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we already have values in params and only update them if we do
|
||||||
|
let foundStart = false
|
||||||
|
let foundEnd = false
|
||||||
|
this.params.filter_by.forEach((f, i) => {
|
||||||
|
if (f === 'due_date' && this.params.filter_comparator[i] === 'greater_equals') {
|
||||||
|
foundStart = true
|
||||||
|
this.params.filter_value[i] = +new Date(parts[0]) / 1000
|
||||||
|
}
|
||||||
|
if (f === 'due_date' && this.params.filter_comparator[i] === 'less_equals') {
|
||||||
|
foundEnd = true
|
||||||
|
this.params.filter_value[i] = +new Date(parts[1]) / 1000
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!foundStart) {
|
||||||
|
this.params.filter_by.push('due_date')
|
||||||
|
this.params.filter_comparator.push('greater_equals')
|
||||||
|
this.params.filter_value.push(+new Date(parts[0]) / 1000)
|
||||||
|
}
|
||||||
|
if (!foundEnd) {
|
||||||
|
this.params.filter_by.push('due_date')
|
||||||
|
this.params.filter_comparator.push('less_equals')
|
||||||
|
this.params.filter_value.push(+new Date(parts[1]) / 1000)
|
||||||
|
}
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,40 +1,64 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="loader-container" :class="{ 'is-loading': taskCollectionService.loading}">
|
<div class="loader-container" :class="{ 'is-loading': taskCollectionService.loading}">
|
||||||
<div class="search">
|
<div class="filter-container">
|
||||||
<div class="field has-addons" :class="{ 'hidden': !showTaskSearch }">
|
<div class="items">
|
||||||
<div class="control has-icons-left has-icons-right">
|
<div class="search">
|
||||||
<input
|
<div class="field has-addons" :class="{ 'hidden': !showTaskSearch }">
|
||||||
class="input"
|
<div class="control has-icons-left has-icons-right">
|
||||||
type="text"
|
<input
|
||||||
placeholder="Search"
|
class="input"
|
||||||
v-focus
|
type="text"
|
||||||
v-model="searchTerm"
|
placeholder="Search"
|
||||||
@keyup.enter="searchTasks"
|
v-focus
|
||||||
@blur="hideSearchBar()"/>
|
v-model="searchTerm"
|
||||||
<span class="icon is-left">
|
@keyup.enter="searchTasks"
|
||||||
<icon icon="search"/>
|
@blur="hideSearchBar()"/>
|
||||||
</span>
|
<span class="icon is-left">
|
||||||
</div>
|
<icon icon="search"/>
|
||||||
<div class="control">
|
</span>
|
||||||
<button
|
</div>
|
||||||
class="button noshadow is-primary"
|
<div class="control">
|
||||||
@click="searchTasks"
|
<button
|
||||||
:class="{'is-loading': taskCollectionService.loading}">
|
class="button noshadow is-primary"
|
||||||
Search
|
@click="searchTasks"
|
||||||
|
:class="{'is-loading': taskCollectionService.loading}">
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="button" @click="showTaskSearch = !showTaskSearch" v-if="!showTaskSearch">
|
||||||
|
<span class="icon">
|
||||||
|
<icon icon="search"/>
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button class="button" @click="showTaskFilter = !showTaskFilter">
|
||||||
|
<span class="icon is-small">
|
||||||
|
<icon icon="filter"/>
|
||||||
|
</span>
|
||||||
|
Filters
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button class="button" @click="showTaskSearch = !showTaskSearch" v-if="!showTaskSearch">
|
<transition name="fade">
|
||||||
<span class="icon">
|
<filters
|
||||||
<icon icon="search"/>
|
v-if="showTaskFilter"
|
||||||
</span>
|
v-model="params"
|
||||||
</button>
|
@change="loadTasks(1)"
|
||||||
|
/>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field task-add" v-if="!list.isArchived">
|
<div class="field task-add" v-if="!list.isArchived">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<p class="control has-icons-left is-expanded" :class="{ 'is-loading': taskService.loading}">
|
<p class="control has-icons-left is-expanded" :class="{ 'is-loading': taskService.loading}">
|
||||||
<input v-focus class="input" :class="{ 'disabled': taskService.loading}" v-model="newTaskText" type="text" placeholder="Add a new task..." @keyup.enter="addTask()"/>
|
<input
|
||||||
|
v-focus
|
||||||
|
class="input"
|
||||||
|
:class="{ 'disabled': taskService.loading}"
|
||||||
|
v-model="newTaskText"
|
||||||
|
type="text"
|
||||||
|
placeholder="Add a new task..."
|
||||||
|
@keyup.enter="addTask()"/>
|
||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<icon icon="tasks"/>
|
<icon icon="tasks"/>
|
||||||
</span>
|
</span>
|
||||||
|
@ -85,14 +109,36 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="pagination is-centered" role="navigation" aria-label="pagination" v-if="taskCollectionService.totalPages > 1">
|
<nav
|
||||||
<router-link class="pagination-previous" :to="getRouteForPagination(currentPage - 1)" tag="button" :disabled="currentPage === 1">Previous</router-link>
|
class="pagination is-centered"
|
||||||
<router-link class="pagination-next" :to="getRouteForPagination(currentPage + 1)" tag="button" :disabled="currentPage === taskCollectionService.totalPages">Next page</router-link>
|
role="navigation"
|
||||||
|
aria-label="pagination"
|
||||||
|
v-if="taskCollectionService.totalPages > 1">
|
||||||
|
<router-link
|
||||||
|
class="pagination-previous"
|
||||||
|
:to="getRouteForPagination(currentPage - 1)"
|
||||||
|
tag="button"
|
||||||
|
:disabled="currentPage === 1">
|
||||||
|
Previous
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
class="pagination-next"
|
||||||
|
:to="getRouteForPagination(currentPage + 1)"
|
||||||
|
tag="button"
|
||||||
|
:disabled="currentPage === taskCollectionService.totalPages">
|
||||||
|
Next page
|
||||||
|
</router-link>
|
||||||
<ul class="pagination-list">
|
<ul class="pagination-list">
|
||||||
<template v-for="(p, i) in pages">
|
<template v-for="(p, i) in pages">
|
||||||
<li :key="'page'+i" v-if="p.isEllipsis"><span class="pagination-ellipsis">…</span></li>
|
<li :key="'page'+i" v-if="p.isEllipsis"><span class="pagination-ellipsis">…</span></li>
|
||||||
<li :key="'page'+i" v-else>
|
<li :key="'page'+i" v-else>
|
||||||
<router-link :to="getRouteForPagination(p.number)" :class="{'is-current': p.number === currentPage}" class="pagination-link" :aria-label="'Goto page ' + p.number">{{ p.number }}</router-link>
|
<router-link
|
||||||
|
:to="getRouteForPagination(p.number)"
|
||||||
|
:class="{'is-current': p.number === currentPage}"
|
||||||
|
class="pagination-link"
|
||||||
|
:aria-label="'Goto page ' + p.number">
|
||||||
|
{{ p.number }}
|
||||||
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -113,6 +159,7 @@
|
||||||
import SingleTaskInList from '../../tasks/reusable/singleTaskInList'
|
import SingleTaskInList from '../../tasks/reusable/singleTaskInList'
|
||||||
import taskList from '../../tasks/helpers/taskList'
|
import taskList from '../../tasks/helpers/taskList'
|
||||||
import {saveListView} from '../../../helpers/saveListView'
|
import {saveListView} from '../../../helpers/saveListView'
|
||||||
|
import Filters from '../reusable/filters'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'List',
|
name: 'List',
|
||||||
|
@ -131,6 +178,7 @@
|
||||||
taskList,
|
taskList,
|
||||||
],
|
],
|
||||||
components: {
|
components: {
|
||||||
|
Filters,
|
||||||
SingleTaskInList,
|
SingleTaskInList,
|
||||||
EditTask,
|
EditTask,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="table-view loader-container" :class="{'is-loading': taskCollectionService.loading}">
|
<div class="table-view loader-container" :class="{'is-loading': taskCollectionService.loading}">
|
||||||
<div class="column-filter">
|
<div class="filter-container">
|
||||||
<button class="button" @click="showActiveColumnsFilter = !showActiveColumnsFilter">
|
<div class="items">
|
||||||
<span class="icon is-small">
|
<button class="button" @click="() => {showActiveColumnsFilter = !showActiveColumnsFilter; showTaskFilter = false}">
|
||||||
<icon icon="th"/>
|
<span class="icon is-small">
|
||||||
</span>
|
<icon icon="th"/>
|
||||||
Columns
|
</span>
|
||||||
</button>
|
Columns
|
||||||
|
</button>
|
||||||
|
<button class="button" @click="() => {showTaskFilter = !showTaskFilter; showActiveColumnsFilter = false}">
|
||||||
|
<span class="icon is-small">
|
||||||
|
<icon icon="filter"/>
|
||||||
|
</span>
|
||||||
|
Filters
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<div class="card" v-if="showActiveColumnsFilter">
|
<div class="card" v-if="showActiveColumnsFilter">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
|
@ -25,6 +33,11 @@
|
||||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">Created By</fancycheckbox>
|
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">Created By</fancycheckbox>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<filters
|
||||||
|
v-if="showTaskFilter"
|
||||||
|
v-model="params"
|
||||||
|
@change="loadTasks(1)"
|
||||||
|
/>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -155,10 +168,12 @@
|
||||||
import Fancycheckbox from '../../global/fancycheckbox'
|
import Fancycheckbox from '../../global/fancycheckbox'
|
||||||
import Sort from '../../tasks/reusable/sort'
|
import Sort from '../../tasks/reusable/sort'
|
||||||
import {saveListView} from '../../../helpers/saveListView'
|
import {saveListView} from '../../../helpers/saveListView'
|
||||||
|
import Filters from '../reusable/filters'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Table',
|
name: 'Table',
|
||||||
components: {
|
components: {
|
||||||
|
Filters,
|
||||||
Sort,
|
Sort,
|
||||||
Fancycheckbox,
|
Fancycheckbox,
|
||||||
DateTableCell,
|
DateTableCell,
|
||||||
|
@ -202,6 +217,10 @@
|
||||||
this.$set(this, 'sortBy', JSON.parse(savedSortBy))
|
this.$set(this, 'sortBy', JSON.parse(savedSortBy))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$set(this.params, 'filter_by', [])
|
||||||
|
this.$set(this.params, 'filter_value', [])
|
||||||
|
this.$set(this.params, 'filter_comparator', [])
|
||||||
|
|
||||||
this.initTasks(1)
|
this.initTasks(1)
|
||||||
|
|
||||||
// Save the current list view to local storage
|
// Save the current list view to local storage
|
||||||
|
@ -210,7 +229,9 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initTasks(page, search = '') {
|
initTasks(page, search = '') {
|
||||||
let params = {sort_by: [], order_by: []}
|
const params = this.params
|
||||||
|
params.sort_by = []
|
||||||
|
params.order_by = []
|
||||||
Object.keys(this.sortBy).map(s => {
|
Object.keys(this.sortBy).map(s => {
|
||||||
params.sort_by.push(s)
|
params.sort_by.push(s)
|
||||||
params.order_by.push(this.sortBy[s])
|
params.order_by.push(this.sortBy[s])
|
||||||
|
|
|
@ -14,6 +14,16 @@ export default {
|
||||||
|
|
||||||
showTaskSearch: false,
|
showTaskSearch: false,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
|
|
||||||
|
showTaskFilter: false,
|
||||||
|
params: {
|
||||||
|
sort_by: ['done', 'id'],
|
||||||
|
order_by: ['asc', 'desc'],
|
||||||
|
filter_by: ['done'],
|
||||||
|
filter_value: ['false'],
|
||||||
|
filter_comparator: ['equals'],
|
||||||
|
filter_concat: 'and',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -28,7 +38,11 @@ export default {
|
||||||
this.taskCollectionService = new TaskCollectionService()
|
this.taskCollectionService = new TaskCollectionService()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadTasks(page, search = '', params = {sort_by: ['done', 'id'], order_by: ['asc', 'desc']}) {
|
loadTasks(
|
||||||
|
page,
|
||||||
|
search = '',
|
||||||
|
params = null,
|
||||||
|
) {
|
||||||
|
|
||||||
// Because this function is triggered every time on navigation, we're putting a condition here to only load it when we actually want to show tasks
|
// Because this function is triggered every time on navigation, we're putting a condition here to only load it when we actually want to show tasks
|
||||||
// FIXME: This is a bit hacky -> Cleanup.
|
// FIXME: This is a bit hacky -> Cleanup.
|
||||||
|
@ -41,6 +55,10 @@ export default {
|
||||||
|
|
||||||
this.$set(this, 'tasks', [])
|
this.$set(this, 'tasks', [])
|
||||||
|
|
||||||
|
if (params === null) {
|
||||||
|
params = this.params
|
||||||
|
}
|
||||||
|
|
||||||
if (search !== '') {
|
if (search !== '') {
|
||||||
params.s = search
|
params.s = search
|
||||||
}
|
}
|
||||||
|
@ -50,10 +68,10 @@ export default {
|
||||||
this.$set(this, 'pages', [])
|
this.$set(this, 'pages', [])
|
||||||
this.currentPage = page
|
this.currentPage = page
|
||||||
|
|
||||||
for (let i = 0; i < this.taskCollectionService.totalPages; i++) {
|
for (let i = 0; i < this.taskCollectionService.totalPages; i++) {
|
||||||
|
|
||||||
// Show ellipsis instead of all pages
|
// Show ellipsis instead of all pages
|
||||||
if(
|
if (
|
||||||
i > 0 && // Always at least the first page
|
i > 0 && // Always at least the first page
|
||||||
(i + 1) < this.taskCollectionService.totalPages && // And the last page
|
(i + 1) < this.taskCollectionService.totalPages && // And the last page
|
||||||
(
|
(
|
||||||
|
@ -63,7 +81,7 @@ export default {
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
// Only add an ellipsis if the last page isn't already one
|
// Only add an ellipsis if the last page isn't already one
|
||||||
if(this.pages[i - 1] && !this.pages[i - 1].isEllipsis) {
|
if (this.pages[i - 1] && !this.pages[i - 1].isEllipsis) {
|
||||||
this.pages.push({
|
this.pages.push({
|
||||||
number: 0,
|
number: 0,
|
||||||
isEllipsis: true,
|
isEllipsis: true,
|
||||||
|
@ -98,7 +116,7 @@ export default {
|
||||||
if (this.tasks === null || this.tasks === []) {
|
if (this.tasks === null || this.tasks === []) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return this.tasks.sort(function(a,b) {
|
return this.tasks.sort(function (a, b) {
|
||||||
if (a.done < b.done)
|
if (a.done < b.done)
|
||||||
return -1
|
return -1
|
||||||
if (a.done > b.done)
|
if (a.done > b.done)
|
||||||
|
@ -142,6 +160,6 @@ export default {
|
||||||
page: page,
|
page: page,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -66,6 +66,7 @@ import { faSort } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faSortUp } from '@fortawesome/free-solid-svg-icons'
|
import { faSortUp } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faList } from '@fortawesome/free-solid-svg-icons'
|
import { faList } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
|
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { faFilter } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { faComments } from '@fortawesome/free-regular-svg-icons'
|
import { faComments } from '@fortawesome/free-regular-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
|
|
||||||
|
@ -111,6 +112,7 @@ library.add(faSort)
|
||||||
library.add(faSortUp)
|
library.add(faSortUp)
|
||||||
library.add(faList)
|
library.add(faList)
|
||||||
library.add(faEllipsisV)
|
library.add(faEllipsisV)
|
||||||
|
library.add(faFilter)
|
||||||
|
|
||||||
Vue.component('icon', FontAwesomeIcon)
|
Vue.component('icon', FontAwesomeIcon)
|
||||||
|
|
||||||
|
|
|
@ -37,35 +37,6 @@
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
|
||||||
max-width: 300px;
|
|
||||||
margin-top: -58px;
|
|
||||||
float: right;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.button, .input {
|
|
||||||
height: $switch-view-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field {
|
|
||||||
transition: width $transition;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-title {
|
.list-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -85,3 +56,68 @@
|
||||||
.edit-list {
|
.edit-list {
|
||||||
padding-bottom: 1em;
|
padding-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-container {
|
||||||
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 400px;
|
||||||
|
max-width: 180px;
|
||||||
|
position: absolute;
|
||||||
|
right: 1.5em;
|
||||||
|
margin-top: -58px;
|
||||||
|
z-index: 99;
|
||||||
|
|
||||||
|
.items {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.button:not(:last-child) {
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
height: $switch-view-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
text-align: left;
|
||||||
|
margin-top: calc(1rem - 1px);
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fancycheckbox {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-right: .5em;
|
||||||
|
|
||||||
|
.button, .input {
|
||||||
|
height: $switch-view-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
transition: width $transition;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filters input {
|
||||||
|
font-size: .9em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,26 +13,5 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.column-filter {
|
|
||||||
text-align: right;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 180px;
|
|
||||||
position: absolute;
|
|
||||||
right: 1.5em;
|
|
||||||
margin-top: -58px;
|
|
||||||
|
|
||||||
.button {
|
|
||||||
height: $switch-view-height;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
text-align: left;
|
|
||||||
margin-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fancycheckbox {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue