@nyaruka/temba-components 0.113.0 → 0.114.0

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 (130) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/demo/index.html +1 -1
  3. package/dist/temba-components.js +793 -966
  4. package/dist/temba-components.js.map +1 -1
  5. package/out-tsc/src/aliaseditor/AliasEditor.js.map +1 -1
  6. package/out-tsc/src/button/Button.js +6 -2
  7. package/out-tsc/src/button/Button.js.map +1 -1
  8. package/out-tsc/src/chat/Chat.js +29 -7
  9. package/out-tsc/src/chat/Chat.js.map +1 -1
  10. package/out-tsc/src/compose/Compose.js +10 -5
  11. package/out-tsc/src/compose/Compose.js.map +1 -1
  12. package/out-tsc/src/contacts/ContactChat.js +240 -114
  13. package/out-tsc/src/contacts/ContactChat.js.map +1 -1
  14. package/out-tsc/src/contacts/ContactFieldEditor.js.map +1 -1
  15. package/out-tsc/src/contacts/events.js.map +1 -1
  16. package/out-tsc/src/contacts/helpers.js +5 -1
  17. package/out-tsc/src/contacts/helpers.js.map +1 -1
  18. package/out-tsc/src/contactsearch/ContactSearch.js +1 -1
  19. package/out-tsc/src/contactsearch/ContactSearch.js.map +1 -1
  20. package/out-tsc/src/dropdown/Dropdown.js +121 -108
  21. package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
  22. package/out-tsc/src/interfaces.js +2 -0
  23. package/out-tsc/src/interfaces.js.map +1 -1
  24. package/out-tsc/src/list/ContentMenu.js +11 -8
  25. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  26. package/out-tsc/src/list/RunList.js.map +1 -1
  27. package/out-tsc/src/list/TembaList.js +21 -14
  28. package/out-tsc/src/list/TembaList.js.map +1 -1
  29. package/out-tsc/src/list/TembaMenu.js +11 -12
  30. package/out-tsc/src/list/TembaMenu.js.map +1 -1
  31. package/out-tsc/src/list/TicketList.js +10 -0
  32. package/out-tsc/src/list/TicketList.js.map +1 -1
  33. package/out-tsc/src/omnibox/Omnibox.js +33 -90
  34. package/out-tsc/src/omnibox/Omnibox.js.map +1 -1
  35. package/out-tsc/src/options/Options.js +49 -47
  36. package/out-tsc/src/options/Options.js.map +1 -1
  37. package/out-tsc/src/select/PopupSelect.js +57 -0
  38. package/out-tsc/src/select/PopupSelect.js.map +1 -0
  39. package/out-tsc/src/select/Select.js +194 -144
  40. package/out-tsc/src/select/Select.js.map +1 -1
  41. package/out-tsc/src/select/UserSelect.js +67 -0
  42. package/out-tsc/src/select/UserSelect.js.map +1 -0
  43. package/out-tsc/src/store/Store.js +65 -14
  44. package/out-tsc/src/store/Store.js.map +1 -1
  45. package/out-tsc/src/tabpane/TabPane.js +72 -115
  46. package/out-tsc/src/tabpane/TabPane.js.map +1 -1
  47. package/out-tsc/src/textinput/TextInput.js +1 -0
  48. package/out-tsc/src/textinput/TextInput.js.map +1 -1
  49. package/out-tsc/src/user/TembaUser.js +24 -37
  50. package/out-tsc/src/user/TembaUser.js.map +1 -1
  51. package/out-tsc/src/utils/index.js +13 -6
  52. package/out-tsc/src/utils/index.js.map +1 -1
  53. package/out-tsc/temba-modules.js +4 -2
  54. package/out-tsc/temba-modules.js.map +1 -1
  55. package/out-tsc/test/temba-omnibox.test.js +43 -4
  56. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  57. package/out-tsc/test/temba-select.test.js +121 -65
  58. package/out-tsc/test/temba-select.test.js.map +1 -1
  59. package/out-tsc/test/utils.test.js +4 -0
  60. package/out-tsc/test/utils.test.js.map +1 -1
  61. package/package.json +1 -1
  62. package/screenshots/truth/compose/attachments-tab.png +0 -0
  63. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  64. package/screenshots/truth/compose/attachments-with-files.png +0 -0
  65. package/screenshots/truth/compose/intial-text.png +0 -0
  66. package/screenshots/truth/compose/no-counter.png +0 -0
  67. package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
  68. package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
  69. package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
  70. package/screenshots/truth/contacts/chat-failure.png +0 -0
  71. package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
  72. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  73. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  74. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  75. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  76. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  77. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  78. package/screenshots/truth/content-menu/item-no-buttons.png +0 -0
  79. package/screenshots/truth/content-menu/items-and-buttons.png +0 -0
  80. package/screenshots/truth/omnibox/selected.png +0 -0
  81. package/screenshots/truth/select/enabled-multi-selection.png +0 -0
  82. package/screenshots/truth/select/endpoint-initial-value-updated.png +0 -0
  83. package/screenshots/truth/select/endpoint-initial-value.png +0 -0
  84. package/screenshots/truth/select/expressions.png +0 -0
  85. package/screenshots/truth/select/functions.png +0 -0
  86. package/screenshots/truth/select/initial-value.png +0 -0
  87. package/screenshots/truth/select/multi-with-endpoint.png +0 -0
  88. package/screenshots/truth/select/multiple-initial-values.png +0 -0
  89. package/screenshots/truth/select/selected-multi-test.png +0 -0
  90. package/screenshots/truth/select/static-initial-value.png +0 -0
  91. package/screenshots/truth/select/static-initial-via-selected.png +0 -0
  92. package/screenshots/truth/select/value-initial.png +0 -0
  93. package/src/aliaseditor/AliasEditor.ts +1 -1
  94. package/src/button/Button.ts +6 -2
  95. package/src/chat/Chat.ts +28 -6
  96. package/src/compose/Compose.ts +11 -6
  97. package/src/contacts/ContactChat.ts +260 -118
  98. package/src/contacts/ContactFieldEditor.ts +1 -1
  99. package/src/contacts/events.ts +1 -0
  100. package/src/contacts/helpers.ts +8 -1
  101. package/src/contactsearch/ContactSearch.ts +3 -3
  102. package/src/dropdown/Dropdown.ts +142 -103
  103. package/src/interfaces.ts +4 -1
  104. package/src/list/ContentMenu.ts +11 -9
  105. package/src/list/RunList.ts +3 -1
  106. package/src/list/TembaList.ts +24 -14
  107. package/src/list/TembaMenu.ts +14 -15
  108. package/src/list/TicketList.ts +11 -0
  109. package/src/omnibox/Omnibox.ts +34 -95
  110. package/src/options/Options.ts +57 -60
  111. package/src/select/PopupSelect.ts +53 -0
  112. package/src/select/Select.ts +182 -112
  113. package/src/select/UserSelect.ts +71 -0
  114. package/src/store/Store.ts +70 -21
  115. package/src/tabpane/TabPane.ts +79 -113
  116. package/src/textinput/TextInput.ts +1 -0
  117. package/src/user/TembaUser.ts +30 -41
  118. package/src/utils/index.ts +12 -8
  119. package/temba-modules.ts +4 -2
  120. package/test/temba-omnibox.test.ts +56 -4
  121. package/test/temba-select.test.ts +170 -56
  122. package/test/utils.test.ts +5 -0
  123. package/test-assets/select/omnibox.json +55 -0
  124. package/web-test-runner.config.mjs +16 -4
  125. package/out-tsc/src/contacts/ContactTickets.js +0 -462
  126. package/out-tsc/src/contacts/ContactTickets.js.map +0 -1
  127. package/out-tsc/test/temba-contact-tickets.test.js +0 -36
  128. package/out-tsc/test/temba-contact-tickets.test.js.map +0 -1
  129. package/src/contacts/ContactTickets.ts +0 -490
  130. package/test/temba-contact-tickets.test.ts +0 -52
@@ -2,7 +2,7 @@
2
2
  import { css, html, PropertyValueMap, TemplateResult } from 'lit';
3
3
  import { property } from 'lit/decorators.js';
4
4
  import { Contact, CustomEventType, Ticket } from '../interfaces';
5
- import { oxford, oxfordFn, postJSON } from '../utils';
5
+ import { fetchResults, oxford, oxfordFn, postJSON } from '../utils';
6
6
  import { ContactStoreElement } from './ContactStoreElement';
7
7
  import { Compose, ComposeValue } from '../compose/Compose';
8
8
  import { fetchContactHistory, getDisplayName } from './helpers';
@@ -30,6 +30,8 @@ import {
30
30
  import { Chat, ChatEvent, MessageType } from '../chat/Chat';
31
31
  import { getUserDisplay } from '../webchat';
32
32
  import { DEFAULT_AVATAR } from '../webchat/assets';
33
+ import { UserSelect } from '../select/UserSelect';
34
+ import { Select } from '../select/Select';
33
35
 
34
36
  export enum Events {
35
37
  MESSAGE_CREATED = 'msg_created',
@@ -253,6 +255,8 @@ export class ContactChat extends ContactStoreElement {
253
255
  --compose-padding: 3px;
254
256
  --compose-curvature: none;
255
257
  border-top: 1px inset rgba(0, 0, 0, 0.05);
258
+
259
+
256
260
  }
257
261
 
258
262
  .chat-wrapper {
@@ -260,7 +264,7 @@ export class ContactChat extends ContactStoreElement {
260
264
  flex-grow: 1;
261
265
  flex-direction: column;
262
266
  min-height: 0;
263
- background: rgb(249, 249, 249);
267
+ background: #f9f9f9;
264
268
  }
265
269
 
266
270
  temba-contact-history {
@@ -300,9 +304,8 @@ export class ContactChat extends ContactStoreElement {
300
304
  color: var(--color-link-primary-hover);
301
305
  }
302
306
 
303
- temba-button#reopen-button {
304
- --button-y: 1px;
305
- --button-x: 12px;
307
+ temba-button {
308
+ margin: 0.1em 0.25em;
306
309
  }
307
310
 
308
311
  temba-completion {
@@ -319,6 +322,10 @@ export class ContactChat extends ContactStoreElement {
319
322
  temba-compose {
320
323
  border-top-right-radius: 0;
321
324
  border-top-left-radius: 0;
325
+ --temba-tabs-options-padding: 0.5em 0.5em 0 0.5em;
326
+ --temba-tabs-border-left: none;
327
+ --temba-tabs-border-right: none;
328
+ --temba-tabs-border-bottom: none;
322
329
  }
323
330
 
324
331
  .error-gutter {
@@ -337,37 +344,42 @@ export class ContactChat extends ContactStoreElement {
337
344
 
338
345
  temba-chat {
339
346
  border-bottom: 1px solid #ddd;
347
+ background: linear-gradient(0deg, #fff, #fff);
348
+ --chat-border-in: 1px solid #eee;
349
+ --color-chat-out: var(--color-message)
350
+ );
340
351
  }
341
352
 
342
- .in-ticket-wrapper {
353
+ .action-bar {
343
354
  }
344
355
 
345
356
  .in-flow {
346
- text-align: center;
347
-
348
- display: flex;
349
-
350
- background: var(--color-primary-dark);
351
- background: #777;
352
- color: #fff;
357
+ border-radius: 0.8em;
353
358
  align-items: center;
354
- border-bottom: 1px solid #ddd;
359
+ background: #666;
360
+ padding: 0.5em 1em;
361
+ margin: 1em;
362
+ margin-right: 2em;
363
+ display: inline-flex;
364
+ opacity: 0.9;
365
+ }
366
+
367
+ .in-flow:hover {
368
+ opacity: 1;
355
369
  }
356
370
 
357
371
  .in-flow .flow-name {
358
- padding: 0.5em 1em;
359
372
  display: flex;
360
- flex-grow: 1;
373
+ color: #fff;
361
374
  }
362
375
 
363
- .in-flow a,
364
- .in-flow .interrupt {
376
+ .in-flow a {
365
377
  font-weight: bold;
366
378
  color: #fff;
367
379
  }
368
380
 
369
- .in-flow .interrupt {
370
- background: rgba(var(--error-rgb), 1);
381
+ .in-flow .interrupt-button {
382
+ margin-left: 1em;
371
383
  }
372
384
 
373
385
  .in-flow .interrupt {
@@ -390,26 +402,46 @@ export class ContactChat extends ContactStoreElement {
390
402
  margin-right: 0.5em;
391
403
  }
392
404
 
405
+ .in-ticket-wrapper {
406
+ }
407
+
393
408
  .in-ticket {
394
- --color-widget-border: transparent;
395
- --color-widget-bg: transparent;
396
- --widget-box-shadow: none;
397
- --temba-select-selected-padding: 0.2em 0.8em;
398
- --temba-select-min-height: 0;
399
- --select-wrapper-bg: transparent;
400
- --select-wrapper-shadow: none;
401
409
  box-shadow: none;
402
- padding: 0.5em;
410
+ padding: 0.5em 0.5em;
403
411
  text-align: center;
404
-
412
+ align-items: center;
413
+ border-bottom: 1px solid #ddd;
405
414
  display: flex;
406
415
  box-shadow: none;
416
+ margin: 0em;
417
+ background: rgba(0, 0, 0, 0.03);
418
+ }
419
+
420
+ temba-user {
421
+ border: 1px solid #ddd;
422
+ padding: 0.2em 0.5em;
423
+ border-radius: var(--curvature);
424
+ min-width: 10em;
425
+ background: #fff;
426
+ }
427
+
428
+ temba-user:hover {
429
+ border: 1px solid #ddd;
430
+ background: #f9f9f9;
407
431
  }
408
432
 
409
433
  .assign-button {
410
434
  --button-mask: #ebebeb;
411
435
  color: #333;
412
- margin-right: 0.5em;
436
+ margin: 0.25em;
437
+ }
438
+
439
+ temba-user-select {
440
+ width: 250px;
441
+ }
442
+
443
+ temba-button {
444
+ --button-border: 1px solid #ddd;
413
445
  }
414
446
  `;
415
447
  }
@@ -495,6 +527,17 @@ export class ContactChat extends ContactStoreElement {
495
527
  this.reset();
496
528
  this.fetchPreviousMessages();
497
529
  }
530
+
531
+ if (changedProperties.has('currentTicket')) {
532
+ const users = this.shadowRoot.querySelector(
533
+ 'temba-user-select'
534
+ ) as UserSelect;
535
+ if (users) {
536
+ users.setValues(
537
+ this.currentTicket?.assignee ? [this.currentTicket?.assignee] : []
538
+ );
539
+ }
540
+ }
498
541
  }
499
542
 
500
543
  private reset() {
@@ -738,14 +781,15 @@ export class ContactChat extends ContactStoreElement {
738
781
 
739
782
  private getUserForEvent(event: MsgEvent | TicketEvent) {
740
783
  let user = null;
741
- if (event.created_by) {
784
+ if (event.type === 'msg_received') {
742
785
  user = {
743
- email: event.created_by.email,
744
- name: `${event.created_by.first_name} ${event.created_by.last_name}`.trim()
786
+ name: this.currentContact.name
745
787
  };
746
- } else if (event.type === 'msg_received') {
788
+ } else if (event.created_by) {
747
789
  user = {
748
- name: this.currentContact.name
790
+ email: event.created_by.email,
791
+ name: `${event.created_by.first_name} ${event.created_by.last_name}`.trim(),
792
+ avatar: event.created_by.avatar
749
793
  };
750
794
  }
751
795
  return user;
@@ -908,15 +952,6 @@ export class ContactChat extends ContactStoreElement {
908
952
  this.chat.fetching = false;
909
953
  }
910
954
 
911
- private getTembaContactHistory(): TemplateResult {
912
- return html`<temba-chat
913
- @temba-scroll-threshold=${this.fetchPreviousMessages}
914
- @temba-fetch-complete=${this.fetchComplete}
915
- avatar=${this.avatar}
916
- agent
917
- ></temba-chat>`;
918
- }
919
-
920
955
  private getTembaCompose(): TemplateResult {
921
956
  if (this.currentTicket) {
922
957
  if (this.currentContact && this.currentContact.status !== 'active') {
@@ -949,6 +984,7 @@ export class ContactChat extends ContactStoreElement {
949
984
  counter
950
985
  autogrow
951
986
  shortcuts
987
+ ?embeddedTabs=${!this.currentTicket}
952
988
  @temba-submitted=${this.handleSend.bind(this)}
953
989
  >
954
990
  </temba-compose>
@@ -964,83 +1000,189 @@ export class ContactChat extends ContactStoreElement {
964
1000
  </div>`;
965
1001
  }
966
1002
 
1003
+ private handleAssignmentChanged(evt: CustomEvent) {
1004
+ const users = evt.currentTarget as UserSelect;
1005
+ const assignee = users.values[0];
1006
+ this.assignTicket(assignee ? assignee.email : null);
1007
+ users.blur();
1008
+ }
1009
+
1010
+ private handleTopicChanged(evt: CustomEvent) {
1011
+ const select = evt.target as Select<any>;
1012
+ const topic = select.values[0];
1013
+
1014
+ if (this.currentTicket.topic.uuid !== topic.uuid) {
1015
+ postJSON(`/api/v2/ticket_actions.json`, {
1016
+ tickets: [this.currentTicket.uuid],
1017
+ action: 'change_topic',
1018
+ topic: topic.uuid
1019
+ })
1020
+ .then(() => {
1021
+ this.refreshTicket();
1022
+ })
1023
+ .catch((response: any) => {
1024
+ console.error(response);
1025
+ });
1026
+ }
1027
+ }
1028
+
1029
+ public assignTicket(email: string) {
1030
+ // if its already assigned to use, it's a noop
1031
+ if (
1032
+ (this.currentTicket.assignee &&
1033
+ this.currentTicket.assignee.email === email) ||
1034
+ (this.currentTicket.assignee === null && email === null)
1035
+ ) {
1036
+ return;
1037
+ }
1038
+
1039
+ postJSON(`/api/v2/ticket_actions.json`, {
1040
+ tickets: [this.currentTicket.uuid],
1041
+ action: 'assign',
1042
+ assignee: email
1043
+ })
1044
+ .then(() => {
1045
+ this.refreshTicket();
1046
+ })
1047
+ .catch((response: any) => {
1048
+ console.error(response);
1049
+ });
1050
+ return true;
1051
+ }
1052
+
1053
+ public refreshTicket() {
1054
+ if (this.currentTicket) {
1055
+ fetchResults(`/api/v2/tickets.json?uuid=${this.currentTicket.uuid}`).then(
1056
+ (values) => {
1057
+ if (values.length > 0) {
1058
+ this.fireCustomEvent(CustomEventType.TicketUpdated, {
1059
+ ticket: values[0],
1060
+ previous: this.currentTicket
1061
+ });
1062
+ this.currentTicket = values[0];
1063
+ }
1064
+ }
1065
+ );
1066
+ }
1067
+ }
1068
+
1069
+ private handleReopen() {
1070
+ const uuid = this.currentTicket.uuid;
1071
+ postJSON(`/api/v2/ticket_actions.json`, {
1072
+ tickets: [uuid],
1073
+ action: 'reopen'
1074
+ })
1075
+ .then(() => {
1076
+ this.refreshTicket();
1077
+ })
1078
+ .catch((response: any) => {
1079
+ console.error(response);
1080
+ });
1081
+ }
1082
+
1083
+ private handleClose() {
1084
+ const uuid = this.currentTicket.uuid;
1085
+ postJSON(`/api/v2/ticket_actions.json`, {
1086
+ tickets: [uuid],
1087
+ action: 'close'
1088
+ })
1089
+ .then(() => {
1090
+ this.refreshTicket();
1091
+ })
1092
+ .catch((response: any) => {
1093
+ console.error(response);
1094
+ });
1095
+ }
1096
+
967
1097
  public render(): TemplateResult {
968
1098
  const inFlow = this.currentContact && this.currentContact.flow;
969
1099
 
970
- // disable ticket view for now
971
- const inTicket = false; // !!this.currentTicket;
972
-
973
- const contactHistory = this.currentContact
974
- ? this.getTembaContactHistory()
975
- : null;
976
- const tembaCompose = this.currentContact ? this.getTembaCompose() : null;
977
-
978
- const contactHistoryAndChatbox = html`
979
- <div class="chat-wrapper">
980
- ${contactHistory}
981
- ${inFlow
982
- ? html`
983
- <div class="in-flow">
984
- <div class="flow-name">
985
- <temba-icon name="flow" size="1.2"></temba-icon>
986
- <div style="flex-grow:1;text-align:left">
987
- Currently in
988
- <a href="/flow/editor/${this.currentContact.flow.uuid}/"
989
- >${this.currentContact.flow.name}</a
990
- >
1100
+ const inTicket = this.currentTicket;
1101
+ const ticketClosed = this.currentTicket && this.currentTicket.closed_on;
1102
+
1103
+ return html`<div class="chat-wrapper">
1104
+ ${this.currentContact
1105
+ ? html`<temba-chat
1106
+ @temba-scroll-threshold=${this.fetchPreviousMessages}
1107
+ @temba-fetch-complete=${this.fetchComplete}
1108
+ avatar=${this.avatar}
1109
+ agent
1110
+ >
1111
+ ${inFlow
1112
+ ? html`
1113
+ <div slot="footer" style="text-align:center;">
1114
+ <div class="in-flow">
1115
+ <div class="flow-name">
1116
+ <temba-icon name="flow" size="1.2"></temba-icon>
1117
+ <div>
1118
+ Currently in
1119
+ <a
1120
+ href="/flow/editor/${this.currentContact.flow
1121
+ .uuid}/"
1122
+ >${this.currentContact.flow.name}</a
1123
+ >
1124
+ </div>
1125
+ </div>
1126
+ ${this.showInterrupt
1127
+ ? html`<temba-button
1128
+ class="interrupt-button"
1129
+ destructive
1130
+ small
1131
+ @click=${this.handleInterrupt}
1132
+ name="Interrupt"
1133
+ >
1134
+ </temba-button>`
1135
+ : null}
1136
+ </div>
1137
+ </div>
1138
+ `
1139
+ : null}
1140
+ <div slot="footer"></div>
1141
+ </temba-chat>
1142
+ ${inTicket
1143
+ ? html`<div class="in-ticket-wrapper">
1144
+ <div class="in-ticket">
1145
+ <temba-user-select
1146
+ placeholder="Assign to.."
1147
+ searchable
1148
+ searchOnFocus
1149
+ clearable
1150
+ .values=${this.currentTicket.assignee
1151
+ ? [this.currentTicket.assignee]
1152
+ : []}
1153
+ @change=${this.handleAssignmentChanged}
1154
+ ?disabled=${ticketClosed}
1155
+ ></temba-user-select>
1156
+
1157
+ <temba-select
1158
+ style="margin:0 0.5em; flex-grow:1"
1159
+ endpoint="/api/v2/topics.json"
1160
+ searchable
1161
+ valuekey="uuid"
1162
+ .values=${[this.currentTicket.topic]}
1163
+ @change=${this.handleTopicChanged}
1164
+ ?disabled=${ticketClosed}
1165
+ ></temba-select>
1166
+
1167
+ ${this.currentTicket.closed_on
1168
+ ? html`
1169
+ <temba-button
1170
+ name="Reopen"
1171
+ @click=${this.handleReopen}
1172
+ ></temba-button>
1173
+ `
1174
+ : html`
1175
+ <temba-button
1176
+ name="Close"
1177
+ destructive
1178
+ @click=${this.handleClose}
1179
+ ></temba-button>
1180
+ `}
991
1181
  </div>
992
- </div>
993
- ${this.showInterrupt
994
- ? html`<div class="interrupt" @click=${this.handleInterrupt}>
995
- Interrupt
996
- </div>`
997
- : null}
998
- </div>
999
- `
1000
- : ''}
1001
- ${inTicket
1002
- ? html`<div class="in-ticket-wrapper">
1003
- <div class="in-ticket">
1004
- ${this.currentTicket.assignee
1005
- ? html`<temba-user
1006
- email=${this.currentTicket.assignee.email}
1007
- scale="0.8"
1008
- style="margin-right:0.25em;margin-bottom:-0.5em;margin-top:-0.5em;margin-right:0.5em;"
1009
- ></temba-user>`
1010
- : html`<temba-button
1011
- name="Assign"
1012
- class="assign-button"
1013
- light
1014
- ></temba-button>`}
1015
- <temba-select
1016
- searchable
1017
- endpoint="/api/v2/topics.json"
1018
- valueKey="uuid"
1019
- .prepareOptions=${(options) => {
1020
- options.forEach((option) => {
1021
- option.icon = 'topic';
1022
- });
1023
- return options;
1024
- }}
1025
- values=${JSON.stringify([
1026
- { ...this.currentTicket.topic, icon: 'topic' }
1027
- ])}
1028
- style="min-width:200px; max-width:300px;margin-right:0.5em;"
1029
- >
1030
- </temba-select>
1031
- <div style="min-width:20px"></div>
1032
-
1033
- ${this.currentTicket.closed_on
1034
- ? html`reopen`
1035
- : html`<div style="text-align:right;flex-grow:1">
1036
- <temba-button name="Close"></temba-button>
1037
- </div>`}
1038
- </div>
1039
- </div>`
1040
- : ''}
1041
- ${tembaCompose}
1042
- </div>
1043
- `;
1044
- return html`${contactHistoryAndChatbox}`;
1182
+ </div> `
1183
+ : null}
1184
+ ${this.getTembaCompose()}`
1185
+ : null}
1186
+ </div>`;
1045
1187
  }
1046
1188
  }
@@ -359,7 +359,7 @@ export class ContactFieldEditor extends RapidElement {
359
359
  }
360
360
 
361
361
  public handleSelectChange(evt: CustomEvent) {
362
- const select = evt.currentTarget as Select;
362
+ const select = evt.currentTarget as Select<any>;
363
363
  let value = '';
364
364
 
365
365
  evt.preventDefault();
@@ -11,6 +11,7 @@ export interface EventGroup {
11
11
  export interface ContactEvent {
12
12
  type: string;
13
13
  created_on: string;
14
+ created_by?: User;
14
15
  }
15
16
 
16
17
  export interface ChannelEvent extends ContactEvent {
@@ -1,4 +1,5 @@
1
1
  import { Contact, NamedUser, User } from '../interfaces';
2
+ import { Store } from '../store/Store';
2
3
  import { fetchResults, getUrl, postUrl, WebResponse } from '../utils';
3
4
  import { ContactHistoryPage } from './events';
4
5
 
@@ -59,6 +60,8 @@ export const fetchContactHistory = (
59
60
  url += `&ticket=${ticket}`;
60
61
  }
61
62
 
63
+ const store = document.querySelector('temba-store') as Store;
64
+
62
65
  getUrl(url, controller)
63
66
  .then((response: WebResponse) => {
64
67
  // on success, remove our abort controller
@@ -67,7 +70,11 @@ export const fetchContactHistory = (
67
70
  return response.controller === controller;
68
71
  }
69
72
  );
70
- resolve(response.json as ContactHistoryPage);
73
+
74
+ const page = response.json as ContactHistoryPage;
75
+ store.resolveUsers(page.events, ['created_by']).then(() => {
76
+ resolve(page);
77
+ });
71
78
  })
72
79
  .catch(() => {
73
80
  // canceled
@@ -423,7 +423,7 @@ export class ContactSearch extends FormElement {
423
423
  }
424
424
 
425
425
  private handleActivityLevelChanged(evt: any) {
426
- const select = evt.target as Select;
426
+ const select = evt.target as Select<any>;
427
427
  const option = select.values[0];
428
428
  if (option) {
429
429
  if (this.exclusions['not_seen_since_days']) {
@@ -455,7 +455,7 @@ export class ContactSearch extends FormElement {
455
455
  if (checkbox.name === 'not_seen_since_days' && value) {
456
456
  const select = checkbox.parentElement.querySelector(
457
457
  'temba-select'
458
- ) as Select;
458
+ ) as Select<any>;
459
459
  if (select.values[0]) {
460
460
  value = parseInt(select.values[0].value);
461
461
  } else {
@@ -563,7 +563,7 @@ export class ContactSearch extends FormElement {
563
563
  .errors=${this.errors}
564
564
  id="recipients"
565
565
  name="recipients"
566
- .value=${this.recipients}
566
+ .values=${this.recipients}
567
567
  endpoint="/contact/omnibox/?"
568
568
  @change=${this.handleRecipientsChanged}
569
569
  >