From a80a590f3757d3d6581c6ec879da26f33c92687e Mon Sep 17 00:00:00 2001
From: Eugen Neuber <eugen.neuber@tugraz.at>
Date: Wed, 13 Jan 2021 16:48:35 +0100
Subject: [PATCH] Use lang attribute in consumer component

TODO: translate some untranslated strings
---
 packages/provider/assets/index.html.ejs       |  11 +-
 packages/provider/src/dbp-provider-demo.js    | 150 +++++++++++++++---
 .../provider/src/i18n/de/translation.json     |  11 +-
 .../provider/src/i18n/en/translation.json     |  11 +-
 4 files changed, 152 insertions(+), 31 deletions(-)

diff --git a/packages/provider/assets/index.html.ejs b/packages/provider/assets/index.html.ejs
index 0ce3cd32..4ec7c098 100644
--- a/packages/provider/assets/index.html.ejs
+++ b/packages/provider/assets/index.html.ejs
@@ -2,6 +2,7 @@
 <html>
 <head>
     <meta charset="UTF-8">
+    <script type="module" src="dbp-provider.js"></script>
     <script type="module" src="dbp-provider-demo.js"></script>
     <!--
         This is for debugging only:
@@ -16,9 +17,13 @@
 </head>
 
 <body>
-
-<dbp-provider-demo lang="de"></dbp-provider-demo>
-
+    <dbp-provider id="root"
+                  root="1"
+                  availability="global"
+                  lang="de"
+    >
+        <dbp-provider-demo id="provider-demo" subscribe="lang:lang"></dbp-provider-demo>
+    </dbp-provider>
 <p>version: <span style="color: white; background-color: black;"><%= buildInfo.info %></span></p>
 </body>
 </html>
diff --git a/packages/provider/src/dbp-provider-demo.js b/packages/provider/src/dbp-provider-demo.js
index da88f580..586e08af 100644
--- a/packages/provider/src/dbp-provider-demo.js
+++ b/packages/provider/src/dbp-provider-demo.js
@@ -14,6 +14,10 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
     constructor() {
         super();
         this.lang = 'de';
+        this.subscribe = '';
+
+        this.deferSubscribe = false;
+        this.deferUnSubscribe = false;
     }
 
     static get scopedElements() {
@@ -29,12 +33,96 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
     static get properties() {
         return {
             lang: { type: String },
+            subscribe: { type: String }
         };
     }
 
     connectedCallback() {
         super.connectedCallback();
         i18n.changeLanguage(this.lang);
+
+        if (this.deferUnSubscribe) {
+            const attrs = this.unsubscribe.split(',');
+            attrs.forEach(element => this.subscribeProviderFor(element));
+            this.deferSubscribe = false;
+            this.unsubscribe = '';
+        }
+        if (this.deferSubscribe) {
+            const attrs = this.subscribe.split(',');
+            attrs.forEach(element => this.subscribeProviderFor(element));
+            this.deferSubscribe = false;
+        }
+    }
+
+    attributeChangedCallback(name, oldValue, newValue) {
+        console.log('ProviderDemo (' + this.id() + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
+        switch(name) {
+            case 'lang':
+                this.lang = newValue;
+                i18n.changeLanguage(this.lang);
+                break;
+            case 'subscribe':
+                if (this.subscribe && this.subscribe.length > 0) {
+                    if (this.connected) {
+                        const attrs = this.subscribe.split(',');
+                        attrs.forEach(element => this.unSubscribeProviderFor(element));
+                    } else {
+                        this.deferUnSubscribe = this.subscribe.length > 0;
+                        this.unsubscribe = this.subscribe;
+                    }
+                }
+                if (newValue !== null) {
+                    this.subscribe = newValue;
+                    if (this.connected) {
+                        const attrs = newValue.split(',');
+                        attrs.forEach(element => this.subscribeProviderFor(element));
+                    } else {
+                        this.deferSubscribe = newValue && newValue.length > 0;
+                    }
+                }
+                break;
+            default:
+                super.attributeChangedCallback(name, oldValue, newValue);
+        }
+        this.render();
+    }
+
+    subscribeProviderFor(element) {
+        console.log('ProviderDemo (' + this.id() + ') subscribeProviderFor( ' + element + ' )');
+        const pair = element.trim().split(':');
+        const global = pair[0];
+        const local = pair[1];
+        const that = this;
+        const event = new CustomEvent('subscribe',
+            {
+                bubbles: true,
+                composed: true,
+                detail: {
+                    name: global,
+                    callback: (value) => {
+                        console.log('ProviderDemo (' + that.id() + ') sub/Callback ' + global + ' -> ' + local + ' = ' + value);
+                        that.attributeChangedCallback(local, that[local], value);
+                    },
+                    sender: this,
+                }
+            });
+        this.parentElement.dispatchEvent(event);
+    }
+
+    unSubscribeProviderFor(element) {
+        console.log('ProviderDemo (' + this.id() + ') unSubscribeProviderFor( ' + element + ' )');
+        const pair = element.trim().split(':');
+        const global = pair[0];
+        const event = new CustomEvent('unsubscribe',
+            {
+                bubbles: true,
+                composed: true,
+                detail: {
+                    name: global,
+                    sender: this,
+                }
+            });
+        this.parentElement.dispatchEvent(event);
     }
 
     static get styles() {
@@ -51,18 +139,13 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
 
     render() {
         return html`
-            <dbp-provider id="root"
-                          root="1"
-                          blah="777"
-                          availability="global"
-                          lang="de"
-            ><section class="section">
-                <p>Provider <em>"root"</em> is the top most in hierarchy:</p>
+            <section class="section">
+                <p>${i18n.t('demo.provider')} <em>"root"</em> is the top most in hierarchy:</p>
 <pre>
 &lt;dbp-provider  id="root"  root="1" availability="global" >&lt;/dbp-provider&gt;
 </pre>
                 <div class="container">
-                    <h1 class="title">Provider-Demo</h1>
+                    <h1 class="title">${i18n.t('demo.provider')}-Demo</h1>
                 </div>
                 <div class="container">
                     <dbp-auth-keycloak lang="${this.lang}" url="https://auth-dev.tugraz.at/auth" realm="tugraz" client-id="auth-dev-mw-frontend-local" load-person try-login></dbp-auth-keycloak>
@@ -77,39 +160,39 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
                                   bar="20"
                 >
                     <div class="container">
-                    <h2>Provider</h2>
-                    <p>Provider <em>"demo"</em> has only <em>border-color</em> to offer:</p>
+                    <h2>${i18n.t('demo.provider')}</h2>
+                    <p>${i18n.t('demo.provider')} <em>"demo"</em> has only <em>border-color</em> to offer:</p>
 <pre>
 &lt;dbp-provider  id="demo"  bc="blue" &gt;&lt;/dbp-provider&gt;
 </pre>
-                    <p>Provider <em>"foo-bar"</em> has some values in its store:</p>
+                    <p>${i18n.t('demo.provider')} <em>"foo-bar"</em> has some values in its store:</p>
 <pre>
 &lt;dbp-provider  id="foo-bar"  foo="9" bar="20" &gt;&lt;/dbp-provider&gt;
 </pre>
-                    <h2>Consumer</h2>
-                    <p>Consumer <em>"c1"</em> will only subscribe to <em>border-color</em></p>
+                    <h2>${i18n.t('demo.consumer')}</h2>
+                    <p>${i18n.t('demo.consumer')} <em>"c1"</em> will only subscribe to <em>border-color</em></p>
 <pre>
 &lt;dbp-consumer  id="c1"  subscribe="bc:border-color" &gt;&lt;/dbp-consumer&gt;
 </pre>
                     <dbp-consumer id="c1"
-                                  subscribe="bc:border-color"
+                                  subscribe="bc:border-color,lang:lang"
                     ></dbp-consumer>
-                    <p>Consumer <em>"c2"</em> subscribes to <em>foo</em></p>
+                    <p>${i18n.t('demo.consumer')} <em>"c2"</em> subscribes to <em>foo</em></p>
 <pre>
 &lt;dbp-consumer  id="c2"  subscribe="foo:foo" &gt;&lt;/dbp-consumer&gt;
 </pre>
                     <dbp-consumer id="c2"
-                                  subscribe="foo:foo"
+                                  subscribe="foo:foo,lang:lang"
                     ></dbp-consumer>
-                    <p>Consumer <em>"c3"</em> subscribes for <em>status</em> which is provided as <em>availability</em></p>
+                    <p>${i18n.t('demo.consumer')} <em>"c3"</em> subscribes for <em>status</em> which is provided as <em>availability</em></p>
 <pre>
 &lt;dbp-consumer  id="c3"  subscribe="availability:status"  border-color="orange" &gt;&lt;/dbp-consumer&gt;
 </pre>
                     <dbp-consumer id="c3"
-                                  subscribe="availability:status"
+                                  subscribe="availability:status,lang:lang"
                                   border-color="orange"
                     ></dbp-consumer>
-                    <p>Consumer <em>"c4"</em> subscribes for <em>status</em> which is provided as <em>unknown-name</em> which does not exist...</p>
+                    <p>${i18n.t('demo.consumer')} <em>"c4"</em> subscribes for <em>status</em> which is provided as <em>unknown-name</em> which does not exist...</p>
 <pre>
 &lt;dbp-consumer  id="c4"  subscribe="unknown-name:status"  border-color="darkgray" &gt;&lt;/dbp-consumer&gt;
 </pre>
@@ -121,9 +204,12 @@ class ProviderDemo extends ScopedElementsMixin(LitElement) {
                 </dbp-provider>
                 </dbp-provider>
             </section>
-            </dbp-provider>
         `;
     }
+
+    id() {
+        return this.getAttribute('id');
+    }
 }
 
 commonUtils.defineCustomElement('dbp-provider-demo', ProviderDemo);
@@ -277,11 +363,11 @@ class Consumer extends HTMLElement {
     }
 }
 
-class DemoConsumer extends Consumer
-{
+class DemoConsumer extends Consumer {
     constructor() {
         super();
 
+        this.lang = 'de';
         // default values
         this.foo = 100;
         this.bar = 900;
@@ -295,17 +381,29 @@ class DemoConsumer extends Consumer
 
     connectedCallback() {
         super.connectedCallback();
+        i18n.changeLanguage(this.lang);
         console.log('DemoConsumer(' + this.id() + ') connectedCallback()');
         this.render();
     }
 
     static get observedAttributes() {
-        return [ ...Consumer.observedAttributes, 'foo', 'bar', 'gong', 'border-color', 'ping'];
+        return [
+            ...Consumer.observedAttributes,
+            'lang', 'foo', 'bar', 'gong', 'border-color', 'ping'
+        ];
     }
 
     attributeChangedCallback(name, oldValue, newValue) {
+        if (oldValue === newValue) {
+            return;
+        }
+
         console.log('DemoConsumer(' + this.id() + ') attributeChangesCallback( ' + name + ', ' + oldValue + ', ' + newValue + ')');
         switch(name) {
+            case 'lang':
+                this.lang = newValue;
+                i18n.changeLanguage(this.lang);
+                break;
             case 'foo':
                 this.foo = parseInt(newValue);
                 break;
@@ -335,12 +433,12 @@ class DemoConsumer extends Consumer
         <div style="border: ${this['border-color']} dotted; padding: 10px;">
             <table style="width:200px;">
                 <tr style="background-color: #aaa;">
-                    <th style="text-align: left;">Item</th>
-                    <th style="text-align: right;">Price</th>
+                    <th style="text-align: left;">${i18n.t('consumer.item')}</th>
+                    <th style="text-align: right;">${i18n.t('consumer.price')}</th>
                 </tr>
                 <tr><td>foo</td><td style="text-align: right;">${this.foo}</td></tr>
                 <tr><td>bar</td><td style="text-align: right;">${this.bar}</td></tr>
-                <tr><td>sum</td><td style="text-align: right;">${sum}</td></tr>
+                <tr><td>${i18n.t('consumer.sum')}</td><td style="text-align: right;">${sum}</td></tr>
             </table>
             <p>Status: <b>${this.status}</b></p>
         </div>
diff --git a/packages/provider/src/i18n/de/translation.json b/packages/provider/src/i18n/de/translation.json
index e41d874c..f92d017b 100644
--- a/packages/provider/src/i18n/de/translation.json
+++ b/packages/provider/src/i18n/de/translation.json
@@ -1,5 +1,14 @@
 {
-  "provider": {
+  "de": "Deutsch",
+  "en": "Englisch",
 
+  "demo": {
+    "provider": "Anbieter",
+    "consumer": "Verbraucher"
+  },
+  "consumer": {
+    "item": "Bezeichnung",
+    "price": "Preis",
+    "sum": "Summe"
   }
 }
\ No newline at end of file
diff --git a/packages/provider/src/i18n/en/translation.json b/packages/provider/src/i18n/en/translation.json
index e41d874c..9b7c38f7 100644
--- a/packages/provider/src/i18n/en/translation.json
+++ b/packages/provider/src/i18n/en/translation.json
@@ -1,5 +1,14 @@
 {
-  "provider": {
+  "de": "German",
+  "en": "English",
 
+  "demo": {
+    "provider": "Provider",
+    "consumer": "Consumer"
+  },
+  "consumer": {
+    "item": "Description",
+    "price": "Price",
+    "sum": "sum"
   }
 }
\ No newline at end of file
-- 
GitLab