@things-factory/integration-ui 5.0.0-alpha.3 → 5.0.0-alpha.32

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.
@@ -1,610 +0,0 @@
1
- import '@material/mwc-button'
2
-
3
- import { css, html, LitElement } from 'lit'
4
-
5
- import { i18next } from '@operato/i18n'
6
- import { ScrollbarStyles } from '@operato/styles'
7
-
8
- function createCronRegex(type) {
9
- // https://gist.github.com/dkandalov/a2aed17cfdeb65243022
10
- var regexByField = {}
11
- regexByField['sec'] = '[0-5]?\\d'
12
- regexByField['min'] = '[0-5]?\\d'
13
- regexByField['hour'] = '[01]?\\d|2[0-3]'
14
- regexByField['day'] = '0?[1-9]|[12]\\d|3[01]'
15
- regexByField['month'] = '[1-9]|1[012]'
16
- regexByField['dayOfWeek'] = '[0-7]'
17
-
18
- var crontabFields = [type]
19
- if (!type) crontabFields = ['sec', 'min', 'hour', 'day', 'month', 'dayOfWeek']
20
-
21
- crontabFields.forEach(field => {
22
- var number = regexByField[field]
23
- var range =
24
- '(?:' +
25
- number +
26
- ')' +
27
- '(?:' +
28
- '(?:-|/|,' +
29
- ('dayOfWeek' === field ? '|#' : '') +
30
- ')' +
31
- '(?:' +
32
- number +
33
- ')' +
34
- ')?'
35
- if (field === 'dayOfWeek') range += '(?:L)?'
36
- if (field === 'month') range += '(?:L|W)?'
37
- regexByField[field] = '\\?|\\*|' + range + '(?:,' + range + ')*'
38
- })
39
-
40
- var monthValues = 'JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC'
41
- var monthRange = '(?:' + monthValues + ')(?:(?:-)(?:' + monthValues + '))?'
42
- regexByField['month'] += '|\\?|\\*|' + monthRange + '(?:,' + monthRange + ')*'
43
-
44
- var dayOfWeekValues = 'MON|TUE|WED|THU|FRI|SAT|SUN'
45
- var dayOfWeekRange = '(?:' + dayOfWeekValues + ')(?:(?:-)(?:' + dayOfWeekValues + '))?'
46
- regexByField['dayOfWeek'] += '|\\?|\\*|' + dayOfWeekRange + '(?:,' + dayOfWeekRange + ')*'
47
-
48
- if (!type)
49
- return (
50
- '^\\s*($' +
51
- '|#' +
52
- '|\\w+\\s*=' +
53
- '|' +
54
- '(' +
55
- regexByField['sec'] +
56
- ')\\s+' +
57
- '(' +
58
- regexByField['min'] +
59
- ')\\s+' +
60
- '(' +
61
- regexByField['hour'] +
62
- ')\\s+' +
63
- '(' +
64
- regexByField['day'] +
65
- ')\\s+' +
66
- '(' +
67
- regexByField['month'] +
68
- ')\\s+' +
69
- '(' +
70
- regexByField['dayOfWeek'] +
71
- ')(|\\s)+' +
72
- ')$'
73
- )
74
- else return `^${regexByField[type]}$`
75
- }
76
-
77
- export class CrontabEditorPopup extends LitElement {
78
- static get properties() {
79
- return {
80
- valueString: String,
81
- second: String,
82
- minute: String,
83
- hour: String,
84
- dayOfMonth: String,
85
- month: String,
86
- dayOfWeek: String,
87
- _tooltip: Array
88
- }
89
- }
90
-
91
- static get styles() {
92
- return [
93
- ScrollbarStyles,
94
- css`
95
- :host {
96
- display: block;
97
- width: 100%;
98
- height: 100%;
99
- border: 0;
100
- background-color: var(--main-section-background-color);
101
- }
102
-
103
- :host * {
104
- box-sizing: border-box;
105
- }
106
- :host *:focus {
107
- outline: none;
108
- }
109
-
110
- form {
111
- display: grid;
112
- width: 100%;
113
- height: 100%;
114
- padding: 1rem;
115
- grid-template: auto auto 1fr auto / repeat(6, 1fr);
116
- grid-gap: 0.5rem;
117
- justify-content: center;
118
- align-items: center;
119
- overflow: auto;
120
- }
121
-
122
- label[for='example'] {
123
- text-align: right;
124
- grid-column: 3;
125
- font: normal 1em var(--theme-font);
126
- color: var(--secondary-color);
127
- text-transform: capitalize;
128
- }
129
-
130
- #example {
131
- grid-column: 4 / span 3;
132
- width: 100%;
133
- height: 100%;
134
- font: normal 0.9em var(--theme-font);
135
- text-transform: capitalize;
136
- border-radius: var(--border-radius);
137
- border: var(--border-dark-color);
138
- }
139
-
140
- input {
141
- width: 100%;
142
- margin-top: var(--margin-default);
143
- padding: 5px;
144
- border-radius: var(--border-radius);
145
- border: var(--border-dark-color);
146
- font: normal 1em var(--theme-font);
147
- }
148
- input:focus {
149
- border: 1px solid var(--primary-color);
150
- }
151
-
152
- input:invalid {
153
- border: 1px solid var(--status-danger-color);
154
- color: var(--status-danger-color);
155
- }
156
-
157
- label {
158
- width: 100%;
159
- height: 100%;
160
- font: normal 0.8em var(--theme-font);
161
- color: var(--primary-color);
162
- }
163
-
164
- label:not([for='example']) {
165
- text-align: center;
166
- }
167
-
168
- #input-wrapper {
169
- grid-column: span 6;
170
- display: flex;
171
- flex-wrap: wrap;
172
- margin: 0 -0.25rem;
173
- }
174
-
175
- #input-wrapper > div {
176
- flex: 1;
177
- display: grid;
178
- grid-template-rows: 1fr auto;
179
- grid-gap: 0.5rem;
180
- min-width: 60px;
181
- max-width: 33%;
182
- margin: 0.25rem;
183
- }
184
-
185
- #tooltip {
186
- grid-column: span 6;
187
- display: grid;
188
- grid-template-columns: auto 1fr;
189
- grid-gap: 0;
190
- margin: auto;
191
- grid-auto-rows: min-content;
192
- align-self: center;
193
- align-items: center;
194
- }
195
-
196
- #tooltip > div {
197
- padding: 0.25rem 0.5rem;
198
- border-bottom: #ccc 1px dashed;
199
- font: normal 0.9em var(--theme-font);
200
- }
201
-
202
- #tooltip > .crontab-value {
203
- text-align: right;
204
- color: var(--secondary-color);
205
- }
206
-
207
- #tooltip > .crontab-description {
208
- text-align: left;
209
- color: #585858;
210
- }
211
-
212
- #button-wrapper {
213
- grid-column: 1 / span 6;
214
- display: flex;
215
- flex-wrap: wrap-reverse;
216
- flex-direction: row-reverse;
217
- margin: -0.25rem;
218
- }
219
-
220
- mwc-button {
221
- background-color: var(--secondary-color);
222
- border-radius: var(--button-border-radius);
223
- --mdc-theme-primary: #fff;
224
- margin: 0.25rem;
225
- }
226
- mwc-button:hover,
227
- mwc-button:active {
228
- background-color: var(--primary-color);
229
- }
230
- `
231
- ]
232
- }
233
-
234
- render() {
235
- return html`
236
- <form
237
- @keydown=${e => {
238
- if (e.key === 'Tab') {
239
- e.stopPropagation()
240
- e.preventDefault()
241
- var focused = this.renderRoot.querySelector(':focus')
242
- var focusedIdx = this.focusableElements.findIndex(el => el == focused)
243
- var nextFocusIdx = (e.shiftKey ? focusedIdx - 1 : focusedIdx + 1) % this.focusableElements.length
244
- if (nextFocusIdx == -1) nextFocusIdx = this.focusableElements.length - 1
245
-
246
- this.focusableElements[nextFocusIdx].focus()
247
- } else if (e.key == 'Enter') {
248
- e.stopPropagation()
249
- e.preventDefault()
250
- this.confirm()
251
- }
252
- }}
253
- >
254
- <label for="example">${i18next.t('label.examples')}</label>
255
- <select id="example" @change=${e => (this.valueString = e.currentTarget.value)} .value=${this.valueString}>
256
- <optgroup label="${i18next.t('label.second by second')}">
257
- <option value="* * * * * *">${i18next.t('text.every second')}</option>
258
- <option value="0/2 * * * * *">${i18next.t('text.every 2 seconds')}</option>
259
- <option value="0/15 * * * * *">${i18next.t('text.every 15 seconds')}</option>
260
- <option value="0/30 * * * * *">${i18next.t('text.every 30 seconds')}</option>
261
- </optgroup>
262
- <optgroup label="${i18next.t('label.minute by minute')}">
263
- <option value="0 * * * * *">${i18next.t('text.every minute')}</option>
264
- <option value="0 0/2 * * * *">${i18next.t('text.every 2 minutes')}</option>
265
- <option value="0 0/15 * * * *">${i18next.t('text.every 15 minutes')}</option>
266
- <option value="0 0/30 * * * *">${i18next.t('text.every half hour')}</option>
267
- </optgroup>
268
- <optgroup label="${i18next.t('label.hourly')}">
269
- <option value="0 0 * * * *">${i18next.t('text.every hour')}</option>
270
- <option value="0 0 0/2 * * *">${i18next.t('text.every 2 hours')}</option>
271
- <option value="0 0 0/12 * * *">${i18next.t('text.every 12 hours')}</option>
272
- <option value="0 0 10-19 * * *">${i18next.t('text.every hour during working time')}</option>
273
- </optgroup>
274
- <optgroup label="${i18next.t('label.daily')}">
275
- <option value="0 0 0 * * *">${i18next.t('text.every day')}</option>
276
- </optgroup>
277
- <optgroup label="${i18next.t('label.weekly')}">
278
- <option value="0 0 0 * * SUN">${i18next.t('text.every sunday')}</option>
279
- <option value="0 0 0 * * 0">${i18next.t('text.every sunday(2)')}</option>
280
- <option value="0 0 0 * * 1-5">${i18next.t('text.every weekday')}</option>
281
- </optgroup>
282
- <optgroup label="${i18next.t('label.monthly')}">
283
- <option value="0 0 0 1 * *">${i18next.t('text.the first day of every month')}</option>
284
- <option value="0 0 10 21 * *">${i18next.t('text.10 am on every payday')}</option>
285
- </optgroup>
286
- <optgroup label="${i18next.t('label.yearly')}">
287
- <option value="0 0 0 1 1 *">${i18next.t('text.the first day of every year')}</option>
288
- <option value="0 0 0 25 12 *">${i18next.t('text.every christmas')}</option>
289
- </optgroup>
290
- </select>
291
- <div id="input-wrapper">
292
- <div>
293
- <input
294
- id="second-input"
295
- class="second"
296
- type="text"
297
- .value=${this.second || ''}
298
- @input=${e => (this.second = e.currentTarget.value)}
299
- @focus=${e => {
300
- this.showTooltip({ type: 'second' })
301
- }}
302
- pattern="${createCronRegex('sec')}"
303
- required
304
- />
305
- <label for="second-input" class="second">${i18next.t('label.second')}</label>
306
- </div>
307
- <div>
308
- <input
309
- id="minute-input"
310
- class="minute"
311
- type="text"
312
- .value=${this.minute || ''}
313
- @input=${e => (this.minute = e.currentTarget.value)}
314
- @focus=${e => {
315
- this.showTooltip({ type: 'minute' })
316
- }}
317
- pattern="${createCronRegex('min')}"
318
- required
319
- />
320
- <label for="minute-input" class="minute">${i18next.t('label.minute')}</label>
321
- </div>
322
- <div>
323
- <input
324
- id="hour-input"
325
- class="hour"
326
- type="text"
327
- .value=${this.hour || ''}
328
- @input=${e => (this.hour = e.currentTarget.value)}
329
- @focus=${e => {
330
- this.showTooltip({ type: 'hour' })
331
- }}
332
- pattern="${createCronRegex('hour')}"
333
- required
334
- />
335
- <label for="hour-input" class="hour">${i18next.t('label.hour')}</label>
336
- </div>
337
- <div>
338
- <input
339
- id="day-of-month-input"
340
- class="day-of-month"
341
- type="text"
342
- .value=${this.dayOfMonth || ''}
343
- @input=${e => (this.dayOfMonth = e.currentTarget.value)}
344
- @focus=${e => {
345
- this.showTooltip({ type: 'dayOfMonth' })
346
- }}
347
- pattern="${createCronRegex('day')}"
348
- required
349
- />
350
- <label for="day-of-month-input" class="day-of-month">${i18next.t('label.day-of-month')}</label>
351
- </div>
352
- <div>
353
- <input
354
- id="month-input"
355
- class="month"
356
- type="text"
357
- .value=${this.month || ''}
358
- @input=${e => (this.month = e.currentTarget.value)}
359
- @focus=${e => {
360
- this.showTooltip({ type: 'month' })
361
- }}
362
- pattern="${createCronRegex('month')}"
363
- required
364
- />
365
- <label for="month-input" class="month">${i18next.t('label.month')}</label>
366
- </div>
367
- <div>
368
- <input
369
- id="day-of-week-input"
370
- class="day-of-week"
371
- type="text"
372
- .value=${this.dayOfWeek || ''}
373
- @input=${e => (this.dayOfWeek = e.currentTarget.value)}
374
- @focus=${e => {
375
- this.showTooltip({ type: 'dayOfWeek' })
376
- }}
377
- pattern="${createCronRegex('dayOfWeek')}"
378
- required
379
- />
380
- <label for="day-of-week-input" class="day-of-week">${i18next.t('label.day-of-week')}</label>
381
- </div>
382
- </div>
383
- <div id="tooltip">
384
- ${this._tooltip.map(
385
- tip => html`
386
- <div class="crontab-value">${tip.value}</div>
387
- <div class="crontab-description">${i18next.t(`text.${tip.description}`)}</div>
388
- `
389
- )}
390
- </div>
391
- <div id="button-wrapper">
392
- <mwc-button
393
- icon="done"
394
- .label="${i18next.t('label.confirm')}"
395
- @click=${e => {
396
- this.confirm()
397
- }}
398
- ></mwc-button>
399
- <mwc-button
400
- icon="clear"
401
- .label="${i18next.t('label.clear')}"
402
- @click=${e => {
403
- this.dispatchEvent(
404
- new CustomEvent('crontab-changed', {
405
- bubbles: true,
406
- composed: true,
407
- detail: {
408
- value: ``
409
- }
410
- })
411
- )
412
- }}
413
- ></mwc-button>
414
- </div>
415
- </form>
416
- `
417
- }
418
-
419
- get focusableElements() {
420
- return Array.from(this.renderRoot.querySelectorAll('select, input, mwc-button'))
421
- }
422
-
423
- connectedCallback() {
424
- super.connectedCallback()
425
-
426
- this._tooltip = []
427
- }
428
-
429
- firstUpdated() {
430
- this.renderRoot.querySelector('input').focus()
431
- }
432
-
433
- updated(changed) {
434
- if (changed.has('valueString')) {
435
- var values = this.valueString.split(' ')
436
-
437
- if (values.length == 1) values = ['*', '*', '*', '*', '*', '*']
438
- else if (values.length == 5) values = ['0'].concat(values)
439
-
440
- this.second = values[0]
441
- this.minute = values[1]
442
- this.hour = values[2]
443
- this.dayOfMonth = values[3]
444
- this.month = values[4]
445
- this.dayOfWeek = values[5]
446
- }
447
- }
448
-
449
- showTooltip({ type }) {
450
- switch (type) {
451
- case 'second':
452
- case 'minute':
453
- this._tooltip = [
454
- {
455
- value: '*',
456
- description: 'any value'
457
- },
458
- {
459
- value: ',',
460
- description: 'value list separator'
461
- },
462
- {
463
- value: '-',
464
- description: 'range of values'
465
- },
466
- {
467
- value: '/',
468
- description: 'step values'
469
- },
470
- {
471
- value: '0-59',
472
- description: 'allowed values'
473
- }
474
- ]
475
- break
476
- case 'hour':
477
- this._tooltip = [
478
- {
479
- value: '*',
480
- description: 'any value'
481
- },
482
- {
483
- value: ',',
484
- description: 'value list separator'
485
- },
486
- {
487
- value: '-',
488
- description: 'range of values'
489
- },
490
- {
491
- value: '/',
492
- description: 'step values'
493
- },
494
- {
495
- value: '0-23',
496
- description: 'allowed values'
497
- }
498
- ]
499
- break
500
-
501
- case 'dayOfMonth':
502
- this._tooltip = [
503
- {
504
- value: '*',
505
- description: 'any value'
506
- },
507
- {
508
- value: ',',
509
- description: 'value list separator'
510
- },
511
- {
512
- value: '-',
513
- description: 'range of values'
514
- },
515
- {
516
- value: '/',
517
- description: 'step values'
518
- },
519
- {
520
- value: '1-31',
521
- description: 'allowed values'
522
- }
523
- ]
524
- break
525
-
526
- case 'month':
527
- this._tooltip = [
528
- {
529
- value: '*',
530
- description: 'any value'
531
- },
532
- {
533
- value: ',',
534
- description: 'value list separator'
535
- },
536
- {
537
- value: '-',
538
- description: 'range of values'
539
- },
540
- {
541
- value: '/',
542
- description: 'step values'
543
- },
544
- {
545
- value: '1-12',
546
- description: 'allowed values'
547
- },
548
- {
549
- value: 'JAN-DEC',
550
- description: 'alternative single values'
551
- }
552
- ]
553
- break
554
-
555
- case 'dayOfWeek':
556
- this._tooltip = [
557
- {
558
- value: '*',
559
- description: 'any value'
560
- },
561
- {
562
- value: ',',
563
- description: 'value list separator'
564
- },
565
- {
566
- value: '-',
567
- description: 'range of values'
568
- },
569
- {
570
- value: '/',
571
- description: 'step values'
572
- },
573
- {
574
- value: '0-6',
575
- description: 'allowed values'
576
- },
577
- {
578
- value: 'SUN-SAT',
579
- description: 'alternative single values'
580
- }
581
- ]
582
- break
583
-
584
- default:
585
- this._tooltip = []
586
- break
587
- }
588
- }
589
-
590
- confirm() {
591
- var form = this.renderRoot.querySelector('form')
592
- var valid = form.checkValidity()
593
- if (!valid) {
594
- form.reportValidity()
595
- return
596
- }
597
-
598
- this.dispatchEvent(
599
- new CustomEvent('crontab-changed', {
600
- bubbles: true,
601
- composed: true,
602
- detail: {
603
- value: `${this.second} ${this.minute} ${this.hour} ${this.dayOfMonth} ${this.month} ${this.dayOfWeek}`
604
- }
605
- })
606
- )
607
- }
608
- }
609
-
610
- customElements.define('crontab-editor-popup', CrontabEditorPopup)
@@ -1,65 +0,0 @@
1
- import '@material/mwc-button'
2
- import '@material/mwc-fab'
3
- import '@material/mwc-icon'
4
- import './crontab-editor-popup'
5
-
6
- import { html } from 'lit'
7
-
8
- import { InputEditor } from '@operato/data-grist'
9
- import { i18next } from '@operato/i18n'
10
- import { openPopup } from '@operato/layout'
11
-
12
- export class CrontabEditor extends InputEditor {
13
- get editorTemplate() {
14
- return html` <input type="text" .value=${this.value || ''} /> `
15
- }
16
-
17
- async firstUpdated() {
18
- await this.updateComplete
19
-
20
- this.shadowRoot.addEventListener('click', e => {
21
- e.stopPropagation()
22
-
23
- this.showEditorPopup()
24
- })
25
-
26
- this.showEditorPopup()
27
- }
28
-
29
- showEditorPopup() {
30
- var change = value => {
31
- this.dispatchEvent(
32
- new CustomEvent('field-change', {
33
- bubbles: true,
34
- composed: true,
35
- detail: {
36
- before: this.value,
37
- after: value,
38
- column: this.column,
39
- record: this.record,
40
- row: this.row
41
- }
42
- })
43
- )
44
- }
45
-
46
- var popup = openPopup(
47
- html`
48
- <crontab-editor-popup
49
- .valueString=${this.value}
50
- @crontab-changed=${e => {
51
- change(e.detail.value)
52
- popup.close()
53
- }}
54
- ></crontab-editor-popup>
55
- `,
56
- {
57
- backdrop: true,
58
- title: i18next.t('title.setting schedule'),
59
- help: 'integration/ui/crontab-editor'
60
- }
61
- )
62
- }
63
- }
64
-
65
- window.customElements.define('crontab-editor', CrontabEditor)