@nyaruka/temba-components 0.72.0 → 0.72.1
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/CHANGELOG.md +6 -0
- package/dist/{c6d002ae.js → 730431a7.js} +2 -3
- package/dist/index.js +2 -3
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/templates/TemplateEditor.js +2 -3
- package/out-tsc/src/templates/TemplateEditor.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/TemplateEditor.ts +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,14 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v0.72.1](https://github.com/nyaruka/temba-components/compare/v0.72.0...v0.72.1)
|
|
8
|
+
|
|
9
|
+
- Recognize template buttons.0 or button.0 [`#400`](https://github.com/nyaruka/temba-components/pull/400)
|
|
10
|
+
|
|
7
11
|
#### [v0.72.0](https://github.com/nyaruka/temba-components/compare/v0.71.4...v0.72.0)
|
|
8
12
|
|
|
13
|
+
> 6 March 2024
|
|
14
|
+
|
|
9
15
|
- Add template editor [`#399`](https://github.com/nyaruka/temba-components/pull/399)
|
|
10
16
|
|
|
11
17
|
#### [v0.71.4](https://github.com/nyaruka/temba-components/compare/v0.71.3...v0.71.4)
|
|
@@ -7235,7 +7235,7 @@ background: #ccc;
|
|
|
7235
7235
|
border: 1px solid var(--color-widget-border);
|
|
7236
7236
|
border-radius: var(--curvature);
|
|
7237
7237
|
padding: 1em;
|
|
7238
|
-
margin-
|
|
7238
|
+
margin-top: 1em;
|
|
7239
7239
|
}
|
|
7240
7240
|
.picker {
|
|
7241
7241
|
margin-bottom: 0.5em;
|
|
@@ -7284,7 +7284,6 @@ background: #ccc;
|
|
|
7284
7284
|
.buttons {
|
|
7285
7285
|
display: flex;
|
|
7286
7286
|
align-items: center;
|
|
7287
|
-
|
|
7288
7287
|
flex-wrap: wrap;
|
|
7289
7288
|
}
|
|
7290
7289
|
|
|
@@ -7314,7 +7313,7 @@ background: #ccc;
|
|
|
7314
7313
|
padding: 1em;
|
|
7315
7314
|
line-height: 2.2em;
|
|
7316
7315
|
}
|
|
7317
|
-
`}firstUpdated(t){super.firstUpdated(t)}updated(t){super.updated(t)}handleTemplateChanged(t){this.selectedTemplate=t.target.values[0];const[e,i]=this.lang.split("-"),o={};this.selectedTemplate?this.selectedTemplate.translations.forEach((t=>{if(t.locale===this.lang||!i&&t.locale.split("-")[0]===e){this.translation=t,this.buttonKeys=[],this.contentKeys=[],this.otherKeys=[];const e=Object.keys(t.components);for(const i of e){i.startsWith("
|
|
7316
|
+
`}firstUpdated(t){super.firstUpdated(t)}updated(t){super.updated(t)}handleTemplateChanged(t){this.selectedTemplate=t.target.values[0];const[e,i]=this.lang.split("-"),o={};this.selectedTemplate?this.selectedTemplate.translations.forEach((t=>{if(t.locale===this.lang||!i&&t.locale.split("-")[0]===e){this.translation=t,this.buttonKeys=[],this.contentKeys=[],this.otherKeys=[];const e=Object.keys(t.components);for(const i of e){i.startsWith("button")?this.buttonKeys.push(i):i===vh||i===yh||i===bh?this.contentKeys.push(i):this.otherKeys.push(i);const e=t.components[i].params||[];e.length>0&&(o[i]=new Array(e.length).fill(""))}if(this.buttonKeys.sort(),this.template===this.selectedTemplate.uuid)for(const t of Object.keys(this.params||{}))if(o[t])for(let e=0;e<this.params[t].length;e++)o[t][e]=this.params[t][e]}})):this.translation=null,this.params=o,this.fireCustomEvent(we.ContextChanged,{template:this.selectedTemplate,translation:this.translation,params:this.params})}handleVariableChanged(t){const e=t.target,i=e.getAttribute("key"),o=parseInt(e.getAttribute("index"));this.params[i][o-1]=e.value,this.fireCustomEvent(we.ContentChanged,{template:this.selectedTemplate,translation:this.translation,params:this.params})}renderVariables(t,e){const i=e.content.split(/{{(\d+)}}/g);if(i.length>0){const e=i.map(((e,i)=>{const o=Math.round(i/2);return i%2==0?D`<span class="text">${e}</span>`:D`<temba-completion
|
|
7318
7317
|
class="variable"
|
|
7319
7318
|
type="text"
|
|
7320
7319
|
value=${this.params[t][o-1]}
|
package/dist/index.js
CHANGED
|
@@ -7235,7 +7235,7 @@ background: #ccc;
|
|
|
7235
7235
|
border: 1px solid var(--color-widget-border);
|
|
7236
7236
|
border-radius: var(--curvature);
|
|
7237
7237
|
padding: 1em;
|
|
7238
|
-
margin-
|
|
7238
|
+
margin-top: 1em;
|
|
7239
7239
|
}
|
|
7240
7240
|
.picker {
|
|
7241
7241
|
margin-bottom: 0.5em;
|
|
@@ -7284,7 +7284,6 @@ background: #ccc;
|
|
|
7284
7284
|
.buttons {
|
|
7285
7285
|
display: flex;
|
|
7286
7286
|
align-items: center;
|
|
7287
|
-
|
|
7288
7287
|
flex-wrap: wrap;
|
|
7289
7288
|
}
|
|
7290
7289
|
|
|
@@ -7314,7 +7313,7 @@ background: #ccc;
|
|
|
7314
7313
|
padding: 1em;
|
|
7315
7314
|
line-height: 2.2em;
|
|
7316
7315
|
}
|
|
7317
|
-
`}firstUpdated(t){super.firstUpdated(t)}updated(t){super.updated(t)}handleTemplateChanged(t){this.selectedTemplate=t.target.values[0];const[e,i]=this.lang.split("-"),o={};this.selectedTemplate?this.selectedTemplate.translations.forEach((t=>{if(t.locale===this.lang||!i&&t.locale.split("-")[0]===e){this.translation=t,this.buttonKeys=[],this.contentKeys=[],this.otherKeys=[];const e=Object.keys(t.components);for(const i of e){i.startsWith("
|
|
7316
|
+
`}firstUpdated(t){super.firstUpdated(t)}updated(t){super.updated(t)}handleTemplateChanged(t){this.selectedTemplate=t.target.values[0];const[e,i]=this.lang.split("-"),o={};this.selectedTemplate?this.selectedTemplate.translations.forEach((t=>{if(t.locale===this.lang||!i&&t.locale.split("-")[0]===e){this.translation=t,this.buttonKeys=[],this.contentKeys=[],this.otherKeys=[];const e=Object.keys(t.components);for(const i of e){i.startsWith("button")?this.buttonKeys.push(i):i===vh||i===yh||i===bh?this.contentKeys.push(i):this.otherKeys.push(i);const e=t.components[i].params||[];e.length>0&&(o[i]=new Array(e.length).fill(""))}if(this.buttonKeys.sort(),this.template===this.selectedTemplate.uuid)for(const t of Object.keys(this.params||{}))if(o[t])for(let e=0;e<this.params[t].length;e++)o[t][e]=this.params[t][e]}})):this.translation=null,this.params=o,this.fireCustomEvent(we.ContextChanged,{template:this.selectedTemplate,translation:this.translation,params:this.params})}handleVariableChanged(t){const e=t.target,i=e.getAttribute("key"),o=parseInt(e.getAttribute("index"));this.params[i][o-1]=e.value,this.fireCustomEvent(we.ContentChanged,{template:this.selectedTemplate,translation:this.translation,params:this.params})}renderVariables(t,e){const i=e.content.split(/{{(\d+)}}/g);if(i.length>0){const e=i.map(((e,i)=>{const o=Math.round(i/2);return i%2==0?D`<span class="text">${e}</span>`:D`<temba-completion
|
|
7318
7317
|
class="variable"
|
|
7319
7318
|
type="text"
|
|
7320
7319
|
value=${this.params[t][o-1]}
|
package/dist/sw.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
if(!self.define){let e,t={};const o=(o,n)=>(o=new URL(o+".js",n).href,t[o]||new Promise((t=>{if("document"in self){const e=document.createElement("script");e.src=o,e.onload=t,document.head.appendChild(e)}else e=o,importScripts(o),t()})).then((()=>{let e=t[o];if(!e)throw new Error(`Module ${o} didn’t register its module`);return e})));self.define=(n,s)=>{const
|
|
1
|
+
if(!self.define){let e,t={};const o=(o,n)=>(o=new URL(o+".js",n).href,t[o]||new Promise((t=>{if("document"in self){const e=document.createElement("script");e.src=o,e.onload=t,document.head.appendChild(e)}else e=o,importScripts(o),t()})).then((()=>{let e=t[o];if(!e)throw new Error(`Module ${o} didn’t register its module`);return e})));self.define=(n,s)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(t[i])return;let r={};const c=e=>o(e,i),l={module:{uri:i},exports:r,require:c};t[i]=Promise.all(n.map((e=>l[e]||c(e)))).then((e=>(s(...e),r)))}}define(["./workbox-919adfb7"],(function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"730431a7.js",revision:"2668305c467cc78a209d10fef36ae7bc"},{url:"templates/components-body.html",revision:"c1eb1440dcc311f3749bb736aa62e95a"},{url:"templates/components-head.html",revision:"5242c9b11b895339bd0a329824d05e21"}],{}),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"))),e.registerRoute("polyfills/*.js",new e.CacheFirst,"GET")}));
|
|
2
2
|
//# sourceMappingURL=sw.js.map
|
package/dist/sw.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sw.js","sources":["../../tmp/
|
|
1
|
+
{"version":3,"file":"sw.js","sources":["../../tmp/60ae454215d763acb39c754ae7732117/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/workspaces/temba-components/node_modules/workbox-routing/registerRoute.mjs';\nimport {CacheFirst as workbox_strategies_CacheFirst} from '/workspaces/temba-components/node_modules/workbox-strategies/CacheFirst.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/workspaces/temba-components/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/workspaces/temba-components/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/workspaces/temba-components/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/workspaces/temba-components/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\n\n\n\n\nself.skipWaiting();\n\nworkbox_core_clientsClaim();\n\n\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"730431a7.js\",\n \"revision\": \"2668305c467cc78a209d10fef36ae7bc\"\n },\n {\n \"url\": \"templates/components-body.html\",\n \"revision\": \"c1eb1440dcc311f3749bb736aa62e95a\"\n },\n {\n \"url\": \"templates/components-head.html\",\n \"revision\": \"5242c9b11b895339bd0a329824d05e21\"\n }\n], {});\n\nworkbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"/index.html\")));\n\n\nworkbox_routing_registerRoute(\"polyfills/*.js\", new workbox_strategies_CacheFirst(), 'GET');\n\n\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox","registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","workbox_strategies_CacheFirst"],"mappings":"0nBAwBAA,KAAKC,cAELC,EAAAA,eAQAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,cACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,oCAEd,CACED,IAAO,iCACPC,SAAY,qCAEb,CAAE,GAEwBC,EAAAC,cAAC,IAAIC,EAAAA,gBAAgCC,EAAAA,wBAA2C,iBAGhFH,EAAAC,cAAC,iBAAkB,IAAIG,aAAiC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<script type="module" src="{{STATIC_URL}}@nyaruka/temba-components/dist/
|
|
1
|
+
<script type="module" src="{{STATIC_URL}}@nyaruka/temba-components/dist/730431a7.js"></script><script>window.TEMBA_COMPONENTS_VERSION="0.72.1"</script>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<script src="{{STATIC_URL}}croppie/croppie.js"></script><link rel="modulepreload" href="{{STATIC_URL}}@nyaruka/temba-components/dist/
|
|
1
|
+
<script src="{{STATIC_URL}}croppie/croppie.js"></script><link rel="modulepreload" href="{{STATIC_URL}}@nyaruka/temba-components/dist/730431a7.js" crossorigin="anonymous">
|
|
@@ -6,7 +6,7 @@ import { CustomEventType } from '../interfaces';
|
|
|
6
6
|
const KEY_HEADER = 'header';
|
|
7
7
|
const KEY_BODY = 'body';
|
|
8
8
|
const KEY_FOOTER = 'footer';
|
|
9
|
-
const KEY_BUTTONS = '
|
|
9
|
+
const KEY_BUTTONS = 'button';
|
|
10
10
|
export class TemplateEditor extends FormElement {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
@@ -22,7 +22,7 @@ export class TemplateEditor extends FormElement {
|
|
|
22
22
|
border: 1px solid var(--color-widget-border);
|
|
23
23
|
border-radius: var(--curvature);
|
|
24
24
|
padding: 1em;
|
|
25
|
-
margin-
|
|
25
|
+
margin-top: 1em;
|
|
26
26
|
}
|
|
27
27
|
.picker {
|
|
28
28
|
margin-bottom: 0.5em;
|
|
@@ -71,7 +71,6 @@ export class TemplateEditor extends FormElement {
|
|
|
71
71
|
.buttons {
|
|
72
72
|
display: flex;
|
|
73
73
|
align-items: center;
|
|
74
|
-
|
|
75
74
|
flex-wrap: wrap;
|
|
76
75
|
}
|
|
77
76
|
|
|
@@ -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 } from 'lit';\nimport { CustomEventType } from '../interfaces';\n\nconst KEY_HEADER = 'header';\nconst KEY_BODY = 'body';\nconst KEY_FOOTER = 'footer';\nconst KEY_BUTTONS = 'buttons';\n\ninterface Component {\n content: string;\n params: { type: string }[];\n}\n\ninterface Translation {\n locale: string;\n status: string;\n channel: { uuid: string; name: string };\n components: { [key: string]: Component };\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 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-bottom: 0.5em;\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 margin-top: 1em;\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\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 align-items: center;\n margin-right: 0.5em;\n margin-top: 0.5em;\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 }\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 // component key to array of strings for variables\n @property({ type: Object })\n params: { [key: string]: string[] };\n\n @property({ type: Object, attribute: false })\n translation: Translation;\n\n @property({ type: Boolean })\n translating: boolean;\n\n buttonKeys = [];\n contentKeys = [];\n otherKeys = [];\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 this.selectedTemplate = (event.target as any).values[0] as Template;\n const [lang, loc] = this.lang.split('-');\n\n const newParams = {};\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 this.buttonKeys = [];\n this.contentKeys = [];\n this.otherKeys = [];\n const keys = Object.keys(translation.components);\n for (const key of keys) {\n if (key.startsWith(KEY_BUTTONS)) {\n this.buttonKeys.push(key);\n } else if (\n key === KEY_HEADER ||\n key === KEY_BODY ||\n key === KEY_FOOTER\n ) {\n this.contentKeys.push(key);\n } else {\n this.otherKeys.push(key);\n }\n\n const compParams = translation.components[key].params || [];\n if (compParams.length > 0) {\n // create an array for the length of params\n newParams[key] = new Array(compParams.length).fill('');\n }\n }\n this.buttonKeys.sort();\n\n // if we are looking at the same template copy our params on top\n if (this.template === this.selectedTemplate.uuid) {\n for (const key of Object.keys(this.params || {})) {\n if (newParams[key]) {\n for (let i = 0; i < this.params[key].length; i++) {\n newParams[key][i] = this.params[key][i];\n }\n }\n }\n }\n }\n });\n } else {\n this.translation = null;\n }\n\n this.params = newParams;\n this.fireCustomEvent(CustomEventType.ContextChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n params: this.params,\n });\n }\n\n private handleVariableChanged(event: CustomEvent) {\n const target = event.target as HTMLInputElement;\n const key = target.getAttribute('key');\n const index = parseInt(target.getAttribute('index'));\n this.params[key][index - 1] = target.value;\n this.fireCustomEvent(CustomEventType.ContentChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n params: this.params,\n });\n }\n\n private renderVariables(key: string, component: Component) {\n const parts = component.content.split(/{{(\\d+)}}/g);\n if (parts.length > 0) {\n const variables = parts.map((part, index) => {\n const keyIndex = Math.round(index / 2);\n if (index % 2 === 0) {\n return html`<span class=\"text\">${part}</span>`;\n }\n return html`<temba-completion\n class=\"variable\"\n type=\"text\"\n value=${this.params[key][keyIndex - 1]}\n @change=${this.handleVariableChanged}\n key=\"${key}\"\n index=\"${keyIndex}}\"\n placeholder=\"variable..\"\n ></temba-completion>`;\n });\n return html`<div class=\"content\">${variables}</div>`;\n }\n }\n\n private renderComponent(key: string, component: Component) {\n return html` <div class=\"component\">\n <div>${key}</div>\n ${this.renderVariables(key, component)}\n </div>`;\n }\n\n public renderContent(components: {\n [key: string]: Component;\n }): TemplateResult {\n let header = null;\n let body = null;\n let footer = null;\n\n if (components[KEY_HEADER]) {\n header = html`<div class=\"header\">\n ${this.renderVariables(KEY_HEADER, components[KEY_HEADER])}\n </div>`;\n }\n\n if (components[KEY_BODY]) {\n body = html`<div class=\"body\">\n ${this.renderVariables(KEY_BODY, components[KEY_BODY])}\n </div>`;\n }\n\n if (components[KEY_FOOTER]) {\n footer = html`<div class=\"footer\">\n ${this.renderVariables(KEY_FOOTER, components[KEY_FOOTER])}\n </div>`;\n }\n\n if (header || body || footer) {\n return html`<div class=\"content\">${header}${body}${footer}</div>`;\n }\n return null;\n }\n\n public renderButtons(components): TemplateResult {\n if (this.buttonKeys.length > 0) {\n const buttons = this.buttonKeys.map(key => {\n const component = components[key];\n return html`<div class=\"button\">\n ${this.renderVariables(key, component)}\n </div>`;\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 return null;\n }\n public render(): TemplateResult {\n let content = null;\n let buttons = null;\n let otherComponents = null;\n if (this.translation) {\n content = this.renderContent(this.translation.components);\n buttons = this.renderButtons(this.translation.components);\n otherComponents = this.otherKeys.map(key => {\n const component = this.translation.components[key];\n return this.renderComponent(key, component);\n });\n } else {\n otherComponents = 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}\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\n ? html` <div class=\"template\">\n ${content} ${buttons} ${otherComponents}\n </div>`\n : 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 } from 'lit';\nimport { CustomEventType } from '../interfaces';\n\nconst KEY_HEADER = 'header';\nconst KEY_BODY = 'body';\nconst KEY_FOOTER = 'footer';\nconst KEY_BUTTONS = 'button';\n\ninterface Component {\n content: string;\n params: { type: string }[];\n}\n\ninterface Translation {\n locale: string;\n status: string;\n channel: { uuid: string; name: string };\n components: { [key: string]: Component };\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 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 .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 margin-top: 1em;\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 align-items: center;\n margin-right: 0.5em;\n margin-top: 0.5em;\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 }\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 // component key to array of strings for variables\n @property({ type: Object })\n params: { [key: string]: string[] };\n\n @property({ type: Object, attribute: false })\n translation: Translation;\n\n @property({ type: Boolean })\n translating: boolean;\n\n buttonKeys = [];\n contentKeys = [];\n otherKeys = [];\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 this.selectedTemplate = (event.target as any).values[0] as Template;\n const [lang, loc] = this.lang.split('-');\n\n const newParams = {};\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 this.buttonKeys = [];\n this.contentKeys = [];\n this.otherKeys = [];\n const keys = Object.keys(translation.components);\n for (const key of keys) {\n if (key.startsWith(KEY_BUTTONS)) {\n this.buttonKeys.push(key);\n } else if (\n key === KEY_HEADER ||\n key === KEY_BODY ||\n key === KEY_FOOTER\n ) {\n this.contentKeys.push(key);\n } else {\n this.otherKeys.push(key);\n }\n\n const compParams = translation.components[key].params || [];\n if (compParams.length > 0) {\n // create an array for the length of params\n newParams[key] = new Array(compParams.length).fill('');\n }\n }\n this.buttonKeys.sort();\n\n // if we are looking at the same template copy our params on top\n if (this.template === this.selectedTemplate.uuid) {\n for (const key of Object.keys(this.params || {})) {\n if (newParams[key]) {\n for (let i = 0; i < this.params[key].length; i++) {\n newParams[key][i] = this.params[key][i];\n }\n }\n }\n }\n }\n });\n } else {\n this.translation = null;\n }\n\n this.params = newParams;\n this.fireCustomEvent(CustomEventType.ContextChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n params: this.params,\n });\n }\n\n private handleVariableChanged(event: CustomEvent) {\n const target = event.target as HTMLInputElement;\n const key = target.getAttribute('key');\n const index = parseInt(target.getAttribute('index'));\n this.params[key][index - 1] = target.value;\n this.fireCustomEvent(CustomEventType.ContentChanged, {\n template: this.selectedTemplate,\n translation: this.translation,\n params: this.params,\n });\n }\n\n private renderVariables(key: string, component: Component) {\n const parts = component.content.split(/{{(\\d+)}}/g);\n if (parts.length > 0) {\n const variables = parts.map((part, index) => {\n const keyIndex = Math.round(index / 2);\n if (index % 2 === 0) {\n return html`<span class=\"text\">${part}</span>`;\n }\n return html`<temba-completion\n class=\"variable\"\n type=\"text\"\n value=${this.params[key][keyIndex - 1]}\n @change=${this.handleVariableChanged}\n key=\"${key}\"\n index=\"${keyIndex}}\"\n placeholder=\"variable..\"\n ></temba-completion>`;\n });\n return html`<div class=\"content\">${variables}</div>`;\n }\n }\n\n private renderComponent(key: string, component: Component) {\n return html` <div class=\"component\">\n <div>${key}</div>\n ${this.renderVariables(key, component)}\n </div>`;\n }\n\n public renderContent(components: {\n [key: string]: Component;\n }): TemplateResult {\n let header = null;\n let body = null;\n let footer = null;\n\n if (components[KEY_HEADER]) {\n header = html`<div class=\"header\">\n ${this.renderVariables(KEY_HEADER, components[KEY_HEADER])}\n </div>`;\n }\n\n if (components[KEY_BODY]) {\n body = html`<div class=\"body\">\n ${this.renderVariables(KEY_BODY, components[KEY_BODY])}\n </div>`;\n }\n\n if (components[KEY_FOOTER]) {\n footer = html`<div class=\"footer\">\n ${this.renderVariables(KEY_FOOTER, components[KEY_FOOTER])}\n </div>`;\n }\n\n if (header || body || footer) {\n return html`<div class=\"content\">${header}${body}${footer}</div>`;\n }\n return null;\n }\n\n public renderButtons(components): TemplateResult {\n if (this.buttonKeys.length > 0) {\n const buttons = this.buttonKeys.map(key => {\n const component = components[key];\n return html`<div class=\"button\">\n ${this.renderVariables(key, component)}\n </div>`;\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 return null;\n }\n public render(): TemplateResult {\n let content = null;\n let buttons = null;\n let otherComponents = null;\n if (this.translation) {\n content = this.renderContent(this.translation.components);\n buttons = this.renderButtons(this.translation.components);\n otherComponents = this.otherKeys.map(key => {\n const component = this.translation.components[key];\n return this.renderComponent(key, component);\n });\n } else {\n otherComponents = 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}\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\n ? html` <div class=\"template\">\n ${content} ${buttons} ${otherComponents}\n </div>`\n : null}\n </div>\n `;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@ import { CustomEventType } from '../interfaces';
|
|
|
6
6
|
const KEY_HEADER = 'header';
|
|
7
7
|
const KEY_BODY = 'body';
|
|
8
8
|
const KEY_FOOTER = 'footer';
|
|
9
|
-
const KEY_BUTTONS = '
|
|
9
|
+
const KEY_BUTTONS = 'button';
|
|
10
10
|
|
|
11
11
|
interface Component {
|
|
12
12
|
content: string;
|
|
@@ -36,7 +36,7 @@ export class TemplateEditor extends FormElement {
|
|
|
36
36
|
border: 1px solid var(--color-widget-border);
|
|
37
37
|
border-radius: var(--curvature);
|
|
38
38
|
padding: 1em;
|
|
39
|
-
margin-
|
|
39
|
+
margin-top: 1em;
|
|
40
40
|
}
|
|
41
41
|
.picker {
|
|
42
42
|
margin-bottom: 0.5em;
|
|
@@ -85,7 +85,6 @@ export class TemplateEditor extends FormElement {
|
|
|
85
85
|
.buttons {
|
|
86
86
|
display: flex;
|
|
87
87
|
align-items: center;
|
|
88
|
-
|
|
89
88
|
flex-wrap: wrap;
|
|
90
89
|
}
|
|
91
90
|
|