Skip to content

Commit

Permalink
add row grouping based on column on datagrid
Browse files Browse the repository at this point in the history
  • Loading branch information
davidcedres committed Oct 3, 2020
1 parent 4218d71 commit d79493c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 52 deletions.
11 changes: 11 additions & 0 deletions src/components/compounds/Table/DataGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ class DataGrid {
return obj;
} , {})
}

groups(column) {
return this.rows.reduce((set, row) => {
set.add(row[column])
return set;
}, new Set())
}

filterRows(column, value) {
return this.rows.filter(row => row[column] === value)
}
}

export default DataGrid
138 changes: 86 additions & 52 deletions src/components/compounds/Table/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ const Table = {
expandable: Boolean,
draggableRows: Boolean,
draggableColumns: Boolean,
editable: Boolean
editable: Boolean,
groupBy: String,
},
setup(props, { emit }) {
Expand All @@ -42,7 +43,8 @@ const Table = {
const rowsPerPage = ref(props.rowsPerPage)
const currentPage = ref(0)
const search = reactive({})
const expanded = ref(new Set())
const expandedRows = ref(new Set())
const expandedGroups = ref(new Set())
// whenever pagination props changes, update the class state accordingly
// thsi way pagination settings are directly passed to props and indirectly passed to class
Expand Down Expand Up @@ -72,11 +74,19 @@ const Table = {
}
const toggleExpanded = rowId => {
if (expanded.value.has(rowId)) {
expanded.value.delete(rowId)
if (expandedRows.value.has(rowId)) {
expandedRows.value.delete(rowId)
return
}
expanded.value.add(rowId)
expandedRows.value.add(rowId)
}
const toggleExpandedGroup = group => {
if (expandedGroups.value.has(group)) {
expandedGroups.value.delete(group)
return
}
expandedGroups.value.add(group)
}
const rootClasses = computed(() => {
Expand All @@ -92,16 +102,11 @@ const Table = {
})
const countColumns = computed(() => {
return (
data.value.getColumns().length +
(props.checkable ? 1 : 0) +
(props.expandable ? 1 : 0)
)
return data.value.getColumns().length + (props.checkable ? 1 : 0) + (props.expandable ? 1 : 0)
})
const handleBackPage = () => {
if (currentPage.value > 0)
currentPage.value -= 1
if (currentPage.value > 0) currentPage.value -= 1
}
const handleNextPage = () => {
Expand All @@ -117,11 +122,13 @@ const Table = {
rowsPerPage,
currentPage,
rootClasses,
expanded,
expandedRows,
toggleExpanded,
expandedGroups,
toggleExpandedGroup,
countColumns,
handleBackPage,
handleNextPage
handleNextPage,
}
},
}
Expand Down Expand Up @@ -180,43 +187,74 @@ export default Table
/>
</td>
</tr>
<template v-for="(row, idx) in data.rows" :key="idx">
<tr
:draggable="draggableRows"
@dragstart="data.onDragStartRow($event, row, idx)"
@drop="data.onDropRow($event, row, idx)"
@dragover="data.onDragOverRow($event, row, idx)"
@dragleave="data.onDragLeaveRow($event, row, idx)"
:class="{ 'has-background-primary': row.selected, 'has-text-white': row.selected }"
>
<td v-if="checkable">
<v-checkbox @change="data.toggleCheck($event, row)" />
</td>
<td v-if="expandable">
<a
><v-tag @click="toggleExpanded(row.id)" type="is-primary">{{
expanded.has(row.id) ? '&uarr;' : '&darr;'
}}</v-tag></a
<template v-if="!groupBy">
<template v-for="(row, idx) in data.rows" :key="idx">
<tr
:draggable="draggableRows"
@dragstart="data.onDragStartRow($event, row, idx)"
@drop="data.onDropRow($event, row, idx)"
@dragover="data.onDragOverRow($event, row, idx)"
@dragleave="data.onDragLeaveRow($event, row, idx)"
:class="{ 'has-background-primary': row.selected, 'has-text-white': row.selected }"
>
<td v-if="checkable">
<v-checkbox @change="data.toggleCheck($event, row)" />
</td>
<td v-if="expandable">
<a @click="toggleExpanded(row.id)" class="is-primary">{{
expandedRows.has(row.id) ? '&uarr;' : '&darr;'
}}</a>
</td>
<td
v-for="column in data.getColumns()"
:key="column.name"
:class="column.style"
:contenteditable="props.editable"
v-on:blur="data.editCell(row, column, $event.target.textContent)"
>
</td>
<td
v-for="column in data.getColumns()"
:key="column.name" :class="column.style"
:contenteditable='props.editable'
v-on:blur="data.editCell(row, column, $event.target.textContent)">
<slot :name="column.name" :row="row">
{{ row[column.name] }}
</slot>
</td>
</tr>
<tr class="expansion" v-if="expanded.has(row.id)">
<td :colspan="countColumns">
<slot name="expanded" :row="row" />
</td>
</tr>
<slot :name="column.name" :row="row">
{{ row[column.name] }}
</slot>
</td>
</tr>
<tr class="expansion" v-if="expandedRows.has(row.id)">
<td :colspan="countColumns">
<slot name="expanded" :row="row" />
</td>
</tr>
</template>
</template>

<template v-if="groupBy">
<template v-for="(group, idx) in data.groups(groupBy)" :key="idx">
<tr>
<td :colspan="countColumns">
<a @click="toggleExpandedGroup(group)" class="mr-4">{{
expandedGroups.has(group) ? '&darr;' : '&rarr;'
}}</a>
{{ groupBy }}: <v-tag type="is-primary" class="mx-4">{{ group }} </v-tag>
</td>
</tr>
<template v-if="expandedGroups.has(group)">
<tr v-for="(row, idx) in data.filterRows(groupBy, group)" :key="idx">
<td
v-for="column in data.getColumns()"
:key="column.name"
:class="column.style"
:contenteditable="props.editable"
v-on:blur="data.editCell(row, column, $event.target.textContent)"
>
<slot :name="column.name" :row="row">
{{ row[column.name] }}
</slot>
</td>
</tr>
</template>
</template>
</template>
</tbody>
</table>

<!-- todo: move the styles to their own scope -->
<div
class="pagination-wrapper"
Expand All @@ -231,11 +269,7 @@ export default Table
</v-select>
<!-- using :disabled wont work, so instead the click action is conditioned and the buttons are always clickable -->
<a class="pagination-previous" @click="handleBackPage">Previous</a>
<a
class="pagination-next"
@click="handleNextPage"
>Next page</a
>
<a class="pagination-next" @click="handleNextPage">Next page</a>
</div>

<div class="tableFooter">
Expand Down

0 comments on commit d79493c

Please sign in to comment.