feat: add button to clear active filters #924
|
@ -219,10 +219,10 @@ describe('Lists', () => {
|
|||
cy.get('.table-view .filter-container .items .button')
|
||||
.contains('Columns')
|
||||
.click()
|
||||
cy.get('.table-view .filter-container .card .card-content .fancycheckbox .check')
|
||||
cy.get('.table-view .filter-container .card.columns-filter .card-content .fancycheckbox .check')
|
||||
.contains('Priority')
|
||||
.click()
|
||||
cy.get('.table-view .filter-container .card .card-content .fancycheckbox .check')
|
||||
cy.get('.table-view .filter-container .card.columns-filter .card-content .fancycheckbox .check')
|
||||
.contains('Done')
|
||||
.click()
|
||||
|
||||
|
|
|
@ -1,37 +1,49 @@
|
|||
<template>
|
||||
<transition name="fade">
|
||||
<filters
|
||||
v-if="visibleInternal"
|
||||
v-model="value"
|
||||
ref="filters"
|
||||
/>
|
||||
</transition>
|
||||
<x-button
|
||||
v-if="hasFilters"
|
||||
type="secondary"
|
||||
@click="clearFilters"
|
||||
>
|
||||
{{ $t('filters.clear') }}
|
||||
</x-button>
|
||||
<popup>
|
||||
<template #trigger="{toggle}">
|
||||
konrad marked this conversation as resolved
Outdated
|
||||
<x-button
|
||||
@click.prevent.stop="toggle()"
|
||||
type="secondary"
|
||||
icon="filter"
|
||||
>
|
||||
{{ $t('filters.title') }}
|
||||
</x-button>
|
||||
</template>
|
||||
<template #content="{isOpen}">
|
||||
<filters
|
||||
v-model="value"
|
||||
ref="filters"
|
||||
class="filter-popup"
|
||||
:class="{'is-open': isOpen}"
|
||||
/>
|
||||
</template>
|
||||
</popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||
import Filters from '../../../components/list/partials/filters'
|
||||
import Filters from '@/components/list/partials/filters'
|
||||
import {getDefaultParams} from '@/components/tasks/mixins/taskList'
|
||||
konrad marked this conversation as resolved
Outdated
dpschen
commented
use use `@`
konrad
commented
Done. I think we should put this in the linter at some point, I keep forgetting it... and webstorm always seems to use relative paths by default. Done. I think we should put this in the linter at some point, I keep forgetting it... and webstorm always seems to use relative paths by default.
|
||||
import Popup from '@/components/misc/popup'
|
||||
|
||||
export default {
|
||||
name: 'filter-popup',
|
||||
components: {
|
||||
Popup,
|
||||
Filters,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
required: true,
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
visibleInternal: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
value: {
|
||||
get() {
|
||||
|
@ -41,34 +53,46 @@ export default {
|
|||
this.$emit('update:modelValue', value)
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('click', this.hidePopup)
|
||||
},
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('click', this.hidePopup)
|
||||
hasFilters() {
|
||||
// this.value also contains the page parameter which we don't want to include in filters
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const {filter_by, filter_value, filter_comparator, filter_concat, s} = this.value
|
||||
konrad marked this conversation as resolved
Outdated
konrad
commented
This feels very hacky... This feels very hacky...
dpschen
commented
Here specifically:
👆 this line is fine – in case you included that in what you meant feels hacky – as long as it works All together my feeling is that Here specifically:
You can remove a parameter by destructuring it and then just use the rest:
```js
const {page, ...value} = this.value
// just continue to use `value`
```
```js
JSON.stringify(filterParams) !== JSON.stringify(def)
```
👆 this line is fine – in case you included that in what you meant feels hacky – as long as it works
All together my feeling is that `hasFilters` should be a computed that is defined where the filters state is saved.
konrad
commented
You mean in that case > You can remove a parameter by destructuring it and then just use the rest:
You mean in that case `value` would contain everything from `this.value` without `page`?
konrad
commented
Changed. Changed.
|
||||
const def = {...getDefaultParams()}
|
||||
|
||||
const params = {filter_by, filter_value, filter_comparator, filter_concat, s}
|
||||
const defaultParams = {
|
||||
filter_by: def.filter_by,
|
||||
filter_value: def.filter_value,
|
||||
filter_comparator: def.filter_comparator,
|
||||
filter_concat: def.filter_concat,
|
||||
s: s ? def.s : undefined,
|
||||
}
|
||||
|
||||
return JSON.stringify(params) !== JSON.stringify(defaultParams)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(value) {
|
||||
this.params = value
|
||||
this.value = value
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
visible() {
|
||||
this.visibleInternal = !this.visibleInternal
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hidePopup(e) {
|
||||
if (!this.visibleInternal) {
|
||||
return
|
||||
}
|
||||
|
||||
closeWhenClickedOutside(e, this.$refs.filters.$el, () => {
|
||||
this.visibleInternal = false
|
||||
})
|
||||
clearFilters() {
|
||||
this.value = {...getDefaultParams()}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.filter-popup {
|
||||
margin: 0;
|
||||
konrad marked this conversation as resolved
Outdated
dpschen
commented
Why the Why the `!important`?
konrad
commented
There was a margin set for There was a margin set for `.filter-container .card` (in `list.scss`). I've removed that one and the `!important` statements.
|
||||
|
||||
&.is-open {
|
||||
margin: 2rem 0 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -458,15 +458,7 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
let foundDone = false
|
||||
this.params.filter_by.forEach((f, i) => {
|
||||
if (f === 'done') {
|
||||
foundDone = i
|
||||
}
|
||||
})
|
||||
if (foundDone === false) {
|
||||
this.filters.done = true
|
||||
}
|
||||
this.filters.done = this.params.filter_by.some((f) => f === 'done') === false
|
||||
},
|
||||
async prepareRelatedObjectFilter(kind, filterName = null, servicePrefix = null) {
|
||||
if (filterName === null) {
|
||||
|
|
54
src/components/misc/popup.vue
Normal file
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<slot name="trigger" :isOpen="open" :toggle="toggle"></slot>
|
||||
<div class="popup" :class="{'is-open': open}" ref="popup">
|
||||
<slot name="content" :isOpen="open"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||
import {onBeforeUnmount, onMounted, ref} from 'vue'
|
||||
|
||||
const open = ref(false)
|
||||
const popup = ref(null)
|
||||
|
||||
const toggle = () => {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
function hidePopup(e) {
|
||||
konrad marked this conversation as resolved
Outdated
dpschen
commented
Picky: use Picky: use `function`. Makes it more clear what a "method" is (now simply function) next to a ref.
konrad
commented
Done. Done.
|
||||
if (!open.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// we actually want to use popup.$el, not its value.
|
||||
// eslint-disable-next-line vue/no-ref-as-operand
|
||||
closeWhenClickedOutside(e, popup.value, () => {
|
||||
open.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('click', hidePopup)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('click', hidePopup)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.popup {
|
||||
transition: opacity $transition;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
|
||||
&.is-open {
|
||||
opacity: 1;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -9,12 +9,12 @@
|
|||
>
|
||||
{{ $t('filters.title') }}
|
||||
</x-button>
|
||||
<filter-popup
|
||||
:visible="showTaskFilter"
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
<filter-popup
|
||||
:visible="showTaskFilter"
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
<div class="dates">
|
||||
<template v-for="(y, yk) in days" :key="yk + 'year'">
|
||||
|
@ -347,7 +347,7 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
let newTask = { ...taskDragged }
|
||||
let newTask = {...taskDragged}
|
||||
|
||||
const didntHaveDates = newTask.startDate === null ? true : false
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import TaskCollectionService from '@/services/taskCollection'
|
||||
|
||||
// FIXME: merge with DEFAULT_PARAMS in filters.vue
|
||||
const DEFAULT_PARAMS = {
|
||||
export const getDefaultParams = () => ({
|
||||
sort_by: ['position', 'id'],
|
||||
order_by: ['asc', 'desc'],
|
||||
filter_by: ['done'],
|
||||
filter_value: ['false'],
|
||||
filter_comparator: ['equals'],
|
||||
filter_concat: 'and',
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
konrad marked this conversation as resolved
Outdated
konrad
commented
I only got this working once I created this factory thing. Every time I'd use the constant directly, the params variable in the components and the value of this const were always the same. I suspect this is due to some JS-reference passing stuff. I only got this working once I created this factory thing. Every time I'd use the constant directly, the params variable in the components and the value of this const were always the same. I suspect this is due to some JS-reference passing stuff.
dpschen
commented
Makes sense. I didn't use a getter function since it seemed to me more "JSONy".
Makes sense. I didn't use a getter function since it seemed to me more "JSONy".
How about:
```js
const DEFAULT_PARAMS = {
sort_by: ['position', 'id'],
order_by: ['asc', 'desc'],
filter_by: ['done'],
filter_value: ['false'],
filter_comparator: ['equals'],
filter_concat: 'and',
}
export const getDefaultParams = () => DEFAULT_PARAMS
```
konrad
commented
I tried that, it did not work unfortunately. My theory is that the function only returns a reference to the const which is then changed. And because everything holds a copy to that same const reference, it is changed everywhere simultaniously. I tried that, it did not work unfortunately. My theory is that the function only returns a reference to the const which is then changed. And because everything holds a copy to that same const reference, it is changed everywhere simultaniously.
dpschen
commented
Maybe:
Maybe:
```js
export const getDefaultParams = () => { ...DEFAULT_PARAMS }
```
konrad
commented
That seems to work. That seems to work.
konrad
commented
Actually, it does not seem to work. Reverted... Actually, it does not seem to work. Reverted...
|
||||
* This mixin provides a base set of methods and properties to get tasks on a list.
|
||||
|
@ -26,7 +26,7 @@ export default {
|
|||
searchTerm: '',
|
||||
|
||||
showTaskFilter: false,
|
||||
params: DEFAULT_PARAMS,
|
||||
params: {...getDefaultParams()},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -94,7 +94,7 @@ export default {
|
|||
this.initTasks(page, search)
|
||||
},
|
||||
loadTasksOnSavedFilter() {
|
||||
if(typeof this.$route.params.listId !== 'undefined' && parseInt(this.$route.params.listId) < 0) {
|
||||
if (typeof this.$route.params.listId !== 'undefined' && parseInt(this.$route.params.listId) < 0) {
|
||||
this.loadTasks(1, '', null, true)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -344,6 +344,7 @@
|
|||
},
|
||||
"filters": {
|
||||
"title": "Filters",
|
||||
"clear": "Clear Filters",
|
||||
"attributes": {
|
||||
"title": "Title",
|
||||
"titlePlaceholder": "The saved filter title goes here…",
|
||||
|
|
|
@ -34,7 +34,6 @@ $filter-container-top-link-share-list: -47px;
|
|||
|
||||
.card {
|
||||
text-align: left;
|
||||
margin-top: calc(1rem - 1px);
|
||||
}
|
||||
|
||||
.fancycheckbox {
|
||||
|
@ -47,10 +46,6 @@ $filter-container-top-link-share-list: -47px;
|
|||
justify-content: space-between;
|
||||
margin-right: .5rem;
|
||||
|
||||
.button, .input {
|
||||
height: $switch-view-height;
|
||||
}
|
||||
|
||||
.field {
|
||||
transition: width $transition;
|
||||
width: 100%;
|
||||
|
|
|
@ -2,18 +2,11 @@
|
|||
<div class="kanban-view">
|
||||
<div class="filter-container" v-if="isSavedFilter">
|
||||
<div class="items">
|
||||
<x-button
|
||||
@click.prevent.stop="toggleFilterPopup"
|
||||
icon="filter"
|
||||
type="secondary"
|
||||
>
|
||||
{{ $t('filters.title') }}
|
||||
</x-button>
|
||||
<filter-popup
|
||||
v-model="params"
|
||||
@update:modelValue="loadBuckets"
|
||||
/>
|
||||
</div>
|
||||
<filter-popup
|
||||
:visible="showFilters"
|
||||
v-model="params"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="{ 'is-loading': loading && !oneTaskUpdating}"
|
||||
|
@ -143,7 +136,7 @@
|
|||
:component-data="taskDraggableTaskComponentData"
|
||||
>
|
||||
<template #item="{element: task}">
|
||||
<kanban-card :task="task" />
|
||||
<kanban-card :task="task"/>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
|
@ -213,7 +206,7 @@
|
|||
<!-- This router view is used to show the task popup while keeping the kanban board itself -->
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="modal">
|
||||
<component :is="Component" />
|
||||
<component :is="Component"/>
|
||||
</transition>
|
||||
</router-view>
|
||||
|
||||
|
@ -224,10 +217,10 @@
|
|||
v-if="showBucketDeleteModal"
|
||||
>
|
||||
<template #header><span>{{ $t('list.kanban.deleteHeaderBucket') }}</span></template>
|
||||
|
||||
|
||||
<template #text>
|
||||
<p>{{ $t('list.kanban.deleteBucketText1') }}<br/>
|
||||
{{ $t('list.kanban.deleteBucketText2') }}</p>
|
||||
{{ $t('list.kanban.deleteBucketText2') }}</p>
|
||||
</template>
|
||||
</modal>
|
||||
</transition>
|
||||
|
@ -300,7 +293,6 @@ export default {
|
|||
filter_comparator: [],
|
||||
filter_concat: 'and',
|
||||
},
|
||||
showFilters: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -328,10 +320,10 @@ export default {
|
|||
return {
|
||||
type: 'transition',
|
||||
tag: 'div',
|
||||
name: !this.dragBucket ? 'move-bucket': null,
|
||||
name: !this.dragBucket ? 'move-bucket' : null,
|
||||
class: [
|
||||
'kanban-bucket-container',
|
||||
{ 'dragging-disabled': !this.canWrite },
|
||||
{'dragging-disabled': !this.canWrite},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -339,10 +331,10 @@ export default {
|
|||
return {
|
||||
type: 'transition',
|
||||
tag: 'div',
|
||||
name: !this.drag ? 'move-card': null,
|
||||
name: !this.drag ? 'move-card' : null,
|
||||
class: [
|
||||
'dropper',
|
||||
{ 'dragging-disabled': !this.canWrite },
|
||||
{'dragging-disabled': !this.canWrite},
|
||||
],
|
||||
}
|
||||
},
|
||||
|
@ -357,19 +349,15 @@ export default {
|
|||
list: state => state.currentList,
|
||||
}),
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleFilterPopup() {
|
||||
this.showFilters = !this.showFilters
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadBuckets() {
|
||||
// Prevent trying to load buckets if the task popup view is active
|
||||
if (this.$route.name !== 'list.kanban') {
|
||||
return
|
||||
}
|
||||
|
||||
const { listId, params } = this.loadBucketParameter
|
||||
const {listId, params} = this.loadBucketParameter
|
||||
|
||||
this.collapsedBuckets = getCollapsedBucketState(listId)
|
||||
|
||||
|
@ -424,7 +412,7 @@ export default {
|
|||
|
||||
const newTask = cloneDeep(task) // cloning the task to avoid vuex store mutations
|
||||
newTask.bucketId = newBucket.id,
|
||||
newTask.kanbanPosition = calculateItemPosition(taskBefore !== null ? taskBefore.kanbanPosition : null, taskAfter !== null ? taskAfter.kanbanPosition : null)
|
||||
newTask.kanbanPosition = calculateItemPosition(taskBefore !== null ? taskBefore.kanbanPosition : null, taskAfter !== null ? taskAfter.kanbanPosition : null)
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('tasks/update', newTask)
|
||||
|
|
|
@ -41,19 +41,11 @@
|
|||
v-if="!showTaskSearch"
|
||||
/>
|
||||
</div>
|
||||
<x-button
|
||||
@click.prevent.stop="showTaskFilter = !showTaskFilter"
|
||||
type="secondary"
|
||||
icon="filter"
|
||||
>
|
||||
{{ $t('filters.title') }}
|
||||
</x-button>
|
||||
<filter-popup
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
<filter-popup
|
||||
:visible="showTaskFilter"
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<card :padding="false" :has-content="false" class="has-overflow">
|
||||
|
@ -126,7 +118,7 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<Pagination
|
||||
<Pagination
|
||||
:total-pages="taskCollectionService.totalPages"
|
||||
:current-page="currentPage"
|
||||
/>
|
||||
|
@ -135,7 +127,7 @@
|
|||
<!-- This router view is used to show the task popup while keeping the kanban board itself -->
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="modal">
|
||||
<component :is="Component" />
|
||||
<component :is="Component"/>
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
|
@ -155,6 +147,7 @@ import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
|||
import {HAS_TASKS} from '@/store/mutation-types'
|
||||
import Nothing from '@/components/misc/nothing.vue'
|
||||
import Pagination from '@/components/misc/pagination.vue'
|
||||
import Popup from '@/components/misc/popup'
|
||||
|
||||
import draggable from 'vuedraggable'
|
||||
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
||||
|
@ -198,6 +191,7 @@ export default {
|
|||
taskList,
|
||||
],
|
||||
components: {
|
||||
Popup,
|
||||
Nothing,
|
||||
FilterPopup,
|
||||
SingleTaskInList,
|
||||
|
@ -294,11 +288,11 @@ export default {
|
|||
|
||||
async saveTaskPosition(e) {
|
||||
this.drag = false
|
||||
|
||||
|
||||
const task = this.tasks[e.newIndex]
|
||||
const taskBefore = this.tasks[e.newIndex - 1] ?? null
|
||||
const taskAfter = this.tasks[e.newIndex + 1] ?? null
|
||||
|
||||
const taskAfter = this.tasks[e.newIndex + 1] ?? null
|
||||
|
||||
const newTask = {
|
||||
...task,
|
||||
position: calculateItemPosition(taskBefore !== null ? taskBefore.position : null, taskAfter !== null ? taskAfter.position : null),
|
||||
|
|
|
@ -2,67 +2,63 @@
|
|||
<div :class="{'is-loading': taskCollectionService.loading}" class="table-view loader-container">
|
||||
<div class="filter-container">
|
||||
<div class="items">
|
||||
<x-button
|
||||
@click.prevent.stop="() => {showActiveColumnsFilter = !showActiveColumnsFilter; showTaskFilter = false}"
|
||||
icon="th"
|
||||
type="secondary"
|
||||
>
|
||||
{{ $t('list.table.columns') }}
|
||||
</x-button>
|
||||
<x-button
|
||||
@click.prevent.stop="() => {showTaskFilter = !showTaskFilter; showActiveColumnsFilter = false}"
|
||||
icon="filter"
|
||||
type="secondary"
|
||||
>
|
||||
{{ $t('filters.title') }}
|
||||
</x-button>
|
||||
<popup>
|
||||
<template #trigger="{toggle}">
|
||||
<x-button
|
||||
@click.prevent.stop="toggle()"
|
||||
icon="th"
|
||||
type="secondary"
|
||||
>
|
||||
{{ $t('list.table.columns') }}
|
||||
</x-button>
|
||||
</template>
|
||||
<template #content="{isOpen}">
|
||||
<card class="columns-filter" :class="{'is-open': isOpen}">
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.id">#</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.done">
|
||||
{{ $t('task.attributes.done') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.title">
|
||||
{{ $t('task.attributes.title') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.priority">
|
||||
{{ $t('task.attributes.priority') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.labels">
|
||||
{{ $t('task.attributes.labels') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.assignees">
|
||||
{{ $t('task.attributes.assignees') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.dueDate">
|
||||
{{ $t('task.attributes.dueDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.startDate">
|
||||
{{ $t('task.attributes.startDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.endDate">
|
||||
{{ $t('task.attributes.endDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.percentDone">
|
||||
{{ $t('task.attributes.percentDone') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.created">
|
||||
{{ $t('task.attributes.created') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.updated">
|
||||
{{ $t('task.attributes.updated') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">
|
||||
{{ $t('task.attributes.createdBy') }}
|
||||
</fancycheckbox>
|
||||
</card>
|
||||
</template>
|
||||
</popup>
|
||||
<filter-popup
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
<transition name="fade">
|
||||
<card v-if="showActiveColumnsFilter">
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.id">#</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.done">
|
||||
{{ $t('task.attributes.done') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.title">
|
||||
{{ $t('task.attributes.title') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.priority">
|
||||
{{ $t('task.attributes.priority') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.labels">
|
||||
{{ $t('task.attributes.labels') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.assignees">
|
||||
{{ $t('task.attributes.assignees') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.dueDate">
|
||||
{{ $t('task.attributes.dueDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.startDate">
|
||||
{{ $t('task.attributes.startDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.endDate">
|
||||
{{ $t('task.attributes.endDate') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.percentDone">
|
||||
{{ $t('task.attributes.percentDone') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.created">
|
||||
{{ $t('task.attributes.created') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.updated">
|
||||
{{ $t('task.attributes.updated') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="saveTaskColumns" v-model="activeColumns.createdBy">
|
||||
{{ $t('task.attributes.createdBy') }}
|
||||
</fancycheckbox>
|
||||
</card>
|
||||
</transition>
|
||||
<filter-popup
|
||||
:visible="showTaskFilter"
|
||||
v-model="params"
|
||||
@update:modelValue="loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<card :padding="false" :has-content="false">
|
||||
|
@ -189,21 +185,23 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import taskList from '../../../components/tasks/mixins/taskList'
|
||||
import taskList from '@/components/tasks/mixins/taskList'
|
||||
import Done from '@/components/misc/Done.vue'
|
||||
import User from '../../../components/misc/user'
|
||||
import PriorityLabel from '../../../components/tasks/partials/priorityLabel'
|
||||
import Labels from '../../../components/tasks/partials/labels'
|
||||
import DateTableCell from '../../../components/tasks/partials/date-table-cell'
|
||||
import Fancycheckbox from '../../../components/input/fancycheckbox'
|
||||
import Sort from '../../../components/tasks/partials/sort'
|
||||
import User from '@/components/misc/user'
|
||||
import PriorityLabel from '@/components/tasks/partials/priorityLabel'
|
||||
import Labels from '@/components/tasks/partials/labels'
|
||||
import DateTableCell from '@/components/tasks/partials/date-table-cell'
|
||||
import Fancycheckbox from '@/components/input/fancycheckbox'
|
||||
import Sort from '@/components/tasks/partials/sort'
|
||||
import {saveListView} from '@/helpers/saveListView'
|
||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||
import Pagination from '@/components/misc/pagination.vue'
|
||||
import Popup from '@/components/misc/popup'
|
||||
konrad marked this conversation as resolved
Outdated
dpschen
commented
use use `@`
|
||||
|
||||
export default {
|
||||
name: 'Table',
|
||||
components: {
|
||||
Popup,
|
||||
Done,
|
||||
FilterPopup,
|
||||
Sort,
|
||||
|
@ -219,7 +217,6 @@ export default {
|
|||
],
|
||||
data() {
|
||||
return {
|
||||
showActiveColumnsFilter: false,
|
||||
activeColumns: {
|
||||
id: true,
|
||||
done: true,
|
||||
|
@ -323,4 +320,12 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.columns-filter {
|
||||
margin: 0;
|
||||
konrad marked this conversation as resolved
Outdated
dpschen
commented
why why `!important`?
|
||||
|
||||
&.is-open {
|
||||
konrad marked this conversation as resolved
dpschen
commented
we shouldn't style elements from outside. we shouldn't style elements from outside.
Why do we need to position this from outside via margin?
konrad
commented
Because by default, there's no margin. And that would let it flow in the other buttons instead. How would you solve it? Where would you apply the margin instead? Because by default, there's no margin. And that would let it flow in the other buttons instead.
How would you solve it? Where would you apply the margin instead?
dpschen
commented
Okay I just tried to fix what I meant but realized there are much more changes needed for that. I think that would be out of the scope of this branch and better fitted when we add a popper.js based popup =) Okay I just tried to fix what I meant but realized there are much more changes needed for that. I think that would be out of the scope of this branch and better fitted when we add a popper.js based popup =)
konrad
commented
Sounds like a topic for another day :) Sounds like a topic for another day :)
dpschen
commented
I think that was the last =) I think that was the last =)
|
||||
margin: 2rem 0 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
The watcher in the component won't ever trigger if the component does not exist at all (with
v-if
). This hides it visually only.Not sure which watcher you mean here. The one inside the
<Filters>
? If so => maybe adeep
watcher helps.I just realize that it also feels generally wrong to put this logic here:
Before the filter popup was just managing the filter and passing along the modelValue.
Probably this could have been easier if the FilterPopup would provide a slot for the popup.
Then maybe another one for the trigger … and then we basically can name the component just popup and integrate popper.js inside.
(that's kind of what my plan was for this anyway)
Exactly.
So that it would not pass along the filter state? I'm actually not sure if this could have been easier in that case - I want to have the same "clear filters" button in all places where the filter popup is being used. I think moving this whole thing in a component simplifies that.
I think I understand what you mean now. I meant something similar to this:
So basically moving the button and the open state to the filter popup component?
Both buttons, clear and toggle, that is
I put something together in
86efb07f09
. That seems to work. Is that what you had in mind?yes / no:
#content
would have been better.isOpen
can be used to control active classes at the buttonshowActiveColumnsFilter
inTable.vue
I did though move the reset button together with the other stuff from the current filters.vue.
So if you would have written:
Then the answer would be yes ✅