Skip to content

Commit

Permalink
Merge pull request #1349 from FlowFuse/1188-table-key-type
Browse files Browse the repository at this point in the history
Support key type option in ui-table for entering fixed strings as item labels
  • Loading branch information
joepavitt authored Oct 4, 2024
2 parents ee584f1 + 8470348 commit 0b233e0
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 11 deletions.
102 changes: 101 additions & 1 deletion cypress/fixtures/flows/dashboard-tables.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@
"dashboard-ui-table-default",
"dashboard-ui-table-max-rows",
"dashboard-ui-table-single-row-click",
"dashboard-ui-table-multi-select"
"dashboard-ui-table-multi-select",
"dashboard-ui-table-table-buttons-string-value",
"dashboard-ui-table-buttons-text-from-payload"
]
]
},
Expand Down Expand Up @@ -137,6 +139,104 @@
]
]
},
{
"id": "dashboard-ui-table-table-buttons-string-value",
"type": "ui-table",
"z": "node-red-tab-tables",
"group": "dashboard-ui-group",
"name": "dashboard-ui-table-table-buttons-string-value",
"label": "dashboard-ui-table-table-buttons-string-value",
"order": 0,
"width": 0,
"height": 0,
"maxrows": 0,
"passthru": false,
"autocols": false,
"showSearch": false,
"selectionType": "none",
"columns": [
{
"title": "ID",
"key": "id",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
},
{
"title": "Name",
"key": "name",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
},
{
"title": "",
"key": "Button Text Is String Value",
"keyType": "str",
"type": "button",
"width": "",
"align": "start"
}
],
"mobileBreakpoint": "sm",
"mobileBreakpointType": "defaults",
"x": 990,
"y": 1020,
"wires": [
[]
]
},
{
"id": "dashboard-ui-table-buttons-text-from-payload",
"type": "ui-table",
"z": "node-red-tab-tables",
"group": "dashboard-ui-group",
"name": "dashboard-ui-table-buttons-text-from-payload",
"label": "text",
"order": 0,
"width": 0,
"height": 0,
"maxrows": 0,
"passthru": false,
"autocols": false,
"showSearch": false,
"selectionType": "none",
"columns": [
{
"title": "ID",
"key": "id",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
},
{
"title": "Name",
"key": "name",
"keyType": "key",
"type": "text",
"width": "",
"align": "start"
},
{
"title": "",
"key": "name",
"keyType": "key",
"type": "button",
"width": "",
"align": "start"
}
],
"mobileBreakpoint": "sm",
"mobileBreakpointType": "defaults",
"x": 1050,
"y": 1060,
"wires": [
[]
]
},
{
"id": "dashboard-ui-group",
"type": "ui-group",
Expand Down
20 changes: 20 additions & 0 deletions cypress/tests/widgets/table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,24 @@ describe('Node-RED Dashboard 2.0 - Tables', () => {

cy.checkOutput('msg.payload[0].value', 4)
})

it('uses table value for button text', () => {
// this one will render the 5 buttons text using the key "name" from the payload
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').should('have.length', 5)
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').eq(0).should('have.text', 'Name 1')
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').eq(1).should('have.text', 'Name 2')
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').eq(2).should('have.text', 'Name 3')
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').eq(3).should('have.text', 'Name 4')
cy.get('#nrdb-ui-widget-dashboard-ui-table-buttons-text-from-payload').find('button').eq(4).should('have.text', 'Name 5')
})
it('uses fixed value for button text', () => {
// this one uses a `str` value for the button text
const fixedString = 'Button Text Is String Value'
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').should('have.length', 5)
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').eq(0).should('have.text', fixedString)
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').eq(1).should('have.text', fixedString)
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').eq(2).should('have.text', fixedString)
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').eq(3).should('have.text', fixedString)
cy.get('#nrdb-ui-widget-dashboard-ui-table-table-buttons-string-value').find('button').eq(4).should('have.text', fixedString)
})
})
4 changes: 2 additions & 2 deletions docs/nodes/widgets/ui-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ _Screenshot of the configuration options available for column types in Node-RED_

If you toggle "off" the "Auto Columns" option, you will have more control to define the columns for your table. For each column, you can define the following:

- **Key**: The key in the object to use for the column data.
- **Value**: The value to use for rendering the control. Typically, you would provide a key to the value in the data row object but it can be changed to provide a fixed string value.
- **Label**: The text to display in the column header.
- **Width**: The width of the column, can be in `px`, `%`, or any other valid CSS sizing.
- **Align:** The alignment of the text in the column. Can be `Left`, `Center`, or `Right`. Note that some columns do look odd with "Center" alignment as the header does also contain space for the sorting icon.
Expand All @@ -137,7 +137,7 @@ _An example of a ui-table displaying various of the cell types available_
- **Progress**: Renders the cell as a progress bar. The `Value` field should contain a number between 0 and 100.
- **Sparkline - Trend**: Renders the cell as a small line chart without axes. The `Value` field should contain an array of numbers to be plotted.
- **Sparkline - Bar**: Renders the cell as a small bar chart without axes. The `Value` field should contain an array of numbers to be plotted.
- **Button**: Renders a clickable button in the cell. The label of the button will be the `row[key]` value.
- **Button**: Renders a clickable button in the cell. The label of the button will be either the `row[key]` or the fixed string entered on the manual column configuration.
- **Row Number**: Renders the row number into the cell.

#### Interaction: Buttons
Expand Down
Binary file modified docs/public/images/node-examples/ui-table-column-config.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions nodes/widgets/locales/en-US/ui_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ <h3>Input</h3>
The ui-table widget requires an array or an object of data to be sent via <code>msg.payload</code>.
If an array is provided, the table will render a row for each object within the array, and, by default, a column for each property in the objects.
If an object is provided, the table will render a single row with columns for each property in the object.
The text displayed for a row can be either a key or a string. Selecting <code>key</code> will look up the value of the named key in the object, while a string will display the string as is.
</p>
<h3>Properties</h3>
<dl class="message-properties">
Expand Down
3 changes: 2 additions & 1 deletion nodes/widgets/locales/en-US/ui_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"maxRows": "Max Rows",
"columns": "Columns",
"autoCalculateColumns": "Auto Calculate Columns",
"key": "Key",
"key": "key:",
"value": "Value",
"label": "Label",
"type": "Type",
"width": "Width",
Expand Down
25 changes: 20 additions & 5 deletions nodes/widgets/ui_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
.node-input-column-row-property:not(:first-child) {
margin-top: 3px;
}
#node-input-column-container .node-input-column-row-property input,
#node-input-column-container .node-input-column-row-property input:not(.red-ui-typedInput-input):not(.red-ui-typedInput),
#node-input-column-container .node-input-column-row-property div.red-ui-typedInput-container,
#node-input-column-container .node-input-column-row-property select {
flex-grow: 1;
width: 50%;
Expand Down Expand Up @@ -178,14 +179,26 @@
// key
const keyRow = $('<div />', { class: 'node-input-column-row-property' }).appendTo(options)
$('<label/>', {
text: `${RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.key')}:`
text: `${RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.value')}:`
}).appendTo(keyRow)
$('<input/>', {
const keyTypedInput = $('<input/>', {
class: 'node-input-column-key',
type: 'text',
placeholder: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.key'),
placeholder: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.value'),
value: col.key
}).appendTo(keyRow)
const keyType = ['str', 'key'].includes(col.keyType) ? col.keyType : 'key'
$('<input/>', {
class: 'node-input-column-keyType',
type: 'hidden',
value: keyType
}).appendTo(keyRow)
$(keyTypedInput).typedInput({
default: 'key',
value: col.key,
typeField: keyRow.find('.node-input-column-keyType'),
types: [{ value: 'key', label: RED._('@flowfuse/node-red-dashboard/ui-table:ui-table.label.key') }, 'str']
})

// label
const labelRow = $('<div />', { class: 'node-input-column-row-property' }).appendTo(options)
Expand Down Expand Up @@ -281,9 +294,11 @@
node.columns = []
columns.each(function (i) {
const column = $(this)
const keyField = column.find('.node-input-column-key')
const o = {
title: column.find('.node-input-column-label').val(),
key: column.find('.node-input-column-key').val(),
key: keyField.typedInput('value'),
keyType: keyField.typedInput('type') || 'key',
type: column.find('.node-input-column-type').find(':selected').val(),
width: column.find('.node-input-column-width').val(),
align: column.find('.node-input-column-align').find(':selected').val()
Expand Down
1 change: 1 addition & 0 deletions nodes/widgets/ui_table.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = function (RED) {
return {
title: col.title || col.label,
key: col.key,
keyType: col.keyType || 'key',
type: col.type,
width: col.width,
align: col.align
Expand Down
3 changes: 2 additions & 1 deletion ui/src/widgets/ui-table/UITable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
{{ col.title }}
</div>
<div class="nrdb-table-cell-align" :style="{'justify-content': isMobile ? 'end' : (col.align || 'start')}">
<UITableCell :row="index + 1" :item="item" :property="col.key" :type="col.type" @action-click="onCellClick" />
<UITableCell :row="index + 1" :item="item" :property="col.key" :propertyType="col.keyType" :type="col.type" @action-click="onCellClick" />
</div>
</td>
</tr>
Expand Down Expand Up @@ -97,6 +97,7 @@ export default {
return this.props.columns.map((col) => {
return {
key: col.key,
keyType: col.keyType || 'key',
title: col.label || col.title,
type: col.type,
align: col.align,
Expand Down
10 changes: 9 additions & 1 deletion ui/src/widgets/ui-table/UITableCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,21 @@ export default {
property: {
type: String,
required: true
},
propertyType: {
type: String,
default: 'key'
}
},
emits: ['update:modelValue', 'action-click'],
computed: {
value: {
get () {
// get nested property from item
// if this is a string property, just return the string
if (this.propertyType === 'str') {
return this.property ?? ''
}
// default to getting property from item by key
const keys = this.property.split('.')
const value = keys.reduce((val, key) => {
return val?.[key] ?? null
Expand Down

0 comments on commit 0b233e0

Please sign in to comment.