@gravitee/ui-components 3.28.8 → 3.29.0-debug-mode-add-menu-4aadeb7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/index.d.ts +1 -0
  3. package/src/index.js +1 -0
  4. package/src/index.js.map +1 -1
  5. package/src/lib/events.d.ts +4 -1
  6. package/src/lib/events.js +0 -1
  7. package/src/lib/events.js.map +1 -1
  8. package/src/organisms/gv-properties/gv-properties.d.ts +1 -1
  9. package/src/organisms/gv-properties/gv-properties.js +8 -5
  10. package/src/organisms/gv-properties/gv-properties.js.map +1 -1
  11. package/src/organisms/gv-resources/gv-resources.d.ts +2 -7
  12. package/src/organisms/gv-resources/gv-resources.js +9 -8
  13. package/src/organisms/gv-resources/gv-resources.js.map +1 -1
  14. package/src/organisms/gv-schema-form/gv-schema-form.d.ts +2 -2
  15. package/src/organisms/gv-schema-form/gv-schema-form.js +11 -6
  16. package/src/organisms/gv-schema-form/gv-schema-form.js.map +1 -1
  17. package/src/organisms/gv-schema-form/gv-schema-form.test.js +15 -0
  18. package/src/organisms/gv-schema-form/gv-schema-form.test.js.map +1 -1
  19. package/src/organisms/gv-schema-form-control/gv-schema-form-control.d.ts +1 -0
  20. package/src/organisms/gv-schema-form-control/gv-schema-form-control.js +9 -1
  21. package/src/organisms/gv-schema-form-control/gv-schema-form-control.js.map +1 -1
  22. package/src/policy-studio/gv-design/gv-design.d.ts +367 -0
  23. package/src/policy-studio/gv-design/gv-design.js +1494 -0
  24. package/src/policy-studio/gv-design/gv-design.js.map +1 -0
  25. package/src/policy-studio/gv-design/gv-design.stories.d.ts +203 -0
  26. package/src/policy-studio/gv-design/gv-design.stories.js +233 -0
  27. package/src/policy-studio/gv-design/gv-design.stories.js.map +1 -0
  28. package/src/policy-studio/gv-design/gv-design.test.d.ts +1 -0
  29. package/src/policy-studio/gv-design/gv-design.test.js +333 -0
  30. package/src/policy-studio/gv-design/gv-design.test.js.map +1 -0
  31. package/src/policy-studio/gv-design/index.d.ts +1 -0
  32. package/src/policy-studio/gv-design/index.js +17 -0
  33. package/src/policy-studio/gv-design/index.js.map +1 -0
  34. package/src/policy-studio/gv-policy-studio/gv-policy-studio.js +3 -0
  35. package/src/policy-studio/gv-policy-studio/gv-policy-studio.js.map +1 -1
  36. package/wc/gv-design.d.ts +1 -0
  37. package/wc/gv-design.js +2 -0
  38. package/wc/gv-design.js.map +1 -0
@@ -0,0 +1,1494 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ /*
22
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
23
+ *
24
+ * Licensed under the Apache License, Version 2.0 (the "License");
25
+ * you may not use this file except in compliance with the License.
26
+ * You may obtain a copy of the License at
27
+ *
28
+ * http://www.apache.org/licenses/LICENSE-2.0
29
+ *
30
+ * Unless required by applicable law or agreed to in writing, software
31
+ * distributed under the License is distributed on an "AS IS" BASIS,
32
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33
+ * See the License for the specific language governing permissions and
34
+ * limitations under the License.
35
+ */
36
+ import { css, html, LitElement } from 'lit';
37
+ import { methods } from '../../lib/studio';
38
+ import { dispatchCustomEvent } from '../../lib/events';
39
+ import { i18n } from '../../lib/i18n';
40
+ import '../../atoms/gv-button';
41
+ import '../../atoms/gv-icon';
42
+ import '../../molecules/gv-option';
43
+ import '../../organisms/gv-documentation';
44
+ import '../../organisms/gv-resizable-views';
45
+ import '../../organisms/gv-schema-form';
46
+ import '../../molecules/gv-row';
47
+ import '../gv-flow';
48
+ import '../gv-flow-step';
49
+ import '../gv-policy-studio-menu';
50
+ import { empty } from '../../styles/empty';
51
+ import { cache } from 'lit/directives/cache.js';
52
+ import { deepClone, deepEqual } from '../../lib/utils';
53
+ import { KeyboardElement, KEYS } from '../../mixins/keyboard-element';
54
+ const FLOW_STEP_FORM_ID = 'flow-step-form';
55
+ /**
56
+ * Design component
57
+ *
58
+ * ⚠️ This component is based on `asciidoctor`, `highlight.js` and `asciidoctor-highlight.js`.
59
+ * To use this component in your project be sure the dependencies are installed or
60
+ * install them with: `npm install asciidoctor highlight.js asciidoctor-highlight.js --save`
61
+ *
62
+ * @fires gv-design:select-policy - Select policy event
63
+ * @fires gv-design:change - Design change event
64
+ *
65
+ * @attr {Array} policies - Policies available
66
+ * @attr {Array} services - Services available
67
+ * @attr {Array} resourceTypes - Resources types available
68
+ * @attr {Object} definition - The definition of flows
69
+ * @attr {Object} documentation - The documentation to display
70
+ * @attr {Object} flowSchema - The flow form configuration to display in gv-schema-form component
71
+ * @attr {Boolean} isDirty - true if component is dirty
72
+ * @attr {Array} selectedFlowsId - The selected flows id
73
+ * @attr {Boolean} sortable - true if flows are sortable
74
+ * @attr {Boolean} readonly - true if readonly
75
+ * @attr {Boolean} readonly-plans - true if plans' flows can't be modified
76
+ * @attr {Boolean} can-add - true if user can add flow
77
+ * @attr {String} flowsTitle - flows menu title
78
+ * @attr {Boolean} has-policy-filter - true if policies have onRequest/onResponse properties
79
+ * @attr {Boolean} has-conditional-steps - true if steps can be conditioned
80
+ */
81
+ export class GvDesign extends KeyboardElement(LitElement) {
82
+ static get properties() {
83
+ return {
84
+ policies: { type: Array },
85
+ services: { type: Object },
86
+ resourceTypes: { type: Array, attribute: 'resource-types' },
87
+ definition: { type: Object },
88
+ _definition: { type: Object, attribute: false },
89
+ documentation: { type: Object },
90
+ flowSchema: { type: Object, attribute: 'flow-schema' },
91
+ isDirty: { type: Boolean, attribute: 'dirty', reflect: true },
92
+ _dragPolicy: { type: Object, attribute: false },
93
+ _dropPolicy: { type: Object, attribute: false },
94
+ selectedFlowsId: { type: Array, attribute: 'selected-flows-id' },
95
+ _selectedFlowsId: { type: Array, attribute: false },
96
+ _currentPolicyId: { type: String, attribute: false },
97
+ _searchPolicyQuery: { type: String, attribute: false },
98
+ _searchFlowQuery: { type: String, attribute: false },
99
+ _flowStepSchema: { type: Object, attribute: false },
100
+ _currentFlowStep: { type: Object, attribute: false },
101
+ _policyFilter: { type: Array, attribute: false },
102
+ _flowFilter: { type: Array, attribute: false },
103
+ _currentAskConfirmation: { type: Boolean, attribute: false },
104
+ hasPolicyFilter: { type: Boolean, attribute: 'has-policy-filter' },
105
+ flowsTitle: { type: String, attribute: 'flows-title' },
106
+ sortable: { type: Boolean },
107
+ canAdd: { type: Boolean, attribute: 'can-add' },
108
+ readonly: { type: Boolean },
109
+ readonlyPlans: { type: Boolean, attribute: 'readonly-plans' },
110
+ hasConditionalSteps: { type: Boolean, attribute: 'has-conditional-steps' },
111
+ };
112
+ }
113
+ static get styles() {
114
+ return [
115
+ empty,
116
+ methods,
117
+ // language=CSS
118
+ css `
119
+ :host {
120
+ box-sizing: border-box;
121
+ --height: var(--gv-policy-studio--h, calc(100vh - 32px));
122
+ height: var(--height);
123
+ --height-in-tabs: calc(var(--height) - 25px);
124
+ }
125
+
126
+ .box {
127
+ height: var(--height);
128
+ display: flex;
129
+ }
130
+
131
+ .design {
132
+ display: flex;
133
+ width: 100%;
134
+ }
135
+
136
+ gv-resizable-views {
137
+ width: 100%;
138
+ }
139
+
140
+ .editable-name {
141
+ padding: 0.5rem 1rem;
142
+ font-size: 16px;
143
+ }
144
+
145
+ .editable-name span {
146
+ color: #bfbfbf;
147
+ font-size: 12px;
148
+ }
149
+
150
+ .form__control {
151
+ margin: 0.5rem;
152
+ }
153
+
154
+ gv-input {
155
+ width: 100%;
156
+ }
157
+
158
+ .flow-name {
159
+ display: flex;
160
+ align-items: center;
161
+ }
162
+
163
+ .flow-name.dirty {
164
+ font-style: italic;
165
+ opacity: 0.8;
166
+ }
167
+
168
+ .flow-name gv-icon {
169
+ --gv-icon--s: 24px;
170
+ margin-right: 0.2rem;
171
+ }
172
+
173
+ .flow-path {
174
+ margin-left: 0.2rem;
175
+ }
176
+
177
+ .title_methods {
178
+ margin-left: 0.5rem;
179
+ }
180
+
181
+ .two-cols {
182
+ display: flex;
183
+ width: 100%;
184
+ height: 100%;
185
+ }
186
+
187
+ .two-cols > * {
188
+ flex: 1;
189
+ }
190
+
191
+ .left-menu {
192
+ border-left: 1px solid #d9d9d9;
193
+ height: var(--height-in-tabs);
194
+ }
195
+
196
+ .right-menu {
197
+ border-right: 1px solid #d9d9d9;
198
+ height: var(--height-in-tabs);
199
+ }
200
+
201
+ .two-cols > *:first-child {
202
+ border-right: 1px solid #d9d9d9;
203
+ }
204
+
205
+ .flow-step__container {
206
+ overflow: hidden;
207
+ position: relative;
208
+ overflow: hidden;
209
+ height: 99%;
210
+ }
211
+
212
+ .flow-step__form {
213
+ padding: 0 0.5rem;
214
+ overflow: auto;
215
+ }
216
+
217
+ .flow-step__form-title {
218
+ text-transform: uppercase;
219
+ letter-spacing: 0.2rem;
220
+ }
221
+
222
+ gv-resizable-views {
223
+ height: var(--height-in-tabs);
224
+ }
225
+
226
+ .flow-settings gv-schema-form {
227
+ flex: 1;
228
+ padding: 0.5rem;
229
+ }
230
+
231
+ .search {
232
+ display: flex;
233
+ justify-content: stretch;
234
+ }
235
+
236
+ gv-input {
237
+ margin: 0.2rem 0;
238
+ width: 100%;
239
+ }
240
+
241
+ .header-actions,
242
+ .search-policies {
243
+ display: flex;
244
+ flex-direction: column;
245
+ align-items: center;
246
+ margin: 0.5rem;
247
+ }
248
+
249
+ .footer-actions > gv-button.btn-large,
250
+ .footer-actions > gv-option {
251
+ width: 100%;
252
+ }
253
+
254
+ .footer-actions {
255
+ display: flex;
256
+ flex-direction: column;
257
+ align-items: center;
258
+ padding: 0.5rem 0;
259
+ margin: 0.5rem 15px;
260
+ border-top: 1px solid #bfbfbf;
261
+ }
262
+
263
+ .header-actions .title {
264
+ text-transform: uppercase;
265
+ text-align: center;
266
+ letter-spacing: 0.3rem;
267
+ color: #bfbfbf;
268
+ font-size: 18px;
269
+ white-space: nowrap;
270
+ overflow: hidden;
271
+ text-overflow: ellipsis;
272
+ width: 240px;
273
+ min-height: 25px;
274
+ }
275
+
276
+ .header-actions > *,
277
+ .search-policies > * {
278
+ margin-bottom: 1rem;
279
+ }
280
+ `,
281
+ ];
282
+ }
283
+ constructor() {
284
+ super();
285
+ this.isDirty = false;
286
+ this.policies = [];
287
+ this.resourceTypes = [];
288
+ this.selectedFlowsId = [];
289
+ this.flowsTitle = 'Flows';
290
+ this.sortable = false;
291
+ this.services = {};
292
+ this._definition = {
293
+ flows: [],
294
+ };
295
+ this._policyFilter = [];
296
+ this._flowFilter = [];
297
+ }
298
+ willUpdate(changedProperties) {
299
+ return __awaiter(this, void 0, void 0, function* () {
300
+ if (changedProperties.has('hasPolicyFilter') && this.hasPolicyFilter === true) {
301
+ this._policyFilterOptions = [
302
+ { id: 'onRequest', title: 'Request', icon: 'navigation:arrow-from-left' },
303
+ { id: 'onResponse', title: 'Response', icon: 'navigation:arrow-from-right' },
304
+ ];
305
+ }
306
+ });
307
+ }
308
+ get _flowFilterOptions() {
309
+ if (this.definedPlans.length > 0) {
310
+ return [
311
+ { id: 'api', title: 'Api', icon: 'shopping:box#3' },
312
+ { id: 'plan', title: 'Plans', icon: 'shopping:sale#2' },
313
+ ];
314
+ }
315
+ }
316
+ get keyboardTarget() {
317
+ return window;
318
+ }
319
+ onKeyboard(controller, event) {
320
+ if (this._currentAskConfirmation == null) {
321
+ if (this.isPressed(KEYS.Shift, KEYS.Alt, KEYS.Space)) {
322
+ const search = this.shadowRoot.querySelector('#search-policy');
323
+ if (search) {
324
+ search.focus();
325
+ event.preventDefault();
326
+ }
327
+ }
328
+ else if (this.isPressed(KEYS.Alt, KEYS.Space)) {
329
+ const search = this.shadowRoot.querySelector('#search-flow');
330
+ if (search) {
331
+ search.focus();
332
+ event.preventDefault();
333
+ }
334
+ }
335
+ }
336
+ }
337
+ set definition(definition) {
338
+ if (definition) {
339
+ definition.flows = definition.flows || [];
340
+ const flows = this._generateFlowsId(definition.flows);
341
+ const resources = this._generateId('resource-', definition.resources);
342
+ const plans = definition.plans == null
343
+ ? []
344
+ : definition.plans.map((plan) => {
345
+ return Object.assign(Object.assign({}, plan), { flows: this._generatePlanFlowsId(plan) });
346
+ });
347
+ this._initialDefinition = Object.assign(Object.assign({}, definition), { flows, resources, plans });
348
+ this._definition = deepClone(this._initialDefinition);
349
+ this.isDirty = false;
350
+ this._selectFirstFlow();
351
+ }
352
+ }
353
+ get definition() {
354
+ return this._definition;
355
+ }
356
+ set selectedFlowsId(selectedFlowsId) {
357
+ if (selectedFlowsId != null && Array.isArray(selectedFlowsId)) {
358
+ this._selectedFlowsId = selectedFlowsId.filter((id) => this._findFlowById(id) != null);
359
+ if (selectedFlowsId.length !== this._selectedFlowsId.length) {
360
+ this._selectFirstFlow(true);
361
+ }
362
+ }
363
+ }
364
+ get selectedFlowsId() {
365
+ return this._selectedFlowsId.filter((id) => this._findFlowById(id) != null);
366
+ }
367
+ _updateSelectedFlows(selectedFlowsId) {
368
+ this.selectedFlowsId = selectedFlowsId;
369
+ dispatchCustomEvent(this, 'select-flows', { flows: this.selectedFlowsId });
370
+ }
371
+ _selectFirstFlow(dispatch = false) {
372
+ if (this.selectedFlowsId.length === 0) {
373
+ let candidate = null;
374
+ if (this.definedFlows.length > 0 && this.definedFlows[0]._id != null) {
375
+ candidate = this.definedFlows[0];
376
+ }
377
+ else if (this.definedPlans.length > 0) {
378
+ const plan = this.definedPlans.find((p) => p.flows != null && p.flows.length > 0 && p.flows[0]._id != null);
379
+ if (plan) {
380
+ candidate = plan.flows[0];
381
+ }
382
+ }
383
+ if (candidate != null) {
384
+ if (dispatch) {
385
+ this._updateSelectedFlows([candidate._id]);
386
+ }
387
+ else {
388
+ this.selectedFlowsId = [candidate._id];
389
+ }
390
+ }
391
+ }
392
+ }
393
+ _getFlowElement(flowId) {
394
+ return this.shadowRoot.querySelector(`[id="${flowId}"]`);
395
+ }
396
+ _onDragEndPolicy() {
397
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((e) => e.onDragEnd());
398
+ }
399
+ _onDropPolicy({ detail }) {
400
+ return __awaiter(this, void 0, void 0, function* () {
401
+ try {
402
+ yield this._askToValidateForms();
403
+ const policy = detail.policy;
404
+ const targetFlow = this._findFlowById(detail.flowId);
405
+ let name = policy.name;
406
+ let description = '';
407
+ let condition = '';
408
+ let configuration = {};
409
+ let _id;
410
+ let _new = false;
411
+ if (detail.flowStep) {
412
+ _id = detail.flowStep._id;
413
+ name = detail.flowStep.name;
414
+ description = detail.flowStep.description || '';
415
+ condition = detail.flowStep.condition || '';
416
+ configuration = detail.flowStep.configuration;
417
+ }
418
+ else {
419
+ _id = this._generateFlowStepId(targetFlow._id, detail.flowKey, detail.position);
420
+ _new = true;
421
+ }
422
+ const flowStep = { _id, _new, name, policy: policy.id, description, condition, enabled: true, configuration };
423
+ const sourceFlow = detail.sourceFlowId != null ? this._findFlowById(detail.sourceFlowId) : targetFlow;
424
+ if (detail.sourcePosition != null) {
425
+ if (detail.sourceFlowKey && detail.sourceFlowKey !== detail.flowKey) {
426
+ sourceFlow[detail.sourceFlowKey].splice(detail.sourcePosition, 1);
427
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
428
+ if (this._currentFlowStep != null && this._currentFlowStep.step._id === _id) {
429
+ this._currentFlowStep.group = detail.flowKey;
430
+ // Special case for update schema after change request to response or inverse
431
+ const schema = this.buildSchema(this._currentFlowStep.policy);
432
+ yield this._setCurrentFlowStep(this._currentFlowStep, schema, true);
433
+ this._getFlowElement(targetFlow._id).requestUpdate();
434
+ }
435
+ }
436
+ else {
437
+ if (detail.position > detail.sourcePosition) {
438
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
439
+ sourceFlow[detail.flowKey].splice(detail.sourcePosition, 1);
440
+ }
441
+ else {
442
+ sourceFlow[detail.flowKey].splice(detail.sourcePosition, 1);
443
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
444
+ }
445
+ }
446
+ // Force Refresh source flow element when move to other flow
447
+ if (targetFlow._id !== sourceFlow._id) {
448
+ this._getFlowElement(targetFlow._id).requestUpdate();
449
+ }
450
+ }
451
+ else {
452
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
453
+ const currentFlowForm = this._getFlowStepForm();
454
+ if (currentFlowForm == null || currentFlowForm.dirty !== true) {
455
+ let step = targetFlow[detail.flowKey][detail.position];
456
+ if (step == null) {
457
+ // When confirm lose change after drop policy
458
+ step = targetFlow[detail.flowKey][detail.position - 1];
459
+ }
460
+ if (detail.cancelEdit !== true) {
461
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
462
+ yield this._editFlowStep({ step, policy, flow: targetFlow, group: detail.flowKey });
463
+ this.updateComplete.then(() => {
464
+ const flowElement = this._getFlowElement(targetFlow._id);
465
+ flowElement.selectedStepId = step._id;
466
+ flowElement.requestUpdate();
467
+ });
468
+ }));
469
+ }
470
+ }
471
+ }
472
+ targetFlow._dirty = true;
473
+ sourceFlow._dirty = true;
474
+ this.isDirty = true;
475
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((gvFlow) => gvFlow.removeCandidate());
476
+ setTimeout(() => {
477
+ this._dragPolicy = null;
478
+ this._dropPolicy = null;
479
+ const currentFlowForm = this._getFlowStepForm();
480
+ // If currentFlowForm exist, it's a simple drop to flow
481
+ // else it's a copy or duplicate between 2 flows
482
+ if (currentFlowForm != null) {
483
+ currentFlowForm.validate();
484
+ // the submit action will add form values to definition and dispatch change event
485
+ currentFlowForm.submit();
486
+ }
487
+ else {
488
+ this.dispatchChange();
489
+ }
490
+ }, 0);
491
+ }
492
+ catch (e) {
493
+ this._currentAskConfirmation = null;
494
+ }
495
+ });
496
+ }
497
+ _onDeletePolicy({ detail }) {
498
+ const targetFlow = this._findFlowById(detail.flowId);
499
+ targetFlow[detail.flowKey].splice(detail.position, 1);
500
+ targetFlow._dirty = true;
501
+ this.isDirty = true;
502
+ if (detail.target.editing) {
503
+ this._closeFlowStepForm(true);
504
+ }
505
+ this._getFlowElement(detail.flowId).requestUpdate();
506
+ this.dispatchChange();
507
+ }
508
+ buildSchema({ schema }) {
509
+ const commonDescription = {
510
+ title: 'Description',
511
+ description: 'Description of flow step',
512
+ type: 'string',
513
+ };
514
+ const commonCondition = {
515
+ title: 'Condition',
516
+ description: 'Condition the execution of the flow step (support EL)',
517
+ type: 'string',
518
+ 'x-schema-form': {
519
+ 'expression-language': true,
520
+ },
521
+ };
522
+ if (schema) {
523
+ const jsonSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
524
+ const properties = Object.assign(Object.assign({ commonDescription }, (this.hasConditionalSteps ? { commonCondition } : {})), jsonSchema.properties);
525
+ return Object.assign(Object.assign({}, jsonSchema), { properties });
526
+ }
527
+ return { properties: Object.assign({ commonDescription }, (this.hasConditionalSteps ? { commonCondition } : {})) };
528
+ }
529
+ _editFlowStep({ step, flow, policy, group }) {
530
+ return __awaiter(this, void 0, void 0, function* () {
531
+ if (step) {
532
+ this._currentPolicyId = policy.id;
533
+ const currentFlowStep = { flow, step, policy, group };
534
+ const schema = this.buildSchema(policy);
535
+ try {
536
+ yield this._setCurrentFlowStep(currentFlowStep, schema);
537
+ this._updateSelectedFlows([flow._id]);
538
+ this._splitMainViews();
539
+ if (localStorage.getItem('gv-policy-studio:keep-documentation-close') == null) {
540
+ this._onOpenDocumentation();
541
+ }
542
+ }
543
+ catch (e) {
544
+ this._currentAskConfirmation = null;
545
+ }
546
+ }
547
+ else {
548
+ yield this._closeFlowStepForm();
549
+ this._maximizeTopView();
550
+ }
551
+ });
552
+ }
553
+ _onEditFlowStep({ detail: { step, flow, policy, group } }) {
554
+ return __awaiter(this, void 0, void 0, function* () {
555
+ return this._editFlowStep({ step, flow, policy, group });
556
+ });
557
+ }
558
+ _getResizableViews() {
559
+ return this.shadowRoot.querySelector('gv-resizable-views');
560
+ }
561
+ _maximizeTopView() {
562
+ if (this.selectedFlowsId.length <= 1) {
563
+ this._getResizableViews().maximizeTop();
564
+ }
565
+ }
566
+ _maximizeBottomView() {
567
+ this._getResizableViews().maximizeBottom();
568
+ }
569
+ _splitMainViews() {
570
+ this._getResizableViews().split();
571
+ }
572
+ _onChangeFlowStepState({ detail }) {
573
+ const targetFlow = this._findFlowById(detail.flowId);
574
+ const step = targetFlow[detail.flowKey][detail.position];
575
+ step.enabled = detail.enabled;
576
+ targetFlow._dirty = true;
577
+ this.isDirty = true;
578
+ }
579
+ dispatchChange() {
580
+ const invalidForms = [...this.shadowRoot.querySelectorAll('gv-schema-form')].filter((form) => {
581
+ form.validate();
582
+ return !form.isValid();
583
+ });
584
+ const errors = invalidForms.length;
585
+ const definition = errors === 0 ? this._buildDefinitionToSend(this._buildDefinitionToSave()) : null;
586
+ dispatchCustomEvent(this, 'change', {
587
+ isDirty: this.isDirty,
588
+ errors,
589
+ definition,
590
+ });
591
+ }
592
+ _onCloseFlowStepForm() {
593
+ return __awaiter(this, void 0, void 0, function* () {
594
+ try {
595
+ yield this._closeFlowStepForm();
596
+ }
597
+ catch (err) {
598
+ this._currentAskConfirmation = null;
599
+ }
600
+ });
601
+ }
602
+ _closeFlowStepForm(force = false) {
603
+ return __awaiter(this, void 0, void 0, function* () {
604
+ yield this._setCurrentFlowStep(null, null, force);
605
+ });
606
+ }
607
+ _askToValidateForms() {
608
+ return __awaiter(this, void 0, void 0, function* () {
609
+ if (this._currentAskConfirmation == null) {
610
+ this._currentAskConfirmation = true;
611
+ return Promise.all(this._submitOrConfirmForms()).then((forms) => {
612
+ if (forms.filter((r) => r != null).length > 0) {
613
+ this._definition = this._buildDefinitionToSave();
614
+ this.getChildren().forEach((e) => e.requestUpdate());
615
+ // Refresh if lose changes lost current step selection
616
+ return this._checkCurrentFlowStep().then(() => {
617
+ this.getChildren().forEach((e) => e.requestUpdate());
618
+ return this.updateComplete.then(() => {
619
+ this._currentAskConfirmation = null;
620
+ return forms;
621
+ });
622
+ });
623
+ }
624
+ else {
625
+ this._currentAskConfirmation = null;
626
+ return forms;
627
+ }
628
+ });
629
+ }
630
+ throw new Error('ask already waiting');
631
+ });
632
+ }
633
+ _setCurrentFlowStep(currentFlowStep, flowStepSchema, force = false) {
634
+ return __awaiter(this, void 0, void 0, function* () {
635
+ if (!force) {
636
+ yield this._askToValidateForms();
637
+ }
638
+ const schema = deepClone(flowStepSchema);
639
+ if (currentFlowStep != null) {
640
+ const configuration = typeof currentFlowStep.step.configuration === 'string'
641
+ ? JSON.parse(currentFlowStep.step.configuration)
642
+ : currentFlowStep.step.configuration;
643
+ const step = Object.assign(Object.assign({}, currentFlowStep.step), { configuration });
644
+ const _initialValues = Object.assign(Object.assign({}, step.configuration), { commonDescription: step.description, commonCondition: step.condition });
645
+ this._currentFlowStep = Object.assign(Object.assign({}, currentFlowStep), { step, _initialValues });
646
+ if (flowStepSchema && flowStepSchema.properties.scope) {
647
+ const _enum = schema.properties.scope.enum;
648
+ if (_enum.find((s) => ['REQUEST', 'REQUEST_CONTENT', 'RESPONSE', 'RESPONSE_CONTENT'].includes(s)) != null) {
649
+ const filtered = this._currentFlowStep.group === 'pre' ? ['REQUEST', 'REQUEST_CONTENT'] : ['RESPONSE', 'RESPONSE_CONTENT'];
650
+ schema.properties.scope.enum = _enum.filter((s) => filtered.includes(s));
651
+ const scope = this._currentFlowStep.step.configuration.scope;
652
+ if (scope == null || !schema.properties.scope.enum.includes(scope)) {
653
+ schema.properties.scope.default = schema.properties.scope.enum[0];
654
+ this._currentFlowStep.step.configuration.scope = schema.properties.scope.enum[0];
655
+ this._currentFlowStep._initialValues.scope = schema.properties.scope.enum[0];
656
+ if (this._currentFlowStep._values) {
657
+ this._currentFlowStep._values.scope = schema.properties.scope.enum[0];
658
+ }
659
+ }
660
+ }
661
+ }
662
+ }
663
+ else {
664
+ this._currentFlowStep = null;
665
+ }
666
+ this._flowStepSchema = schema;
667
+ });
668
+ }
669
+ _refresh(closeStepForm = true) {
670
+ if (closeStepForm) {
671
+ this._closeFlowStepForm(true);
672
+ }
673
+ this._definition = deepClone(this._definition);
674
+ }
675
+ _onSelectFlows({ detail }) {
676
+ return __awaiter(this, void 0, void 0, function* () {
677
+ try {
678
+ yield this._closeFlowStepForm();
679
+ this._onCloseDocumentation();
680
+ this._updateSelectedFlows(detail.flows);
681
+ this._splitMainViews();
682
+ }
683
+ catch (e) {
684
+ this._currentAskConfirmation = null;
685
+ }
686
+ });
687
+ }
688
+ _onOpenDocumentationFromMenu({ detail: { policy } }) {
689
+ return __awaiter(this, void 0, void 0, function* () {
690
+ try {
691
+ if (this.documentation == null || this.documentation.id !== policy.id) {
692
+ yield this._closeFlowStepForm();
693
+ this._currentPolicyId = policy.id;
694
+ if (this.getSelectedFlow()) {
695
+ this._splitMainViews();
696
+ }
697
+ else {
698
+ this._maximizeBottomView();
699
+ }
700
+ dispatchCustomEvent(this, 'fetch-documentation', { policy });
701
+ }
702
+ }
703
+ catch (e) { }
704
+ });
705
+ }
706
+ _fetchDocumentation(policy) {
707
+ if (this.documentation == null || this.documentation.id !== policy.id) {
708
+ dispatchCustomEvent(this, 'fetch-documentation', { policy });
709
+ }
710
+ }
711
+ _onOpenDocumentation() {
712
+ if (this._currentFlowStep && this._currentFlowStep.policy) {
713
+ this._fetchDocumentation(this._currentFlowStep.policy);
714
+ }
715
+ }
716
+ _onOpenDocumentationFromForm() {
717
+ localStorage.removeItem('gv-policy-studio:keep-documentation-close');
718
+ this._onOpenDocumentation();
719
+ }
720
+ _findFlowCollection(flowId) {
721
+ const plan = this.definedPlans.find((p) => p.flows.find((flow) => flow._id === flowId) != null);
722
+ return { plan, flows: plan != null ? plan.flows : this.definedFlows };
723
+ }
724
+ _findFlowById(flowId) {
725
+ let flow = this.definedFlows.find((f) => f._id === flowId);
726
+ if (flow == null) {
727
+ const plansFlows = this.definedPlans.map((p) => p.flows).reduce((acc, val) => acc.concat(val), []);
728
+ flow = plansFlows.find((f) => f._id === flowId);
729
+ }
730
+ return flow;
731
+ }
732
+ getSelectedFlow(index = 0) {
733
+ const selectedFlowId = this.selectedFlowsId[index];
734
+ return this._findFlowById(selectedFlowId);
735
+ }
736
+ _onTargetPolicy({ detail }) {
737
+ if (this._currentAskConfirmation == null) {
738
+ this._dragPolicy = detail;
739
+ }
740
+ }
741
+ _onChangeFlowStep({ detail }) {
742
+ this._currentFlowStep._values = detail.values;
743
+ }
744
+ _writeFlowStep(values) {
745
+ const { commonDescription, commonCondition } = values, configuration = __rest(values, ["commonDescription", "commonCondition"]);
746
+ if (this._currentFlowStep.step._new ||
747
+ this._currentFlowStep.step.description !== commonDescription ||
748
+ this._currentFlowStep.step.condition !== commonCondition ||
749
+ !deepEqual(this._currentFlowStep.step.configuration, configuration)) {
750
+ const flow = this._findFlowById(this._currentFlowStep.flow._id);
751
+ const position = flow[this._currentFlowStep.group].findIndex((step) => step._id === this._currentFlowStep.step._id);
752
+ flow[this._currentFlowStep.group][position].description = commonDescription;
753
+ flow[this._currentFlowStep.group][position].condition = commonCondition;
754
+ flow[this._currentFlowStep.group][position].configuration = deepClone(configuration);
755
+ delete flow[this._currentFlowStep.group][position]._new;
756
+ flow[this._currentFlowStep.group][position]._dirty = true;
757
+ flow._dirty = true;
758
+ this.isDirty = true;
759
+ this._currentFlowStep.flow = flow;
760
+ this._currentFlowStep.step = flow[this._currentFlowStep.group][position];
761
+ this.dispatchChange();
762
+ }
763
+ }
764
+ _onSubmitFlowStep({ detail }) {
765
+ return __awaiter(this, void 0, void 0, function* () {
766
+ this._writeFlowStep(detail.values);
767
+ yield this.requestUpdate('_definition');
768
+ this.getChildren().forEach((c) => c.requestUpdate());
769
+ });
770
+ }
771
+ _onCancelFlow() {
772
+ this._splitMainViews();
773
+ }
774
+ _onSubmitFlow({ detail: { values } }) {
775
+ const selectedFlow = this.getSelectedFlow();
776
+ const _values = Object.assign({}, this._createFlowFromSchema(), values);
777
+ const selectedFlowUpdated = Object.assign({}, selectedFlow, _values);
778
+ if (!deepEqual(selectedFlow, selectedFlowUpdated)) {
779
+ Object.assign(selectedFlow, selectedFlowUpdated, { _dirty: true });
780
+ this.isDirty = true;
781
+ this.dispatchChange();
782
+ this._refresh();
783
+ }
784
+ }
785
+ _onCancelFlowMode() {
786
+ this._splitMainViews();
787
+ }
788
+ _onSubmitFlowMode({ detail: { values } }) {
789
+ this._definition['flow-mode'] = values['flow-mode'] || 'DEFAULT';
790
+ this.isDirty = true;
791
+ this.dispatchChange();
792
+ this._refresh();
793
+ }
794
+ _onDragStartFlowStep(flow, { detail }) {
795
+ if (this._currentAskConfirmation == null) {
796
+ this._dropPolicy = detail;
797
+ this._dragPolicy = detail;
798
+ }
799
+ }
800
+ _renderFlowEmptyState(readonlyMode) {
801
+ return html `<div slot="content" class="empty">
802
+ <div>
803
+ Select a flow
804
+ ${readonlyMode !== true
805
+ ? html `or <gv-button @gv-button:click="${this._onAddFlow}" outlined icon="code:plus" large>design new one </gv-button>`
806
+ : ''}
807
+ </div>
808
+ </div>`;
809
+ }
810
+ _renderFlow(index = 0, hasEmptyState = true, readonlyMode = false) {
811
+ const flow = this.getSelectedFlow(index);
812
+ if (flow) {
813
+ const { plan } = this._findFlowCollection(flow._id);
814
+ const selectedStepId = this._currentFlowStep ? this._currentFlowStep.step._id : null;
815
+ return html `<gv-flow
816
+ style="height: 100%"
817
+ .id="${flow._id}"
818
+ .flow="${flow}"
819
+ .plan="${plan}"
820
+ .policies="${this.policies}"
821
+ slot="content"
822
+ ?disabled="${this._currentAskConfirmation}"
823
+ .dragPolicy="${this._dragPolicy}"
824
+ .dropPolicy="${this._dropPolicy}"
825
+ .selectedStepId="${selectedStepId}"
826
+ ?readonly="${readonlyMode}"
827
+ ?has-policy-filter="${this._policyFilterOptions != null}"
828
+ flows-title="${this.flowsTitle}"
829
+ @gv-flow:drag-start="${this._onDragStartFlowStep.bind(this, flow)}"
830
+ @gv-flow:edit="${this._onEditFlowStep}"
831
+ @gv-flow:change-state="${this._onChangeFlowStepState}"
832
+ @gv-flow:drop="${this._onDropPolicy}"
833
+ @gv-flow:delete="${this._onDeletePolicy}"
834
+ ></gv-flow>`;
835
+ }
836
+ else if (hasEmptyState) {
837
+ return this._renderFlowEmptyState(readonlyMode);
838
+ }
839
+ return html ``;
840
+ }
841
+ _onFetchResources(event) {
842
+ const { currentTarget, regexTypes } = event.detail;
843
+ const options = this.definedResources
844
+ .filter((resource) => regexTypes == null || new RegExp(regexTypes).test(resource.type))
845
+ .map((resource, index) => {
846
+ const resourceType = this.resourceTypes.find((type) => type.id === resource.type);
847
+ const row = document.createElement('gv-row');
848
+ const picture = resourceType.icon ? resourceType.icon : null;
849
+ row.item = { picture, name: resource.name };
850
+ return {
851
+ element: row,
852
+ value: resource.name,
853
+ id: resource.type,
854
+ };
855
+ });
856
+ currentTarget.options = options;
857
+ }
858
+ _renderPolicy(readonlyMode) {
859
+ if (this._flowStepSchema && this.documentation) {
860
+ return html `<gv-resizable-views direction="horizontal" no-overflow>
861
+ <div slot="top">${this._renderFlowStepForm(readonlyMode)}</div>
862
+ <div slot="bottom">
863
+ <gv-documentation
864
+ .text="${this.documentation.content}"
865
+ .image="${this.documentation.image}"
866
+ ?disabled="${this._currentAskConfirmation}"
867
+ @gv-documentation:close="${this._onCloseDocumentation}"
868
+ ></gv-documentation>
869
+ </div>
870
+ </gv-resizable-views>`;
871
+ }
872
+ else if (this.documentation) {
873
+ return html `<gv-documentation
874
+ .text="${this.documentation.content}"
875
+ .image="${this.documentation.image}"
876
+ ?disabled="${this._currentAskConfirmation}"
877
+ @gv-documentation:close="${this._onCloseDocumentation}"
878
+ ></gv-documentation>`;
879
+ }
880
+ else if (this._flowStepSchema) {
881
+ return this._renderFlowStepForm(readonlyMode);
882
+ }
883
+ return html ``;
884
+ }
885
+ _getFlowStepForm() {
886
+ return this.shadowRoot.querySelector(`#${FLOW_STEP_FORM_ID}`);
887
+ }
888
+ _onResetFlowStep() {
889
+ if (this._currentFlowStep) {
890
+ delete this._currentFlowStep._values;
891
+ this._getFlowStepForm().reset();
892
+ }
893
+ }
894
+ _generateFlowsId(list, force = false) {
895
+ return this._generateId('f', list, force, true);
896
+ }
897
+ _generatePlanFlowsId(plan, force = false) {
898
+ return this._generateId(plan.id, plan.flows, force, true);
899
+ }
900
+ _generateFlowStepId(flowId, flowKey, position) {
901
+ return `${flowId}_${flowKey}_${position}`;
902
+ }
903
+ _generateId(prefix, list, force = false, isFlow = false) {
904
+ if (list == null) {
905
+ return list;
906
+ }
907
+ return deepClone(list).map((e, index) => {
908
+ const _id = `${prefix}_${index}`;
909
+ if (isFlow) {
910
+ if (e.pre) {
911
+ e.pre.forEach((step, stepIndex) => (step._id = this._generateFlowStepId(_id, 'pre', stepIndex)));
912
+ }
913
+ if (e.post) {
914
+ e.post.forEach((step, stepIndex) => (step._id = this._generateFlowStepId(_id, 'post', stepIndex)));
915
+ }
916
+ }
917
+ if (force || e._id == null) {
918
+ return Object.assign(Object.assign({}, e), { _id });
919
+ }
920
+ return e;
921
+ });
922
+ }
923
+ getChildren() {
924
+ return [
925
+ ...Array.from(this.shadowRoot.querySelectorAll('gv-flow')),
926
+ ...Array.from(this.shadowRoot.querySelectorAll('gv-resizable-views')),
927
+ ];
928
+ }
929
+ getUpdateComplete() {
930
+ const _super = Object.create(null, {
931
+ getUpdateComplete: { get: () => super.getUpdateComplete }
932
+ });
933
+ return __awaiter(this, void 0, void 0, function* () {
934
+ yield _super.getUpdateComplete.call(this);
935
+ yield Promise.all(this.getChildren().map((e) => e.updateComplete));
936
+ });
937
+ }
938
+ shouldUpdate(changedProperties) {
939
+ // Just refresh gv-flow components
940
+ if (changedProperties.has('_dragPolicy')) {
941
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((flow) => (flow.dragPolicy = this._dragPolicy));
942
+ return false;
943
+ }
944
+ if (changedProperties.has('_dropPolicy')) {
945
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((flow) => (flow.dropPolicy = this._dropPolicy));
946
+ return false;
947
+ }
948
+ return super.shouldUpdate(changedProperties);
949
+ }
950
+ updated(props) {
951
+ if (props.has('documentation') && this.documentation != null && this.selectedFlowsId.length > 1) {
952
+ this._updateSelectedFlows([this.selectedFlowsId[0]]);
953
+ }
954
+ }
955
+ _renderFlowStepForm(readonlyMode) {
956
+ const values = this._currentFlowStep._values || this._currentFlowStep._initialValues;
957
+ const groups = [
958
+ { items: ['commonDescription', 'commonCondition'] },
959
+ {
960
+ name: i18n('gv-policy-studio.policy-settings'),
961
+ default: true,
962
+ },
963
+ ];
964
+ return html `${cache(this._flowStepSchema && this._currentFlowStep
965
+ ? html `<div class="flow-step__container">
966
+ <div class="flow-step__form">
967
+ <gv-schema-form
968
+ .id="${FLOW_STEP_FORM_ID}"
969
+ .schema="${this._flowStepSchema}"
970
+ .icon="design:edit"
971
+ has-header
972
+ validate-on-render
973
+ .values="${values}"
974
+ .dirty="${this._currentFlowStep._values != null}"
975
+ ?readonly="${readonlyMode}"
976
+ scrollable
977
+ .groups="${groups}"
978
+ @gv-schema-form:change="${this._onChangeFlowStep}"
979
+ @gv-schema-form:reset="${this._onResetFlowStep}"
980
+ @gv-schema-form:fetch-resources="${this._onFetchResources}"
981
+ @gv-schema-form:submit="${this._onSubmitFlowStep}"
982
+ >
983
+ <div slot="title" class="flow-step__form-title">${this._currentFlowStep.step.name}</div>
984
+ <gv-button
985
+ slot="header-left"
986
+ icon="general:close"
987
+ outlined
988
+ small
989
+ @gv-button:click="${this._onCloseFlowStepForm}"
990
+ title="Close"
991
+ ></gv-button>
992
+ <gv-button
993
+ slot="header-left"
994
+ icon="home:book"
995
+ ?disabled="${this.documentation != null}"
996
+ outlined
997
+ small
998
+ @gv-button:click="${this._onOpenDocumentationFromForm}"
999
+ title="Open documentation"
1000
+ ></gv-button>
1001
+ </gv-schema-form>
1002
+ </div>
1003
+ </div>`
1004
+ : '')}`;
1005
+ }
1006
+ _onCloseDocumentation() {
1007
+ this.documentation = null;
1008
+ if (this._currentFlowStep == null) {
1009
+ this._maximizeTopView();
1010
+ }
1011
+ else {
1012
+ localStorage.setItem('gv-policy-studio:keep-documentation-close', true);
1013
+ }
1014
+ }
1015
+ _onDeleteFlow({ detail }) {
1016
+ const flowId = detail.content._id;
1017
+ const { flows } = this._findFlowCollection(flowId);
1018
+ const flow = flows.find((f) => f._id === flowId);
1019
+ this._deleteFlow(flows, flow);
1020
+ }
1021
+ get definedFlows() {
1022
+ return this._definition && this._definition.flows ? this._definition.flows : [];
1023
+ }
1024
+ get definedPlans() {
1025
+ return this._definition && this._definition.plans ? this._definition.plans : [];
1026
+ }
1027
+ get definedResources() {
1028
+ return this._definition && this._definition.resources ? this._definition.resources : [];
1029
+ }
1030
+ get definedProperties() {
1031
+ return this._definition && this._definition.properties ? this._definition.properties : [];
1032
+ }
1033
+ _onDuplicateFlow({ detail }) {
1034
+ return __awaiter(this, void 0, void 0, function* () {
1035
+ try {
1036
+ yield this._askToValidateForms();
1037
+ const flowId = detail.content._id;
1038
+ const { plan, flows } = this._findFlowCollection(flowId);
1039
+ this._addFlow(flows, this._findFlowById(flowId));
1040
+ if (plan != null) {
1041
+ let planIndex = null;
1042
+ this.definedPlans.find((p, i) => {
1043
+ if (p.id === plan.id) {
1044
+ planIndex = i;
1045
+ return true;
1046
+ }
1047
+ return false;
1048
+ });
1049
+ plan.flows = flows;
1050
+ this.definedPlans[planIndex].flows = this._generatePlanFlowsId(plan, true);
1051
+ this._updateSelectedFlows([this.definedPlans[planIndex].flows[flows.length - 1]._id]);
1052
+ }
1053
+ else {
1054
+ this._definition.flows = this._generateFlowsId(this._definition.flows);
1055
+ this._updateSelectedFlows([this._definition.flows[this._definition.flows.length - 1]._id]);
1056
+ }
1057
+ }
1058
+ catch (err) {
1059
+ this._currentAskConfirmation = null;
1060
+ }
1061
+ });
1062
+ }
1063
+ _onChangeFlowState({ detail }) {
1064
+ const flow = this._findFlowById(detail.content._id);
1065
+ flow.enabled = detail.enabled;
1066
+ flow._dirty = true;
1067
+ this.isDirty = true;
1068
+ this.dispatchChange();
1069
+ }
1070
+ _onAddFlowPlan({ detail }) {
1071
+ return __awaiter(this, void 0, void 0, function* () {
1072
+ try {
1073
+ yield this._askToValidateForms();
1074
+ this._addFlow(this.definedPlans[detail.planIndex].flows);
1075
+ this.definedPlans[detail.planIndex].flows = this._generatePlanFlowsId(this.definedPlans[detail.planIndex]);
1076
+ this._updateSelectedFlows([this.definedPlans[detail.planIndex].flows[this.definedPlans[detail.planIndex].flows.length - 1]._id]);
1077
+ }
1078
+ catch (err) {
1079
+ this._currentAskConfirmation = null;
1080
+ }
1081
+ });
1082
+ }
1083
+ _onAddFlow() {
1084
+ return __awaiter(this, void 0, void 0, function* () {
1085
+ try {
1086
+ yield this._askToValidateForms();
1087
+ this._addFlow(this._definition.flows);
1088
+ this._definition.flows = this._generateFlowsId(this._definition.flows);
1089
+ this._updateSelectedFlows([this._definition.flows[this._definition.flows.length - 1]._id]);
1090
+ }
1091
+ catch (err) {
1092
+ this._currentAskConfirmation = null;
1093
+ }
1094
+ });
1095
+ }
1096
+ _addFlow(collection, duplicate = null) {
1097
+ const flow = duplicate == null
1098
+ ? this._createFlowFromSchema()
1099
+ : Object.assign(Object.assign({}, duplicate), { _id: null,
1100
+ // reset the id to avoid issue with AM that persists the ID
1101
+ id: null, _dirty: true });
1102
+ collection.push(flow);
1103
+ this.isDirty = true;
1104
+ this.dispatchChange();
1105
+ return collection;
1106
+ }
1107
+ _createFlowFromSchema() {
1108
+ const newFlow = {
1109
+ name: '',
1110
+ pre: [],
1111
+ post: [],
1112
+ _dirty: true,
1113
+ };
1114
+ return this._instantiate(this.flowSchema.properties, newFlow);
1115
+ }
1116
+ _instantiate(propertiesDefinition, initiator = {}) {
1117
+ const property = Object.assign({}, initiator);
1118
+ if (propertiesDefinition) {
1119
+ for (const key of Object.keys(propertiesDefinition)) {
1120
+ const entry = propertiesDefinition[key];
1121
+ if (entry.type === 'object') {
1122
+ property[key] = this._instantiate(entry.properties);
1123
+ }
1124
+ if (entry.default !== undefined) {
1125
+ property[key] = entry.default;
1126
+ }
1127
+ else if (entry.type === 'string') {
1128
+ property[key] = '';
1129
+ }
1130
+ }
1131
+ }
1132
+ return property;
1133
+ }
1134
+ _deleteFlow(collection, flow) {
1135
+ const index = collection.indexOf(flow);
1136
+ collection.splice(index, 1);
1137
+ const selectedFlows = this.selectedFlowsId.filter((flowId) => flowId !== flow._id);
1138
+ if (selectedFlows.length === 1) {
1139
+ this._updateSelectedFlows(selectedFlows);
1140
+ }
1141
+ else {
1142
+ this._selectFirstFlow(true);
1143
+ }
1144
+ this._refresh();
1145
+ this.isDirty = true;
1146
+ this.dispatchChange();
1147
+ }
1148
+ _findFlowIndex(list, id) {
1149
+ let index = null;
1150
+ list.find((f, i) => {
1151
+ if (f._id === id) {
1152
+ index = i;
1153
+ return true;
1154
+ }
1155
+ return false;
1156
+ });
1157
+ return index;
1158
+ }
1159
+ _onReorderFlows({ detail: { plan } }) {
1160
+ return __awaiter(this, void 0, void 0, function* () {
1161
+ try {
1162
+ yield this._askToValidateForms();
1163
+ this.isDirty = true;
1164
+ this.dispatchChange();
1165
+ if (plan != null) {
1166
+ const newOrder = this._generatePlanFlowsId(plan, true);
1167
+ if (this.selectedFlowsId) {
1168
+ this._updateSelectedFlows(this.selectedFlowsId.map((flowId) => {
1169
+ const index = this._findFlowIndex(plan.flows, flowId);
1170
+ return index != null ? newOrder[index]._id : flowId;
1171
+ }));
1172
+ }
1173
+ plan.flows = newOrder;
1174
+ }
1175
+ else {
1176
+ const newOrder = this._generateFlowsId(this._definition.flows, true);
1177
+ if (this.selectedFlowsId) {
1178
+ this._updateSelectedFlows(this.selectedFlowsId.map((flowId) => {
1179
+ const index = this._findFlowIndex(this._definition.flows, flowId);
1180
+ return index != null ? newOrder[index]._id : flowId;
1181
+ }));
1182
+ }
1183
+ this._definition.flows = newOrder;
1184
+ }
1185
+ }
1186
+ catch (err) {
1187
+ this._currentAskConfirmation = false;
1188
+ }
1189
+ });
1190
+ }
1191
+ _onSearchPolicy({ detail }) {
1192
+ this._searchPolicyQuery = detail;
1193
+ }
1194
+ _onClearPolicy() {
1195
+ this._searchPolicyQuery = null;
1196
+ }
1197
+ _onSearchFlows({ detail }) {
1198
+ this._searchFlowQuery = detail;
1199
+ }
1200
+ _onClearFlows() {
1201
+ this._searchFlowQuery = null;
1202
+ }
1203
+ _filterNotValidStep(step) {
1204
+ return step._new !== true;
1205
+ }
1206
+ _removePrivateProperties(o) {
1207
+ const copy = Object.assign({}, o);
1208
+ Object.keys(o)
1209
+ .filter((key) => key.startsWith('_'))
1210
+ .forEach((key) => {
1211
+ delete copy[key];
1212
+ });
1213
+ return copy;
1214
+ }
1215
+ _submitOrConfirmForms() {
1216
+ return [...this.shadowRoot.querySelectorAll('gv-schema-form')]
1217
+ .filter((form) => {
1218
+ const isValid = form.isValid();
1219
+ if (isValid && form.dirty) {
1220
+ form.submit();
1221
+ }
1222
+ return !isValid;
1223
+ })
1224
+ .map((form) => form.confirm(true));
1225
+ }
1226
+ getPropertiesElement() {
1227
+ return this.shadowRoot.querySelector('gv-properties');
1228
+ }
1229
+ _checkCurrentFlowStep() {
1230
+ return __awaiter(this, void 0, void 0, function* () {
1231
+ if (this._currentFlowStep && this.selectedFlowsId) {
1232
+ const closePromises = this.selectedFlowsId
1233
+ .map((flowId) => {
1234
+ const flow = this._findFlowById(flowId);
1235
+ const currentStep = [...flow.pre, ...flow.post].find((step) => step._id === this._currentFlowStep.step._id);
1236
+ if (currentStep == null) {
1237
+ return this._closeFlowStepForm(true);
1238
+ }
1239
+ return null;
1240
+ })
1241
+ .filter((p) => p !== null);
1242
+ return Promise.all(closePromises);
1243
+ }
1244
+ return Promise.resolve();
1245
+ });
1246
+ }
1247
+ saved() {
1248
+ if (this.isDirty) {
1249
+ this._initialDefinition = deepClone(this._definitionSaved);
1250
+ this._definition = deepClone(this._definitionSaved);
1251
+ this._definitionSaved = null;
1252
+ this.isDirty = false;
1253
+ this._checkCurrentFlowStep();
1254
+ this.definedPlans.forEach((plan) => {
1255
+ plan.flows.forEach((flow) => (flow._dirty = false));
1256
+ });
1257
+ this.definedFlows.forEach((flow) => (flow._dirty = false));
1258
+ this.getChildren().forEach((e) => e.requestUpdate());
1259
+ }
1260
+ }
1261
+ _mapFlowsWithValidStep(flows) {
1262
+ return flows.map((flow) => {
1263
+ flow.pre = flow.pre.filter(this._filterNotValidStep);
1264
+ flow.post = flow.post.filter(this._filterNotValidStep);
1265
+ return flow;
1266
+ });
1267
+ }
1268
+ _buildDefinitionToSave() {
1269
+ // Copy definition and remove invalid step
1270
+ // Keep private properties like _id and others stuff useful for render
1271
+ const flows = this._mapFlowsWithValidStep(this._definition.flows || []);
1272
+ const definition = Object.assign(Object.assign({}, this._definition), { flows });
1273
+ if (this._definition.plans != null) {
1274
+ const plans = this._definition.plans.map((plan) => (Object.assign(Object.assign({}, plan), { flows: this._mapFlowsWithValidStep(plan.flows) })));
1275
+ return Object.assign(Object.assign({}, definition), { plans });
1276
+ }
1277
+ return definition;
1278
+ }
1279
+ _mapFlowsWithValidProperty(flows) {
1280
+ return flows.map((f) => {
1281
+ const flow = this._removePrivateProperties(f);
1282
+ flow.pre = flow.pre.map(this._removePrivateProperties);
1283
+ flow.post = flow.post.map(this._removePrivateProperties);
1284
+ return flow;
1285
+ });
1286
+ }
1287
+ _buildDefinitionToSend(definitionToSave) {
1288
+ // Copy definition and remove all private properties
1289
+ const flows = this._mapFlowsWithValidProperty(definitionToSave.flows);
1290
+ let definition = Object.assign(Object.assign({}, this._definition), { flows });
1291
+ if (this._definition.plans != null) {
1292
+ const plans = definitionToSave.plans.map((plan) => (Object.assign(Object.assign({}, plan), { flows: this._mapFlowsWithValidProperty(plan.flows) })));
1293
+ definition = Object.assign(Object.assign({}, definition), { plans });
1294
+ }
1295
+ if (this._definition.properties != null) {
1296
+ const properties = this._definition.properties.map(this._removePrivateProperties);
1297
+ definition = Object.assign(Object.assign({}, definition), { properties });
1298
+ }
1299
+ if (this._definition.resources != null) {
1300
+ const resources = this._definition.resources.map(this._removePrivateProperties);
1301
+ definition = Object.assign(Object.assign({}, definition), { resources });
1302
+ }
1303
+ return definition;
1304
+ }
1305
+ get filteredFlows() {
1306
+ if (this._flowFilter.length === 0 || this._flowFilter.includes('api')) {
1307
+ return this.definedFlows;
1308
+ }
1309
+ return null;
1310
+ }
1311
+ get filteredPlans() {
1312
+ if (this._flowFilter.length === 0 || this._flowFilter.includes('plan')) {
1313
+ return this.definedPlans;
1314
+ }
1315
+ return null;
1316
+ }
1317
+ _onFilterFlows({ detail }) {
1318
+ if (this._flowFilter.includes(detail.id)) {
1319
+ this._flowFilter = [];
1320
+ }
1321
+ else {
1322
+ this._flowFilter = [detail.id];
1323
+ }
1324
+ }
1325
+ _getFilteredPolicies() {
1326
+ if (this._policyFilter.length > 0) {
1327
+ return this.policies.filter((policy) => {
1328
+ return ((policy.onRequest && this._policyFilter.includes('onRequest')) || (policy.onResponse && this._policyFilter.includes('onResponse')));
1329
+ });
1330
+ }
1331
+ return this.policies;
1332
+ }
1333
+ _onFilterPolicies({ detail }) {
1334
+ if (this._policyFilter.includes(detail.id)) {
1335
+ this._policyFilter = [];
1336
+ }
1337
+ else {
1338
+ this._policyFilter = [detail.id];
1339
+ }
1340
+ }
1341
+ _renderContent(readonlyMode) {
1342
+ return html `<div id="design" slot="content" class="design">
1343
+ <gv-resizable-views no-overflow>
1344
+ <div slot="top">${this._renderFlow(0, true, readonlyMode)}</div>
1345
+
1346
+ <div slot="bottom">
1347
+ ${this._renderFlow(1, false, readonlyMode)} ${this._renderPolicy(readonlyMode)} ${this._renderFlowForm(readonlyMode)}
1348
+ </div>
1349
+ </gv-resizable-views>
1350
+ ${readonlyMode !== true
1351
+ ? html `<gv-policy-studio-menu
1352
+ class="right-menu"
1353
+ ?disabled="${this._currentAskConfirmation}"
1354
+ .policies="${this._getFilteredPolicies()}"
1355
+ .selectedIds="${[this._currentPolicyId]}"
1356
+ .query="${this._searchPolicyQuery}"
1357
+ ?has-policy-filter="${this._policyFilterOptions != null}"
1358
+ ?readonly="${readonlyMode}"
1359
+ @gv-policy-studio-menu:target-policy="${this._onTargetPolicy}"
1360
+ @gv-policy-studio-menu:fetch-documentation="${this._onOpenDocumentationFromMenu}"
1361
+ @gv-policy-studio-menu:dragend-policy="${this._onDragEndPolicy}"
1362
+ >
1363
+ <div slot="header" class="search-policies">
1364
+ ${this._policyFilterOptions != null
1365
+ ? html `<gv-option
1366
+ ?disabled="${this._currentAskConfirmation}"
1367
+ .options="${this._policyFilterOptions}"
1368
+ multiple
1369
+ outlined
1370
+ .value="${this._policyFilter}"
1371
+ small
1372
+ @gv-option:select="${this._onFilterPolicies}"
1373
+ ></gv-option>`
1374
+ : ''}
1375
+ <gv-input
1376
+ id="search-policy"
1377
+ ?disabled="${this._currentAskConfirmation}"
1378
+ placeholder="Filter policies (Shift + Alt + Space)"
1379
+ type="search"
1380
+ small
1381
+ @gv-input:input="${this._onSearchPolicy}"
1382
+ @gv-input:clear="${this._onClearPolicy}"
1383
+ ></gv-input>
1384
+ </div>
1385
+ </gv-policy-studio-menu>`
1386
+ : ''}
1387
+ </div>`;
1388
+ }
1389
+ _renderFlowForm(readonlyMode) {
1390
+ if (this.flowSchema && this._flowStepSchema == null && this.documentation == null && this.selectedFlowsId.length === 1) {
1391
+ const flow = this.getSelectedFlow();
1392
+ if (flow) {
1393
+ const values = deepClone(flow);
1394
+ return html `<div slot="content" class="flow-settings">
1395
+ <gv-schema-form
1396
+ .schema="${this.flowSchema}"
1397
+ id="settings-form"
1398
+ .values="${values}"
1399
+ has-header
1400
+ scrollable
1401
+ ?readonly="${readonlyMode}"
1402
+ @gv-schema-form:cancel="${this._onCancelFlow}"
1403
+ @gv-schema-form:submit="${this._onSubmitFlow}"
1404
+ >
1405
+ <div slot="title" class="flow-step__form-title">Flow configuration</div>
1406
+ </gv-schema-form>
1407
+ </div>`;
1408
+ }
1409
+ }
1410
+ }
1411
+ render() {
1412
+ const readonlyMode = this._getReadonlyModeForDesign();
1413
+ return html `<div class="box">
1414
+ <gv-policy-studio-menu
1415
+ class="left-menu"
1416
+ .api-name="${this._definition.name}"
1417
+ .flows="${this.filteredFlows}"
1418
+ .plans="${this.filteredPlans}"
1419
+ .selectedIds="${this.selectedFlowsId}"
1420
+ ?disabled="${this._currentAskConfirmation}"
1421
+ ?sortable="${this.sortable && this.readonly !== true}"
1422
+ ?readonly="${this.readonly}"
1423
+ ?readonlyPlans="${this.readonlyPlans}"
1424
+ flows-title="${this.flowsTitle}"
1425
+ .query="${this._searchFlowQuery}"
1426
+ ?can-add="${this.canAdd && !this.readonly}"
1427
+ @gv-policy-studio-menu:reorder-flows="${this._onReorderFlows}"
1428
+ @gv-policy-studio-menu:change-flow-state="${this._onChangeFlowState}"
1429
+ @gv-policy-studio-menu:add-flow="${this._onAddFlow}"
1430
+ @gv-policy-studio-menu:add-flow-plan="${this._onAddFlowPlan}"
1431
+ @gv-policy-studio-menu:delete-flow="${this._onDeleteFlow}"
1432
+ @gv-policy-studio-menu:duplicate-flow="${this._onDuplicateFlow}"
1433
+ @gv-policy-studio-menu:select-flows="${this._onSelectFlows}"
1434
+ >
1435
+ <div slot="header" class="header-actions">
1436
+ ${this._flowFilterOptions != null
1437
+ ? html `<gv-option
1438
+ ?disabled="${this._currentAskConfirmation}"
1439
+ .options="${this._flowFilterOptions}"
1440
+ multiple
1441
+ outlined
1442
+ .value="${this._flowFilter}"
1443
+ small
1444
+ @gv-option:select="${this._onFilterFlows}"
1445
+ ></gv-option>`
1446
+ : ''}
1447
+ <gv-input
1448
+ ?disabled="${this._currentAskConfirmation}"
1449
+ id="search-flow"
1450
+ placeholder="Filter flows (Alt + Space)"
1451
+ type="search"
1452
+ small
1453
+ @gv-input:input="${this._onSearchFlows}"
1454
+ @gv-input:clear="${this._onClearFlows}"
1455
+ ></gv-input>
1456
+ </div>
1457
+ </gv-policy-studio-menu>
1458
+ ${this._renderContent(readonlyMode)}
1459
+ </div>`;
1460
+ }
1461
+ /**
1462
+ * Determine if the design view should be in readonly mode or not
1463
+ * It is in readonly mode if:
1464
+ * the readonly attribute is set to true
1465
+ * OR
1466
+ * the main selected flow belongs to a plan and the readonly-plans attribute is set to true
1467
+ * OR
1468
+ * the second flow for comparison belongs to a plan and the readonly-plans attribute is set to true
1469
+ * @returns {boolean|*|{type: BooleanConstructor}|{attribute: string, type: BooleanConstructor}|{type: *}|{attribute: string, type: *}}
1470
+ * @private
1471
+ */
1472
+ _getReadonlyModeForDesign() {
1473
+ if (this.readonly) {
1474
+ return true;
1475
+ }
1476
+ const flow = this.getSelectedFlow(0);
1477
+ if (!flow) {
1478
+ return false;
1479
+ }
1480
+ const { plan: flowPlan } = this._findFlowCollection(flow._id);
1481
+ const readonlyMode = flowPlan && this.readonlyPlans;
1482
+ if (readonlyMode) {
1483
+ return true;
1484
+ }
1485
+ const comparedFlow = this.getSelectedFlow(1);
1486
+ if (!comparedFlow) {
1487
+ return false;
1488
+ }
1489
+ const { plan: comparedFlowPlan } = this._findFlowCollection(comparedFlow._id);
1490
+ return comparedFlowPlan && this.readonlyPlans;
1491
+ }
1492
+ }
1493
+ window.customElements.define('gv-design', GvDesign);
1494
+ //# sourceMappingURL=gv-design.js.map