Skip to content

Commit 6ade46e

Browse files
Merge filters for tables
2 parents 93e960e + 00e68aa commit 6ade46e

File tree

8 files changed

+350
-67
lines changed

8 files changed

+350
-67
lines changed

src/App.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<v-app>
33
<v-app-bar app clipped-left color="white" class="elevation-1" height="56">
4-
<v-app-bar-nav-icon @click="mini = !mini"></v-app-bar-nav-icon>
4+
<v-app-bar-nav-icon @click="toggleMenu"></v-app-bar-nav-icon>
55

66
<v-img
77
max-width="33"
@@ -62,15 +62,15 @@ export default {
6262
data () {
6363
return {
6464
drawer: true,
65+
mini: true,
6566
items: [
6667
{ title: 'Dashboard', icon: 'mdi-view-dashboard', route: 'Dashboard', associatedRoutes: ['Dashboard'] },
6768
{ title: 'Usuarios', icon: 'mdi-account-group', route: 'Users', associatedRoutes: ['Users', 'UserDetail'] },
6869
{ title: 'Proyectos', icon: 'mdi-inbox-multiple', route: 'Projects', associatedRoutes: ['Projects', 'ProjectDetail'] },
6970
{ title: 'Transacciones', icon: 'mdi-cash-multiple', route: 'Transactions', associatedRoutes: ['Transactions'] },
7071
{ title: 'Métricas', icon: 'mdi-chart-pie', route: 'Metrics', associatedRoutes: ['Metrics'] },
7172
{ title: 'Servidores', icon: 'mdi-server', route: 'Servers', associatedRoutes: ['Servers'] }
72-
],
73-
mini: true
73+
]
7474
}
7575
},
7676
@@ -80,6 +80,13 @@ export default {
8080
},
8181
isSelected (associatedRoutes) {
8282
return associatedRoutes.includes(this.$router.currentRoute.name)
83+
},
84+
toggleMenu () {
85+
if (this.$vuetify.breakpoint.mdAndDown) {
86+
this.drawer = !this.drawer
87+
} else {
88+
this.mini = !this.mini
89+
}
8390
}
8491
}
8592
}

src/components/Map.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default {
2828
2929
data () {
3030
return {
31-
zoom: 4,
31+
zoom: 15,
3232
rotation: 0
3333
}
3434
}

src/components/ProjectsTable.vue

Lines changed: 184 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,98 @@
88
:items-per-page="itemsPerPage"
99
:footer-props="footerProps"
1010
>
11+
<template v-slot:top>
12+
<v-card-actions class="px-2 py-2">
13+
<v-menu
14+
:close-on-content-click="false"
15+
min-width="500"
16+
max-width="500"
17+
offset-y
18+
>
19+
<template v-slot:activator="{ on, attrs }">
20+
<v-btn
21+
icon
22+
v-bind="attrs"
23+
v-on="on"
24+
class="pa-0 ma-0"
25+
>
26+
<v-icon>mdi-filter-variant-plus</v-icon>
27+
</v-btn>
28+
</template>
29+
30+
<v-card>
31+
<v-card-text>
32+
<v-autocomplete
33+
v-model="selectedCategories"
34+
:items="categories"
35+
label="Categorías"
36+
chips
37+
deletable-chips
38+
clearable
39+
multiple
40+
small-chips
41+
prepend-icon="mdi-tag"
42+
></v-autocomplete>
43+
<v-autocomplete
44+
v-model="selectedStates"
45+
:items="states"
46+
label="Estados"
47+
chips
48+
deletable-chips
49+
clearable
50+
multiple
51+
small-chips
52+
prepend-icon="mdi-state-machine"
53+
></v-autocomplete>
54+
</v-card-text>
55+
</v-card>
56+
</v-menu>
57+
<span class="mx-4">
58+
<v-chip small class="mr-2 my-1" :color="activeFilter ? 'primary lighten-3' : ''" @click="clickActiveFilter">
59+
<v-icon small left v-if="activeFilter">mdi-check</v-icon>
60+
<v-icon small left v-else>mdi-minus</v-icon>
61+
Activos
62+
</v-chip>
63+
<v-chip small class="mr-2 my-1" :color="blockedFilter ? 'primary lighten-3' : ''" @click="clickBlockedFilter">
64+
<v-icon small left v-if="blockedFilter">mdi-check</v-icon>
65+
<v-icon small left v-else>mdi-minus</v-icon>
66+
Bloqueados
67+
</v-chip>
68+
<v-chip small class="mr-2 my-1" color="amber lighten-3" v-for="category in selectedCategories" :key="category">
69+
<v-icon small left>mdi-check</v-icon>
70+
{{ category }}
71+
</v-chip>
72+
<v-chip small class="mr-2 my-1" color="pink lighten-3" v-for="state in states.filter(s => selectedStates.includes(s.value)).map(f => f.text)" :key="state">
73+
<v-icon small left>mdi-check</v-icon>
74+
{{ state }}
75+
</v-chip>
76+
</span>
77+
<v-spacer></v-spacer>
78+
<v-radio-group v-model="operator" row dense hide-details class="pa-0 ma-0">
79+
<v-radio label="OR" value="or" class="pa-0 my-0 mx-2"></v-radio>
80+
<v-radio label="AND" value="and" class="pa-0 ma-0 mx-2"></v-radio>
81+
</v-radio-group>
82+
</v-card-actions>
83+
<v-divider></v-divider>
84+
</template>
85+
86+
<template v-slot:item.blocked="{ item }">
87+
<div>
88+
<v-tooltip bottom v-if="item.isBlocked">
89+
<template v-slot:activator="{ on, attrs }">
90+
<v-icon color="red" dark v-bind="attrs" v-on="on">mdi-cancel</v-icon>
91+
</template>
92+
<span>Usuario bloqueado</span>
93+
</v-tooltip>
94+
<v-tooltip bottom v-else>
95+
<template v-slot:activator="{ on, attrs }">
96+
<v-icon color="green" dark v-bind="attrs" v-on="on">mdi-check-circle-outline</v-icon>
97+
</template>
98+
<span>Activo</span>
99+
</v-tooltip>
100+
</div>
101+
</template>
102+
11103
<template v-slot:item.owner="{ item }">
12104
<a href="#" @click.prevent="goToUserDetails(item.owner.dbId)">{{ item.owner.email }}</a>
13105
</template>
@@ -37,7 +129,7 @@
37129
</template>
38130

39131
<script>
40-
import { ALL_PROJECTS_QUERY } from '@/graphql/graphql'
132+
import { ALL_PROJECTS_QUERY, CATEGORIES_QUERY } from '@/graphql/graphql'
41133
42134
const DEFAULT_ROWS_PER_PAGE = 10
43135
const PROJECT_SORT_ENUM = {
@@ -64,14 +156,36 @@ export default {
64156
options: {},
65157
headers: [
66158
{ text: 'ID', align: 'start', sortable: true, value: 'dbId' },
159+
{ text: 'Activo', sortable: true, value: 'blocked' },
67160
{ text: 'Nombre', sortable: true, value: 'name' },
68161
{ text: 'Categoría', sortable: true, value: 'category.name' },
69162
{ text: 'Estado', sortable: true, value: 'currentState' },
70163
{ text: 'Recaudado', sortable: false, value: 'amountCollected' },
71164
{ text: 'Objetivo', sortable: true, value: 'goal' },
72165
{ text: 'Emprendedor', sortable: true, value: 'owner' },
73166
{ text: 'Detalles', align: 'end', sortable: false, value: 'actions' }
74-
]
167+
],
168+
blockedFilter: false,
169+
activeFilter: false,
170+
selectedCategories: [],
171+
selectedStates: [],
172+
states: [{
173+
text: 'Created',
174+
value: 'CREATED'
175+
}, {
176+
text: 'Funding',
177+
value: 'FUNDING'
178+
}, {
179+
text: 'In Progress',
180+
value: 'IN_PROGRESS'
181+
}, {
182+
text: 'Complete',
183+
value: 'COMPLETE'
184+
}, {
185+
text: 'Canceled',
186+
value: 'CANCELED'
187+
}],
188+
operator: 'or'
75189
}
76190
},
77191
@@ -80,6 +194,10 @@ export default {
80194
return this.allProjects?.edges?.map((e) => e.node) || []
81195
},
82196
197+
categories () {
198+
return this.allCategories?.edges?.map((e) => e.node?.name) || []
199+
},
200+
83201
totalCount () {
84202
return this.allProjects?.totalCount || this.projects?.length || 0
85203
},
@@ -108,6 +226,16 @@ export default {
108226
'disable-items-per-page': this.loading,
109227
'disable-pagination': this.loading
110228
}
229+
},
230+
231+
filters () {
232+
return {
233+
[this.operator]: [
234+
{ [this.operator]: [{ isBlocked: (this.blockedFilter === this.activeFilter) ? undefined : this.blockedFilter || !this.activeFilter }] },
235+
{ [this.operator]: [{ categoryNameIn: (this.selectedCategories.length) ? this.selectedCategories : undefined }] },
236+
{ [this.operator]: [{ currentStateIn: (this.selectedStates.length) ? this.selectedStates : undefined }] }
237+
]
238+
}
111239
}
112240
},
113241
@@ -118,39 +246,59 @@ export default {
118246
119247
goToProjectDetails (id) {
120248
this.$router.push({ name: 'ProjectDetail', params: { id: id } })
249+
},
250+
251+
clickActiveFilter () {
252+
this.blockedFilter = false
253+
this.activeFilter = !this.activeFilter
254+
},
255+
256+
clickBlockedFilter () {
257+
this.activeFilter = false
258+
this.blockedFilter = !this.blockedFilter
259+
},
260+
261+
paginate (val, oldVal) {
262+
const isPreviousPage = val?.page < oldVal?.page
263+
const isNextPage = val?.page > oldVal?.page
264+
265+
let first = this.options.itemsPerPage
266+
let last
267+
let endCursor
268+
let startCursor
269+
270+
if (isNextPage) {
271+
endCursor = this.endCursor
272+
}
273+
274+
if (isPreviousPage) {
275+
first = undefined
276+
last = this.options.itemsPerPage
277+
startCursor = [this.startCursor]
278+
}
279+
280+
this.$apollo.queries.allProjects.refetch({
281+
first: first,
282+
last: last,
283+
endCursor: endCursor,
284+
startCursor: startCursor,
285+
sort: this.sorting,
286+
filters: this.filters
287+
})
121288
}
122289
},
123290
124291
watch: {
125292
options: {
126293
handler (val, oldVal) {
127-
const isPreviousPage = val?.page < oldVal?.page
128-
const isNextPage = val?.page > oldVal?.page
129-
130-
let first = this.options.itemsPerPage
131-
let last
132-
let endCursor
133-
let startCursor
134-
135-
if (isNextPage) {
136-
endCursor = this.endCursor
137-
}
138-
139-
if (isPreviousPage) {
140-
first = undefined
141-
last = this.options.itemsPerPage
142-
startCursor = [this.startCursor]
143-
}
144-
145-
this.$apollo.queries.allProjects.refetch({
146-
first: first,
147-
last: last,
148-
endCursor: endCursor,
149-
startCursor: startCursor,
150-
sort: this.sorting
151-
})
294+
this.paginate(val, oldVal)
152295
},
153296
deep: true
297+
},
298+
filters: {
299+
handler (val, oldVal) {
300+
this.paginate(val, oldVal)
301+
}
154302
}
155303
},
156304
@@ -162,7 +310,16 @@ export default {
162310
first: this.itemsPerPage
163311
}
164312
}
313+
},
314+
allCategories: {
315+
query: CATEGORIES_QUERY
165316
}
166317
}
167318
}
168319
</script>
320+
321+
<style>
322+
.v-radio > .v-label {
323+
font-size: small !important;
324+
}
325+
</style>

0 commit comments

Comments
 (0)