Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ktableview): add bulk actions feature [KHCP-13106] #2365

Merged
merged 39 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e91a4b9
chore(sandbox): minor fixes [KHCP-13106]
portikM Aug 28, 2024
c7f7263
feat(ktableview): add bulk actions column feature [KHCP-13106]
portikM Aug 28, 2024
7dc9feb
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Aug 28, 2024
c64633e
fix(ktableview): add bulk actions dropdown [KHCP-13106]
portikM Aug 28, 2024
eebd4ed
test(ktableview): add bulk actions tests [KHCP-13106]
portikM Aug 29, 2024
75808d1
fix: address pr feedback
portikM Aug 29, 2024
9b1a4b7
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Aug 29, 2024
dd74e96
fix(ktableview): sticky bulk actions column [KHCP-13106]
portikM Aug 29, 2024
463e5c8
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 3, 2024
7e95911
fix(ktableview): add bulk actions dropdown component [KHCP-13106]
portikM Sep 3, 2024
7afb892
fix(ktableview): allow disable row bulk actions [KHCP-13106]
portikM Sep 3, 2024
8861fae
test(ktableview): bulk actions disabled [KHCP-13106]
portikM Sep 3, 2024
44f630a
fix(ktableview): minor fixes [KHCP-13106]
portikM Sep 3, 2024
00b5e96
fix(ktableview): add row bulk action prop [KHCP-13106]
portikM Sep 3, 2024
980d992
docs(ktableview): update component docs [KHCP-13106]
portikM Sep 4, 2024
5b8c319
fix: minor fix
portikM Sep 4, 2024
d3226da
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 4, 2024
847d695
fix: minor fix
portikM Sep 4, 2024
186ca59
fix: minor fix
portikM Sep 4, 2024
43ddc51
fix: address pr feedback
portikM Sep 4, 2024
25c1d3f
fix(ktableview): apply pr feedback
portikM Sep 4, 2024
5f90e2e
fix: address pr feedback
portikM Sep 4, 2024
569bd95
fix: address pr feedback
portikM Sep 4, 2024
6e2d6f4
fix: address pr feedback
portikM Sep 4, 2024
f739206
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 4, 2024
a41d3b0
fix: minor fix
portikM Sep 4, 2024
0c436c6
test(ktableview): fix component tests [KHCP-13106]
portikM Sep 4, 2024
e7d199a
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 5, 2024
923b057
fix: address pr feedback
portikM Sep 5, 2024
b453ca5
fix: address pr feedback
portikM Sep 6, 2024
8d9f7d0
fix: apply pr feedback
portikM Sep 6, 2024
b4e9b76
test(ktableview): fix test [KHCP-13106]
portikM Sep 6, 2024
9e449f3
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 6, 2024
6c7bc07
fix: address pr feedback
portikM Sep 6, 2024
646cff1
fix: address pr feedback
portikM Sep 6, 2024
b514494
fix: minor fix
portikM Sep 6, 2024
e88f0c1
fix: address pr feedback
portikM Sep 6, 2024
581975b
fix: minor fix
portikM Sep 9, 2024
e9045d0
Merge branch 'main' into feat/khcp-13106-ktableview-bulk-actions
portikM Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 227 additions & 6 deletions docs/components/table-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface TableViewHeader {
key: string
/** visible column header text */
label: string
/** in a nutshell, this property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */
/** this property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */
sortable?: boolean
/** allow toggling column visibility */
hidable?: boolean
Expand All @@ -51,7 +51,12 @@ For an example of `headers` prop usage please refer to [`data` prop documentatio

#### Reserved Header Keys

- `actions` - the column displays an actions [KDropdown](/components/dropdown) button for each row and displays no label (as if `hideLabel` was `true`; you can set `hideLabel` parameter to `false` to show the label). KTableView will automatically render the actions dropdown button with an icon and you simply need to provide dropdown items via the [`action-items` slot](#action-items).
- `bulkActions` - the column displays individual checkboxes to allow selecting individual rows, while the column header displays a checkbox will check or uncheck all visible table rows. KTableView will render a dropdown on the right of the table toolbar directly above the table and you simply need to provide dropdown items via the [`bulk-action-items` slot](#bulk-action-items). Refer to the [`bulk-action-items` slot](#bulk-action-items) for the example.
- `actions` - the column displays an actions [KDropdown](/components/dropdown) button for each row and displays no label (as if `hideLabel` was `true`; you can set `hideLabel` parameter to `false` to show the label). KTableView will automatically render the actions dropdown and you simply need to provide dropdown items via the [`action-items` slot](#action-items).

:::tip NOTE
KTableView automatically displays the bulk action checkbox as the first column, and the `actions` menu in the last column, when enabled.
:::

### data

Expand Down Expand Up @@ -347,6 +352,77 @@ const getRowLink = (row: Record<string, any>): RowLink => ({
</script>
```

### rowBulkActionEnabled

Function for enabling or disabling row selection when `bulkActions` are enabled for the table. Helpful for making some rows unavailable for bulk actions selection. The function receives the row data object as a parameter and must return a `boolean` or an object that matches the following interface:

```ts
type RowBulkAction = boolean | { enabled: boolean, disabledTooltip?: string }
```

When the function returns a boolean value of `true`, bulk action selection will be enabled for the row.

When `false` is returned, the bulk action checkbox will be disabled.

If an object is returned, the `enabled` property determines if the row can be selected. The `disabledTooltip` value, if provided, will show the string as a tooltip message if the user hovers over the disabled checkbox.

Default value is `() => true`.

<KTableView
:row-bulk-action-enabled="getRowBulkAction"
:data="basicData"
:headers="basicHeaders(false, null, null, true)"
:pagination-attributes="{ totalCount: basicData.length }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>

```vue
<template>
<KTableView
:row-bulk-action-enabled="getRowBulkActionEnabled"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>
</template>

<script setup lang="ts">
import type { RowBulkAction } from '@kong/kongponents'

...

const getRowBulkActionEnabled = (row: Record<string, any>): RowBulkAction => {
if (row.id === 2) {
return false
}

if (row.id === 3) {
return { enabled: false }
}

if (row.id === 4) {
return {
enabled: false,
disabledTooltip: 'This row is disabled.',
}
}

return true
}
</script>
```

### cellAttrs

Function for adding custom attributes to each table cell. The function should return an object with `key: value` pairs for each attribute.
Expand Down Expand Up @@ -553,6 +629,7 @@ A `error-action-click` event is emitted when error state action button is clicke
You can slot in your custom content into each column header. For that, use column `key` value prefixed with `column-*` like in the example below.

Slot props:

* `column` - column header object

<KTableView
Expand Down Expand Up @@ -582,6 +659,7 @@ Slot props:
You can provide each individual cell's content via slot. Each cell slot is named after the header `key` it corresponds to.

Slot props:

* `row` - table row object
* `rowKey` - table row index
* `rowValue` - the cell value
Expand Down Expand Up @@ -617,6 +695,7 @@ This slot is not supported for the [`actions` column](#reserved-header-keys).
Utilize HTML in the column header's tooltip by utilizing this slot. Similar to the column header slot, it uses the column `key` value prefixed with `tooltip-*` as shown in the example below.

Slot props:

* `column` - column header object

<KTableView
Expand Down Expand Up @@ -698,6 +777,7 @@ Slot content to be displayed when in error state.
Slot for passing action dropdown items. See [KDropdownItem component docs](/components/dropdown#kdropdownitem) for details.

Slot props:

* `row` - table row object
* `rowKey` - table row index

Expand Down Expand Up @@ -743,6 +823,105 @@ This slot is only available when the `actions` header key is present in [`header
</KTableView>
```

### bulk-action-items

Slot for passing bulk action dropdown items.
adamdehaven marked this conversation as resolved.
Show resolved Hide resolved
adamdehaven marked this conversation as resolved.
Show resolved Hide resolved

:::warning IMPORTANT
Content must be provided through either this or [`bulk-actions` slot](#bulk-actions) when bulk actions is enabled for the table, otherwise bulk actions column won't be rendered.
:::

Slot props:

- `selectedRows` - array of selected table row objects

See also: [`row-select` event](#row-select).

<KTableView
:data="paginatedData1"
:headers="basicHeaders(false, null, null, true)"
:pagination-attributes="{ totalCount: basicPaginatedData.length, pageSizes: [5, 10] }"
@page-change="onPageChange1"
@page-size-change="onPageSizeChange1"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>

```vue
<template>
<KTableView
:data="paginatedData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length, pageSizes: [5, 10] }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>
</template>

<script setup lang="ts">
import type { TableViewHeader, TableViewData } from '@kong/kongponents'

const headers: Array<TableViewHeader> = [
{
key: 'bulkActions',
label: 'Bulk actions',
},
...
]

const tableData = ref<TableViewData>([ ... ])
const paginatedData = tableData.slice(...)
</script>
```

### bulk-actions

Slot for passing custom bulk actions trigger element. Content provided through this slot will replace default bulk actions dropdown.

Slot props:

- `selectedRows` - array of selected table row objects

<KTableView
:data="basicData"
:headers="basicHeaders(false, null, null, true)"
:pagination-attributes="{ totalCount: basicData.length }"
>
<template #bulk-actions="{ selectedRows }">
<KButton
appearance="danger"
:disabled="!selectedRows.length"
>
Delete ({{ selectedRows.length }} items selected)
</KButton>
</template>
</KTableView>

```html
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #bulk-actions="{ selectedRows }">
<KButton
appearance="danger"
:disabled="!selectedRows.length"
>
Delete ({{ selectedRows.length }} items selected)
</KButton>
</template>
</KTableView>
```

## Events

### Row Events
Expand Down Expand Up @@ -859,15 +1038,25 @@ Emitted when error state action button is clicked.

Emitted when the user performs sorting, resizes columns or toggles column visibility. Event payload is object of type `TablePreferences` interface (see [`tablePreferences` prop](#tablepreferences) for details).

### row-select

Emitted when user interacts with checkboxes in bulk actions column. Payload is array of selected table row objects.

<script setup lang="ts">
import { ref } from 'vue'
import { AddIcon, SearchIcon, MoreIcon } from '@kong/icons'
import { ToastManager } from '@/index'

const toaster = new ToastManager()

const basicHeaders = (actions: boolean = false, sortable: string | null = null, hidable: string | null = null): Array<TableViewHeader> => {
const basicHeaders = (actions: boolean = false, sortable: string | null = null, hidable: string | null = null, bulkActions: boolean = false): Array<TableViewHeader> => {
const keys = {
...(bulkActions && {
actions: {
key: 'bulkActions',
label: 'Bulk actions',
},
}),
name: {
key: 'name',
label: 'Full Name'
Expand Down Expand Up @@ -1001,13 +1190,13 @@ const sortBasicData = (sortData: TableSortPayload): void => {

const extraRecords: TableViewData = [
{
id: 1,
id: 11,
name: 'Chris Lo',
username: 'Krislow',
email: 'dj@kris.low',
},
{
id: 2,
id: 12,
name: 'Vitaliy Yarmak',
username: 'Tamarack',
email: 'Right@sail.xyz',
Expand All @@ -1023,10 +1212,23 @@ const onPageChange = ({ page }: PageChangeData) => {
paginatedData.value = basicPaginatedData.slice((paginatedPageSize.value * (page - 1)), (paginatedPageSize.value * (page - 1)) + paginatedPageSize.value)
}
}
const onPageSizeChange = ({ pageSize }: PageChangeData) => {
const onPageSizeChange = ({ pageSize }: PageSizeChangeData) => {
paginatedPageSize.value = pageSize
}

const paginatedPageSize1 = ref<number>(5)
const paginatedData1 = ref<TableViewData>(basicPaginatedData.slice(0, paginatedPageSize1.value))
const onPageChange1 = ({ page }: PageChangeData) => {
if (page === 1) {
paginatedData1.value = basicPaginatedData.slice(0, paginatedPageSize1.value)
} else {
paginatedData1.value = basicPaginatedData.slice((paginatedPageSize1.value * (page - 1)), (paginatedPageSize1.value * (page - 1)) + paginatedPageSize1.value)
}
}
const onPageSizeChange1 = ({ pageSize }: PageSizeChangeData) => {
paginatedPageSize1.value = pageSize
}

const getRowLink = (row: Record<string, any>): TableRowAttributes => ({
// using static route for demonstration purposes
// but you can generate dynamic routes based on the row data
Expand Down Expand Up @@ -1080,6 +1282,25 @@ const onCellClick = (event, cell) => {
}

const toggleModel = ref<boolean[]>([false, false, false])

const getRowBulkAction = (data: Record<string, any>): RowBulkAction => {
if (data.id === 2) {
return false
}

if (data.id === 3) {
return { enabled: false }
}

if (data.id === 4) {
return {
enabled: false,
disabledTooltip: 'This row is disabled.',
}
}

return true
}
</script>

<style lang="scss" scoped>
Expand Down
Loading