@nyaruka/temba-components 0.91.1 → 0.91.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.
@@ -85,6 +85,10 @@ export class TemplateEditor extends FormElement {
85
85
  align-items: center;
86
86
  }
87
87
 
88
+ .button .content {
89
+ margin-bottom: 0;
90
+ }
91
+
88
92
  .button .display {
89
93
  margin-right: 0.5em;
90
94
  background: #f9f9f9;
@@ -108,6 +112,7 @@ export class TemplateEditor extends FormElement {
108
112
  max-height: 50vh;
109
113
  overflow-y: auto;
110
114
  overflow-x: hidden;
115
+ padding-bottom: 0;
111
116
  }
112
117
  `;
113
118
  }
@@ -184,7 +189,10 @@ export class TemplateEditor extends FormElement {
184
189
  // create a regex match based on the variable names
185
190
  const variableRegex = new RegExp(`{{(${Object.keys(component.variables || []).join('|')})}}`, 'g');
186
191
  let variables = null;
187
- const parts = ((_a = component.content) === null || _a === void 0 ? void 0 : _a.split(variableRegex)) || [];
192
+ let parts = [];
193
+ if (component.content && component.content.trim().length > 0) {
194
+ parts = ((_a = component.content) === null || _a === void 0 ? void 0 : _a.split(variableRegex)) || [];
195
+ }
188
196
  if (parts.length > 0) {
189
197
  variables = parts.map((part, index) => {
190
198
  if (index % 2 === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateEditor.js","sourceRoot":"","sources":["../../../src/templates/TemplateEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { property } from 'lit/decorators.js';\nimport { FormElement } from '../FormElement';\nimport { TemplateResult, html, css, PropertyValueMap, LitElement } from 'lit';\nimport { CustomEventType } from '../interfaces';\nimport { MediaPicker } from '../mediapicker/MediaPicker';\n\ninterface Component {\n name: string;\n type: string;\n content: string;\n variables: { [key: string]: number };\n}\n\ninterface Translation {\n locale: string;\n status: string;\n channel: { uuid: string; name: string };\n components: Component[];\n variables: { type: string }[];\n}\n\ninterface Template {\n created_on: string;\n modified_on: string;\n name: string;\n translations: Translation[];\n uuid: string;\n}\n\nexport class TemplateEditor extends FormElement {\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true\n };\n\n static get styles() {\n return css`\n .component {\n background: #fff;\n border: 1px solid var(--color-widget-border);\n border-radius: var(--curvature);\n padding: 1em;\n margin-top: 1em;\n }\n\n .content {\n margin-bottom: 1em;\n }\n\n .picker {\n margin-bottom: 0.5em;\n display: block;\n }\n .param {\n display: flex;\n margin-bottom: 0.5em;\n align-items: center;\n }\n label {\n margin-right: 0.5em;\n }\n\n .content span {\n margin-right: 0.25em;\n }\n\n .error-message {\n padding-left: 0.5em;\n }\n\n .variable {\n display: inline-block;\n margin: 0.25em 0em;\n margin-right: 0.25em;\n }\n\n .button-wrapper {\n background: #f9f9f9;\n border-radius: var(--curvature);\n padding: 0.5em;\n display: flex;\n flex-direction: column;\n }\n\n .button-header {\n font-weight: normal;\n margin-left: 0.25em;\n margin-bottom: -0.5em;\n font-size: 0.9em;\n color: #777;\n }\n\n .buttons {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .button {\n background: #fff;\n padding: 0.3em 1em;\n border: 1px solid #e6e6e6;\n border-radius: var(--curvature);\n min-height: 23px;\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-right: 0.5em;\n margin-top: 0.5em;\n align-items: center;\n }\n\n .button .display {\n margin-right: 0.5em;\n background: #f9f9f9;\n padding: 0.25em 1em;\n border-radius: var(--curvature);\n }\n\n temba-textinput,\n temba-completion {\n --temba-textinput-padding: 5px 5px;\n --temba-textinput-font-size: 0.9em;\n line-height: initial;\n }\n\n .template {\n background: #fff;\n border-radius: var(--curvature);\n border: 1px solid var(--color-widget-border);\n padding: 1em;\n line-height: 2.2em;\n max-height: 50vh;\n overflow-y: auto;\n overflow-x: hidden;\n }\n `;\n }\n\n @property({ type: String })\n url: string;\n\n // initial template uuid\n @property({ type: String })\n template: string;\n\n @property({ type: Object })\n selectedTemplate: Template;\n\n @property({ type: String })\n lang = 'eng-US';\n\n @property({ type: Array })\n variables: string[];\n\n @property({ type: Object, attribute: false })\n translation: Translation;\n\n @property({ type: Boolean })\n translating: boolean;\n\n public firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n }\n\n public updated(changedProperties: Map<string, any>): void {\n super.updated(changedProperties);\n }\n\n private handleTemplateChanged(event: CustomEvent) {\n const prev = this.selectedTemplate;\n this.selectedTemplate = (event.target as any).values[0] as Template;\n const [lang, loc] = this.lang.split('-');\n if (this.selectedTemplate) {\n this.selectedTemplate.translations.forEach((translation) => {\n if (\n translation.locale === this.lang ||\n (!loc && translation.locale.split('-')[0] === lang)\n ) {\n this.translation = translation;\n // initialize our variables array\n const newVariables = new Array(\n (translation.variables || []).length\n ).fill('');\n\n if (!prev) {\n // copy our previous variables into newVariables\n if (this.variables) {\n this.variables.forEach((variable, index) => {\n newVariables[index] = variable;\n });\n }\n }\n this.variables = newVariables;\n }\n });\n } else {\n this.translation = null;\n }\n\n this.fireCustomEvent(CustomEventType.ContextChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n variables: this.variables\n });\n }\n\n private handleAttachmentsChanged(event: CustomEvent) {\n const media = event.target as MediaPicker;\n const index = parseInt(media.getAttribute('index'));\n\n if (media.attachments.length === 0) {\n this.variables[index] = '';\n } else {\n const attachment = media.attachments[0];\n if (attachment.url && attachment.content_type) {\n this.variables[index] = `${attachment.content_type}:${attachment.url}`;\n } else {\n this.variables[index] = ``;\n }\n }\n this.fireContentChange();\n }\n\n private handleVariableChanged(event: CustomEvent) {\n const target = event.target as HTMLInputElement;\n const variableIndex = parseInt(target.getAttribute('index'));\n this.variables[variableIndex] = target.value;\n this.fireContentChange();\n }\n\n private fireContentChange() {\n this.fireCustomEvent(CustomEventType.ContentChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n variables: this.variables\n });\n }\n\n private renderVariables(component: Component) {\n // create a regex match based on the variable names\n const variableRegex = new RegExp(\n `{{(${Object.keys(component.variables || []).join('|')})}}`,\n 'g'\n );\n\n let variables = null;\n const parts = component.content?.split(variableRegex) || [];\n if (parts.length > 0) {\n variables = parts.map((part, index) => {\n if (index % 2 === 0) {\n return html`<span class=\"text\">${part}</span>`;\n }\n const variableIndex = component.variables[part];\n return html`<temba-completion\n class=\"variable\"\n type=\"text\"\n value=${variableIndex < this.variables.length\n ? this.variables[variableIndex]\n : null}\n @keyup=${this.handleVariableChanged}\n name=\"${component.name}\"\n index=\"${variableIndex}\"\n placeholder=\"{{${part}}}\"\n ></temba-completion>`;\n });\n } else {\n variables = Object.values(component.variables).map((variableIndex) => {\n const variableSpec = this.translation.variables[variableIndex];\n if (\n variableSpec.type === 'image' ||\n variableSpec.type === 'document' ||\n variableSpec.type === 'audio' ||\n variableSpec.type === 'video'\n ) {\n let attachments = [];\n if (this.variables[variableIndex]) {\n const parts = this.variables[variableIndex].split(':');\n attachments = [{ url: parts[1], content_type: parts[0] }];\n }\n\n return html`<div\n style=\"\n display: flex; \n align-items: center; \n border-radius: var(--curvature);\n ${attachments.length === 0\n ? `background-color:rgba(255,0,0,.07);`\n : ``}\n \"\n >\n <temba-media-picker\n accept=\"${variableSpec.type === 'document'\n ? 'application/pdf'\n : variableSpec.type + '/*'}\"\n max=\"1\"\n index=${variableIndex}\n icon=\"attachment_${variableSpec.type}\"\n attachments=${JSON.stringify(attachments)}\n @change=${this.handleAttachmentsChanged.bind(this)}\n ></temba-media-picker>\n <div>\n ${attachments.length == 0\n ? html`Attach ${variableSpec.type} to continue`\n : ''}\n </div>\n </div>`;\n }\n });\n }\n\n return html`<div class=\"content\">${variables}</div> `;\n }\n\n public renderComponents(components: Component[]): TemplateResult {\n const nonButtons = components\n .filter((comp) => !comp.type.startsWith('button/'))\n .map(\n (component) =>\n html`<div class=\"${component['name']}\">\n ${this.renderVariables(component)}\n </div>`\n );\n const buttonComponents = components.filter((comp) =>\n comp.type.startsWith('button/')\n );\n const buttons =\n buttonComponents.length > 0 ? this.renderButtons(buttonComponents) : null;\n return html`<div class=\"main\">${nonButtons}</div>\n <div class=\"buttons\">\n ${buttons}\n <div></div>\n </div>`;\n }\n\n public renderButtons(components): TemplateResult {\n const buttons = components.map((component) => {\n if (component.display) {\n return html`\n <div class=\"button\">\n <div class=\"display\">${component.display}</div>\n ${this.renderVariables(component)}\n </div>\n `;\n } else {\n return html`\n <div class=\"button\">${this.renderVariables(component)}</div>\n `;\n }\n });\n return html`<div class=\"button-wrapper\">\n <div class=\"button-header\">Template Buttons</div>\n <div class=\"buttons\">${buttons}</div>\n </div>`;\n }\n\n public render(): TemplateResult {\n let content = null;\n if (this.translation) {\n content = this.renderComponents(this.translation.components);\n } else {\n content = html`<div class=\"error-message\">\n No approved translation was found for current language.\n </div>`;\n }\n\n return html`\n <div>\n <temba-select\n searchable\n ?clearable=${!this.translating}\n ?disabled=${this.translating}\n valuekey=\"uuid\"\n class=\"picker\"\n value=\"${this.template}\"\n endpoint=\"${this.url}?comps_as_list=true\"\n shouldExclude=${(template) => template.status !== 'approved'}\n placeholder=\"Select a template\"\n @temba-content-changed=${this.swallowEvent}\n @change=${this.handleTemplateChanged}\n >\n </temba-select>\n\n ${this.template ? html` <div class=\"template\">${content}</div>` : null}\n </div>\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"TemplateEditor.js","sourceRoot":"","sources":["../../../src/templates/TemplateEditor.ts"],"names":[],"mappings":"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","sourcesContent":["import { property } from 'lit/decorators.js';\nimport { FormElement } from '../FormElement';\nimport { TemplateResult, html, css, PropertyValueMap, LitElement } from 'lit';\nimport { CustomEventType } from '../interfaces';\nimport { MediaPicker } from '../mediapicker/MediaPicker';\n\ninterface Component {\n name: string;\n type: string;\n content: string;\n variables: { [key: string]: number };\n}\n\ninterface Translation {\n locale: string;\n status: string;\n channel: { uuid: string; name: string };\n components: Component[];\n variables: { type: string }[];\n}\n\ninterface Template {\n created_on: string;\n modified_on: string;\n name: string;\n translations: Translation[];\n uuid: string;\n}\n\nexport class TemplateEditor extends FormElement {\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true\n };\n\n static get styles() {\n return css`\n .component {\n background: #fff;\n border: 1px solid var(--color-widget-border);\n border-radius: var(--curvature);\n padding: 1em;\n margin-top: 1em;\n }\n\n .content {\n margin-bottom: 1em;\n }\n\n .picker {\n margin-bottom: 0.5em;\n display: block;\n }\n .param {\n display: flex;\n margin-bottom: 0.5em;\n align-items: center;\n }\n label {\n margin-right: 0.5em;\n }\n\n .content span {\n margin-right: 0.25em;\n }\n\n .error-message {\n padding-left: 0.5em;\n }\n\n .variable {\n display: inline-block;\n margin: 0.25em 0em;\n margin-right: 0.25em;\n }\n\n .button-wrapper {\n background: #f9f9f9;\n border-radius: var(--curvature);\n padding: 0.5em;\n display: flex;\n flex-direction: column;\n }\n\n .button-header {\n font-weight: normal;\n margin-left: 0.25em;\n margin-bottom: -0.5em;\n font-size: 0.9em;\n color: #777;\n }\n\n .buttons {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .button {\n background: #fff;\n padding: 0.3em 1em;\n border: 1px solid #e6e6e6;\n border-radius: var(--curvature);\n min-height: 23px;\n display: flex;\n flex-direction: row;\n align-items: center;\n margin-right: 0.5em;\n margin-top: 0.5em;\n align-items: center;\n }\n\n .button .content {\n margin-bottom: 0;\n }\n\n .button .display {\n margin-right: 0.5em;\n background: #f9f9f9;\n padding: 0.25em 1em;\n border-radius: var(--curvature);\n }\n\n temba-textinput,\n temba-completion {\n --temba-textinput-padding: 5px 5px;\n --temba-textinput-font-size: 0.9em;\n line-height: initial;\n }\n\n .template {\n background: #fff;\n border-radius: var(--curvature);\n border: 1px solid var(--color-widget-border);\n padding: 1em;\n line-height: 2.2em;\n max-height: 50vh;\n overflow-y: auto;\n overflow-x: hidden;\n padding-bottom: 0;\n }\n `;\n }\n\n @property({ type: String })\n url: string;\n\n // initial template uuid\n @property({ type: String })\n template: string;\n\n @property({ type: Object })\n selectedTemplate: Template;\n\n @property({ type: String })\n lang = 'eng-US';\n\n @property({ type: Array })\n variables: string[];\n\n @property({ type: Object, attribute: false })\n translation: Translation;\n\n @property({ type: Boolean })\n translating: boolean;\n\n public firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n }\n\n public updated(changedProperties: Map<string, any>): void {\n super.updated(changedProperties);\n }\n\n private handleTemplateChanged(event: CustomEvent) {\n const prev = this.selectedTemplate;\n this.selectedTemplate = (event.target as any).values[0] as Template;\n const [lang, loc] = this.lang.split('-');\n if (this.selectedTemplate) {\n this.selectedTemplate.translations.forEach((translation) => {\n if (\n translation.locale === this.lang ||\n (!loc && translation.locale.split('-')[0] === lang)\n ) {\n this.translation = translation;\n // initialize our variables array\n const newVariables = new Array(\n (translation.variables || []).length\n ).fill('');\n\n if (!prev) {\n // copy our previous variables into newVariables\n if (this.variables) {\n this.variables.forEach((variable, index) => {\n newVariables[index] = variable;\n });\n }\n }\n this.variables = newVariables;\n }\n });\n } else {\n this.translation = null;\n }\n\n this.fireCustomEvent(CustomEventType.ContextChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n variables: this.variables\n });\n }\n\n private handleAttachmentsChanged(event: CustomEvent) {\n const media = event.target as MediaPicker;\n const index = parseInt(media.getAttribute('index'));\n\n if (media.attachments.length === 0) {\n this.variables[index] = '';\n } else {\n const attachment = media.attachments[0];\n if (attachment.url && attachment.content_type) {\n this.variables[index] = `${attachment.content_type}:${attachment.url}`;\n } else {\n this.variables[index] = ``;\n }\n }\n this.fireContentChange();\n }\n\n private handleVariableChanged(event: CustomEvent) {\n const target = event.target as HTMLInputElement;\n const variableIndex = parseInt(target.getAttribute('index'));\n this.variables[variableIndex] = target.value;\n this.fireContentChange();\n }\n\n private fireContentChange() {\n this.fireCustomEvent(CustomEventType.ContentChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n variables: this.variables\n });\n }\n\n private renderVariables(component: Component) {\n // create a regex match based on the variable names\n const variableRegex = new RegExp(\n `{{(${Object.keys(component.variables || []).join('|')})}}`,\n 'g'\n );\n\n let variables = null;\n\n let parts = [];\n if (component.content && component.content.trim().length > 0) {\n parts = component.content?.split(variableRegex) || [];\n }\n\n if (parts.length > 0) {\n variables = parts.map((part, index) => {\n if (index % 2 === 0) {\n return html`<span class=\"text\">${part}</span>`;\n }\n const variableIndex = component.variables[part];\n return html`<temba-completion\n class=\"variable\"\n type=\"text\"\n value=${variableIndex < this.variables.length\n ? this.variables[variableIndex]\n : null}\n @keyup=${this.handleVariableChanged}\n name=\"${component.name}\"\n index=\"${variableIndex}\"\n placeholder=\"{{${part}}}\"\n ></temba-completion>`;\n });\n } else {\n variables = Object.values(component.variables).map((variableIndex) => {\n const variableSpec = this.translation.variables[variableIndex];\n if (\n variableSpec.type === 'image' ||\n variableSpec.type === 'document' ||\n variableSpec.type === 'audio' ||\n variableSpec.type === 'video'\n ) {\n let attachments = [];\n if (this.variables[variableIndex]) {\n const parts = this.variables[variableIndex].split(':');\n attachments = [{ url: parts[1], content_type: parts[0] }];\n }\n\n return html`<div\n style=\"\n display: flex; \n align-items: center; \n border-radius: var(--curvature);\n ${attachments.length === 0\n ? `background-color:rgba(255,0,0,.07);`\n : ``}\n \"\n >\n <temba-media-picker\n accept=\"${variableSpec.type === 'document'\n ? 'application/pdf'\n : variableSpec.type + '/*'}\"\n max=\"1\"\n index=${variableIndex}\n icon=\"attachment_${variableSpec.type}\"\n attachments=${JSON.stringify(attachments)}\n @change=${this.handleAttachmentsChanged.bind(this)}\n ></temba-media-picker>\n <div>\n ${attachments.length == 0\n ? html`Attach ${variableSpec.type} to continue`\n : ''}\n </div>\n </div>`;\n }\n });\n }\n\n return html`<div class=\"content\">${variables}</div> `;\n }\n\n public renderComponents(components: Component[]): TemplateResult {\n const nonButtons = components\n .filter((comp) => !comp.type.startsWith('button/'))\n .map(\n (component) =>\n html`<div class=\"${component['name']}\">\n ${this.renderVariables(component)}\n </div>`\n );\n const buttonComponents = components.filter((comp) =>\n comp.type.startsWith('button/')\n );\n const buttons =\n buttonComponents.length > 0 ? this.renderButtons(buttonComponents) : null;\n return html`<div class=\"main\">${nonButtons}</div>\n <div class=\"buttons\">\n ${buttons}\n <div></div>\n </div>`;\n }\n\n public renderButtons(components): TemplateResult {\n const buttons = components.map((component) => {\n if (component.display) {\n return html`\n <div class=\"button\">\n <div class=\"display\">${component.display}</div>\n ${this.renderVariables(component)}\n </div>\n `;\n } else {\n return html`\n <div class=\"button\">${this.renderVariables(component)}</div>\n `;\n }\n });\n return html`<div class=\"button-wrapper\">\n <div class=\"button-header\">Template Buttons</div>\n <div class=\"buttons\">${buttons}</div>\n </div>`;\n }\n\n public render(): TemplateResult {\n let content = null;\n if (this.translation) {\n content = this.renderComponents(this.translation.components);\n } else {\n content = html`<div class=\"error-message\">\n No approved translation was found for current language.\n </div>`;\n }\n\n return html`\n <div>\n <temba-select\n searchable\n ?clearable=${!this.translating}\n ?disabled=${this.translating}\n valuekey=\"uuid\"\n class=\"picker\"\n value=\"${this.template}\"\n endpoint=\"${this.url}?comps_as_list=true\"\n shouldExclude=${(template) => template.status !== 'approved'}\n placeholder=\"Select a template\"\n @temba-content-changed=${this.swallowEvent}\n @change=${this.handleTemplateChanged}\n >\n </temba-select>\n\n ${this.template ? html` <div class=\"template\">${content}</div>` : null}\n </div>\n `;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nyaruka/temba-components",
3
- "version": "0.91.1",
3
+ "version": "0.91.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",
@@ -110,6 +110,10 @@ export class TemplateEditor extends FormElement {
110
110
  align-items: center;
111
111
  }
112
112
 
113
+ .button .content {
114
+ margin-bottom: 0;
115
+ }
116
+
113
117
  .button .display {
114
118
  margin-right: 0.5em;
115
119
  background: #f9f9f9;
@@ -133,6 +137,7 @@ export class TemplateEditor extends FormElement {
133
137
  max-height: 50vh;
134
138
  overflow-y: auto;
135
139
  overflow-x: hidden;
140
+ padding-bottom: 0;
136
141
  }
137
142
  `;
138
143
  }
@@ -247,7 +252,12 @@ export class TemplateEditor extends FormElement {
247
252
  );
248
253
 
249
254
  let variables = null;
250
- const parts = component.content?.split(variableRegex) || [];
255
+
256
+ let parts = [];
257
+ if (component.content && component.content.trim().length > 0) {
258
+ parts = component.content?.split(variableRegex) || [];
259
+ }
260
+
251
261
  if (parts.length > 0) {
252
262
  variables = parts.map((part, index) => {
253
263
  if (index % 2 === 0) {