dees-wcctools/ts_web/elements/wcc-properties.ts
2021-09-27 13:30:02 +02:00

364 lines
10 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
LitElement,
property,
html,
customElement,
TemplateResult,
state,
} from 'lit-element';
import { WccDashboard } from './wcc-dashboard';
export type TPropertyType = 'String' | 'Number' | 'Boolean' | 'Object' | 'Enum' | 'Array';
export type TEnvironment = 'native' | 'desktop' | 'tablet' | 'phablet' | 'phone';
export type TTheme = 'bright' | 'dark';
let environment: TEnvironment = 'native';
export const setEnvironment = (envArg) => {
environment = envArg;
};
@customElement('wcc-properties')
export class WccProperties extends LitElement {
@property()
dashboardRef: WccDashboard;
@property()
public selectedItem: TemplateResult | LitElement;
@property()
public selectedViewport: TEnvironment = 'native';
@property()
public selectedTheme: TTheme = 'dark';
@property()
public warning: string = null;
@state()
propertyContent: TemplateResult[] = [];
public render(): TemplateResult {
return html`
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<style>
:host {
font-family: 'Roboto', sans-serif;
box-sizing: border-box;
position: absolute;
left: 200px;
height: 100px;
bottom: 0px;
right: 0px;
overflow: hidden;
background: #111;
color: #fff;
}
.grid {
display: grid;
grid-template-columns: auto 150px 300px 70px;
}
.properties {
border-right: 1px solid #999;
height: 100px;
overflow-y: auto;
display: grid;
grid-template-columns: 33% 33% 33%;
}
.properties .property {
padding: 5px;
background: #444;
border: 1px solid #000;
}
.properties input, .properties select {
display: block;
width: 100%;
background: #333;
border: none;
color: #fff;
}
.viewportSelector,
.themeSelector {
user-select: none;
border-right: 1px solid #999;
}
.selectorButtons2 {
display: grid;
grid-template-columns: 50% 50%;
}
.selectorButtons4 {
display: grid;
grid-template-columns: 25% 25% 25% 25%;
}
.button {
padding: 10px;
text-align: center;
border: 1px solid #000;
transition: all 0.2s;
}
.button:hover {
cursor: pointer;
color: #333;
background: #fff;
}
.button.selected {
background: #455a64;
}
.button.selected:hover {
cursor: pointer;
color: #ffffff;
background: #455a64;
}
.panelheading {
padding: 5px;
font-weight: bold;
background: #444;
border: 1px solid #000;
}
.docs {
text-align: center;
line-height: 100px;
text-transform: uppercase;
}
.docs:hover {
cursor: pointer;
color: #333;
background: #fff;
}
.warning {
position: absolute;
background: #800000;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
text-align: center;
padding: 20px;
font-size: 25px;
}
</style>
<div class="grid">
<div class="properties">
<div class="panelheading">Properties</div>
${this.propertyContent}
</div>
<div class="themeSelector">
<div class="panelheading">Theme</div>
<div class="selectorButtons2">
<div
class="button ${this.selectedTheme === 'dark' ? 'selected' : null}"
@click=${() => {
this.selectTheme('dark');
}}
>
Dark<br /><i class="material-icons">brightness_3</i>
</div>
<div
class="button ${this.selectedTheme === 'bright' ? 'selected' : null}"
@click=${() => {
this.selectTheme('bright');
}}
>
Bright<br /><i class="material-icons">flare</i>
</div>
</div>
</div>
<div class="viewportSelector">
<div class="panelheading">Viewport</div>
<div class="selectorButtons4">
<div
class="button ${this.selectedViewport === 'phone' ? 'selected' : null}"
@click=${() => {
this.selectViewport('phone');
}}
>
Phone<br /><i class="material-icons">smartphone</i>
</div>
<div
class="button ${this.selectedViewport === 'phablet' ? 'selected' : null}"
@click=${() => {
this.selectViewport('phablet');
}}
>
Phablet<br /><i class="material-icons">smartphone</i>
</div>
<div
class="button ${this.selectedViewport === 'tablet' ? 'selected' : null}"
@click=${() => {
this.selectViewport('tablet');
}}
>
Tablet<br /><i class="material-icons">tablet</i>
</div>
<div
class="button ${this.selectedViewport === 'desktop' ||
this.selectedViewport === 'native'
? 'selected'
: null}"
@click=${() => {
this.selectViewport('native');
}}
>
Desktop<br /><i class="material-icons">desktop_windows</i>
</div>
</div>
</div>
<div class="docs">Docs</div>
</div>
${this.warning ? html`<div class="warning">${this.warning}</div>` : null}
`;
}
public async createProperties() {
console.log('creating properties');
const isEnumeration = (propertyArg): boolean => {
const keys = Object.keys(propertyArg.type);
const values = [];
for (const key of keys) {
let value = propertyArg.type[key];
if (typeof value === 'number') {
value = value.toString();
}
values.push(value);
}
for (const key of keys) {
if (values.indexOf(key) < 0) {
return false;
}
}
return true;
};
const getEnumValues = (propertyArg): any[] => {
console.log(JSON.stringify(propertyArg));
const enumValues : any[] = [];
Object.keys(propertyArg.type).forEach((valueArg: string) => {
enumValues.push(valueArg);
});
return enumValues;
};
const determinePropertyType = (propertyArg: any): TPropertyType => {
const typeName: any | undefined = propertyArg.type.name;
if (typeName) {
return typeName;
} else {
return Array.isArray(propertyArg)
? 'Array'
: isEnumeration(propertyArg)
? 'Enum'
: 'Object';
}
};
if (this.selectedItem && !((this.selectedItem as any)._classProperties)) {
const anonItem: any = this.selectedItem;
if (!anonItem._classProperties) {
return html`You have selected a page!`;
}
const wccFrame = await this.dashboardRef.wccFrame;
let selectedElement: HTMLElement;
for (const element of Array.from(wccFrame.children)) {
if (element instanceof (this.selectedItem as any)) {
selectedElement = element as HTMLElement;
break;
}
}
console.log(selectedElement);
const classProperties: Map<string, any> = anonItem._classProperties;
const propertyArray: TemplateResult[] = [];
for (const key of classProperties.keys()) {
if (key === 'goBright' || key === 'domtools') {
continue;
}
const property = classProperties.get(key);
const propertyTypeString = determinePropertyType(property);
propertyArray.push(
html`
<div class="property">
${key} / ${propertyTypeString}<br>
${(() => {
switch (propertyTypeString) {
case 'Boolean':
return html`<input
type="checkbox"
?checked=${selectedElement[key]}
@input="${(eventArg: any) => {
selectedElement[key] = eventArg.target.checked;
}}"
/>`;
case 'String':
return html`<input
type="text"
value=${selectedElement[key]}
@input="${(eventArg: any) => {
selectedElement[key] = eventArg.target.value;
}}"
/>`;
case 'Number':
return html`<input
type="number"
value=${selectedElement[key]}
@input="${(eventArg: any) => {
selectedElement[key] = eventArg.target.value;
}}"
/>`;
case 'Enum':
const enumValues: any[] = getEnumValues(property);
return html`<select
@change="${(eventArg:any)=>{
selectedElement[key]=eventArg.target.value;
}}">
${enumValues.map(valueArg => {
return html`
<option ?selected=${valueArg === selectedElement[key] ? true : false} name="${valueArg}">${valueArg}</option>
`;
})}
</select>`;
}
})()}
</div>
`
);
}
this.propertyContent = propertyArray;
} else {
return null;
}
}
public selectTheme(themeArg: TTheme) {
this.selectedTheme = themeArg;
this.dispatchEvent(
new CustomEvent('selectedTheme', {
detail: themeArg,
})
);
console.log(this.dashboardRef.selectedType);
this.dashboardRef.buildUrl();
}
public async performUpdate() {
await this.createProperties();
super.performUpdate();
}
public selectViewport(viewport: TEnvironment) {
this.selectedViewport = viewport;
setEnvironment(viewport);
this.dispatchEvent(
new CustomEvent('selectedViewport', {
detail: viewport,
})
);
this.dashboardRef.buildUrl();
}
}