Skip to content

Commit c9f4d7b

Browse files
authored
0.16.0. (#87)
1 parent ca2b494 commit c9f4d7b

22 files changed

+290
-90
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.16.0
2+
3+
This version fixes the bug with search in the toolbox. The search now includes custom labels provided by the `labelProvider` callback.
4+
5+
Additionally, this version adds the `descriptionProvider` to the configuration of the toolbox. The description is visible when you put a mouse cursor on a step in the toolbox for a while.
6+
17
## 0.15.4
28

39
This version adds rounding configuration to the `designer-theme.scss` file.

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ Add the below code to your head section in HTML document.
9898
```html
9999
<head>
100100
...
101-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.15.4/css/designer.css" rel="stylesheet">
102-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.15.4/css/designer-light.css" rel="stylesheet">
103-
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.15.4/css/designer-dark.css" rel="stylesheet">
104-
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.15.4/dist/index.umd.js"></script>
101+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.16.0/css/designer.css" rel="stylesheet">
102+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.16.0/css/designer-light.css" rel="stylesheet">
103+
<link href="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.16.0/css/designer-dark.css" rel="stylesheet">
104+
<script src="https://cdn.jsdelivr.net/npm/sequential-workflow-designer@0.16.0/dist/index.umd.js"></script>
105105
```
106106

107107
Call the designer by:

angular/designer/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sequential-workflow-designer-angular",
33
"description": "Angular wrapper for Sequential Workflow Designer component.",
4-
"version": "0.15.4",
4+
"version": "0.16.0",
55
"author": {
66
"name": "NoCode JS",
77
"url": "https://nocode-js.com/"
@@ -15,7 +15,7 @@
1515
"peerDependencies": {
1616
"@angular/common": "12 - 16",
1717
"@angular/core": "12 - 16",
18-
"sequential-workflow-designer": "^0.15.4"
18+
"sequential-workflow-designer": "^0.16.0"
1919
},
2020
"dependencies": {
2121
"tslib": "^2.3.0"

demos/angular-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"@angular/platform-browser-dynamic": "^15.2.9",
2727
"@angular/router": "^15.2.9",
2828
"rxjs": "~7.8.0",
29-
"sequential-workflow-designer": "^0.15.4",
30-
"sequential-workflow-designer-angular": "^0.15.4",
29+
"sequential-workflow-designer": "^0.16.0",
30+
"sequential-workflow-designer-angular": "^0.16.0",
3131
"tslib": "^2.3.0",
3232
"zone.js": "~0.13.0"
3333
},

demos/angular-app/yarn.lock

+8-8
Original file line numberDiff line numberDiff line change
@@ -5956,17 +5956,17 @@ send@0.18.0:
59565956
range-parser "~1.2.1"
59575957
statuses "2.0.1"
59585958

5959-
sequential-workflow-designer-angular@^0.15.4:
5960-
version "0.15.4"
5961-
resolved "https://registry.yarnpkg.com/sequential-workflow-designer-angular/-/sequential-workflow-designer-angular-0.15.4.tgz#e6b666f93a278198ca69f1d759ee4351d706f322"
5962-
integrity sha512-veCBtClEo7uBRnP96seaklNkwK8MPb0OrOzusLBBMMP/4sQzqAPjrNa/rtemiWP5R1v2UlNt80dDRvAYS6ttjg==
5959+
sequential-workflow-designer-angular@^0.16.0:
5960+
version "0.16.0"
5961+
resolved "https://registry.yarnpkg.com/sequential-workflow-designer-angular/-/sequential-workflow-designer-angular-0.16.0.tgz#15008ef30015510f1b7ffc9de94ffc037fdb33e4"
5962+
integrity sha512-kK62yAqAXVDaXoFpWAdKHt74W8zHJJgb+FiU6k6ygM3ge4nz4NzyO2aN8+M5ossDIDH2p2kiZNElE0G9lNvUhg==
59635963
dependencies:
59645964
tslib "^2.3.0"
59655965

5966-
sequential-workflow-designer@^0.15.4:
5967-
version "0.15.4"
5968-
resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.15.4.tgz#13f69308ab2772f342a8b19b77f6232f810cc374"
5969-
integrity sha512-sLP6fxU6bdoqOAs7hN5Xz9ynJpbobG18nSPNLQW0pGtffgEfN+WMAv0TDV+CIQ/Fh+XJARnMRO+u+GgkQX3jBQ==
5966+
sequential-workflow-designer@^0.16.0:
5967+
version "0.16.0"
5968+
resolved "https://registry.yarnpkg.com/sequential-workflow-designer/-/sequential-workflow-designer-0.16.0.tgz#9771cdb00063e6da395df3d9bc5a280460cf087c"
5969+
integrity sha512-9xWdA3C7dQ/z2O61BNA+8QORFR5WGWT4vX7mTAk5HwTE4YcJ+GI4XTjx+5bE8k2E+PL/QmuvbY8rQBFoV9wXvw==
59705970
dependencies:
59715971
sequential-workflow-model "^0.2.0"
59725972

demos/react-app/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
"dependencies": {
77
"react": "^18.2.0",
88
"react-dom": "^18.2.0",
9-
"sequential-workflow-designer": "^0.15.4",
10-
"sequential-workflow-designer-react": "^0.15.4"
9+
"sequential-workflow-designer": "^0.16.0",
10+
"sequential-workflow-designer-react": "^0.16.0"
1111
},
1212
"devDependencies": {
1313
"@types/jest": "^29.2.5",

designer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "sequential-workflow-designer",
33
"description": "Customizable no-code component for building flow-based programming applications.",
4-
"version": "0.15.4",
4+
"version": "0.16.0",
55
"type": "module",
66
"main": "./lib/esm/index.js",
77
"types": "./lib/index.d.ts",

designer/sass/designer-theme.scss

+10
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,9 @@
353353
$stepType: '',
354354
$labelTextColor: #fff,
355355
$labelFillColor: #2411db,
356+
$labelStrokeColor: #2411db,
357+
$labelStrokeWidth: 0,
358+
$labelShadow: '',
356359
$inputStrokeWidth: 2,
357360
$inputStrokeColor: #000,
358361
$inputFillColor: #fff
@@ -363,6 +366,13 @@
363366
}
364367
& > .sqd-label > .sqd-label-rect {
365368
fill: $labelFillColor;
369+
stroke-width: $labelStrokeWidth;
370+
@if $labelStrokeWidth > 0 {
371+
stroke: $labelStrokeColor;
372+
}
373+
@if $labelShadow != '' {
374+
filter: drop-shadow($labelShadow);
375+
}
366376
}
367377
& > g > {
368378
@include _sqd-input(

designer/src/api/designer-api.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ControlBarApi } from './control-bar-api';
33
import { EditorApi } from './editor-api';
44
import { PathBarApi } from './path-bar-api';
55
import { ToolboxApi } from './toolbox-api';
6+
import { ToolboxDataProvider } from '../toolbox/toolbox-data-provider';
67
import { ViewportApi } from './viewport-api';
78
import { WorkspaceApi } from './workspace-api';
89

@@ -11,17 +12,11 @@ export class DesignerApi {
1112
const workspace = new WorkspaceApi(context.state, context.workspaceController);
1213
const viewportController = context.services.viewportController.create(workspace);
1314
const viewport = new ViewportApi(context.workspaceController, viewportController);
15+
const toolboxDataProvider = new ToolboxDataProvider(context.componentContext.iconProvider, context.configuration.toolbox);
1416

1517
return new DesignerApi(
1618
new ControlBarApi(context.state, context.historyController, context.definitionModifier, viewport),
17-
new ToolboxApi(
18-
context.state,
19-
context,
20-
context.behaviorController,
21-
context.componentContext.iconProvider,
22-
context.configuration.toolbox,
23-
context.configuration.uidGenerator
24-
),
19+
new ToolboxApi(context.state, context, context.behaviorController, toolboxDataProvider, context.configuration.uidGenerator),
2520
new EditorApi(context.state, context.definitionWalker, context.definitionModifier),
2621
workspace,
2722
viewport,

designer/src/api/toolbox-api.ts

+7-29
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
import { Step } from '../definition';
22
import { BehaviorController } from '../behaviors/behavior-controller';
33
import { ObjectCloner, SimpleEventListener, Uid, Vector } from '../core';
4-
import { StepDefinition, ToolboxConfiguration, ToolboxGroupConfiguration, UidGenerator } from '../designer-configuration';
4+
import { StepDefinition, UidGenerator } from '../designer-configuration';
55
import { DesignerState } from '../designer-state';
66
import { DragStepBehavior } from '../behaviors/drag-step-behavior';
77
import { DesignerContext } from '../designer-context';
8-
import { IconProvider } from '../core/icon-provider';
8+
import { ToolboxDataProvider, ToolboxGroupData } from '../toolbox/toolbox-data-provider';
99

1010
export class ToolboxApi {
1111
public constructor(
1212
private readonly state: DesignerState,
1313
private readonly designerContext: DesignerContext,
1414
private readonly behaviorController: BehaviorController,
15-
private readonly iconProvider: IconProvider,
16-
private readonly configuration: ToolboxConfiguration | false,
15+
private readonly toolboxDataProvider: ToolboxDataProvider,
1716
private readonly uidGenerator: UidGenerator | undefined
1817
) {}
1918

@@ -29,26 +28,12 @@ export class ToolboxApi {
2928
this.state.onIsToolboxCollapsedChanged.subscribe(listener);
3029
}
3130

32-
public tryGetIconUrl(step: StepDefinition): string | null {
33-
return this.iconProvider.getIconUrl(step);
31+
public getAllGroups(): ToolboxGroupData[] {
32+
return this.toolboxDataProvider.getAllGroups();
3433
}
3534

36-
public getLabel(step: StepDefinition): string {
37-
const labelProvider = this.getConfiguration().labelProvider;
38-
return labelProvider ? labelProvider(step) : step.name;
39-
}
40-
41-
public filterGroups(filter: string | undefined): ToolboxGroupConfiguration[] {
42-
return this.getConfiguration()
43-
.groups.map(group => {
44-
return {
45-
name: group.name,
46-
steps: group.steps.filter(s => {
47-
return filter ? s.name.toLowerCase().includes(filter) : true;
48-
})
49-
};
50-
})
51-
.filter(group => group.steps.length > 0);
35+
public applyFilter(allGroups: ToolboxGroupData[], filter: string | undefined): ToolboxGroupData[] {
36+
return this.toolboxDataProvider.applyFilter(allGroups, filter);
5237
}
5338

5439
/**
@@ -70,11 +55,4 @@ export class ToolboxApi {
7055
newStep.id = this.uidGenerator ? this.uidGenerator() : Uid.next();
7156
return newStep;
7257
}
73-
74-
private getConfiguration(): ToolboxConfiguration {
75-
if (!this.configuration) {
76-
throw new Error('Toolbox is disabled');
77-
}
78-
return this.configuration;
79-
}
8058
}

designer/src/designer-configuration.ts

+2
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,15 @@ export interface CustomActionHandlerContext {
112112

113113
export interface ToolboxConfiguration {
114114
labelProvider?: StepLabelProvider;
115+
descriptionProvider?: StepDescriptionProvider;
115116
isCollapsed?: boolean;
116117
groups: ToolboxGroupConfiguration[];
117118
}
118119

119120
export type StepDefinition = Omit<Step, 'id'>;
120121

121122
export type StepLabelProvider = (step: StepDefinition) => string;
123+
export type StepDescriptionProvider = (step: StepDefinition) => string;
122124

123125
export interface ToolboxGroupConfiguration {
124126
name: string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { ToolboxDataProvider } from './toolbox-data-provider';
2+
import { IconProvider } from '../core/icon-provider';
3+
import { StepDefinition } from '../designer-configuration';
4+
5+
describe('ToolboxDataProvider', () => {
6+
const iconProvider = new IconProvider({
7+
iconUrlProvider: (_, type) => `${type}.jpg`
8+
});
9+
10+
const sendEmailStep = {
11+
componentType: 'task',
12+
name: 'Send email',
13+
properties: {},
14+
type: 'sendEmail'
15+
};
16+
const writeFileStep = {
17+
componentType: 'task',
18+
name: 'Write file',
19+
properties: {},
20+
type: 'writeFile'
21+
};
22+
const groups = [
23+
{
24+
name: 'Foo',
25+
steps: [sendEmailStep, writeFileStep]
26+
}
27+
];
28+
29+
describe('getAllGroups()', () => {
30+
it('return empty array if configuration is false', () => {
31+
const dataProvider = new ToolboxDataProvider(iconProvider, false);
32+
33+
expect(dataProvider.getAllGroups()).toEqual([]);
34+
});
35+
36+
it('returns groups with correct labels and descriptions', () => {
37+
const dataProvider = new ToolboxDataProvider(iconProvider, {
38+
groups
39+
});
40+
41+
const data = dataProvider.getAllGroups();
42+
const group1 = data[0];
43+
44+
expect(group1.name).toEqual('Foo');
45+
expect(group1.items.length).toEqual(2);
46+
const g1i1 = group1.items[0];
47+
expect(g1i1.iconUrl).toEqual('sendEmail.jpg');
48+
expect(g1i1.label).toEqual('Send email');
49+
expect(g1i1.lowerCaseLabel).toEqual('send email');
50+
expect(g1i1.description).toEqual('Send email');
51+
expect(g1i1.step).toEqual(groups[0].steps[0]);
52+
});
53+
54+
it('returns groups with correct labels and descriptions when custom providers are provided', () => {
55+
const dataProvider = new ToolboxDataProvider(iconProvider, {
56+
groups,
57+
labelProvider: reverseStepName,
58+
descriptionProvider: step => `Description of ${step.name}`
59+
});
60+
61+
const data = dataProvider.getAllGroups();
62+
const group1 = data[0];
63+
64+
expect(group1.name).toEqual('Foo');
65+
expect(group1.items.length).toEqual(2);
66+
const g1i1 = group1.items[0];
67+
expect(g1i1.iconUrl).toEqual('sendEmail.jpg');
68+
expect(g1i1.label).toEqual('liame dneS');
69+
expect(g1i1.lowerCaseLabel).toEqual('liame dnes');
70+
expect(g1i1.description).toEqual('Description of Send email');
71+
expect(g1i1.step).toEqual(groups[0].steps[0]);
72+
});
73+
});
74+
75+
describe('applyFilter()', () => {
76+
it('filters by label', () => {
77+
const dataProvider = new ToolboxDataProvider(iconProvider, {
78+
groups
79+
});
80+
81+
const allGroups = dataProvider.getAllGroups();
82+
expect(allGroups[0].items.length).toBe(2);
83+
84+
const r1 = dataProvider.applyFilter(allGroups, 'not existing label');
85+
expect(r1.length).toBe(0);
86+
87+
const r2 = dataProvider.applyFilter(allGroups, 'liame');
88+
expect(r2.length).toBe(0);
89+
90+
const r3 = dataProvider.applyFilter(allGroups, 'fil');
91+
expect(r3[0].items.length).toBe(1);
92+
expect(r3[0].items[0].step).toBe(writeFileStep);
93+
94+
const r4 = dataProvider.applyFilter(allGroups, 'Send email');
95+
expect(r4[0].items.length).toBe(1);
96+
expect(r4[0].items[0].step).toBe(sendEmailStep);
97+
});
98+
99+
it('filters by custom label', () => {
100+
const dataProvider = new ToolboxDataProvider(iconProvider, {
101+
groups,
102+
labelProvider: reverseStepName
103+
});
104+
105+
const allGroups = dataProvider.getAllGroups();
106+
expect(allGroups[0].items.length).toBe(2);
107+
108+
const r1 = dataProvider.applyFilter(allGroups, 'not existing label');
109+
expect(r1.length).toBe(0);
110+
111+
const r2 = dataProvider.applyFilter(allGroups, 'liame');
112+
expect(r2[0].items.length).toBe(1);
113+
114+
const r3 = dataProvider.applyFilter(allGroups, 'ELIF');
115+
expect(r3[0].items.length).toBe(1);
116+
expect(r3[0].items[0].step).toBe(writeFileStep);
117+
118+
const r4 = dataProvider.applyFilter(allGroups, 'Send email');
119+
expect(r4.length).toBe(0);
120+
});
121+
});
122+
});
123+
124+
function reverseStepName(step: StepDefinition): string {
125+
return step.name.split('').reverse().join('');
126+
}

0 commit comments

Comments
 (0)