Skip to content

Commit

Permalink
feat: Add table component to viewer (#920)
Browse files Browse the repository at this point in the history
* feat: Add table component to viewer

* fix: Fix default rowCount

* feat: Add generic data on editor view

* fix: Refactor form field table styles

* test: Add tests

* fix: Turn data source into FEEL only

* chore: Remove unnecessary new line

* chore: Remove FEEL check on dataSource

* chore: Sort by asc first

* chore: Remove unnecessary label check

* chore: Use const instead of let

* fix: Create EditorTable

* chore: Fix formatting

* chore: Make label id optional

* fix: Add row gap
  • Loading branch information
vsgoulart authored Dec 6, 2023
1 parent 686957a commit 3b114f2
Show file tree
Hide file tree
Showing 13 changed files with 1,026 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';

import { get } from 'min-dash';

export class TableDataSourceBehavior extends CommandInterceptor {
constructor(eventBus) {
super(eventBus);

this.preExecute('formField.add', function(context) {

const { formField } = context;

if (get(formField, [ 'type' ]) !== 'table') {
return;
}

context.formField = {
...formField,
dataSource: `=${formField.id}`
};
}, true);
}
}

TableDataSourceBehavior.$inject = [ 'eventBus' ];
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PathBehavior from './PathBehavior';
import ValidateBehavior from './ValidateBehavior';
import ValuesSourceBehavior from './ValuesSourceBehavior';
import { ColumnsSourceBehavior } from './ColumnsSourceBehavior';
import { TableDataSourceBehavior } from './TableDataSourceBehavior';

export default {
__init__: [
Expand All @@ -12,12 +13,14 @@ export default {
'pathBehavior',
'validateBehavior',
'valuesSourceBehavior',
'columnsSourceBehavior'
'columnsSourceBehavior',
'tableDataSourceBehavior'
],
idBehavior: [ 'type', IdBehavior ],
keyBehavior: [ 'type', KeyBehavior ],
pathBehavior: [ 'type', PathBehavior ],
validateBehavior: [ 'type', ValidateBehavior ],
valuesSourceBehavior: [ 'type', ValuesSourceBehavior ],
columnsSourceBehavior: [ 'type', ColumnsSourceBehavior ]
columnsSourceBehavior: [ 'type', ColumnsSourceBehavior ],
tableDataSourceBehavior: [ 'type', TableDataSourceBehavior ]
};
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function Source(props) {
debounce,
description: 'Specify the source from which to populate the table',
element: field,
feel: 'optional',
feel: 'required',
getValue,
id,
label: 'Data source',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Label, Table } from '@bpmn-io/form-js-viewer';
import { editorFormFieldClasses } from '../Util';
import classNames from 'classnames';

/**
* @param {import('@bpmn-io/form-js-viewer/src/render/components/form-fields/Table').Props} props
* @returns {import("preact").JSX.Element}
*/
export default function EditorTable(props) {
const { columnsExpression, columns, id, label } = props.field;
const shouldUseMockColumns =
(typeof columnsExpression === 'string' && columnsExpression.length > 0) ||
(Array.isArray(columns) && columns.length === 0);
const editorColumns = shouldUseMockColumns
? [
{ key: '1', label: 'Column 1' },
{ key: '2', label: 'Column 2' },
{ key: '3', label: 'Column 3' }
]
: columns;
const prefixId = `fjs-form-${id}`;

return (
<div class={ editorFormFieldClasses('table', { disabled: true }) }>
<Label id={ prefixId } label={ label } />
<div class="fjs-table-middle-container">
<div class="fjs-table-inner-container">
<table class={ classNames('fjs-table', 'fjs-disabled') } id={ prefixId }>
<thead class="fjs-table-head">
<tr class="fjs-table-tr">
{editorColumns.map(({ key, label }) => (
<th key={ key } class="fjs-table-th">
{label}
</th>
))}
</tr>
</thead>
<tbody class="fjs-table-body">
<tr class="fjs-table-tr">
{editorColumns.map(({ key }) => (
<td class="fjs-table-td" key={ key }>
Content
</td>
))}
</tr>
</tbody>
</table>
</div>
</div>
</div>
);
}

EditorTable.config = Table.config;
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import EditorIFrame from './EditorIFrame';
import EditorText from './EditorText';
import EditorTable from './EditorTable';

export const editorFormFields = [
EditorIFrame,
EditorText
EditorText,
EditorTable
];
110 changes: 106 additions & 4 deletions packages/form-js-viewer/assets/form-js-base.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
--color-grey-225-10-93: hsl(225, 10%, 93%);
--color-grey-225-10-95: hsl(225, 10%, 95%);
--color-grey-225-10-97: hsl(225, 10%, 97%);
--color-grey-0-0-88: hsl(0, 0%, 88%);

--color-blue-219-100-53: hsl(219, 99%, 53%);
--color-blue-219-100-53-05: hsla(219, 99%, 53%, 0.5);
Expand Down Expand Up @@ -52,10 +53,9 @@
--color-background-inverted: var(--cds-background-inverse, var(--color-grey-225-10-90));
--color-background-inverted-hover: var(--cds-background-inverse-hover, var(--color-grey-225-10-93));
--color-background-active: var(--cds-background-active, var(--color-grey-225-10-75));
--color-layer: var(
--cds-layer,
var(--cds-layer-01, var(--color-white))
);
--color-layer: var(--cds-layer,
var(--cds-layer-01, var(--color-white)));
--color-layer-accent: var(--cds-layer-accent, var(--color-grey-0-0-88));

--color-icon-base: var(--cds-icon-primary, var(--color-black));
--color-icon-inverted: var(--cds-icon-inverse, var(--color-black));
Expand Down Expand Up @@ -989,6 +989,108 @@
overflow: hidden;
}

.fjs-container .fjs-form-field-table {
display: flex;
flex-direction: column;
row-gap: 4px;
}

.fjs-container .fjs-table-middle-container {
display: flex;
flex-direction: column;
overflow-x: hidden;
border: 1px solid var(--color-borders-group);
border-radius: 3px;
}

.fjs-container .fjs-table-middle-container.fjs-table-empty {
border: none;
color: var(--color-text-disabled);
padding-left: 16px;
}

.fjs-container .fjs-table-inner-container {
display: flex;
flex-direction: column;
overflow-x: auto;
}

.fjs-container .fjs-table {
overflow-y: auto;
border-collapse: collapse;
}

.fjs-container .fjs-table-head {
background-color: var(--color-layer-accent);
}

.fjs-container .fjs-table-th {
min-width: 120px;
cursor: pointer;
}

.fjs-container .fjs-table-th-label {
user-select: none;
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
}

.fjs-container .fjs-table-th:focus {
outline: var(--outline-definition);
outline-offset: -1px;
}

.fjs-container .fjs-table-th,
.fjs-container .fjs-table-td {
text-align: left;
height: 32px;
padding: 0 16px;
}

.fjs-container .fjs-table-body .fjs-table-tr:not(:last-child) {
border-bottom: 1px solid var(--color-borders-group);
}

.fjs-container .fjs-table-nav {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
border-top: 1px solid var(--color-borders-group);
}

.fjs-container .fjs-table-nav-button {
border: unset;
background: unset;
width: 32px;
height: 32px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border-left: 1px solid var(--color-borders-group);
}

.fjs-container .fjs-table-nav-button:first-of-type {
margin-left: 16px;
}

.fjs-container .fjs-table-nav-button:focus {
outline: var(--outline-definition);
outline-offset: -1px;
}

.fjs-container .fjs-table-nav-button svg {
width: 16px;
}

.fjs-container .fjs-table-sort-icon-asc,
.fjs-container .fjs-table-sort-icon-desc {
width: 16px;
}

/**
* Flatpickr style adjustments
*/
Expand Down
13 changes: 13 additions & 0 deletions packages/form-js-viewer/src/render/components/Label.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ import classNames from 'classnames';

import { useSingleLineTemplateEvaluation } from '../hooks';


/**
* @typedef Props
* @property {string} [id]
* @property {string|undefined} label
* @property {string} [class]
* @property {boolean} [collapseOnEmpty]
* @property {boolean} [required]
* @property {import("preact").VNode} [children]
*
* @param {Props} props
* @returns {import("preact").JSX.Element}
*/
export default function Label(props) {
const {
id,
Expand Down
Loading

0 comments on commit 3b114f2

Please sign in to comment.