@gravitee/ui-components 3.24.1-6614-conditional-policy-fb499f8 → 3.24.2-migrate-codemirror-4150e72

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [3.24.2](https://github.com/gravitee-io/gravitee-ui-components/compare/v3.24.1...v3.24.2) (2021-12-14)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * revert unneeded changed introduced in `upgrade to Lit 2` ([f0aef5f](https://github.com/gravitee-io/gravitee-ui-components/commit/f0aef5f7ffc97b139ebc8a5f5947f3ed5acc5cea))
7
+ * wait for Lit component to be ready before updating their properties ([3baf7df](https://github.com/gravitee-io/gravitee-ui-components/commit/3baf7dfe1fec74ab6778eceebfde6dd8a5061b65))
8
+
1
9
  ## [3.24.1](https://github.com/gravitee-io/gravitee-ui-components/compare/v3.24.0...v3.24.1) (2021-12-13)
2
10
 
3
11
 
@@ -91,10 +91,6 @@
91
91
  "manual": "Manual validation"
92
92
  }
93
93
  },
94
- "gv-policy-studio": {
95
- "common-settings": "Common settings",
96
- "policy-settings": "Policy settings"
97
- },
98
94
  "gv-promote": {
99
95
  "empty": "No information to display",
100
96
  "error": "An error has occurred",
@@ -91,10 +91,6 @@
91
91
  "manual": "Validation manuelle"
92
92
  }
93
93
  },
94
- "gv-policy-studio": {
95
- "common-settings": "Common settings",
96
- "policy-settings": "Policy settings"
97
- },
98
94
  "gv-promote": {
99
95
  "empty": "Aucun élément à afficher ici",
100
96
  "error": "Une erreur est survenue pendant le chargement",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravitee/ui-components",
3
- "version": "3.24.1-6614-conditional-policy-fb499f8",
3
+ "version": "3.24.2-migrate-codemirror-4150e72",
4
4
  "description": "Gravitee.io UI Components library, based on Web Components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -49,6 +49,20 @@
49
49
  "package.json": "npm run lint:package"
50
50
  },
51
51
  "dependencies": {
52
+ "@codemirror/autocomplete": "^0.19.5",
53
+ "@codemirror/basic-setup": "^0.19.0",
54
+ "@codemirror/closebrackets": "^0.19.0",
55
+ "@codemirror/fold": "^0.19.1",
56
+ "@codemirror/gutter": "^0.19.4",
57
+ "@codemirror/highlight": "^0.19.6",
58
+ "@codemirror/history": "^0.19.0",
59
+ "@codemirror/lang-java": "^0.19.1",
60
+ "@codemirror/lang-javascript": "^0.19.2",
61
+ "@codemirror/language": "^0.19.3",
62
+ "@codemirror/language-data": "^0.19.1",
63
+ "@codemirror/matchbrackets": "^0.19.3",
64
+ "@codemirror/state": "^0.19.5",
65
+ "@codemirror/view": "^0.19.16",
52
66
  "@formatjs/intl-locale": "^2.4.40",
53
67
  "@formatjs/intl-relativetimeformat": "^9.3.2",
54
68
  "clipboard-copy": "^4.0.0",
@@ -67,6 +81,8 @@
67
81
  "@babel/core": "7.16.0",
68
82
  "@babel/plugin-syntax-dynamic-import": "7.8.3",
69
83
  "@babel/preset-env": "7.16.4",
84
+ "@codemirror/commands": "^0.19.5",
85
+ "@codemirror/lang-html": "^0.19.3",
70
86
  "@commitlint/cli": "15.0.0",
71
87
  "@commitlint/config-conventional": "15.0.0",
72
88
  "@highcharts/map-collection": "1.1.3",
@@ -17,7 +17,7 @@ import { classMap } from 'lit/directives/class-map';
17
17
  import { ifDefined } from 'lit/directives/if-defined';
18
18
  import { repeat } from 'lit/directives/repeat';
19
19
 
20
- import { LitElement, html, css } from 'lit';
20
+ import { css, html, LitElement } from 'lit';
21
21
  import { skeleton } from '../styles/skeleton';
22
22
  import { link } from '../styles/link';
23
23
  import { input } from '../styles/input';
@@ -59,7 +59,6 @@ export class GvSelectNative extends InputElement(LitElement) {
59
59
  medium: { type: Boolean },
60
60
  small: { type: Boolean },
61
61
  value: { type: String | Array },
62
- _value: { type: String | Array, attribute: false },
63
62
  label: { type: String },
64
63
  title: { type: String },
65
64
  name: { type: String },
@@ -182,7 +181,7 @@ export class GvSelectNative extends InputElement(LitElement) {
182
181
  }
183
182
 
184
183
  getInputElement() {
185
- return super.getInputElement();
184
+ return this.shadowRoot.querySelector('select');
186
185
  }
187
186
 
188
187
  async firstUpdated(changedProperties) {
@@ -201,26 +200,12 @@ export class GvSelectNative extends InputElement(LitElement) {
201
200
  }
202
201
  }
203
202
 
204
- set value(value) {
205
- if (this.multiple) {
206
- if (value == null) {
207
- this._value = null;
208
- this.updateState(this._value);
209
- }
210
- if (Array.isArray(value)) {
211
- this._value = value;
212
- this.updateState(this._value);
213
- }
214
- } else {
215
- this._value = value;
216
- this.updateState(this._value);
203
+ willUpdate(changedProperties) {
204
+ if (changedProperties.has('value')) {
205
+ this.updateState(changedProperties.get('value'));
217
206
  }
218
207
  }
219
208
 
220
- get value() {
221
- return this._value;
222
- }
223
-
224
209
  updateState(value) {
225
210
  super.updateState(value);
226
211
  if (value && this._options && this.valid) {
@@ -66,7 +66,6 @@ export class GvSelect extends withResizeObserver(InputElement(LitElement)) {
66
66
  medium: { type: Boolean },
67
67
  small: { type: Boolean },
68
68
  value: { type: String | Array },
69
- _value: { type: String | Array, attribute: false },
70
69
  label: { type: String },
71
70
  title: { type: String },
72
71
  name: { type: String },
@@ -238,26 +237,12 @@ export class GvSelect extends withResizeObserver(InputElement(LitElement)) {
238
237
  super.disconnectedCallback();
239
238
  }
240
239
 
241
- set value(value) {
242
- if (this.multiple) {
243
- if (value == null) {
244
- this._value = null;
245
- this.updateState(this._value);
246
- }
247
- if (Array.isArray(value)) {
248
- this._value = value;
249
- this.updateState(this._value);
250
- }
251
- } else {
252
- this._value = value;
253
- this.updateState(this._value);
240
+ willUpdate(changedProperties) {
241
+ if (changedProperties.has('value')) {
242
+ this.updateState(changedProperties.get('value'));
254
243
  }
255
244
  }
256
245
 
257
- get value() {
258
- return this._value;
259
- }
260
-
261
246
  updateState(value) {
262
247
  super.updateState(value);
263
248
  if (value && this._options && this.valid) {
package/src/index.js CHANGED
@@ -31,6 +31,7 @@ export { GvCardList } from './molecules/gv-card-list';
31
31
  export { GvCard } from './molecules/gv-card';
32
32
  export { GvCategoryList } from './molecules/gv-category-list';
33
33
  export { GvCategory } from './molecules/gv-category';
34
+ export { GvCodeEditor } from './molecules/gv-code-editor';
34
35
  export { GvCodeHint } from './molecules/gv-code-hint';
35
36
  export { GvCode } from './molecules/gv-code';
36
37
  export { GvConfirm } from './molecules/gv-confirm';
@@ -51,7 +52,6 @@ export { GvRatingList } from './molecules/gv-rating-list';
51
52
  export { GvRating } from './molecules/gv-rating';
52
53
  export { GvRowExpandable } from './molecules/gv-row-expandable';
53
54
  export { GvRow } from './molecules/gv-row';
54
- export { GvScrollLayout } from './molecules/gv-scroll-layout';
55
55
  export { GvStats } from './molecules/gv-stats';
56
56
  export { GvStepper } from './molecules/gv-stepper';
57
57
  export { GvTable } from './molecules/gv-table';
@@ -0,0 +1,407 @@
1
+ /*
2
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { LitElement, html, css } from 'lit-element';
17
+
18
+ import { shapeClipboard } from '../styles/shapes';
19
+ import { dispatchCustomEvent } from '../lib/events';
20
+ import { uuid } from '../lib/utils';
21
+ import { classMap } from 'lit-html/directives/class-map';
22
+
23
+ import { EditorView, basicSetup } from '@codemirror/basic-setup';
24
+ import { EditorState, Compartment, Prec, EditorSelection } from '@codemirror/state';
25
+ import { autocompletion, startCompletion, pickedCompletion } from '@codemirror/autocomplete';
26
+ import { json } from '@codemirror/lang-json';
27
+ import { languages } from '@codemirror/language-data';
28
+ import { placeholder, keymap } from '@codemirror/view';
29
+ import { get } from 'object-path';
30
+
31
+ const languageCompartment = new Compartment();
32
+ const readonlyCompartment = new Compartment();
33
+ const placeholderCompartment = new Compartment();
34
+
35
+ /**
36
+ * Code editor component
37
+ *
38
+ * ## Details
39
+ * * has @theme facet
40
+ *
41
+ * @fires gv-code:input - input events with the `value` on `detail`
42
+ * @fires gv-code:ready - event dispatch when component is ready
43
+ * @fires gv-code:clipboard-copy - event dispatch when component the `value` has been copied to clipboard
44
+ *
45
+ * @attr {String} label - code language
46
+ * @attr {String} value - code content to be highlighted
47
+ * @attr {options} Object - options based on codemirror https://codemirror.net/doc/manual.html#config
48
+ * @attr {Object} grammar - The grammar for Expression Language support
49
+ * @attr {String} placeholder - an example value to display in the input when empty
50
+ * @attr {Number} rows - number of rows of the text element
51
+ * @attr {Boolean} large - for a large input (only if the field has one row)
52
+ * @attr {Boolean} medium - for a medium input (only if the field has one row) (Default)
53
+ * @attr {Boolean} small - for a small input (only if the field has one row)
54
+ *
55
+ * @attr {Boolean} [clipboard=false]- true if field has clipboard button
56
+ * @attr {Boolean} [autofocus=false] - true to put the focus on the input
57
+ * @attr {Boolean} [readonly=false] - true if field is readonly mode
58
+ */
59
+ export class GvCodeEditor extends LitElement {
60
+ static get properties() {
61
+ return {
62
+ value: { type: String },
63
+ readonly: { type: Boolean },
64
+ placeholder: { type: String },
65
+ options: { type: Object },
66
+ rows: { type: Number },
67
+ clipboard: { type: Boolean },
68
+ grammar: { type: Object },
69
+ _clipboardIcon: { type: String },
70
+ _codeMirror: { type: Object },
71
+ _error: { type: String, attribute: false },
72
+ };
73
+ }
74
+
75
+ constructor() {
76
+ super();
77
+ this._id = `gv-code-${uuid()}`;
78
+ this.value = '';
79
+ this.readonly = false;
80
+ this.autofocus = false;
81
+ this.clipboard = false;
82
+ this._clipboardIcon = shapeClipboard;
83
+ }
84
+
85
+ render() {
86
+ const classes = {
87
+ singleLine: this.singleLine,
88
+ };
89
+ return html` <div id="${this._id}" class="${classMap(classes)}"></div> `;
90
+ }
91
+
92
+ _onChange() {
93
+ dispatchCustomEvent(this, 'input', this.value);
94
+ }
95
+
96
+ get singleLine() {
97
+ return this.rows === 1;
98
+ }
99
+
100
+ _getModelType(typeId) {
101
+ if (this.grammar != null) {
102
+ return get(this.grammar, `_types.${typeId}`);
103
+ }
104
+ return null;
105
+ }
106
+
107
+ _isMap(typeId) {
108
+ return ['Map', 'HttpHeaders', 'MultiValueMap'].includes(typeId);
109
+ }
110
+
111
+ _getEnum(typeId) {
112
+ if (this.grammar != null) {
113
+ return get(this.grammar, `_enums.${typeId}`);
114
+ }
115
+ return [''];
116
+ }
117
+
118
+ _convertType(type) {
119
+ if (type) {
120
+ const lowerType = type.toLowerCase();
121
+ if (lowerType === 'string') {
122
+ // class, constant, enum, function, interface, keyword, method, namespace, property, text, type, and variable.
123
+ return 'text';
124
+ } else if (lowerType === 'httpheaders' || lowerType === 'multivaluemap') {
125
+ return 'type';
126
+ } else if (lowerType === 'int' || lowerType === 'long') {
127
+ return 'variable';
128
+ } else if (lowerType.includes('[]')) {
129
+ return 'enum';
130
+ }
131
+ }
132
+ return 'variable';
133
+ }
134
+
135
+ _autocomplete(ctx) {
136
+ const { handler, match } = this._completionHandlers
137
+ .filter((handler) => (this.grammar != null && handler.supportEL === true) || handler.supportEL !== true)
138
+ .map((handler) => ({ handler, match: handler.expr ? ctx.matchBefore(handler.expr) : true }))
139
+ .find(({ match, expr }) => match);
140
+ return handler.run.call(this, ctx, match);
141
+ }
142
+
143
+ _buildMethods(type) {
144
+ const modelType = this._getModelType(type);
145
+ return modelType.methods.map(({ name, params = [], returnType }) => {
146
+ const command = `${name}()`;
147
+ const displayParams = params.map((p) => `${p.type} ${p.name}`);
148
+ const label = `${name}(${displayParams.join(', ')})`;
149
+ const detail = `return ${returnType}`;
150
+ return {
151
+ type: 'method',
152
+ command,
153
+ apply: (view, completion, from, to) => {
154
+ const anchor = from + name.length + 1;
155
+ view.dispatch({
156
+ changes: { from, to, insert: completion.command },
157
+ selection: { anchor },
158
+ userEvent: 'input.complete',
159
+ annotations: pickedCompletion.of(view),
160
+ });
161
+ },
162
+ label,
163
+ detail,
164
+ };
165
+ });
166
+ }
167
+
168
+ get _completionHandlers() {
169
+ return [
170
+ {
171
+ expr: /{#[a-z]*/,
172
+ supportEL: true,
173
+ run(ctx, match) {
174
+ const prefix = match.text.replaceAll('{#', '');
175
+ const from = ctx.pos - prefix.length;
176
+ const options = Object.keys(this.grammar)
177
+ .filter((command) => !command.startsWith('_') && command.startsWith(prefix))
178
+ .map((command) => {
179
+ return {
180
+ // class, constant, enum, function, interface, keyword, method, namespace, property, text, type, and variable.
181
+ type: 'variable',
182
+ command,
183
+ apply: command,
184
+ label: command,
185
+ };
186
+ });
187
+ return { from, options };
188
+ },
189
+ },
190
+ {
191
+ expr: /{#[a-z]*.[a-zA-Z]*/,
192
+ run(ctx, match) {
193
+ const tokens = match.text.split('.');
194
+ const key = tokens[0].replaceAll('{#', '');
195
+ const prefix = tokens[1];
196
+ const candidate = this.grammar[key][prefix];
197
+ let options = [];
198
+ let from = ctx.pos;
199
+ if (candidate) {
200
+ // const modelType = this._getModelType(candidate._type);
201
+ if (this._isMap(candidate._type)) {
202
+ options = this._getEnum(candidate._type).map((value) => {
203
+ const type = this._convertType(candidate._type);
204
+ const command = `['${value}'][0]`;
205
+ return {
206
+ type,
207
+ command,
208
+ apply: command,
209
+ label: value,
210
+ };
211
+ });
212
+ }
213
+ } else {
214
+ from -= prefix.length;
215
+ const candidate = this.grammar[key];
216
+ if (candidate._type) {
217
+ options = this._buildMethods(candidate._type);
218
+ } else {
219
+ options = Object.keys(candidate)
220
+ .filter((command) => !command.startsWith('_') && command.startsWith(prefix))
221
+ .map((command) => ({
222
+ type: this._convertType(candidate[command]._type),
223
+ command,
224
+ apply: command,
225
+ label: command,
226
+ }));
227
+ }
228
+ }
229
+ return { from, options };
230
+ },
231
+ },
232
+ {
233
+ expr: /{#[a-z]*.[a-zA-Z]*.[a-zA-Z]*/,
234
+ run(ctx, match) {
235
+ const tokens = match.text.split('.');
236
+ const key = tokens[0].replaceAll('{#', '');
237
+ const word = tokens[1];
238
+ const prefix = tokens[2];
239
+ const candidate = this.grammar[key][word];
240
+ let options = [];
241
+ let from = ctx.pos;
242
+ if (candidate) {
243
+ if (this._isMap(candidate._type)) {
244
+ options = this._getEnum(candidate._type)
245
+ .filter((command) => !command.startsWith('_') && command.startsWith(prefix))
246
+ .map((label) => {
247
+ const type = this._convertType(candidate._type);
248
+ return {
249
+ type,
250
+ command: `['${label}'][0]`,
251
+ apply(view, completion, _from, to) {
252
+ const from = _from - prefix.length - 1;
253
+ view.dispatch({
254
+ changes: { from, to, insert: completion.command },
255
+ selection: { anchor: from + completion.command.length },
256
+ userEvent: 'input.complete',
257
+ annotations: pickedCompletion.of(view),
258
+ });
259
+ },
260
+ label,
261
+ };
262
+ });
263
+ } else {
264
+ if (candidate._type) {
265
+ options = this._buildMethods(candidate._type);
266
+ } else {
267
+ from -= prefix.length;
268
+ options = Object.keys(candidate)
269
+ .filter((command) => command.startsWith(prefix))
270
+ .map((command) => {
271
+ return {
272
+ type: this._convertType(candidate[command]._type),
273
+ command,
274
+ apply: command,
275
+ label: command,
276
+ };
277
+ });
278
+ }
279
+ }
280
+ }
281
+ return { from, options };
282
+ },
283
+ },
284
+ {
285
+ run(ctx) {
286
+ const autocompleteLanguage = ctx.state.languageDataAt('autocomplete', ctx.pos);
287
+ if (autocompleteLanguage.length > 0) {
288
+ return autocompleteLanguage[0](ctx);
289
+ }
290
+ return { from: ctx.pos, options: [] };
291
+ },
292
+ },
293
+ ];
294
+ }
295
+
296
+ getExtensions() {
297
+ return [
298
+ basicSetup,
299
+ languageCompartment.of(json()),
300
+ placeholderCompartment.of(placeholder(this.placeholder || '')),
301
+ EditorState.transactionFilter.of((tr) => (this.singleLine && tr.newDoc.lines > 1 ? [] : tr)),
302
+ readonlyCompartment.of(EditorView.editable.of(!this.readonly)),
303
+ EditorView.updateListener.of((update) => {
304
+ this.value = update.view.contentDOM.innerText;
305
+ }),
306
+ autocompletion({
307
+ activateOnTyping: true,
308
+ override: [this._autocomplete.bind(this)],
309
+ }),
310
+ Prec.high(this.insertELKeymap()),
311
+ ];
312
+ }
313
+
314
+ insertELKeymap() {
315
+ return keymap.of([
316
+ {
317
+ key: 'Ctrl-Shift-e',
318
+ mac: 'Cmd-Shift-e',
319
+ run(view) {
320
+ view.dispatch(
321
+ view.state.changeByRange((range) => ({
322
+ changes: [{ from: range.from, to: range.to, insert: '{#}' }],
323
+ range: EditorSelection.range(range.from + 2, range.to + 2),
324
+ })),
325
+ );
326
+ startCompletion(view);
327
+ return true;
328
+ },
329
+ },
330
+ ]);
331
+ }
332
+
333
+ firstUpdated() {
334
+ super.firstUpdated();
335
+ const parent = this.shadowRoot.querySelector(`[id=${this._id}]`);
336
+ this._editorState = EditorState.create({
337
+ doc: this.value,
338
+ extensions: this.getExtensions(),
339
+ });
340
+ this._editorView = new EditorView({
341
+ root: this.shadowRoot,
342
+ parent,
343
+ state: this._editorState,
344
+ });
345
+ parent.appendChild(this._editorView.dom);
346
+ }
347
+
348
+ async updated(properties) {
349
+ if (properties.has('placeholder')) {
350
+ this._editorView.dispatch({
351
+ effects: placeholderCompartment.reconfigure(placeholder(this.placeholder)),
352
+ });
353
+ }
354
+ if (properties.has('value')) {
355
+ this._editorState.update({ changes: { from: 0, to: this._editorState.doc.length, insert: this.value } });
356
+ }
357
+ if (properties.has('readonly')) {
358
+ this._editorView.dispatch({
359
+ effects: readonlyCompartment.reconfigure(EditorView.editable.of(!this.readonly)),
360
+ });
361
+ }
362
+
363
+ if (properties.has('options') && this.options) {
364
+ if (this.options.mode) {
365
+ const language = languages.find((language) => {
366
+ return language.name.toUpperCase() === this.options.mode.toUpperCase() || language.alias.includes(this.options.mode);
367
+ });
368
+ if (language != null) {
369
+ if (language.support == null) {
370
+ await language.load();
371
+ }
372
+ this._editorView.dispatch({
373
+ effects: languageCompartment.reconfigure(language.support.extension),
374
+ });
375
+ } else {
376
+ console.warn(
377
+ `Cannot find language ${this.options.mode}, please use language supported by CodeMirror 6`,
378
+ languages.map((l) => l.name),
379
+ );
380
+ }
381
+ }
382
+ }
383
+ }
384
+
385
+ static get styles() {
386
+ return [
387
+ // language=CSS
388
+ css`
389
+ :host {
390
+ box-sizing: border-box;
391
+ display: block;
392
+ margin: 0 0.2rem 0.2rem 0.2rem;
393
+ }
394
+
395
+ .singleLine .cm-gutters {
396
+ display: none;
397
+ }
398
+
399
+ .singleLine .cm-scroller {
400
+ overflow: hidden;
401
+ }
402
+ `,
403
+ ];
404
+ }
405
+ }
406
+
407
+ window.customElements.define('gv-code-editor', GvCodeEditor);
@@ -158,7 +158,8 @@ export class GvSchemaForm extends LitElement {
158
158
  const { resolve } = this._confirm;
159
159
  this._confirm = null;
160
160
  this._onReset();
161
- this.requestUpdate().then(() => {
161
+ this.requestUpdate();
162
+ this.updateComplete.then(() => {
162
163
  resolve(this);
163
164
  });
164
165
  }
@@ -268,6 +269,7 @@ export class GvSchemaForm extends LitElement {
268
269
  }
269
270
 
270
271
  async performUpdate() {
272
+ await Promise.all(this.getControls().map((e) => e.updateComplete));
271
273
  this.getControls().forEach((s) => {
272
274
  s.requestUpdate();
273
275
  });
@@ -287,7 +289,6 @@ export class GvSchemaForm extends LitElement {
287
289
  const isWriteOnly = control.writeOnly === true;
288
290
  const value = get(this._values, key);
289
291
  return html`<gv-schema-form-control
290
- data-a="dd"
291
292
  .id="${key}"
292
293
  .errors="${this.errors}"
293
294
  .control="${control}"
@@ -395,7 +396,11 @@ export class GvSchemaForm extends LitElement {
395
396
  }
396
397
  const keys = this.schema.properties ? Object.keys(this.schema.properties) : [];
397
398
  this._ignoreProperties = [];
398
- return repeat(keys, (key) => this._renderControl(key));
399
+ return repeat(
400
+ keys,
401
+ (key) => key,
402
+ (key) => this._renderControl(key),
403
+ );
399
404
  }
400
405
 
401
406
  getControls() {
@@ -486,8 +491,9 @@ export class GvSchemaForm extends LitElement {
486
491
  }
487
492
 
488
493
  async getUpdateComplete() {
489
- await super.getUpdateComplete();
494
+ const result = await super.getUpdateComplete();
490
495
  await Promise.all(this.getControls().map((e) => e.updateComplete));
496
+ return result;
491
497
  }
492
498
 
493
499
  render() {
@@ -14,7 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { css, html, LitElement } from 'lit';
17
- import { ref, createRef } from 'lit/directives/ref.js';
18
17
  import { methods } from '../lib/studio';
19
18
  import { dispatchCustomEvent } from '../lib/events';
20
19
  import '../atoms/gv-button';
@@ -32,7 +31,6 @@ import './gv-policy-studio-menu';
32
31
  import { empty } from '../styles/empty';
33
32
  import { cache } from 'lit/directives/cache';
34
33
  import { deepClone, deepEqual } from '../lib/utils';
35
- import { i18n } from '../lib/i18n';
36
34
  import { KeyboardElement, KEYS } from '../mixins/keyboard-element';
37
35
 
38
36
  const FLOW_STEP_FORM_ID = 'flow-step-form';
@@ -95,7 +93,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
95
93
  _currentPolicyId: { type: String, attribute: false },
96
94
  _searchPolicyQuery: { type: String, attribute: false },
97
95
  _searchFlowQuery: { type: String, attribute: false },
98
- _flowStepSchemas: { type: Object, attribute: false },
96
+ _flowStepSchema: { type: Object, attribute: false },
99
97
  _currentFlowStep: { type: Object, attribute: false },
100
98
  _policyFilter: { type: Array, attribute: false },
101
99
  _flowFilter: { type: Array, attribute: false },
@@ -207,17 +205,16 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
207
205
  border-right: 1px solid #d9d9d9;
208
206
  }
209
207
 
210
- .flow-step__form {
211
- overflow: auto;
208
+ .flow-step__container {
209
+ overflow: hidden;
210
+ position: relative;
211
+ overflow: hidden;
212
+ height: 99%;
212
213
  }
213
214
 
214
- .flow-step__form-h2 {
215
- font-size: 21px;
216
- font-weight: 600;
217
- padding-bottom: 0.3em;
218
- border-bottom: 1px solid #eaecef;
219
- margin-top: 24px;
220
- margin-bottom: 16px;
215
+ .flow-step__form {
216
+ padding: 0 0.5rem;
217
+ overflow: auto;
221
218
  }
222
219
 
223
220
  .flow-step__form-title {
@@ -225,10 +222,6 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
225
222
  letter-spacing: 0.2rem;
226
223
  }
227
224
 
228
- .flow-step__form-schema {
229
- margin: 0;
230
- }
231
-
232
225
  gv-tabs {
233
226
  width: 100%;
234
227
  height: 100%;
@@ -553,14 +546,8 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
553
546
  if (this._currentFlowStep != null && this._currentFlowStep.step._id === _id) {
554
547
  this._currentFlowStep.group = detail.flowKey;
555
548
  // Special case for update schema after change request to response or inverse
556
- await this._setCurrentFlowStep(
557
- this._currentFlowStep,
558
- {
559
- flowStepPolicySchema: this.buildPolicySchema(this._currentFlowStep.policy),
560
- flowStepCommonSchema: this.buildCommonSchema(),
561
- },
562
- true,
563
- );
549
+ const schema = this.buildSchema(this._currentFlowStep.policy);
550
+ await this._setCurrentFlowStep(this._currentFlowStep, schema, true);
564
551
  this._getFlowElement(targetFlow._id).requestUpdate();
565
552
  }
566
553
  } else {
@@ -627,21 +614,17 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
627
614
  this._splitMainViews();
628
615
  }
629
616
 
630
- buildPolicySchema({ schema }) {
631
- if (schema) {
632
- const jsonSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
633
- const properties = { ...jsonSchema.properties };
634
- return { ...jsonSchema, properties };
635
- }
636
- return { properties: {} };
637
- }
638
-
639
- buildCommonSchema() {
617
+ buildSchema({ schema }) {
640
618
  const description = {
641
619
  title: 'Description',
642
620
  description: 'Description of flow step',
643
621
  type: 'string',
644
622
  };
623
+ if (schema) {
624
+ const jsonSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
625
+ const properties = { description, ...jsonSchema.properties };
626
+ return { ...jsonSchema, properties };
627
+ }
645
628
  return { properties: { description } };
646
629
  }
647
630
 
@@ -649,11 +632,9 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
649
632
  if (step) {
650
633
  this._currentPolicyId = policy.id;
651
634
  const currentFlowStep = { flow, step, policy, group };
635
+ const schema = this.buildSchema(policy);
652
636
  try {
653
- await this._setCurrentFlowStep(currentFlowStep, {
654
- flowStepPolicySchema: this.buildPolicySchema(policy),
655
- flowStepCommonSchema: this.buildCommonSchema(),
656
- });
637
+ await this._setCurrentFlowStep(currentFlowStep, schema);
657
638
  this._updateSelectedFlows([flow._id]);
658
639
  this._splitMainViews();
659
640
  if (localStorage.getItem('gv-policy-studio:keep-documentation-close') == null) {
@@ -707,7 +688,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
707
688
  }
708
689
 
709
690
  async _closeFlowStepForm(force = false) {
710
- await this._setCurrentFlowStep(null, {}, force);
691
+ await this._setCurrentFlowStep(null, null, force);
711
692
  }
712
693
 
713
694
  async _askToValidateForms() {
@@ -734,13 +715,12 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
734
715
  throw new Error('ask already waiting');
735
716
  }
736
717
 
737
- async _setCurrentFlowStep(currentFlowStep, { flowStepPolicySchema, flowStepCommonSchema }, force = false) {
718
+ async _setCurrentFlowStep(currentFlowStep, flowStepSchema, force = false) {
738
719
  if (!force) {
739
720
  await this._askToValidateForms();
740
721
  }
741
722
 
742
- const policySchema = deepClone(flowStepPolicySchema);
743
- const commonSchema = deepClone(flowStepCommonSchema);
723
+ const schema = deepClone(flowStepSchema);
744
724
  if (currentFlowStep != null) {
745
725
  const configuration =
746
726
  typeof currentFlowStep.step.configuration === 'string'
@@ -748,22 +728,21 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
748
728
  : currentFlowStep.step.configuration;
749
729
  const step = { ...currentFlowStep.step, configuration };
750
730
 
751
- const _initialPolicyValues = { ...step.configuration };
752
- const _initialCommonValues = { description: step.description };
753
- this._currentFlowStep = { ...currentFlowStep, step, _initialPolicyValues, _initialCommonValues };
731
+ const _initialValues = { ...step.configuration, description: step.description };
732
+ this._currentFlowStep = { ...currentFlowStep, step, _initialValues };
754
733
 
755
- if (flowStepPolicySchema && flowStepPolicySchema.properties.scope) {
756
- const _enum = policySchema.properties.scope.enum;
734
+ if (flowStepSchema && flowStepSchema.properties.scope) {
735
+ const _enum = schema.properties.scope.enum;
757
736
  if (_enum.find((scope) => ['REQUEST', 'REQUEST_CONTENT', 'RESPONSE', 'RESPONSE_CONTENT'].includes(scope)) != null) {
758
737
  const filtered = this._currentFlowStep.group === 'pre' ? ['REQUEST', 'REQUEST_CONTENT'] : ['RESPONSE', 'RESPONSE_CONTENT'];
759
- policySchema.properties.scope.enum = _enum.filter((scope) => filtered.includes(scope));
738
+ schema.properties.scope.enum = _enum.filter((scope) => filtered.includes(scope));
760
739
  const scope = this._currentFlowStep.step.configuration.scope;
761
- if (scope == null || !policySchema.properties.scope.enum.includes(scope)) {
762
- policySchema.properties.scope.default = policySchema.properties.scope.enum[0];
763
- this._currentFlowStep.step.configuration.scope = policySchema.properties.scope.enum[0];
764
- this._currentFlowStep._initialPolicyValues.scope = policySchema.properties.scope.enum[0];
765
- if (this._currentFlowStep._policyValues) {
766
- this._currentFlowStep._policyValues.scope = policySchema.properties.scope.enum[0];
740
+ if (scope == null || !schema.properties.scope.enum.includes(scope)) {
741
+ schema.properties.scope.default = schema.properties.scope.enum[0];
742
+ this._currentFlowStep.step.configuration.scope = schema.properties.scope.enum[0];
743
+ this._currentFlowStep._initialValues.scope = schema.properties.scope.enum[0];
744
+ if (this._currentFlowStep._values) {
745
+ this._currentFlowStep._values.scope = schema.properties.scope.enum[0];
767
746
  }
768
747
  }
769
748
  }
@@ -772,13 +751,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
772
751
  this._currentFlowStep = null;
773
752
  }
774
753
 
775
- this._flowStepSchemas =
776
- flowStepPolicySchema && flowStepCommonSchema
777
- ? {
778
- commonSchema,
779
- policySchema,
780
- }
781
- : null;
754
+ this._flowStepSchema = schema;
782
755
  }
783
756
 
784
757
  _refresh(closeStepForm = true) {
@@ -856,18 +829,12 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
856
829
  }
857
830
  }
858
831
 
859
- _onChangeFlowStepPolicy({ detail }) {
860
- this._currentFlowStep._policyValues = detail.values;
861
- }
862
-
863
- _onChangeFlowStepCommon({ detail }) {
864
- this._currentFlowStep._commonValues = detail.values;
832
+ _onChangeFlowStep({ detail }) {
833
+ this._currentFlowStep._values = detail.values;
865
834
  }
866
835
 
867
- _writeFlowStep() {
868
- const configuration = this._currentFlowStep._policyValues;
869
- const { description } = this._currentFlowStep._commonValues;
870
-
836
+ _writeFlowStep(values) {
837
+ const { description, ...configuration } = values;
871
838
  if (
872
839
  this._currentFlowStep.step._new ||
873
840
  this._currentFlowStep.step.description !== description ||
@@ -887,8 +854,8 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
887
854
  }
888
855
  }
889
856
 
890
- async _onSubmitFlowStep() {
891
- this._writeFlowStep();
857
+ async _onSubmitFlowStep({ detail }) {
858
+ this._writeFlowStep(detail.values);
892
859
  await this.requestUpdate('_definition');
893
860
  this.getChildren().forEach((c) => c.requestUpdate());
894
861
  }
@@ -1019,7 +986,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1019
986
  }
1020
987
 
1021
988
  _renderPolicy(readonlyMode) {
1022
- if (this._flowStepSchemas && this.documentation) {
989
+ if (this._flowStepSchema && this.documentation) {
1023
990
  return html`<gv-resizable-views direction="horizontal" no-overflow>
1024
991
  <div slot="top">${this._renderFlowStepForm(readonlyMode)}</div>
1025
992
  <div slot="bottom">
@@ -1038,7 +1005,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1038
1005
  ?disabled="${this._currentAskConfirmation}"
1039
1006
  @gv-documentation:close="${this._onCloseDocumentation}"
1040
1007
  ></gv-documentation>`;
1041
- } else if (this._flowStepSchemas) {
1008
+ } else if (this._flowStepSchema) {
1042
1009
  return this._renderFlowStepForm(readonlyMode);
1043
1010
  }
1044
1011
  return html``;
@@ -1050,8 +1017,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1050
1017
 
1051
1018
  _onResetFlowStep() {
1052
1019
  if (this._currentFlowStep) {
1053
- delete this._currentFlowStep._policyValues;
1054
- delete this._currentFlowStep._commonValues;
1020
+ delete this._currentFlowStep._values;
1055
1021
  this._getFlowStepForm().reset();
1056
1022
  }
1057
1023
  }
@@ -1121,27 +1087,27 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1121
1087
  }
1122
1088
 
1123
1089
  _renderFlowStepForm(readonlyMode) {
1124
- const policyValues = this._currentFlowStep._policyValues || this._currentFlowStep._initialPolicyValues;
1125
- const commonValues = this._currentFlowStep._commonValues || this._currentFlowStep._initialCommonValues;
1126
-
1127
- const gvSchemaFormPolicyRef = createRef();
1128
- const gvSchemaFormCommonRef = createRef();
1129
-
1130
- const submitPolicySchemaForm = () => {
1131
- gvSchemaFormPolicyRef.value._onSubmit();
1132
- gvSchemaFormCommonRef.value._onSubmit();
1133
- };
1134
-
1135
- const resetPolicySchemaForm = () => {
1136
- gvSchemaFormPolicyRef.value._onReset();
1137
- gvSchemaFormCommonRef.value._onReset();
1138
- };
1139
-
1090
+ const values = this._currentFlowStep._values || this._currentFlowStep._initialValues;
1140
1091
  return html`${cache(
1141
- this._flowStepSchemas && this._currentFlowStep
1142
- ? html`
1143
- <gv-scroll-layout class="flow-step__form">
1144
- <div slot="header-left">
1092
+ this._flowStepSchema && this._currentFlowStep
1093
+ ? html`<div class="flow-step__container">
1094
+ <div class="flow-step__form">
1095
+ <gv-schema-form
1096
+ .id="${FLOW_STEP_FORM_ID}"
1097
+ .schema="${this._flowStepSchema}"
1098
+ .icon="design:edit"
1099
+ has-header
1100
+ validate-on-render
1101
+ .values="${values}"
1102
+ .dirty="${this._currentFlowStep._values != null}"
1103
+ ?readonly="${readonlyMode}"
1104
+ scrollable
1105
+ @gv-schema-form:change="${this._onChangeFlowStep}"
1106
+ @gv-schema-form:reset="${this._onResetFlowStep}"
1107
+ @gv-schema-form:fetch-resources="${this._onFetchResources}"
1108
+ @gv-schema-form:submit="${this._onSubmitFlowStep}"
1109
+ >
1110
+ <div slot="title" class="flow-step__form-title">${this._currentFlowStep.step.name}</div>
1145
1111
  <gv-button
1146
1112
  slot="header-left"
1147
1113
  icon="general:close"
@@ -1159,60 +1125,9 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1159
1125
  @gv-button:click="${this._onOpenDocumentationFromForm}"
1160
1126
  title="Open documentation"
1161
1127
  ></gv-button>
1162
- </div>
1163
-
1164
- <div slot="header-title" class="flow-step__form-title">${this._currentFlowStep.step.name}</div>
1165
-
1166
- <div slot="header-right">
1167
- <gv-button
1168
- id="reset"
1169
- outlined
1170
- small
1171
- @gv-button:click="${resetPolicySchemaForm}"
1172
- icon="general:update"
1173
- title="Reset"
1174
- ></gv-button>
1175
-
1176
- <gv-button id="submit" small @gv-button:click="${submitPolicySchemaForm}" icon="code:check" .title="Ok"></gv-button>
1177
- </div>
1178
-
1179
- <div slot="content">
1180
- <h2 class="flow-step__form-h2">${i18n('gv-policy-studio.common-settings')}</h2>
1181
- <gv-schema-form
1182
- ${ref(gvSchemaFormCommonRef)}
1183
- class="flow-step__form-schema"
1184
- .id="${FLOW_STEP_FORM_ID}"
1185
- .schema="${this._flowStepSchemas.commonSchema}"
1186
- .icon="design:edit"
1187
- validate-on-render
1188
- .values="${commonValues}"
1189
- .dirty="${this._currentFlowStep._commonValues != null}"
1190
- ?readonly="${readonlyMode}"
1191
- @gv-schema-form:change="${this._onChangeFlowStepCommon}"
1192
- @gv-schema-form:reset="${this._onResetFlowStep}"
1193
- @gv-schema-form:fetch-resources="${this._onFetchResources}"
1194
- @gv-schema-form:submit="${this._onSubmitFlowStep}"
1195
- ></gv-schema-form>
1196
-
1197
- <h2 class="flow-step__form-h2">${i18n('gv-policy-studio.policy-settings')}</h2>
1198
- <gv-schema-form
1199
- ${ref(gvSchemaFormPolicyRef)}
1200
- class="flow-step__form-schema"
1201
- .id="${FLOW_STEP_FORM_ID}"
1202
- .schema="${this._flowStepSchemas.policySchema}"
1203
- .icon="design:edit"
1204
- validate-on-render
1205
- .values="${policyValues}"
1206
- .dirty="${this._currentFlowStep._policyValues != null}"
1207
- ?readonly="${readonlyMode}"
1208
- @gv-schema-form:change="${this._onChangeFlowStepPolicy}"
1209
- @gv-schema-form:reset="${this._onResetFlowStep}"
1210
- @gv-schema-form:fetch-resources="${this._onFetchResources}"
1211
- @gv-schema-form:submit="${this._onSubmitFlowStep}"
1212
- ></gv-schema-form>
1213
- </div>
1214
- </gv-scroll-layout>
1215
- `
1128
+ </gv-schema-form>
1129
+ </div>
1130
+ </div>`
1216
1131
  : '',
1217
1132
  )}`;
1218
1133
  }
@@ -1733,7 +1648,7 @@ export class GvPolicyStudio extends KeyboardElement(LitElement) {
1733
1648
  }
1734
1649
 
1735
1650
  _renderFlowForm(readonlyMode) {
1736
- if (this.flowSchema && this._flowStepSchemas == null && this.documentation == null && this.selectedFlowsId.length === 1) {
1651
+ if (this.flowSchema && this._flowStepSchema == null && this.documentation == null && this.selectedFlowsId.length === 1) {
1737
1652
  const flow = this.getSelectedFlow();
1738
1653
  if (flow) {
1739
1654
  const values = deepClone(flow);
@@ -0,0 +1 @@
1
+ import '../src/molecules/gv-code-editor';
@@ -1,129 +0,0 @@
1
- /*
2
- * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
- import { css, LitElement, html } from 'lit';
17
- import { classMap } from 'lit-html/directives/class-map';
18
- import { skeleton } from '../styles/skeleton';
19
-
20
- /**
21
- * Scroll layout component
22
- *
23
- * ## Details
24
- * * has @theme facet
25
- *
26
- */
27
- export class GvScrollLayout extends LitElement {
28
- static get properties() {
29
- return {
30
- skeleton: { type: Boolean },
31
- };
32
- }
33
-
34
- static get styles() {
35
- return [
36
- // language=CSS
37
- css`
38
- :host {
39
- box-sizing: border-box;
40
- position: relative;
41
- }
42
-
43
- .container {
44
- display: flex;
45
- flex-direction: column;
46
-
47
- /* for Firefox */
48
- min-height: 0;
49
- height: 100%;
50
- }
51
-
52
- .header,
53
- .content {
54
- background-color: var(--bgc);
55
- }
56
-
57
- .header {
58
- display: flex;
59
- border-bottom: 1px solid #d9d9d9;
60
- box-sizing: border-box;
61
- min-height: 45px;
62
- --gv-icon--s: 26px;
63
- align-items: center;
64
- padding: 0 1rem;
65
- position: relative;
66
- }
67
-
68
- .header .left,
69
- .header .right {
70
- display: flex;
71
- flex: 1;
72
- z-index: 10;
73
- align-items: center;
74
- }
75
-
76
- .header .right {
77
- justify-content: flex-end;
78
- }
79
-
80
- .header .title {
81
- color: #28444f;
82
- font-size: 18px;
83
- display: flex;
84
- width: 100%;
85
- align-items: center;
86
- }
87
-
88
- .content {
89
- box-sizing: border-box;
90
- align-self: center;
91
- width: 100%;
92
- overflow: auto;
93
- max-width: 775px;
94
- padding: 0px 0.5rem;
95
-
96
- /* for Firefox */
97
- min-height: 0;
98
- }
99
-
100
- .content.empty {
101
- display: none;
102
- }
103
- `,
104
- skeleton,
105
- ];
106
- }
107
-
108
- render() {
109
- return html`
110
- <div class="container">
111
- <div class="header">
112
- <div class="left">
113
- <slot name="header-left"></slot>
114
- </div>
115
- <div class="header-title">
116
- <slot name="header-title"></slot>
117
- </div>
118
- <div class="right">
119
- <slot name="header-right"></slot>
120
- </div>
121
- </div>
122
-
123
- <div class="${classMap({ content: true, empty: this.skeleton })}"><slot name="content"></slot></div>
124
- </div>
125
- `;
126
- }
127
- }
128
-
129
- window.customElements.define('gv-scroll-layout', GvScrollLayout);
@@ -1 +0,0 @@
1
- import '../src/molecules/gv-scroll-layout';