code-workshop-kit
Version:
The future of remote code workshops & training
274 lines (257 loc) • 8.13 kB
JavaScript
import { css, html, LitElement } from 'lit-element';
import { nothing } from 'lit-html';
import { getParticipantCookie } from './getParticipantCookie';
export class AdminSidebar extends LitElement {
constructor() {
super(...arguments);
this.opened = false;
this.keyToStrings = { enableCaching: 'Caching', followMode: 'Follow Mode' };
}
static get properties() {
return {
opened: {
type: Boolean,
reflect: true,
},
options: {
attribute: false,
},
};
}
static get styles() {
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;
}
draw-checkbox {
0% {
stroke-dashoffset: 33;
}
100% {
stroke-dashoffset: 0;
}
}
`;
}
connectedCallback() {
super.connectedCallback();
this.setupWs();
}
setupWs() {
// 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() {
this.opened = !this.opened;
}
async toggleOption(e) {
const target = e.target;
const newOpts = this.options;
if (newOpts) {
newOpts[target.getAttribute('id')] = 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() {
return html `
${this.opened
? nothing
: html `<div class="open-button" =${this.toggleUI} =${this.toggleUI}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39 29">
<path
d="M2.5,0h34A2.5,2.5,0,0,1,39,2.5h0A2.5,2.5,0,0,1,36.5,5H2.5A2.5,2.5,0,0,1,0,2.5H0A2.5,2.5,0,0,1,2.5,0Z"
/>
<path
d="M2.5,12h34A2.5,2.5,0,0,1,39,14.5h0A2.5,2.5,0,0,1,36.5,17H2.5A2.5,2.5,0,0,1,0,14.5H0A2.5,2.5,0,0,1,2.5,12Z"
/>
<path
d="M2.5,24h18A2.5,2.5,0,0,1,23,26.5h0A2.5,2.5,0,0,1,20.5,29H2.5A2.5,2.5,0,0,1,0,26.5H0A2.5,2.5,0,0,1,2.5,24Z"
/>
</svg>
</div>`}
${this.opened
? html `
<div class="container">
<div class="header">
<div =${this.toggleUI} =${this.toggleUI} class="close-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29.042 29.042">
<path
d="M.733,24.774,24.774.732a2.5,2.5,0,0,1,3.536,0h0a2.5,2.5,0,0,1,0,3.536L4.268,28.309a2.5,2.5,0,0,1-3.535,0h0A2.5,2.5,0,0,1,.733,24.774Z"
/>
<path
d="M4.268.732,28.309,24.774a2.5,2.5,0,0,1,0,3.536h0a2.5,2.5,0,0,1-3.535,0L.732,4.268a2.5,2.5,0,0,1,0-3.536h0A2.5,2.5,0,0,1,4.268.732Z"
/>
</svg>
</div>
<h3>Admin UI</h3>
</div>
<div class="content">
<div class="options">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
<symbol id="cwk-checkmark" viewBox="0 0 24 24">
<path
stroke-miterlimit="10"
fill="none"
d="M22.9 3.7l-15.2 16.6-6.6-7.1"
></path>
</symbol>
</svg>
${this.options
? html `
${Object.entries(this.options).map((entry) => html `
<div class="cwk-checkbox-wrapper">
<input
?checked=${entry[1]}
id="${entry[0]}"
type="checkbox"
=${this.toggleOption}
class="cwk-checkbox"
/>
<label for="${entry[0]}">
${this.keyToStrings[entry[0]]}
<svg><use xlink:href="#cwk-checkmark" /></svg>
</label>
</div>
`)}
`
: nothing}
</div>
</div>
</div>
`
: nothing}
</div>
`;
}
}
//# sourceMappingURL=AdminSidebar.js.map