@nyaruka/temba-components 0.26.1 → 0.26.4

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 (90) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/demo/index.html +32 -13
  3. package/dist/3f6be8fc.js +4296 -0
  4. package/dist/index.js +304 -208
  5. package/dist/sw.js +1 -1
  6. package/dist/sw.js.map +1 -1
  7. package/dist/templates/components-body.html +1 -1
  8. package/dist/templates/components-head.html +1 -1
  9. package/out-tsc/src/contacts/ContactChat.js +99 -85
  10. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  11. package/out-tsc/src/contacts/ContactHistory.js +30 -36
  12. package/out-tsc/src/contacts/ContactHistory.js.map +1 -1
  13. package/out-tsc/src/contacts/events.js +61 -74
  14. package/out-tsc/src/contacts/events.js.map +1 -1
  15. package/out-tsc/src/list/TembaMenu.js +63 -22
  16. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  17. package/out-tsc/src/tabpane/Tab.js +46 -0
  18. package/out-tsc/src/tabpane/Tab.js.map +1 -0
  19. package/out-tsc/src/tabpane/TabPane.js +109 -0
  20. package/out-tsc/src/tabpane/TabPane.js.map +1 -0
  21. package/out-tsc/temba-modules.js +4 -0
  22. package/out-tsc/temba-modules.js.map +1 -1
  23. package/out-tsc/test/temba-contact-history.test.js +9 -7
  24. package/out-tsc/test/temba-contact-history.test.js.map +1 -1
  25. package/package.json +1 -1
  26. package/screenshots/truth/alert/error.png +0 -0
  27. package/screenshots/truth/alert/info.png +0 -0
  28. package/screenshots/truth/alert/warning.png +0 -0
  29. package/screenshots/truth/checkbox/checked.png +0 -0
  30. package/screenshots/truth/checkbox/default.png +0 -0
  31. package/screenshots/truth/contacts/history-expanded.png +0 -0
  32. package/screenshots/truth/contacts/history.png +0 -0
  33. package/screenshots/truth/counter/summary.png +0 -0
  34. package/screenshots/truth/counter/text.png +0 -0
  35. package/screenshots/truth/counter/unicode-variables.png +0 -0
  36. package/screenshots/truth/counter/unicode.png +0 -0
  37. package/screenshots/truth/counter/variable.png +0 -0
  38. package/screenshots/truth/dialog/focused.png +0 -0
  39. package/screenshots/truth/list/items-selected.png +0 -0
  40. package/screenshots/truth/list/items-updated.png +0 -0
  41. package/screenshots/truth/list/items.png +0 -0
  42. package/screenshots/truth/list/menu-submenu.png +0 -0
  43. package/screenshots/truth/modax/form.png +0 -0
  44. package/screenshots/truth/modax/simple.png +0 -0
  45. package/screenshots/truth/options/block.png +0 -0
  46. package/screenshots/truth/select/disabled-multi-selection.png +0 -0
  47. package/screenshots/truth/select/disabled-selection.png +0 -0
  48. package/screenshots/truth/select/disabled.png +0 -0
  49. package/screenshots/truth/select/embedded.png +0 -0
  50. package/screenshots/truth/select/expression-selected.png +0 -0
  51. package/screenshots/truth/select/expressions.png +0 -0
  52. package/screenshots/truth/select/functions.png +0 -0
  53. package/screenshots/truth/select/local-options.png +0 -0
  54. package/screenshots/truth/select/remote-options.png +0 -0
  55. package/screenshots/truth/select/search-enabled.png +0 -0
  56. package/screenshots/truth/select/search-multi-no-matches.png +0 -0
  57. package/screenshots/truth/select/search-selected-focus.png +0 -0
  58. package/screenshots/truth/select/search-selected.png +0 -0
  59. package/screenshots/truth/select/search-with-selected.png +0 -0
  60. package/screenshots/truth/select/searching.png +0 -0
  61. package/screenshots/truth/select/selected-multi.png +0 -0
  62. package/screenshots/truth/select/selected-single.png +0 -0
  63. package/screenshots/truth/select/selection-clearable.png +0 -0
  64. package/screenshots/truth/select/with-placeholder.png +0 -0
  65. package/screenshots/truth/select/without-placeholder.png +0 -0
  66. package/screenshots/truth/textinput/date-form.png +0 -0
  67. package/screenshots/truth/textinput/date-initialized.png +0 -0
  68. package/screenshots/truth/textinput/input-disabled.png +0 -0
  69. package/screenshots/truth/textinput/input-focused.png +0 -0
  70. package/screenshots/truth/textinput/input-form.png +0 -0
  71. package/screenshots/truth/textinput/input-inserted.png +0 -0
  72. package/screenshots/truth/textinput/input-placeholder.png +0 -0
  73. package/screenshots/truth/textinput/input-updated.png +0 -0
  74. package/screenshots/truth/textinput/input.png +0 -0
  75. package/screenshots/truth/textinput/textarea-focused.png +0 -0
  76. package/screenshots/truth/textinput/textarea.png +0 -0
  77. package/screenshots/truth/tip/bottom.png +0 -0
  78. package/screenshots/truth/tip/left.png +0 -0
  79. package/screenshots/truth/tip/right.png +0 -0
  80. package/screenshots/truth/tip/top.png +0 -0
  81. package/src/contacts/ContactChat.ts +113 -94
  82. package/src/contacts/ContactHistory.ts +57 -59
  83. package/src/contacts/events.ts +61 -75
  84. package/src/list/TembaMenu.ts +67 -23
  85. package/src/tabpane/Tab.ts +42 -0
  86. package/src/tabpane/TabPane.ts +113 -0
  87. package/temba-modules.ts +4 -0
  88. package/test/temba-contact-history.test.ts +9 -7
  89. package/test-assets/style.css +7 -1
  90. package/dist/e477aebd.js +0 -4200
@@ -14,35 +14,36 @@ const DEFAULT_REFRESH = 10000;
14
14
  export class ContactChat extends RapidElement {
15
15
  public static get styles() {
16
16
  return css`
17
- :host {
18
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.2),
19
- 0 1px 2px 0 rgba(0, 0, 0, 0.06);
20
-
21
- height: 100%;
22
- border-radius: var(--curvature);
23
-
24
- flex-grow: 1;
25
- width: 100%;
26
- display: block;
27
- background: #f2f2f2;
28
- overflow: hidden;
29
- }
30
-
31
17
  .left-pane {
32
18
  box-shadow: -13px 10px 7px 14px rgba(0, 0, 0, 0);
33
19
  transition: box-shadow 600ms linear;
34
20
  }
35
21
 
36
22
  .left-pane.open {
37
- box-shadow: -13px 10px 7px 14px rgba(0, 0, 0, 0.15);
38
23
  z-index: 1000;
39
24
  }
40
25
 
26
+ :host {
27
+ flex-grow: 1;
28
+ display: flex;
29
+ flex-direction: row;
30
+ min-height: 0;
31
+ border-radius: var(--curvature);
32
+ }
33
+
41
34
  .chat-wrapper {
42
35
  display: flex;
36
+ flex-grow: 1;
43
37
  flex-direction: column;
44
- height: 100%;
45
38
  overflow: hidden;
39
+ min-height: 0;
40
+ }
41
+
42
+ temba-contact-history {
43
+ flex-grow: 1;
44
+ display: flex;
45
+ flex-direction: column;
46
+ min-height: 0;
46
47
  }
47
48
 
48
49
  .chatbox {
@@ -53,6 +54,11 @@ export class ContactChat extends RapidElement {
53
54
  flex-direction: column;
54
55
  z-index: 3;
55
56
  border-bottom-left-radius: var(--curvature);
57
+ border-bottom-right-radius: var(--curvature);
58
+ }
59
+
60
+ .chatbox.full {
61
+ border-bottom-right-radius: 0 !important;
56
62
  }
57
63
 
58
64
  .closed-footer {
@@ -176,6 +182,9 @@ export class ContactChat extends RapidElement {
176
182
  @property({ type: Boolean })
177
183
  showDetails = true;
178
184
 
185
+ @property({ type: Boolean })
186
+ toolbar = false;
187
+
179
188
  @property({ type: Boolean })
180
189
  monitor = false;
181
190
 
@@ -321,14 +330,13 @@ export class ContactChat extends RapidElement {
321
330
 
322
331
  public render(): TemplateResult {
323
332
  return html`
324
- <div style="display: flex; height: 100%;">
325
- <div
326
- style="flex-grow: 1; margin-right: 0em;"
327
- class="left-pane ${this.showDetails ? 'open' : ''}"
328
- >
329
- <div class="chat-wrapper">
330
- ${this.currentContact
331
- ? html` <temba-contact-history
333
+ <div
334
+ style="flex-grow: 1; margin-right: 0em; display:flex; flex-direction:row; min-height: 0;"
335
+ class="left-pane ${this.showDetails ? 'open' : ''}"
336
+ >
337
+ <div class="chat-wrapper">
338
+ ${this.currentContact
339
+ ? html`<temba-contact-history
332
340
  .uuid=${this.currentContact.uuid}
333
341
  .contact=${this.currentContact}
334
342
  .ticket=${
@@ -349,7 +357,9 @@ export class ContactChat extends RapidElement {
349
357
  @click=${this.handleReopen}
350
358
  ></temba-button>
351
359
  </div>`
352
- : html` <div class="chatbox">
360
+ : html` <div
361
+ class="chatbox ${this.toolbar ? 'full' : ''}"
362
+ >
353
363
  <temba-completion
354
364
  @change=${this.handleChatChange}
355
365
  .value=${this.currentChat}
@@ -375,81 +385,88 @@ export class ContactChat extends RapidElement {
375
385
  </div>`
376
386
  }
377
387
  </div>`
378
- : null}
379
- </div>
388
+ : null}
380
389
  </div>
381
- ${this.currentContact
382
- ? html`<temba-contact-details
383
- style="z-index: 10"
384
- class="${this.showDetails ? '' : 'hidden'}"
385
- showGroups="true"
386
- .visible=${this.showDetails}
387
- .ticket=${this.currentTicket}
388
- .contact=${this.currentContact}
389
- ></temba-contact-details>`
390
- : null}
390
+ </div>
391
+
392
+ ${this.toolbar
393
+ ? html`${
394
+ this.currentContact
395
+ ? html`<temba-contact-details
396
+ style="z-index: 10"
397
+ class="${this.showDetails ? '' : 'hidden'}"
398
+ showGroups="true"
399
+ .visible=${this.showDetails}
400
+ .ticket=${this.currentTicket}
401
+ .contact=${this.currentContact}
402
+ ></temba-contact-details>`
403
+ : null
404
+ }
391
405
 
392
406
  <div class="toolbar ${this.showDetails ? '' : 'closed'}">
393
- ${this.currentContact
394
- ? html`
395
- <temba-tip
396
- style="margin-top:5px"
397
- text="${this.showDetails ? 'Hide Details' : 'Show Details'}"
398
- position="left"
399
- hideOnChange
400
- >
401
- <temba-icon
402
- id="details-button"
403
- name="${this.showDetails ? 'chevrons-left' : 'sidebar'}"
404
- @click="${this.handleDetailSlider}"
405
- clickable
406
- animatechange="spin"
407
- ></temba-icon>
408
- </temba-tip>
409
-
410
- ${this.currentTicket
411
- ? html`<temba-tip
412
- style="margin-top:5px"
413
- text="Assign"
414
- position="left"
415
- >
416
- <temba-icon
417
- id="assign-button"
418
- name="user"
419
- @click="${() => {
420
- const modax = this.shadowRoot.getElementById(
421
- 'assign-dialog'
422
- ) as Modax;
423
- modax.open = true;
424
- }}"
425
- clickable
426
- ></temba-icon>
427
- </temba-tip>
428
- <temba-tip
429
- style="margin-top:5px"
430
- text="Add Note"
431
- position="left"
432
- >
433
- <temba-icon
434
- id="add-note-button"
435
- name="edit"
436
- @click="${() => {
437
- const note = this.shadowRoot.getElementById(
438
- 'note-dialog'
439
- ) as Modax;
440
- note.open = true;
441
- }}"
442
- clickable
443
- ></temba-icon>
444
- </temba-tip>`
445
- : null}
446
- `
447
- : null}
407
+ ${
408
+ this.currentContact
409
+ ? html`
410
+ <temba-tip
411
+ style="margin-top:5px"
412
+ text="${this.showDetails ? 'Hide Details' : 'Show Details'}"
413
+ position="left"
414
+ hideOnChange
415
+ >
416
+ <temba-icon
417
+ id="details-button"
418
+ name="${this.showDetails ? 'chevrons-left' : 'sidebar'}"
419
+ @click="${this.handleDetailSlider}"
420
+ clickable
421
+ animatechange="spin"
422
+ ></temba-icon>
423
+ </temba-tip>
424
+
425
+ ${this.currentTicket
426
+ ? html`<temba-tip
427
+ style="margin-top:5px"
428
+ text="Assign"
429
+ position="left"
430
+ >
431
+ <temba-icon
432
+ id="assign-button"
433
+ name="user"
434
+ @click="${() => {
435
+ const modax = this.shadowRoot.getElementById(
436
+ 'assign-dialog'
437
+ ) as Modax;
438
+ modax.open = true;
439
+ }}"
440
+ clickable
441
+ ></temba-icon>
442
+ </temba-tip>
443
+ <temba-tip
444
+ style="margin-top:5px"
445
+ text="Add Note"
446
+ position="left"
447
+ >
448
+ <temba-icon
449
+ id="add-note-button"
450
+ name="edit"
451
+ @click="${() => {
452
+ const note = this.shadowRoot.getElementById(
453
+ 'note-dialog'
454
+ ) as Modax;
455
+ note.open = true;
456
+ }}"
457
+ clickable
458
+ ></temba-icon>
459
+ </temba-tip>`
460
+ : null}
461
+ `
462
+ : null
463
+ }
448
464
  </div>
449
465
  </div>
450
466
 
451
- ${this.currentTicket
452
- ? html`<temba-modax
467
+ ${
468
+ this.currentTicket
469
+ ? html`<temba-modax
453
470
  header="Add Note"
454
471
  id="note-dialog"
455
472
  @temba-submitted=${this.refresh}
@@ -461,6 +478,8 @@ export class ContactChat extends RapidElement {
461
478
  @temba-submitted=${this.handleTicketAssigned}
462
479
  endpoint="/ticket/assign/${this.currentTicket.uuid}/"
463
480
  /></temba-modax>`
481
+ : null
482
+ }`
464
483
  : null}
465
484
  `;
466
485
  }
@@ -110,22 +110,24 @@ export class ContactHistory extends RapidElement {
110
110
  return css`
111
111
  ${getEventStyles()}
112
112
 
113
- :host {
114
- flex-grow: 1;
115
- flex-direction: column;
113
+ .wrapper {
114
+ border: 0px solid green;
116
115
  display: flex;
117
116
  flex-direction: column;
118
117
  align-items: items-stretch;
118
+ flex-grow: 1;
119
+ min-height: 0;
119
120
  }
120
121
 
121
122
  .events {
122
- height: 200px;
123
123
  overflow-y: scroll;
124
124
  overflow-x: hidden;
125
- flex-grow: 1;
126
- border-top-left-radius: var(--curvature);
127
- padding-top: 1em;
128
125
  background: #fff;
126
+ display: flex;
127
+ flex-direction: column;
128
+ flex-grow: 1;
129
+ min-height: 0;
130
+ padding-top: 3em;
129
131
  }
130
132
 
131
133
  temba-loading {
@@ -180,12 +182,9 @@ export class ContactHistory extends RapidElement {
180
182
  }
181
183
 
182
184
  .sticky-bin {
183
- display: flex;
184
- flex-direction: column;
185
- z-index: 2;
186
185
  border-top-left-radius: var(--curvature);
187
- overflow: hidden;
188
- box-shadow: 0px 3px 3px 0px rgba(0, 0, 0, 0.15);
186
+ z-index: 2;
187
+ box-shadow: rgb(0 0 0 / 15%) 0px 3px 3px 0px;
189
188
  background: rgb(240, 240, 240);
190
189
  }
191
190
 
@@ -382,7 +381,6 @@ export class ContactHistory extends RapidElement {
382
381
  if (forceOpen) {
383
382
  grouped[grouped.length - 1].open = forceOpen;
384
383
  }
385
-
386
384
  this.eventGroups = [...previousGroups, ...grouped];
387
385
  }
388
386
  this.refreshing = false;
@@ -452,6 +450,7 @@ export class ContactHistory extends RapidElement {
452
450
  if (changedProperties.has('refreshing') && !this.refreshing) {
453
451
  if (this.lastRefreshAdded > 0) {
454
452
  const events = this.getEventsPane();
453
+
455
454
  // if we are near the bottom, push us to the bottom to show new stuff
456
455
  if (this.lastHeight > 0) {
457
456
  const addedHeight = events.scrollHeight - this.lastHeight;
@@ -573,7 +572,6 @@ export class ContactHistory extends RapidElement {
573
572
  }
574
573
  eventGroup = {
575
574
  open: false,
576
- closing: false,
577
575
  events: [event],
578
576
  type: currentEventGroupType,
579
577
  };
@@ -649,21 +647,17 @@ export class ContactHistory extends RapidElement {
649
647
  }
650
648
 
651
649
  private handleEventGroupHide(event: MouseEvent) {
650
+ event.preventDefault();
651
+ event.stopPropagation();
652
+
652
653
  const grouping = event.currentTarget as HTMLDivElement;
653
654
  const groupIndex = parseInt(grouping.getAttribute('data-group-index'));
654
655
  const eventGroup =
655
656
  this.eventGroups[this.eventGroups.length - groupIndex - 1];
656
657
 
657
- // mark us as closing
658
- eventGroup.closing = true;
659
- this.requestUpdate('eventGroups');
658
+ eventGroup.open = false;
660
659
 
661
- // after our animation, close it up for real
662
- setTimeout(() => {
663
- eventGroup.closing = false;
664
- eventGroup.open = false;
665
- this.requestUpdate('eventGroups');
666
- }, 300);
660
+ this.requestUpdate('eventGroups');
667
661
  }
668
662
 
669
663
  private handleScroll() {
@@ -913,12 +907,16 @@ export class ContactHistory extends RapidElement {
913
907
  : null;
914
908
 
915
909
  return html`
916
- ${this.ticket
917
- ? html`<div class="sticky-bin">${unfetchedTickets}</div>`
918
- : null}
919
- ${this.fetching
920
- ? html`<temba-loading units="5" size="10"></temba-loading>`
921
- : html`<div style="height:0em"></div>`}
910
+ ${
911
+ this.ticket
912
+ ? html`<div class="sticky-bin">${unfetchedTickets}</div>`
913
+ : null
914
+ }
915
+ ${
916
+ this.fetching
917
+ ? html`<temba-loading units="5" size="10"></temba-loading>`
918
+ : html`<div style="height:0em"></div>`
919
+ }
922
920
  <div class="events" @scroll=${this.handleScroll}>
923
921
  ${this.eventGroups.map((eventGroup: EventGroup, index: number) => {
924
922
  const grouping = getEventGroupType(eventGroup.events[0], this.ticket);
@@ -928,9 +926,7 @@ export class ContactHistory extends RapidElement {
928
926
  grouping: true,
929
927
  [grouping]: true,
930
928
  expanded: eventGroup.open,
931
- closing: eventGroup.closing,
932
929
  });
933
-
934
930
  return html`<div class="${classes}">
935
931
  ${grouping === 'verbose'
936
932
  ? html`<div
@@ -938,36 +934,37 @@ export class ContactHistory extends RapidElement {
938
934
  @click=${this.handleEventGroupShow}
939
935
  data-group-index="${groupIndex}"
940
936
  >
941
- ${eventGroup.events.length}
942
- ${eventGroup.events.length === 1 ? html`event` : html`events`}
937
+ ${eventGroup.open
938
+ ? html`<temba-icon
939
+ @click=${this.handleEventGroupHide}
940
+ data-group-index="${groupIndex}"
941
+ name="x"
942
+ clickable
943
+ ></temba-icon>`
944
+ : html`${eventGroup.events.length}
945
+ ${eventGroup.events.length === 1
946
+ ? html`event`
947
+ : html`events`} `}
943
948
  </div>`
944
949
  : null}
945
- ${grouping === 'verbose'
946
- ? html`
947
- <temba-icon
948
- @click=${this.handleEventGroupHide}
949
- data-group-index="${groupIndex}"
950
- class="grouping-close-button"
951
- name="x"
952
- clickable
953
- ></temba-icon>
954
- `
955
- : null}
956
- ${eventGroup.events.map((event: ContactEvent) => {
957
- if (
958
- event.type === Events.TICKET_ASSIGNED &&
959
- (event as TicketEvent).note
960
- ) {
961
- const noteEvent = { ...event };
962
- noteEvent.type = Events.TICKET_NOTE_ADDED;
963
-
964
- return html`${this.renderEventContainer(
965
- noteEvent
966
- )}${this.renderEventContainer(event)}`;
967
- } else {
968
- return this.renderEventContainer(event);
969
- }
970
- })}
950
+
951
+ <div class="items">
952
+ ${eventGroup.events.map((event: ContactEvent) => {
953
+ if (
954
+ event.type === Events.TICKET_ASSIGNED &&
955
+ (event as TicketEvent).note
956
+ ) {
957
+ const noteEvent = { ...event };
958
+ noteEvent.type = Events.TICKET_NOTE_ADDED;
959
+
960
+ return html`${this.renderEventContainer(
961
+ noteEvent
962
+ )}${this.renderEventContainer(event)}`;
963
+ } else {
964
+ return this.renderEventContainer(event);
965
+ }
966
+ })}
967
+ </div>
971
968
  </div>`;
972
969
  })}
973
970
  </div>
@@ -984,6 +981,7 @@ export class ContactHistory extends RapidElement {
984
981
  New Messages
985
982
  </div>
986
983
  </div>
984
+ </div>
987
985
  `;
988
986
  }
989
987
  }