diff --git a/README.md b/README.md index fbf89ed..9c4aad0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ > First Commit: 2022-06-03 -> Last Commit: 2022-06-06 (Added eslint on 2022-06-07) +> Last Commit before hand-in: 2022-06-06 + +> Commits after: 'Added eslint', 'small refactoring of provider and consumer div creation', 'added Text-Strategy' > Contact: M. Voss diff --git a/assignment/index.js b/assignment/index.js index daae9f9..3a9b4ef 100644 --- a/assignment/index.js +++ b/assignment/index.js @@ -1 +1 @@ -(()=>{var v=new Map;function y(n,r){var t;r&&(v.has(n)?(t=v.get(n))==null||t.push(r):v.set(n,[r]))}var g=[],U="provider",V="provider-form",k="consumer",G="consumer-form";function d(){let n=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);return n()+"-"+n()+"-"+n()+"-"+n()+"-"+n()}function D(){return document.getElementById(k)}function O(){return document.getElementById(U)}function S(n,r,t){return new CustomEvent(n,{detail:{id:r,value:t}})}function h(n){return n==null?void 0:n.replaceAll(" ","-").toLowerCase()}function tt(n,r){return{type:"data-"+n,value:r}}function u(n){return tt("form-element",n)}function E(n,r){n.setAttribute(r.type,r.value)}function b(n){function r(){var e;(e=document.getElementById(n))==null||e.remove()}let t=document.createElement("button");return t.textContent="X",t.addEventListener("click",r),t.classList.add("delete"),E(t,u("delete-"+n)),t}var x=class{};var p=class extends x{constructor(t,e,a){super();this.id=d(),this.topic=h(t),this.label=e,this.strategy=a}static getConsumerWrapper(t,e){let a=document.createElement("div");return a.id=t,a.classList.add("consumer-item"),e&&e.length>0&&a.setAttribute("data-label",e),a}getElement(){let t=p.getConsumerWrapper(this.id,this.getLabel());t.textContent=this.getLabel()+": ",t.appendChild(this.getDisplayElement());let e=document.createElement("p");return e.textContent=this.topic,t.appendChild(b(this.id)),t.appendChild(e),t}getDisplayElement(){return this.strategy.createConsumerElement(this.topic,{label:this.label,id:this.id,value:!1})}getLabel(){return this.label?this.label:"simple-consumer"}};var T=class{},L=(t=>(t.BOOLEAN_STRATEGY="BOOLEAN_STRATEGY",t.NUMBER_STRATEGY="NUMBER_STRATEGY",t))(L||{});var f=class extends T{constructor(){super(...arguments);this.strategyType="NUMBER_STRATEGY"}dispatchEvent(t,...e){let a=e[0],o=e[1],l=t.target,m=S(a,o,l==null?void 0:l.valueAsNumber),s=v.get(a);s==null||s.forEach(i=>{i.dispatchEvent(m)})}createProviderElement(t,e){let a=d(),o=document.createElement("form");o.classList.add("number-strategy-form"),o.id=a;let l=d(),m=A(l,e||t,"provider-item-label_"+t);o.appendChild(m);let s=M(l,"provider-item-input_"+t,"number");return s.setAttribute("name",e||t),s.setAttribute("min","0"),s.setAttribute("max","1"),s.setAttribute("step","0.1"),s.setAttribute("placeholder","% max. value"),s.addEventListener("change",i=>this.dispatchEvent(i,t,l)),o.appendChild(s),o.appendChild(b(a)),o}createConsumerElement(t,e){let a=document.createElement("span"),o=parseFloat(e.value);return isNaN(o)?a.textContent="N/A":a.textContent=o.toString(),a.addEventListener(t,this.update),y(t,a),a}update(t){let e=t.detail,a=this;a&&(a.textContent=e.value)}};function et(n,r){let t=document.createElement("div");if(r!=null)switch(r){case"BOOLEAN_STRATEGY".valueOf():t=new c().createProviderElement(n);break;case"NUMBER_STRATEGY".valueOf():t=new f().createProviderElement(n);break;default:console.error("Cannot create provider for non existent strategy: ",r);break}return t}function nt(n,r,t){let e=null;if(t!=null)switch(t){case"BOOLEAN_STRATEGY".valueOf():e=new p(n,r,new c);break;case"NUMBER_STRATEGY".valueOf():e=new p(n,r,new f);break;default:console.error("Cannot create provider for non existent strategy: ",t);break}return e}function H(n,r){var o,l,m;let t="",e="",a=null;if(n.forEach((s,i)=>{i===I?t=h(s.toString()):i===P?a=s:i===_&&(e=s)}),t&&t.length>0&&a){let s=(o=nt(t,e,a))==null?void 0:o.getElement();switch(r){case R.PROVIDER:(l=O())==null||l.appendChild(et(t,a));break;case R.CONSUMER:s&&((m=D())==null||m.appendChild(s));break;default:console.error("No device implementation exists for given type: ",r);break}}}var R=(t=>(t.PROVIDER="PROVIDER",t.CONSUMER="CONSUMER",t))(R||{});var I="topic",_="name",P="strategies";function Y(n){let r=document.createElement("input");return E(r,u("submit_"+h(n))),r.setAttribute("type","submit"),r.setAttribute("value",n),r}function C(n){let r=document.createElement("option");return E(r,u("select-option_"+h(n))),r.setAttribute("value",n),r.textContent=n,r}function W(n){n.appendChild(document.createElement("br"));let r=d(),t=document.createElement("label");E(t,u("strategy-select-label")),t.setAttribute("for",r),t.textContent="Use Case",n.appendChild(t);let e=document.createElement("select");E(e,u("strategy-select")),e.id=r,e.setAttribute("name",P),Object.keys(L).filter(a=>isNaN(Number(a))).forEach(a=>{e.appendChild(C(a))}),n.appendChild(e)}function rt(n){n.appendChild(document.createElement("br"));let r=d(),t=document.createElement("label");E(t,u("consumer-topic-label")),t.setAttribute("for",r),t.textContent="Available Topics",n.appendChild(t);let e=document.createElement("select");E(e,u("consumer-topic-select")),e.id=r,e.setAttribute("name",I),g.forEach(a=>{e.appendChild(C(a))}),n.appendChild(e)}function K(n){let r=d(),t=document.createElement("span");return t.setAttribute("role","error"),t.id=r,t.style.display="none",t.style.color="red",t.textContent=n,t}function q(n){if(n){let r=j("Topic","provider-topic",I);n.appendChild(r[0]),n.appendChild(r[1]),W(n);let t=Y("Add Provider"),e=K("Invalid: Duplicate Topic");n.appendChild(t),n.appendChild(e),n.addEventListener("submit",a=>{a.preventDefault();let o=a.target,l=new FormData(o),m=!0,s="";if(l.forEach((i,N)=>{N===I&&(s=h(i.toString()),g.includes(s)?(e.style.display="",m=!1):(g.push(s),m=!0))}),m){let i=document.querySelector('#consumer-form > select[data-form-element="consumer-topic-select"]');i==null||i.appendChild(C(s)),e.style.display="none",o.reset(),H(l,"PROVIDER")}})}}function A(n,r,t){let e=document.createElement("label");return e.setAttribute("for",n),E(e,u((t||r)+"-label")),e.textContent=r,e}function M(n,r,t){let e=document.createElement("input");return e.id=n,E(e,u(r+"-input")),e.setAttribute("type",t),e}function j(n,r,t){let e=d(),a=A(e,n,r),o=M(e,r,"text");return o.setAttribute("name",t),o.setAttribute("placeholder",n),o.setAttribute("required","true"),[a,o]}function X(n){if(n){n.innerHTML="";let r=j("Name","consumer-name",_);n.appendChild(r[0]),n.appendChild(r[1]),rt(n),W(n);let t=Y("Add Consumer");n.appendChild(t);let e=K("Invalid: Name cannot be empty.");n.appendChild(e),n.addEventListener("submit",a=>{a.preventDefault();let o=a.target,l=new FormData(o),m=!0;l.forEach((s,i)=>{i===_&&(s.toString().trim().length===0?(e.style.display="",m=!1):m=!0)}),m&&(e.style.display="none",o.reset(),H(l,"CONSUMER"))})}}var F="bool-strategy-off",w="bool-strategy-on",c=class extends T{constructor(){super(...arguments);this.strategyType="BOOLEAN_STRATEGY"}static parseValue(t){return t.value>0||t.value<0||t.value==="true"||t.value===!0}static setValue(t,e){t?(e.textContent="ON",e.classList.contains(F)&&e.classList.remove(F),e.classList.add(w)):(e.textContent="OFF",e.classList.contains(w)&&e.classList.remove(w),e.classList.add(F))}dispatchEvent(t,...e){let a=e[0],o=e[1],l=t.target,m=S(a,o,l==null?void 0:l.checked),s=v.get(a);s==null||s.forEach(i=>{i.dispatchEvent(m)})}createProviderElement(t,e){let a=d(),o=document.createElement("form");o.id=a,o.classList.add("bool-strategy-form");let l=d(),m=A(l,e||t,"provider-item-label_"+t);o.appendChild(m);let s=M(l,"provider-item-input_"+t,"checkbox");return s.setAttribute("name",e||t),s.addEventListener("change",i=>this.dispatchEvent(i,t,l)),o.appendChild(s),o.appendChild(b(a)),o}createConsumerElement(t,e){let a=c.parseValue(e),o=document.createElement("span");return c.setValue(a,o),o.addEventListener(t,this.update),y(t,o),o}update(t){let e=t.detail,a=this;a&&c.setValue(c.parseValue(e),a)}};var z;(z=document.getElementById("load-demo-button"))==null||z.addEventListener("click",n=>{let r="light-1",t="light-2",e="heating-1";g.push(r),g.push(t),g.push(e);let a=document.querySelector('#consumer-form > select[data-form-element="consumer-topic-select"]');a==null||a.appendChild(C(r)),a==null||a.appendChild(C(t)),a==null||a.appendChild(C(e));let o=O(),l=new c().createProviderElement(r);o==null||o.appendChild(l);let m=new c().createProviderElement(t);o==null||o.appendChild(m);let s=new f().createProviderElement(e);o==null||o.appendChild(s);let i=D(),N=new p(r,"Kitchen - Light (Left)",new c);i==null||i.appendChild(N.getElement());let Q=new p(r,"Kitchen - Light (Right)",new c);i==null||i.appendChild(Q.getElement());let Z=new p(t,"Living Room - Light (All)",new c);i==null||i.appendChild(Z.getElement());let $=new p(e,"Living Room - (Heating)",new f);i==null||i.appendChild($.getElement());let B=n.target;B.disabled=!0,B.style.display="none"});var J;(J=document.getElementById("load-demo-button"))==null||J.click();q(document.getElementById(V));X(document.getElementById(G));})(); +(()=>{var g=new Map;function y(n,a){var t;a&&(g.has(n)?(t=g.get(n))==null||t.push(a):g.set(n,[a]))}var h=[],U="provider",V="provider-form",Y="consumer",W="consumer-form";function c(){let n=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);return n()+"-"+n()+"-"+n()+"-"+n()+"-"+n()}function O(){return document.getElementById(Y)}function _(){return document.getElementById(U)}function D(n,a,t){return new CustomEvent(n,{detail:{id:a,value:t}})}function v(n){return n==null?void 0:n.replaceAll(" ","-").toLowerCase()}function I(n,a){let t=document.createElement("form");return t.classList.add(`${a}-form`),t.id=n,t}function nt(n,a){return{type:"data-"+n,value:a}}function u(n){return nt("form-element",n)}function E(n,a){n.setAttribute(a.type,a.value)}function T(n){function a(){var e;(e=document.getElementById(n))==null||e.remove()}let t=document.createElement("button");return t.textContent="X",t.addEventListener("click",a),t.classList.add("delete"),E(t,u("delete-"+n)),t}var R=class{};var d=class extends R{constructor(t,e,r){super();this.id=c(),this.topic=v(t),this.label=e,this.strategy=r}static getConsumerWrapper(t,e){let r=document.createElement("div");return r.id=t,r.classList.add("consumer-item"),e&&e.length>0&&r.setAttribute("data-label",e),r}getElement(){let t=d.getConsumerWrapper(this.id,this.getLabel());t.textContent=this.getLabel()+": ",t.appendChild(this.getDisplayElement());let e=document.createElement("p");return e.textContent=this.topic,t.appendChild(T(this.id)),t.appendChild(e),t}getDisplayElement(){return this.strategy.createConsumerElement(this.topic,{label:this.label,id:this.id,value:!1})}getLabel(){return this.label?this.label:"simple-consumer"}};var f=class{},b=(e=>(e.BOOLEAN_STRATEGY="BOOLEAN_STRATEGY",e.NUMBER_STRATEGY="NUMBER_STRATEGY",e.TEXT_STRATEGY="TEXT_STRATEGY",e))(b||{});var C=class extends f{constructor(){super(...arguments);this.strategyType="NUMBER_STRATEGY"}dispatchEvent(t,...e){let r=e[0],o=e[1],l=t.target,m=D(r,o,l==null?void 0:l.valueAsNumber),s=g.get(r);s==null||s.forEach(i=>{i.dispatchEvent(m)})}createProviderElement(t,e){let r=c(),o=I(r,"number-strategy"),l=c(),m=L(l,e||t,"provider-item-label_"+t);o.appendChild(m);let s=A(l,"provider-item-input_"+t,"number");return s.setAttribute("name",e||t),s.setAttribute("min","0"),s.setAttribute("max","1"),s.setAttribute("step","0.1"),s.setAttribute("placeholder","% max. value"),s.addEventListener("change",i=>this.dispatchEvent(i,t,l)),o.appendChild(s),o.appendChild(T(r)),o}createConsumerElement(t,e){let r=document.createElement("span"),o=parseFloat(e.value);return isNaN(o)?r.textContent="N/A":r.textContent=o.toString(),r.addEventListener(t,this.update),y(t,r),r}update(t){let e=t.detail,r=this;r&&(r.textContent=e.value)}};var S=class extends f{constructor(){super(...arguments);this.strategyType="TEXT_STRATEGY"}createConsumerElement(t,e){let r=document.createElement("span");return r.textContent=e.value,r.addEventListener(t,this.update),y(t,r),r}createProviderElement(t,e){let r=c(),o=I(r,"text-strategy"),l=c(),m=L(l,e||t,"provider-item-label_"+t);o.appendChild(m);let s=A(l,"provider-item-input_"+t,"text");return s.setAttribute("name",e||t),s.setAttribute("placeholder","some led display"),s.addEventListener("input",i=>this.dispatchEvent(i,t,l)),o.appendChild(s),o.appendChild(T(r)),o}dispatchEvent(t,...e){let r=e[0],o=e[1],l=t.target,m=D(r,o,l==null?void 0:l.value),s=g.get(r);s==null||s.forEach(i=>{i.dispatchEvent(m)})}update(t){let e=t.detail,r=this;r&&(r.textContent=e.value)}};function rt(n,a){let t=document.createElement("div");if(a!=null)switch(a){case"BOOLEAN_STRATEGY":t=new p().createProviderElement(n);break;case"NUMBER_STRATEGY":t=new C().createProviderElement(n);break;case"TEXT_STRATEGY":t=new S().createProviderElement(n);break;default:console.error("Cannot create provider for non existent strategy: ",a);break}return t}function at(n,a,t){let e=null;if(t!=null)switch(t){case"BOOLEAN_STRATEGY":e=new d(n,a,new p);break;case"NUMBER_STRATEGY":e=new d(n,a,new C);break;case"TEXT_STRATEGY":e=new d(n,a,new S);break;default:console.error("Cannot create consumer for non existent strategy: ",t);break}return e}function F(n,a){var o,l,m;let t="",e="",r=null;if(console.log("formData",n),n.forEach((s,i)=>{i===x?(t=v(s.toString()),console.log("topic",t)):i===w?(r=s,console.log("strategyType",r)):i===H&&(e=s)}),t&&t.length>0&&r){let s=(o=at(t,e,r))==null?void 0:o.getElement();switch(a){case N.PROVIDER:(l=_())==null||l.appendChild(rt(t,r));break;case N.CONSUMER:s&&((m=O())==null||m.appendChild(s));break;default:console.error("No device implementation exists for given type: ",a);break}}}var N=(t=>(t.PROVIDER="PROVIDER",t.CONSUMER="CONSUMER",t))(N||{});var x="topic",H="name",w="strategies";function X(n){let a=document.createElement("input");return E(a,u("submit_"+v(n))),a.setAttribute("type","submit"),a.setAttribute("value",n),a}function M(n){let a=document.createElement("option");return E(a,u("select-option_"+v(n))),a.setAttribute("value",n),a.textContent=n,a}function K(n){n.appendChild(document.createElement("br"));let a=c(),t=document.createElement("label");E(t,u("strategy-select-label")),t.setAttribute("for",a),t.textContent="Use Case",n.appendChild(t);let e=document.createElement("select");E(e,u("strategy-select")),e.id=a,e.setAttribute("name",w),Object.keys(b).filter(r=>isNaN(Number(r))).forEach(r=>{e.appendChild(M(r))}),n.appendChild(e)}function ot(n){n.appendChild(document.createElement("br"));let a=c(),t=document.createElement("label");E(t,u("consumer-topic-label")),t.setAttribute("for",a),t.textContent="Available Topics",n.appendChild(t);let e=document.createElement("select");E(e,u("consumer-topic-select")),e.id=a,e.setAttribute("name",x),h.forEach(r=>{e.appendChild(M(r))}),n.appendChild(e)}function q(n){let a=c(),t=document.createElement("span");return t.setAttribute("role","error"),t.id=a,t.style.display="none",t.style.color="red",t.textContent=n,t}function j(n){if(n){let a=$("Topic","provider-topic",x);n.appendChild(a[0]),n.appendChild(a[1]),K(n);let t=X("Add Provider"),e=q("Invalid: Duplicate Topic");n.appendChild(t),n.appendChild(e),n.addEventListener("submit",r=>{r.preventDefault();let o=r.target,l=new FormData(o),m=!0,s="";if(l.forEach((i,P)=>{P===x&&(s=v(i.toString()),h.includes(s)?(e.style.display="",m=!1):(h.push(s),m=!0))}),m){let i=document.querySelector('#consumer-form > select[data-form-element="consumer-topic-select"]');i==null||i.appendChild(M(s)),e.style.display="none",o.reset(),F(l,"PROVIDER")}})}}function L(n,a,t){let e=document.createElement("label");return e.setAttribute("for",n),E(e,u((t||a)+"-label")),e.textContent=a,e}function A(n,a,t){let e=document.createElement("input");return e.id=n,E(e,u(a+"-input")),e.setAttribute("type",t),e}function $(n,a,t){let e=c(),r=L(e,n,a),o=A(e,a,"text");return o.setAttribute("name",t),o.setAttribute("placeholder",n),o.setAttribute("required","true"),[r,o]}function z(n){if(n){n.innerHTML="";let a=$("Name","consumer-name",H);n.appendChild(a[0]),n.appendChild(a[1]),ot(n),K(n);let t=X("Add Consumer");n.appendChild(t);let e=q("Invalid: Name cannot be empty.");n.appendChild(e),n.addEventListener("submit",r=>{r.preventDefault();let o=r.target,l=new FormData(o),m=!0;l.forEach((s,i)=>{i===H&&(s.toString().trim().length===0?(e.style.display="",m=!1):m=!0)}),m&&(e.style.display="none",o.reset(),F(l,"CONSUMER"))})}}var B="bool-strategy-off",G="bool-strategy-on",p=class extends f{constructor(){super(...arguments);this.strategyType="BOOLEAN_STRATEGY"}static parseValue(t){return t.value>0||t.value<0||t.value==="true"||t.value===!0}static setValue(t,e){t?(e.textContent="ON",e.classList.contains(B)&&e.classList.remove(B),e.classList.add(G)):(e.textContent="OFF",e.classList.contains(G)&&e.classList.remove(G),e.classList.add(B))}dispatchEvent(t,...e){let r=e[0],o=e[1],l=t.target,m=D(r,o,l==null?void 0:l.checked),s=g.get(r);s==null||s.forEach(i=>{i.dispatchEvent(m)})}createProviderElement(t,e){let r=c(),o=I(r,"bool-strategy"),l=c(),m=L(l,e||t,"provider-item-label_"+t);o.appendChild(m);let s=A(l,"provider-item-input_"+t,"checkbox");return s.setAttribute("name",e||t),s.addEventListener("change",i=>this.dispatchEvent(i,t,l)),o.appendChild(s),o.appendChild(T(r)),o}createConsumerElement(t,e){let r=p.parseValue(e),o=document.createElement("span");return p.setValue(r,o),o.addEventListener(t,this.update),y(t,o),o}update(t){let e=t.detail,r=this;r&&p.setValue(p.parseValue(e),r)}};var J;(J=document.getElementById("load-demo-button"))==null||J.addEventListener("click",n=>{let a="light-1",t="light-2",e="heating-1";h.push(a),h.push(t),h.push(e);let r=document.querySelector('#consumer-form > select[data-form-element="consumer-topic-select"]');r==null||r.appendChild(M(a)),r==null||r.appendChild(M(t)),r==null||r.appendChild(M(e));let o=_(),l=new p().createProviderElement(a);o==null||o.appendChild(l);let m=new p().createProviderElement(t);o==null||o.appendChild(m);let s=new C().createProviderElement(e);o==null||o.appendChild(s);let i=O(),P=new d(a,"Kitchen - Light (Left)",new p);i==null||i.appendChild(P.getElement());let Z=new d(a,"Kitchen - Light (Right)",new p);i==null||i.appendChild(Z.getElement());let tt=new d(t,"Living Room - Light (All)",new p);i==null||i.appendChild(tt.getElement());let et=new d(e,"Living Room - (Heating)",new C);i==null||i.appendChild(et.getElement());let k=n.target;k.disabled=!0,k.style.display="none"});var Q;(Q=document.getElementById("load-demo-button"))==null||Q.click();j(document.getElementById(V));z(document.getElementById(W));})(); diff --git a/src/devices/DeviceService.ts b/src/devices/DeviceService.ts index 535f0ce..c0be8ec 100644 --- a/src/devices/DeviceService.ts +++ b/src/devices/DeviceService.ts @@ -5,6 +5,7 @@ import {getConsumerContainer, getProviderContainer, replaceSpaceWithDash} from ' import {CONSUMER_FORM_NAME, STRATEGIES_FORM_NAME, TOPIC_FORM_NAME} from './FormService' import {ConsumerImpl} from './consumer/ConsumerImpl' import {Consumer} from './consumer/Consumer' +import {TextStrategy} from './strategies/TextStrategy' /** * Creates a provider element for the given topic and strategy type. @@ -16,12 +17,15 @@ export function createProvider(topic: string, strategyType: StrategyType): HTMLE if (strategyType != null) { switch (strategyType) { - case StrategyType.BOOLEAN_STRATEGY.valueOf(): + case StrategyType.BOOLEAN_STRATEGY: result = new BooleanStrategy().createProviderElement(topic) break - case StrategyType.NUMBER_STRATEGY.valueOf(): + case StrategyType.NUMBER_STRATEGY: result = new NumberStrategy().createProviderElement(topic) break + case StrategyType.TEXT_STRATEGY: + result = new TextStrategy().createProviderElement(topic) + break default: console.error('Cannot create provider for non existent strategy: ', strategyType) break @@ -42,14 +46,17 @@ export function createConsumer(topic: string, label: string, strategyType: Strat if (strategyType != null) { switch (strategyType) { - case StrategyType.BOOLEAN_STRATEGY.valueOf(): + case StrategyType.BOOLEAN_STRATEGY: result = new ConsumerImpl(topic, label, new BooleanStrategy()) break - case StrategyType.NUMBER_STRATEGY.valueOf(): + case StrategyType.NUMBER_STRATEGY: result = new ConsumerImpl(topic, label, new NumberStrategy()) break + case StrategyType.TEXT_STRATEGY: + result = new ConsumerImpl(topic, label, new TextStrategy()) + break default: - console.error('Cannot create provider for non existent strategy: ', strategyType) + console.error('Cannot create consumer for non existent strategy: ', strategyType) break } } @@ -68,14 +75,18 @@ export function createDeviceWithFormData(formData: FormData, deviceType: DeviceT let name = '' let strategyType: StrategyType | null = null + console.log('formData', formData) + // I am aware, that this is technically the second time that we are looping over the same FormData, // but it should be feasible with this certainly limited amount of ever available from input values. formData.forEach((value, key) => { if (key === TOPIC_FORM_NAME) { topic = replaceSpaceWithDash(value.toString()) + console.log('topic', topic) } else if (key === STRATEGIES_FORM_NAME) { // force TypeCast, we know that the select options are being generated by the available StrategyTypes strategyType = value as unknown as StrategyType + console.log('strategyType', strategyType) } else if (key === CONSUMER_FORM_NAME) { name = value as string } @@ -84,7 +95,7 @@ export function createDeviceWithFormData(formData: FormData, deviceType: DeviceT // generate new provider and add to container if ((topic && topic.length > 0) && strategyType) { const consumerElement = createConsumer(topic, name, strategyType)?.getElement() - + switch (deviceType) { case DeviceType.PROVIDER: getProviderContainer()?.appendChild(createProvider(topic, strategyType)) diff --git a/src/devices/strategies/BooleanStrategy.ts b/src/devices/strategies/BooleanStrategy.ts index 6ca4023..43895ee 100644 --- a/src/devices/strategies/BooleanStrategy.ts +++ b/src/devices/strategies/BooleanStrategy.ts @@ -1,6 +1,6 @@ import {Strategy, StrategyType} from './Strategy' import {EventData} from '../../entities/EventData' -import {createCustomEvent, createDeletionButton} from '../../domUtils' +import {createBaseForm, createCustomEvent, createDeletionButton} from '../../domUtils' import {addGlobalConsumerDisplay, getRandomID, TOPIC_CONSUMER_MAP} from '../../constants' import {createInputElement, createLabelElement} from '../FormService' @@ -53,17 +53,15 @@ export class BooleanStrategy extends Strategy { createProviderElement(topic: string, label?: string): HTMLElement { const formId = getRandomID() - const formElement = document.createElement('form') - formElement.id = formId - formElement.classList.add('bool-strategy-form') + const formElement = createBaseForm(formId, 'bool-strategy') - const randomID = getRandomID() - const labelElement = createLabelElement(randomID, label ? label : topic, 'provider-item-label_' + topic) + const labelID = getRandomID() + const labelElement = createLabelElement(labelID, label ? label : topic, 'provider-item-label_' + topic) formElement.appendChild(labelElement) - const inputElement = createInputElement(randomID, 'provider-item-input_' + topic, 'checkbox') + const inputElement = createInputElement(labelID, 'provider-item-input_' + topic, 'checkbox') inputElement.setAttribute('name', label ? label : topic) - inputElement.addEventListener('change', (event) => this.dispatchEvent(event, topic, randomID)) + inputElement.addEventListener('change', (event) => this.dispatchEvent(event, topic, labelID)) formElement.appendChild(inputElement) formElement.appendChild(createDeletionButton(formId)) diff --git a/src/devices/strategies/NumberStrategy.ts b/src/devices/strategies/NumberStrategy.ts index c98bc61..d370961 100644 --- a/src/devices/strategies/NumberStrategy.ts +++ b/src/devices/strategies/NumberStrategy.ts @@ -1,7 +1,7 @@ import {Strategy, StrategyType} from './Strategy' import {EventData} from '../../entities/EventData' import {addGlobalConsumerDisplay, getRandomID, TOPIC_CONSUMER_MAP} from '../../constants' -import {createCustomEvent, createDeletionButton} from '../../domUtils' +import {createBaseForm, createCustomEvent, createDeletionButton} from '../../domUtils' import {createInputElement, createLabelElement} from '../FormService' /** @@ -29,21 +29,19 @@ export class NumberStrategy extends Strategy { */ createProviderElement(topic: string, label?: string): HTMLElement { const formId = getRandomID() - const formElement = document.createElement('form') - formElement.classList.add('number-strategy-form') - formElement.id = formId + const formElement = createBaseForm(formId, 'number-strategy') - const randomID = getRandomID() - const labelElement = createLabelElement(randomID, label ? label : topic, 'provider-item-label_' + topic) + const labelID = getRandomID() + const labelElement = createLabelElement(labelID, label ? label : topic, 'provider-item-label_' + topic) formElement.appendChild(labelElement) - const inputElement = createInputElement(randomID, 'provider-item-input_' + topic, 'number') + const inputElement = createInputElement(labelID, 'provider-item-input_' + topic, 'number') inputElement.setAttribute('name', label ? label : topic) inputElement.setAttribute('min', '0') inputElement.setAttribute('max', '1') inputElement.setAttribute('step', '0.1') inputElement.setAttribute('placeholder', '% max. value') - inputElement.addEventListener('change', (event) => this.dispatchEvent(event, topic, randomID)) + inputElement.addEventListener('change', (event) => this.dispatchEvent(event, topic, labelID)) formElement.appendChild(inputElement) formElement.appendChild(createDeletionButton(formId)) diff --git a/src/devices/strategies/Strategy.ts b/src/devices/strategies/Strategy.ts index 5d45aed..7338de5 100644 --- a/src/devices/strategies/Strategy.ts +++ b/src/devices/strategies/Strategy.ts @@ -24,7 +24,7 @@ export abstract class Strategy { /** * @param event -> dispatches data for its topic */ - abstract dispatchEvent(event: Event): void; + abstract dispatchEvent(event: Event, ...args: string[]): void; /** * Updates the underlying div that represents the display / api for implementing strategy @@ -36,5 +36,6 @@ export abstract class Strategy { export enum StrategyType { BOOLEAN_STRATEGY = 'BOOLEAN_STRATEGY', - NUMBER_STRATEGY = 'NUMBER_STRATEGY' + NUMBER_STRATEGY = 'NUMBER_STRATEGY', + TEXT_STRATEGY = 'TEXT_STRATEGY' } diff --git a/src/devices/strategies/TextStrategy.ts b/src/devices/strategies/TextStrategy.ts new file mode 100644 index 0000000..b17a440 --- /dev/null +++ b/src/devices/strategies/TextStrategy.ts @@ -0,0 +1,59 @@ +import {Strategy, StrategyType} from './Strategy' +import {EventData} from '../../entities/EventData' +import {createBaseForm, createCustomEvent, createDeletionButton} from '../../domUtils' +import {addGlobalConsumerDisplay, getRandomID, TOPIC_CONSUMER_MAP} from '../../constants' +import {createInputElement, createLabelElement} from '../FormService' + +export class TextStrategy extends Strategy { + strategyType: StrategyType = StrategyType.TEXT_STRATEGY + + createConsumerElement(topic: string, eventData: EventData): HTMLElement { + const consumerDisplay = document.createElement('span') + consumerDisplay.textContent = eventData.value + consumerDisplay.addEventListener(topic, this.update) + addGlobalConsumerDisplay(topic, consumerDisplay) + return consumerDisplay + } + + createProviderElement(topic: string, label?: string): HTMLElement { + const formID = getRandomID() + const form = createBaseForm(formID, 'text-strategy') + + const labelID = getRandomID() + const labelElement = createLabelElement(labelID, label ? label : topic, 'provider-item-label_' + topic) + form.appendChild(labelElement) + + const inputElement = createInputElement(labelID, 'provider-item-input_' + topic, 'text') + inputElement.setAttribute('name', label ? label : topic) + inputElement.setAttribute('placeholder', 'some led display') + inputElement.addEventListener('input', (event) => this.dispatchEvent(event, topic, labelID)) + form.appendChild(inputElement) + + form.appendChild(createDeletionButton(formID)) + + return form + } + + dispatchEvent(event: Event, ...args: string[]): void { + const topic = args[0] as string + const randomID = args[1] as string + const textField = event.target as HTMLInputElement + const changeEvent = createCustomEvent(topic, randomID, textField?.value) + const consumers = TOPIC_CONSUMER_MAP.get(topic) + consumers?.forEach(item => { + item.dispatchEvent(changeEvent) + }) + } + + update(event: Event): void { + const eventData: EventData = (event).detail as EventData + + // force typecast + const displayElement = this as unknown as HTMLSpanElement + + if (displayElement) { + displayElement.textContent = eventData.value + } + } + +} diff --git a/src/domUtils.ts b/src/domUtils.ts index 7fc74f4..0c09792 100644 --- a/src/domUtils.ts +++ b/src/domUtils.ts @@ -23,6 +23,14 @@ export function replaceSpaceWithDash(value: string) { return value?.replaceAll(' ', '-').toLowerCase() } +export function createBaseForm(id: string, label: string): HTMLFormElement { + const formElement = document.createElement('form') + formElement.classList.add(`${label}-form`) + formElement.id = id + + return formElement +} + export function createDataAttribute(suffix: string, value: any): DataAttribute { return { type: 'data-' + suffix,