Skip to content

Commit abf550d

Browse files
committed
Merge branch 'feature/active-filters' into develop
# Conflicts: # js/Components/Table.vue
2 parents be35bd3 + 5ba89fa commit abf550d

File tree

3 files changed

+107
-39
lines changed

3 files changed

+107
-39
lines changed

js/Components/Table.vue

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@
109109
/>
110110
</slot>
111111

112+
<TableActiveFilters
113+
v-if="queryBuilderProps.hasEnabledFilters"
114+
:filters="queryBuilderProps.filters"
115+
:on-filter-change="changeFilterValue"
116+
/>
117+
112118
<slot
113119
name="tableWrapper"
114120
:meta="resourceMeta"
@@ -195,11 +201,12 @@ import HeaderCell from "./HeaderCell.vue";
195201
import TableAddSearchRow from "./TableAddSearchRow.vue";
196202
import TableColumns from "./TableColumns.vue";
197203
import TableFilter from "./TableFilter.vue";
204+
import TableActiveFilters from "./TableActiveFilters.vue";
198205
import TableGlobalSearch from "./TableGlobalSearch.vue";
199206
import TableSearchRows from "./TableSearchRows.vue";
200207
import TableReset from "./TableReset.vue";
201208
import TableWrapper from "./TableWrapper.vue";
202-
import { computed, onMounted, ref, watch, onUnmounted, getCurrentInstance, Transition, provide } from "vue";
209+
import { computed, getCurrentInstance, onMounted, onUnmounted, provide, ref, Transition, watch } from "vue";
203210
import qs from "qs";
204211
import clone from "lodash-es/clone";
205212
import filter from "lodash-es/filter";
@@ -272,7 +279,7 @@ const props = defineProps({
272279
required: false,
273280
},
274281
275-
activeClasses:{
282+
activeClasses: {
276283
type: Object,
277284
required: false,
278285
default() {
@@ -303,7 +310,7 @@ const queryBuilderProps = computed(() => {
303310
304311
const queryBuilderData = ref(queryBuilderProps.value);
305312
306-
const pageName = computed(() =>{
313+
const pageName = computed(() => {
307314
return queryBuilderProps.value.pageName;
308315
});
309316
@@ -312,19 +319,19 @@ const forcedVisibleSearchInputs = ref([]);
312319
const tableFieldset = ref(null);
313320
314321
const hasOnlyData = computed(() => {
315-
if(queryBuilderProps.value.hasToggleableColumns) {
322+
if (queryBuilderProps.value.hasToggleableColumns) {
316323
return false;
317324
}
318325
319-
if(queryBuilderProps.value.hasFilters) {
326+
if (queryBuilderProps.value.hasFilters) {
320327
return false;
321328
}
322329
323-
if(queryBuilderProps.value.hasSearchInputs) {
330+
if (queryBuilderProps.value.hasSearchInputs) {
324331
return false;
325332
}
326333
327-
if(queryBuilderProps.value.globalSearch) {
334+
if (queryBuilderProps.value.globalSearch) {
328335
return false;
329336
}
330337
@@ -333,26 +340,26 @@ const hasOnlyData = computed(() => {
333340
});
334341
335342
const resourceData = computed(() => {
336-
if(Object.keys(props.resource).length === 0){
343+
if (Object.keys(props.resource).length === 0) {
337344
return props.data;
338345
}
339346
340-
if("data" in props.resource) {
347+
if ("data" in props.resource) {
341348
return props.resource.data;
342349
}
343350
344351
return props.resource;
345352
});
346353
347354
const resourceMeta = computed(() => {
348-
if(Object.keys(props.resource).length === 0){
355+
if (Object.keys(props.resource).length === 0) {
349356
return props.meta;
350357
}
351358
352-
if("links" in props.resource && "meta" in props.resource) {
353-
if(Object.keys(props.resource.links).length === 4
354-
&& "next" in props.resource.links
355-
&& "prev" in props.resource.links) {
359+
if ("links" in props.resource && "meta" in props.resource) {
360+
if (Object.keys(props.resource.links).length === 4
361+
&& "next" in props.resource.links
362+
&& "prev" in props.resource.links) {
356363
return {
357364
...props.resource.meta,
358365
next_page_url: props.resource.links.next,
@@ -361,19 +368,19 @@ const resourceMeta = computed(() => {
361368
}
362369
}
363370
364-
if("meta" in props.resource) {
371+
if ("meta" in props.resource) {
365372
return props.resource.meta;
366373
}
367374
368375
return props.resource;
369376
});
370377
371378
const hasData = computed(() => {
372-
if(resourceData.value.length > 0){
379+
if (resourceData.value.length > 0) {
373380
return true;
374381
}
375382
376-
if(resourceMeta.value.total > 0) {
383+
if (resourceMeta.value.total > 0) {
377384
return true;
378385
}
379386
@@ -393,15 +400,15 @@ function showSearchInput(key) {
393400
}
394401
395402
const canBeReset = computed(() => {
396-
if(forcedVisibleSearchInputs.value.length > 0){
403+
if (forcedVisibleSearchInputs.value.length > 0) {
397404
return true;
398405
}
399406
400407
const queryStringData = qs.parse(location.search.substring(1));
401408
402409
const page = queryStringData[pageName.value];
403410
404-
if(page > 1) {
411+
if (page > 1) {
405412
return true;
406413
}
407414
@@ -411,11 +418,11 @@ const canBeReset = computed(() => {
411418
forEach(["filter", "columns", "cursor", "sort"], (key) => {
412419
const value = queryStringData[prefix + key];
413420
414-
if(key === "sort" && value === queryBuilderProps.value.defaultSort) {
421+
if (key === "sort" && value === queryBuilderProps.value.defaultSort) {
415422
return;
416423
}
417424
418-
if(value !== undefined) {
425+
if (value !== undefined) {
419426
dirty = true;
420427
}
421428
});
@@ -451,7 +458,7 @@ function changeSearchInputValue(key, value) {
451458
clearTimeout(debounceTimeouts[key]);
452459
453460
debounceTimeouts[key] = setTimeout(() => {
454-
if(visitCancelToken.value && props.preventOverlappingRequests){
461+
if (visitCancelToken.value && props.preventOverlappingRequests) {
455462
visitCancelToken.value.cancel();
456463
}
457464
@@ -522,7 +529,7 @@ function getColumnsForQuery() {
522529
return column.key;
523530
}).sort();
524531
525-
if (isEqual(visibleColumnKeys, queryBuilderProps.value.defaultVisibleToggleableColumns)){
532+
if (isEqual(visibleColumnKeys, queryBuilderProps.value.defaultVisibleToggleableColumns)) {
526533
return {};
527534
}
528535
@@ -535,11 +542,11 @@ function dataForNewQueryString() {
535542
536543
const queryData = {};
537544
538-
if(Object.keys(filterForQuery).length > 0) {
545+
if (Object.keys(filterForQuery).length > 0) {
539546
queryData.filter = filterForQuery;
540547
}
541548
542-
if(Object.keys(columnsForQuery).length > 0) {
549+
if (Object.keys(columnsForQuery).length > 0) {
543550
queryData.columns = columnsForQuery;
544551
}
545552
@@ -548,20 +555,20 @@ function dataForNewQueryString() {
548555
const sort = queryBuilderData.value.sort;
549556
const perPage = queryBuilderData.value.perPage;
550557
551-
if(cursor) {
558+
if (cursor) {
552559
queryData.cursor = cursor;
553560
}
554561
555-
if(page > 1) {
562+
if (page > 1) {
556563
queryData.page = page;
557564
}
558565
559-
if(perPage > 1) {
566+
if (perPage > 1) {
560567
queryData.perPage = perPage;
561568
}
562569
563570
564-
if(sort) {
571+
if (sort) {
565572
queryData.sort = sort;
566573
}
567574
@@ -579,10 +586,10 @@ function generateNewQueryString() {
579586
580587
delete queryStringData[pageName.value];
581588
582-
forEach(dataForNewQueryString(), (value, key) =>{
583-
if(key === "page") {
589+
forEach(dataForNewQueryString(), (value, key) => {
590+
if (key === "page") {
584591
queryStringData[pageName.value] = value;
585-
} else if(key === "perPage") {
592+
} else if (key === "perPage") {
586593
queryStringData.perPage = value;
587594
} else {
588595
queryStringData[prefix + key] = value;
@@ -613,7 +620,7 @@ const isVisiting = ref(false);
613620
const visitCancelToken = ref(null);
614621
615622
function visit(url) {
616-
if(!url) {
623+
if (!url) {
617624
return;
618625
}
619626
@@ -624,7 +631,7 @@ function visit(url) {
624631
replace: true,
625632
preserveState: true,
626633
preserveScroll: props.preserveScroll !== false,
627-
onBefore(){
634+
onBefore() {
628635
isVisiting.value = true;
629636
},
630637
onCancelToken(cancelToken) {
@@ -634,12 +641,12 @@ function visit(url) {
634641
isVisiting.value = false;
635642
},
636643
onSuccess() {
637-
if("queryBuilderProps" in $inertia.page.props){
644+
if ("queryBuilderProps" in $inertia.page.props) {
638645
queryBuilderData.value.cursor = queryBuilderProps.value.cursor;
639646
queryBuilderData.value.page = queryBuilderProps.value.page;
640647
}
641648
642-
if(props.preserveScroll === "table-top") {
649+
if (props.preserveScroll === "table-top") {
643650
const offset = -8;
644651
const top = tableFieldset.value.getBoundingClientRect().top + window.pageYOffset + offset;
645652
@@ -653,7 +660,7 @@ function visit(url) {
653660
}
654661
655662
watch(queryBuilderData, () => {
656-
visit(location.pathname + "?" + generateNewQueryString());
663+
visit(location.pathname + "?" + generateNewQueryString());
657664
}, { deep: true });
658665
659666
const inertiaListener = () => {
@@ -671,7 +678,7 @@ onUnmounted(() => {
671678
//
672679
673680
function sortBy(column) {
674-
if(queryBuilderData.value.sort == column) {
681+
if (queryBuilderData.value.sort == column) {
675682
queryBuilderData.value.sort = `-${column}`;
676683
} else {
677684
queryBuilderData.value.sort = column;

js/Components/TableActiveFilters.vue

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<template>
2+
<div class="flex items-center justify-start my-3 text-sm">
3+
<div class="">
4+
<svg
5+
xmlns="http://www.w3.org/2000/svg"
6+
class="h-5 w-5 text-gray-300"
7+
viewBox="0 0 20 20"
8+
fill="currentColor"
9+
>
10+
<path
11+
fill-rule="evenodd"
12+
d="M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z"
13+
clip-rule="evenodd"
14+
/>
15+
</svg>
16+
</div>
17+
18+
<button
19+
v-for="(filter) in filters.filter((filter) => filter.value)"
20+
:key="filter.label"
21+
class="block group ml-3 flex items-center justify-between px-2 py-1 rounded bg-gray-100"
22+
@click="onFilterChange(filter.key, null)"
23+
>
24+
<span class="capitalize text-gray-500">{{ filter.label.replace('_', ' ') }}</span>:
25+
<span class="ml-1 group-hover:line-through">{{ filter.options[filter.value] }}</span>
26+
27+
<svg
28+
:class="`group-hover:${activeClasses.text}`"
29+
xmlns="http://www.w3.org/2000/svg"
30+
class="h-4 w-4 ml-1 text-gray-400"
31+
viewBox="0 0 20 20"
32+
fill="currentColor"
33+
>
34+
<path
35+
fill-rule="evenodd"
36+
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
37+
clip-rule="evenodd"
38+
/>
39+
</svg>
40+
</button>
41+
</div>
42+
</template>
43+
44+
<script setup>
45+
import { inject } from "vue";
46+
47+
defineProps({
48+
filters: {
49+
type: Object,
50+
required: true,
51+
},
52+
53+
onFilterChange: {
54+
type: Function,
55+
required: true,
56+
},
57+
});
58+
59+
const activeClasses = inject("activeClasses");
60+
61+
</script>

php/InertiaTable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ protected function getQueryBuilderProps(): array
147147

148148
'filters' => $this->transformFilters(),
149149
'hasFilters' => $this->filters->isNotEmpty(),
150-
'hasEnabledFilters' => $this->filters->filter->value->isNotEmpty(),
150+
'hasEnabledFilters' => $this->filters->whereNotNull('value')->isNotEmpty(),
151151

152152
'searchInputs' => $searchInputs = $this->transformSearchInputs(),
153153
'searchInputsWithoutGlobal' => $searchInputsWithoutGlobal = $searchInputs->where('key', '!=', 'global'),

0 commit comments

Comments
 (0)