@nyaruka/temba-components 0.159.1 → 0.159.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.159.1",
3
+ "version": "0.159.2",
4
4
  "description": "Web components to support rapidpro and related projects",
5
5
  "author": "Nyaruka <code@nyaruka.coim>",
6
6
  "main": "dist/index.js",
package/src/interfaces.ts CHANGED
@@ -160,6 +160,7 @@ export interface Msg {
160
160
  export interface ObjectReference {
161
161
  uuid: string;
162
162
  name: string;
163
+ url?: string;
163
164
  }
164
165
 
165
166
  export interface Shortcut {
@@ -41,7 +41,7 @@ const BROADCAST_COLOR = '#8e5ea7';
41
41
  // triggers use the same green as the flow pill
42
42
  const TRIGGER_COLOR = '#16a34a';
43
43
 
44
- export class ContactEvents extends EndpointMonitorElement {
44
+ export class ContactTimeline extends EndpointMonitorElement {
45
45
  @property({ type: String })
46
46
  contact: string;
47
47
 
@@ -64,7 +64,14 @@ export class ContactEvents extends EndpointMonitorElement {
64
64
  lang_campaigns_label = 'Campaigns';
65
65
 
66
66
  @property({ type: String })
67
- lang_empty = 'No events for this contact yet.';
67
+ lang_empty = 'No upcoming events';
68
+
69
+ @property({ type: String })
70
+ lang_empty_help =
71
+ 'Events appear here when a contact joins a campaign. Scheduled flows and messages will also show up here.';
72
+
73
+ @property({ type: String })
74
+ lang_campaigns_link = 'View campaigns';
68
75
 
69
76
  @property({ type: String })
70
77
  lang_projected_info =
@@ -101,11 +108,44 @@ export class ContactEvents extends EndpointMonitorElement {
101
108
  display: block;
102
109
  }
103
110
 
111
+ /* empty state follows the list design system: centered icon, a short
112
+ title, muted explanatory copy, and a single call-to-action link */
104
113
  .empty {
105
- padding: 4em 1em;
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
106
117
  text-align: center;
118
+ padding: 7em 1em 4em;
107
119
  color: var(--text-color);
108
- opacity: 0.55;
120
+ }
121
+
122
+ .empty temba-icon {
123
+ margin-bottom: 0.75em;
124
+ --icon-color: var(--text-3, #7b8593);
125
+ }
126
+
127
+ .empty-title {
128
+ font-weight: 600;
129
+ margin-bottom: 0.4em;
130
+ }
131
+
132
+ .empty-help {
133
+ font-size: 0.875em;
134
+ line-height: 1.5;
135
+ max-width: 22em;
136
+ margin-bottom: 1em;
137
+ color: var(--text-3, #7b8593);
138
+ }
139
+
140
+ .empty-link {
141
+ font-size: 0.875em;
142
+ font-weight: 500;
143
+ color: var(--color-link-primary);
144
+ text-decoration: none;
145
+ }
146
+
147
+ .empty-link:hover {
148
+ text-decoration: underline;
109
149
  }
110
150
 
111
151
  /* row of campaign pills the contact is currently a member of */
@@ -128,7 +168,8 @@ export class ContactEvents extends EndpointMonitorElement {
128
168
  }
129
169
 
130
170
  /* each pill is colored with its campaign's hue - background, border
131
- and text all derived from --pill-hue. read-only badges, not links */
171
+ and text all derived from --pill-hue. clickable links to the
172
+ campaign's read page */
132
173
  .campaign-pill {
133
174
  display: inline-flex;
134
175
  align-items: center;
@@ -146,6 +187,21 @@ export class ContactEvents extends EndpointMonitorElement {
146
187
  border: 1px solid
147
188
  color-mix(in srgb, var(--pill-hue) 25%, var(--color-widget-bg, #fff));
148
189
  color: var(--pill-hue);
190
+ cursor: pointer;
191
+ transition: background 100ms ease-in-out;
192
+ }
193
+
194
+ .campaign-pill:hover {
195
+ background: color-mix(
196
+ in srgb,
197
+ var(--pill-hue) 22%,
198
+ var(--color-widget-bg, #fff)
199
+ );
200
+ }
201
+
202
+ .campaign-pill:focus-visible {
203
+ outline: 2px solid var(--pill-hue);
204
+ outline-offset: 1px;
149
205
  }
150
206
 
151
207
  /* status-badge dot leading each campaign pill, in the same hue */
@@ -424,7 +480,7 @@ export class ContactEvents extends EndpointMonitorElement {
424
480
  const requestedContact = this.contact;
425
481
  try {
426
482
  const response = await this.store.getUrl(
427
- `/contact/events/${encodeURIComponent(this.contact)}/`,
483
+ `/contact/timeline/${encodeURIComponent(this.contact)}/`,
428
484
  { force: true }
429
485
  );
430
486
  if (this.contact !== requestedContact) {
@@ -570,7 +626,7 @@ export class ContactEvents extends EndpointMonitorElement {
570
626
  // capture the contact at request time so a paged response that returns
571
627
  // after the user has switched contacts can't append onto the new timeline
572
628
  const requestedContact = this.contact;
573
- const url = `/contact/events/${encodeURIComponent(
629
+ const url = `/contact/timeline/${encodeURIComponent(
574
630
  this.contact
575
631
  )}/?before=${encodeURIComponent(this.nextBefore)}`;
576
632
 
@@ -609,7 +665,7 @@ export class ContactEvents extends EndpointMonitorElement {
609
665
 
610
666
  this.loadingMoreFuture = true;
611
667
  const requestedContact = this.contact;
612
- const url = `/contact/events/${encodeURIComponent(
668
+ const url = `/contact/timeline/${encodeURIComponent(
613
669
  this.contact
614
670
  )}/?after=${encodeURIComponent(this.nextAfter)}`;
615
671
 
@@ -710,6 +766,13 @@ export class ContactEvents extends EndpointMonitorElement {
710
766
  html`<div
711
767
  class="campaign-pill"
712
768
  style="--pill-hue:${this.getCampaignColor(campaign.uuid)}"
769
+ role="button"
770
+ tabindex="0"
771
+ @click=${(e: Event) => this.handlePillClicked(e, campaign)}
772
+ @keydown=${(e: KeyboardEvent) =>
773
+ this.handleActivationKey(e, () =>
774
+ this.handlePillClicked(e, campaign)
775
+ )}
713
776
  >
714
777
  <span class="campaign-dot"></span>${campaign.name}
715
778
  </div>`
@@ -742,7 +805,14 @@ export class ContactEvents extends EndpointMonitorElement {
742
805
  pastDescending.length === 0
743
806
  ) {
744
807
  return html`<div class="empty">
745
- <slot name="empty">${this.lang_empty}</slot>
808
+ <slot name="empty">
809
+ <temba-icon name=${Icon.schedule} size="2"></temba-icon>
810
+ <div class="empty-title">${this.lang_empty}</div>
811
+ <div class="empty-help">${this.lang_empty_help}</div>
812
+ <a class="empty-link" href="/campaign/" onclick="goto(event)"
813
+ >${this.lang_campaigns_link}</a
814
+ >
815
+ </slot>
746
816
  </div>`;
747
817
  }
748
818
 
package/temba-modules.ts CHANGED
@@ -31,7 +31,7 @@ import { ContactFields } from './src/live/ContactFields';
31
31
  import { ContactFieldEditor } from './src/live/ContactFieldEditor';
32
32
 
33
33
  import { ContactBadges } from './src/live/ContactBadges';
34
- import { ContactEvents } from './src/live/ContactEvents';
34
+ import { ContactTimeline } from './src/live/ContactTimeline';
35
35
  import { TembaSlider } from './src/form/TembaSlider';
36
36
  import { RunList } from './src/list/RunList';
37
37
  import { FlowStoreElement } from './src/store/FlowStoreElement';
@@ -149,7 +149,7 @@ addCustomElement('temba-dropdown', Dropdown);
149
149
  addCustomElement('temba-tabs', TabPane);
150
150
  addCustomElement('temba-tab', Tab);
151
151
  addCustomElement('temba-contact-badges', ContactBadges);
152
- addCustomElement('temba-contact-events', ContactEvents);
152
+ addCustomElement('temba-contact-timeline', ContactTimeline);
153
153
  addCustomElement('temba-slider', TembaSlider);
154
154
  addCustomElement('temba-content-menu', ContentMenu);
155
155
  addCustomElement('temba-compose', Compose);