|
1 | 1 | <script>
|
2 |
| -import { computed, reactive, ref, watch, watchEffect } from 'vue' |
| 2 | +import { computed, reactive, ref, watch } from 'vue' |
3 | 3 | import VTag from '../../primitives/Tag/Tag.vue'
|
4 | 4 | import VButton from '../../primitives/Button/Button.vue'
|
5 | 5 | import VCheckbox from '../../primitives/Checkbox/Checkbox.vue'
|
@@ -40,6 +40,7 @@ export default {
|
40 | 40 | editable: Boolean,
|
41 | 41 | groupBy: String,
|
42 | 42 | sticky: Boolean,
|
| 43 | + mobileCards: Boolean, |
43 | 44 | },
|
44 | 45 |
|
45 | 46 | setup(props, { slots }) {
|
@@ -159,158 +160,168 @@ export default {
|
159 | 160 |
|
160 | 161 | <template>
|
161 | 162 | <!-- eslint-disable @pathscale/vue3/v-directive -->
|
162 |
| - <div class="table-container" :class="{ 'sticky-table': sticky }"> |
163 |
| - <div class="tableHeader" v-if="hasHeader"> |
164 |
| - <slot name="header"> |
165 |
| - <v-button |
166 |
| - @click="data.resetFilters()" |
167 |
| - v-if="hasResetBtn" |
168 |
| - type="is-light has-text-black" |
169 |
| - class="my-2"> |
170 |
| - ↻ |
171 |
| - </v-button> |
172 |
| - </slot> |
173 |
| - </div> |
174 |
| - <table |
175 |
| - class="table" |
176 |
| - :class="[ |
177 |
| - { |
178 |
| - 'is-bordered': bordered, |
179 |
| - 'is-striped': striped, |
180 |
| - 'is-narrow': narrow, |
181 |
| - 'is-hoverable': hoverable, |
182 |
| - 'is-fullwidth': fullwidth, |
183 |
| - }, |
184 |
| - ]" |
185 |
| - style="position: relative"> |
186 |
| - <thead class="thead"> |
187 |
| - <tr class="tr"> |
188 |
| - <td class="td" v-if="checkable" /> |
189 |
| - <td v-if="expandable" /> |
190 |
| - <th |
191 |
| - class="th" |
192 |
| - v-for="(column, idx) in data.getColumns()" |
193 |
| - :key="idx" |
194 |
| - :class="columnClasses(column)" |
195 |
| - @click="handleSort(column)" |
196 |
| - :draggable="draggableColumns" |
197 |
| - @dragstart="data.onDragStartColumn($event, row, idx)" |
198 |
| - @drop="data.onDropColumn($event, column, idx)" |
199 |
| - @dragover="data.onDragOverColumn($event, column, idx)" |
200 |
| - @dragleave="data.onDragLeaveColumn($event, column, idx)"> |
201 |
| - {{ column.caption }} |
202 |
| - <span v-if="sortable"> |
203 |
| - {{ column.ascendant ? '↓' : '\t↑' }} |
204 |
| - </span> |
205 |
| - </th> |
206 |
| - </tr> |
207 |
| - </thead> |
208 |
| - <tbody class="tbody"> |
209 |
| - <tr v-if="searchable"> |
210 |
| - <td v-if="checkable" /> |
211 |
| - <td v-if="expandable" /> |
212 |
| - <td v-for="column in data.getColumns()" :key="column.name" :class="column.style"> |
213 |
| - <v-input |
214 |
| - name="search" |
215 |
| - type="text" |
216 |
| - v-model="search[column.name]" |
217 |
| - @input="data.searchColumn(column.name, search[column.name])" |
218 |
| - placeholder="Search" /> |
219 |
| - </td> |
220 |
| - </tr> |
221 |
| - <template v-if="!groupBy"> |
222 |
| - <template v-for="(row, idx) in data.rows" :key="idx"> |
223 |
| - <tr |
224 |
| - :draggable="draggableRows" |
225 |
| - @dragstart="data.onDragStartRow($event, row, idx)" |
226 |
| - @drop="data.onDropRow($event, row, idx)" |
227 |
| - @dragover="data.onDragOverRow($event, row, idx)" |
228 |
| - @dragleave="data.onDragLeaveRow($event, row, idx)" |
229 |
| - :class="selectedClasses(row)"> |
230 |
| - <td v-if="checkable"> |
231 |
| - <v-checkbox @change="data.toggleCheck($event, row)" /> |
232 |
| - </td> |
233 |
| - <td v-if="expandable"> |
234 |
| - <a @click="toggleExpanded(row.id)" class="is-primary">{{ |
235 |
| - expandedRows.has(row.id) ? '↑' : '↓' |
236 |
| - }}</a> |
237 |
| - </td> |
238 |
| - <td |
239 |
| - v-for="column in data.getColumns()" |
240 |
| - :key="column.name" |
241 |
| - :class="cellClasses(column)" |
242 |
| - :contenteditable="props.editable" |
243 |
| - @blur="data.editCell(row, column, $event.target.textContent)"> |
244 |
| - <slot :name="column.name" :row="row"> |
245 |
| - {{ row[column.name] }} |
246 |
| - </slot> |
247 |
| - </td> |
248 |
| - </tr> |
249 |
| - <tr class="expansion" v-if="expandedRows.has(row.id)"> |
250 |
| - <td :colspan="countColumns"> |
251 |
| - <slot name="expanded" :row="row" /> |
252 |
| - </td> |
253 |
| - </tr> |
254 |
| - </template> |
255 |
| - </template> |
256 |
| - |
257 |
| - <template v-if="groupBy"> |
258 |
| - <template v-for="(group, idx) in data.groups(groupBy)" :key="idx"> |
259 |
| - <tr> |
260 |
| - <td :colspan="countColumns" class="is-aligned-center"> |
261 |
| - <a @click="toggleExpandedGroup(group)" class="mr-4">{{ |
262 |
| - expandedGroups.has(group) ? '↓' : '→' |
263 |
| - }}</a> |
264 |
| - {{ groupBy }}: |
265 |
| - <v-tag type="is-primary" class="mx-4"> |
266 |
| - {{ group }} |
267 |
| - </v-tag> |
268 |
| - </td> |
269 |
| - </tr> |
270 |
| - <template v-if="expandedGroups.has(group)"> |
271 |
| - <tr v-for="(row, rowIdx) in data.filterRows(groupBy, group)" :key="rowIdx"> |
| 163 | + <div class="v-table"> |
| 164 | + <div |
| 165 | + class="table-wrapper table-container" |
| 166 | + :class="{ 'sticky-table': sticky, 'has-mobile-cards': mobileCards }"> |
| 167 | + <div class="tableHeader" v-if="hasHeader"> |
| 168 | + <slot name="header"> |
| 169 | + <v-button |
| 170 | + @click="data.resetFilters()" |
| 171 | + v-if="hasResetBtn" |
| 172 | + type="is-light has-text-black" |
| 173 | + class="my-2"> |
| 174 | + ↻ |
| 175 | + </v-button> |
| 176 | + </slot> |
| 177 | + </div> |
| 178 | + <table |
| 179 | + class="table" |
| 180 | + :class="[ |
| 181 | + { |
| 182 | + 'is-bordered': bordered, |
| 183 | + 'is-striped': striped, |
| 184 | + 'is-narrow': narrow, |
| 185 | + 'is-hoverable': hoverable, |
| 186 | + 'is-fullwidth': fullwidth, |
| 187 | + }, |
| 188 | + ]" |
| 189 | + style="position: relative;"> |
| 190 | + <thead class="thead"> |
| 191 | + <tr class="tr"> |
| 192 | + <td class="td" v-if="checkable" /> |
| 193 | + <td v-if="expandable" /> |
| 194 | + <th |
| 195 | + class="th" |
| 196 | + v-for="(column, idx) in data.getColumns()" |
| 197 | + :key="idx" |
| 198 | + :class="columnClasses(column)" |
| 199 | + @click="handleSort(column)" |
| 200 | + :draggable="draggableColumns" |
| 201 | + @dragstart="data.onDragStartColumn($event, row, idx)" |
| 202 | + @drop="data.onDropColumn($event, column, idx)" |
| 203 | + @dragover="data.onDragOverColumn($event, column, idx)" |
| 204 | + @dragleave="data.onDragLeaveColumn($event, column, idx)"> |
| 205 | + {{ column.caption }} |
| 206 | + <span v-if="sortable"> |
| 207 | + {{ column.ascendant ? '↓' : '\t↑' }} |
| 208 | + </span> |
| 209 | + </th> |
| 210 | + </tr> |
| 211 | + </thead> |
| 212 | + <tbody class="tbody"> |
| 213 | + <tr v-if="searchable"> |
| 214 | + <td v-if="checkable" /> |
| 215 | + <td v-if="expandable" /> |
| 216 | + <td |
| 217 | + v-for="column in data.getColumns()" |
| 218 | + :data-label="column.caption" |
| 219 | + :key="column.name" |
| 220 | + :class="column.style"> |
| 221 | + <v-input |
| 222 | + name="search" |
| 223 | + type="text" |
| 224 | + v-model="search[column.name]" |
| 225 | + @input="data.searchColumn(column.name, search[column.name])" |
| 226 | + placeholder="Search" /> |
| 227 | + </td> |
| 228 | + </tr> |
| 229 | + <template v-if="!groupBy"> |
| 230 | + <template v-for="(row, idx) in data.rows" :key="idx"> |
| 231 | + <tr |
| 232 | + :draggable="draggableRows" |
| 233 | + @dragstart="data.onDragStartRow($event, row, idx)" |
| 234 | + @drop="data.onDropRow($event, row, idx)" |
| 235 | + @dragover="data.onDragOverRow($event, row, idx)" |
| 236 | + @dragleave="data.onDragLeaveRow($event, row, idx)" |
| 237 | + :class="selectedClasses(row)"> |
| 238 | + <td v-if="checkable"> |
| 239 | + <v-checkbox @change="data.toggleCheck($event, row)" /> |
| 240 | + </td> |
| 241 | + <td v-if="expandable"> |
| 242 | + <a @click="toggleExpanded(row.id)" class="is-primary">{{ |
| 243 | + expandedRows.has(row.id) ? '↑' : '↓' |
| 244 | + }}</a> |
| 245 | + </td> |
272 | 246 | <td
|
273 | 247 | v-for="column in data.getColumns()"
|
| 248 | + :data-label="column.caption" |
274 | 249 | :key="column.name"
|
275 |
| - :class="column.style" |
| 250 | + :class="cellClasses(column)" |
276 | 251 | :contenteditable="props.editable"
|
277 | 252 | @blur="data.editCell(row, column, $event.target.textContent)">
|
278 | 253 | <slot :name="column.name" :row="row">
|
279 | 254 | {{ row[column.name] }}
|
280 | 255 | </slot>
|
281 | 256 | </td>
|
282 | 257 | </tr>
|
| 258 | + <tr class="expansion" v-if="expandedRows.has(row.id)"> |
| 259 | + <td :colspan="countColumns"> |
| 260 | + <slot name="expanded" :row="row" /> |
| 261 | + </td> |
| 262 | + </tr> |
283 | 263 | </template>
|
284 | 264 | </template>
|
285 |
| - </template> |
286 |
| - </tbody> |
287 |
| - </table> |
288 | 265 |
|
289 |
| - <div v-if="pagination" class="pagination-container px-1"> |
290 |
| - <v-select v-model="computedRowsPerPage"> |
291 |
| - > |
292 |
| - <option v-for="value in rowsPerPageOptions" :key="value" :value="value"> |
293 |
| - {{ value }} |
294 |
| - </option> |
295 |
| - </v-select> |
| 266 | + <template v-if="groupBy"> |
| 267 | + <template v-for="(group, idx) in data.groups(groupBy)" :key="idx"> |
| 268 | + <tr> |
| 269 | + <td :colspan="countColumns" class="is-aligned-center"> |
| 270 | + <a @click="toggleExpandedGroup(group)" class="mr-4">{{ |
| 271 | + expandedGroups.has(group) ? '↓' : '→' |
| 272 | + }}</a> |
| 273 | + {{ groupBy }}: |
| 274 | + <v-tag type="is-primary" class="mx-4"> |
| 275 | + {{ group }} |
| 276 | + </v-tag> |
| 277 | + </td> |
| 278 | + </tr> |
| 279 | + <template v-if="expandedGroups.has(group)"> |
| 280 | + <tr v-for="(row, rowIdx) in data.filterRows(groupBy, group)" :key="rowIdx"> |
| 281 | + <td |
| 282 | + v-for="column in data.getColumns()" |
| 283 | + :data-label="column.caption" |
| 284 | + :key="column.name" |
| 285 | + :class="column.style" |
| 286 | + :contenteditable="props.editable" |
| 287 | + @blur="data.editCell(row, column, $event.target.textContent)"> |
| 288 | + <slot :name="column.name" :row="row"> |
| 289 | + {{ row[column.name] }} |
| 290 | + </slot> |
| 291 | + </td> |
| 292 | + </tr> |
| 293 | + </template> |
| 294 | + </template> |
| 295 | + </template> |
| 296 | + </tbody> |
| 297 | + </table> |
296 | 298 |
|
297 |
| - <v-pagination |
298 |
| - class="px-1" |
299 |
| - :total="total" |
300 |
| - :current="currentPage + 1" |
301 |
| - @update:current="handlePageChange" |
302 |
| - :range-before="1" |
303 |
| - :range-after="1" |
304 |
| - order="is-centered" |
305 |
| - :per-page="computedRowsPerPage" |
306 |
| - aria-next-label="Next page" |
307 |
| - aria-previous-label="Previous page" |
308 |
| - aria-page-label="Page" |
309 |
| - aria-current-label="Current page" /> |
310 |
| - </div> |
| 299 | + <div v-if="pagination" class="pagination-container px-1"> |
| 300 | + <v-select v-model="computedRowsPerPage"> |
| 301 | + > |
| 302 | + <option v-for="value in rowsPerPageOptions" :key="value" :value="value"> |
| 303 | + {{ value }} |
| 304 | + </option> |
| 305 | + </v-select> |
| 306 | + |
| 307 | + <v-pagination |
| 308 | + class="px-1" |
| 309 | + :total="total" |
| 310 | + :current="currentPage + 1" |
| 311 | + @update:current="handlePageChange" |
| 312 | + :range-before="1" |
| 313 | + :range-after="1" |
| 314 | + order="is-centered" |
| 315 | + :per-page="computedRowsPerPage" |
| 316 | + aria-next-label="Next page" |
| 317 | + aria-previous-label="Previous page" |
| 318 | + aria-page-label="Page" |
| 319 | + aria-current-label="Current page" /> |
| 320 | + </div> |
311 | 321 |
|
312 |
| - <div class="tableFooter" v-if="slots.footer"> |
313 |
| - <slot name="footer" /> |
| 322 | + <div class="tableFooter" v-if="slots.footer"> |
| 323 | + <slot name="footer" /> |
| 324 | + </div> |
314 | 325 | </div>
|
315 | 326 | </div>
|
316 | 327 | </template>
|
0 commit comments