import { css, CSSResult, html, LitElement, PropertyDeclarations } from 'lit-element'; import { nothing, TemplateResult } from 'lit-html'; import { getParticipantCookie } from './getParticipantCookie'; import { AdminConfig } from '../types/State'; export class AdminSidebar extends LitElement { public opened = false; public options?: AdminConfig; public keyToStrings = { enableCaching: 'Caching', followMode: 'Follow Mode' }; public websocketPort?: number; public ws?: WebSocket; public websocketOpen?: Promise; public resolveWebsocketOpen?: () => void; static get properties(): PropertyDeclarations { return { opened: { type: Boolean, reflect: true, }, options: { attribute: false, }, }; } static get styles(): CSSResult { return css` :host { display: block; z-index: 1; top: 0; position: absolute; left: 0; } *, *:before, *:after { box-sizing: border-box; } .container { height: 100vh; width: 250px; background-color: #efefef; } .header { display: flex; align-items: center; } .header h3 { margin: 0; text-align: center; flex-grow: 1; font-weight: lighter; font-size: 24px; } .close-button, .open-button { cursor: pointer; width: 30px; margin: 20px 0 20px 20px; display: inline-block; } .open-button { height: 22.3px; } .close-button { height: 20px; padding: 0 5px; } .content { width: 100%; margin: 20px auto; } .options { text-align: right; margin-right: 15px; font-weight: lighter; font-size: 18px; } /* HTML5 Boilerplate accessible hidden styles */ .cwk-checkbox { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .cwk-checkbox-wrapper { margin-bottom: 12px; } .cwk-checkbox-wrapper input:checked + label > svg { height: 14px; animation: draw-checkbox ease-in-out 0.2s forwards; } .cwk-checkbox-wrapper input:checked + label::after { background-color: var(--cwk-color-primary); } .cwk-checkbox-wrapper label:active::after { background-color: #e6e6e6; } .cwk-checkbox-wrapper label { line-height: 20px; cursor: pointer; position: relative; font-size: 18px; } .cwk-checkbox-wrapper label::after { content: ''; height: 20px; width: 20px; margin-left: 10px; float: right; border: 2px solid var(--cwk-color-primary); border-radius: 3px; transition: 0.15s all ease-out; margin-top: 2px; } .cwk-checkbox-wrapper svg { stroke: var(--cwk-color-white); stroke-width: 5px; height: 0; width: 14px; position: absolute; stroke-dasharray: 33; right: -27px; top: 4.5px; } @keyframes draw-checkbox { 0% { stroke-dashoffset: 33; } 100% { stroke-dashoffset: 0; } } `; } connectedCallback(): void { super.connectedCallback(); this.setupWs(); } setupWs(): void { // gets replaced by CWK server this.ws = new WebSocket(`ws://localhost:${this.websocketPort || '%websocketport%'}/wds`); this.websocketOpen = new Promise((resolve) => { this.resolveWebsocketOpen = resolve; }); this.ws.addEventListener('open', () => { if (this.resolveWebsocketOpen) { this.resolveWebsocketOpen(); } if (this.ws) { this.ws.send(JSON.stringify({ type: 'config-init' })); } }); this.ws.addEventListener('message', (e) => { const { type, config } = JSON.parse(e.data); if (type === 'config-init') { this.options = { ...config, }; } }); } toggleUI(): void { this.opened = !this.opened; } async toggleOption(e: Event): Promise { const target = e.target as HTMLInputElement; const newOpts = this.options; if (newOpts) { newOpts[target.getAttribute('id') as keyof AdminConfig] = target.checked; this.options = newOpts; const participantCookie = getParticipantCookie(); // sync to server await this.websocketOpen; if (this.ws) { this.ws.send( JSON.stringify({ type: 'config-updated', config: this.options, key: target.getAttribute('id'), byAdmin: participantCookie, }), ); } } } render(): TemplateResult { return html` ${ this.opened ? nothing : html`
` } ${ this.opened ? html`

Admin UI

${this.options ? html` ${Object.entries(this.options).map( (entry) => html`
`, )} ` : nothing}
` : nothing } `; } }