diff --git a/connection-edit.js b/connection-edit.js new file mode 100644 index 0000000..2a38b4a --- /dev/null +++ b/connection-edit.js @@ -0,0 +1,128 @@ +export class ConnectionEdit extends HTMLElement { + textEn = { + page: 'Page', + access: 'Access', + read: 'read', + readWrite: 'read and write', + doesntExist: "Error: The page doesn't exist", + samePage: "Error: Cannot connect to same page", + alreadyConnected: "Error: This page is already connected", + } + + textEs = { + page: 'Página', + access: 'Accesso', + read: 'leer', + readWrite: 'leer y escribir', + doesntExist: 'Error: La página no existe', + samePage: "Error: no se puede conectar a la misma página", + alreadyConnected: "Error: esta página ya está conectada", + } + + constructor() { + super() + this.attachShadow({mode: 'open'}) + this.language = navigator.language + const pageLabel = document.createElement('label') + pageLabel.innerText = this.text.page + this.pageInput = document.createElement('input') + const accessLabel = document.createElement('label') + accessLabel.innerText = this.text.access + this.accessSelect = document.createElement('select') + const wrap = document.createElement('div') + wrap.append(this.accessSelect) + const opts = ['read', 'readWrite'].map(value => { + const el = document.createElement('option') + el.value = value + el.innerText = this.text[value] + return el + }) + this.accessSelect.append(...opts) + this.accessSelect.value = 'read' + const fields = document.createElement('div') + fields.classList.add('fields') + fields.append( + pageLabel, + this.pageInput, + accessLabel, + wrap, + ) + this.shadowRoot.append( + fields, + ) + } + + connectedCallback() { + const style = document.createElement('style') + style.textContent = ` + :host { + display: flex; + flex-direction: column; + align-items: stretch; + } + .fields { + display: grid; + grid-template-columns: fit-content(50%) 1fr; + gap: 5px 10px; + } + .error { + color: red; + } + ` + this.shadowRoot.append(style) + } + + display() { + + } + + get data() { + return { + networkAccess: this.netSelect.value, + } + } + + set data(value) { + this.netText.innerText = JSON.stringify(value) + this.netSelect.value = value.networkAccess ?? 'local' + this.display() + } + + set error(error) { + this._error = error + if (error === undefined) { + if (this.errorEl) { + this.errorEl.remove() + this.errorEl = undefined + } + } else { + if (!this.errorEl) { + this.errorEl = document.createElement('p') + this.errorEl.classList.add('error') + this.shadowRoot.append(this.errorEl) + } + this.errorEl.innerText = this.text[error] + } + } + + get error() { + return this._error + } + + get language() { + return this._language + } + + set language(language) { + this._language = language + this.text = this.langEs ? this.textEs : this.textEn + } + + get langEs() { + return /^es\b/.test(this.language) + } + + get lang() { + return this.language.split('-')[0] + } +} \ No newline at end of file diff --git a/connections.js b/connections.js new file mode 100644 index 0000000..7b24a20 --- /dev/null +++ b/connections.js @@ -0,0 +1,126 @@ +export class Connections extends HTMLElement { + textEn = { + add: 'Add connection', + cancel: 'Cancel', + } + + textEs = { + add: 'Añadir conexión', + cancel: 'Cancelar', + } + + constructor() { + super() + this.attachShadow({mode: 'open'}) + this.language = navigator.language + this.content = document.createElement('div') + const bGroup = document.createElement( + 'm-forms-button-group' + ) + bGroup.addPrimary(this.text.add, () => { + this.add() + }) + this.shadowRoot.append( + this.content, + bGroup, + ) + } + + connectedCallback() { + const style = document.createElement('style') + style.textContent = ` + :host { + display: flex; + flex-direction: column; + align-items: stretch; + margin-bottom: 5px; + } + m-dialog::part(footer) { + padding-top: 15px; + } + ` + this.shadowRoot.append(style) + } + + add() { + const dialog = document.createElement('m-dialog') + dialog.top = 180 + const edit = document.createElement( + 'm-settings-connection-edit' + ) + dialog.bodyEl.append(edit) + const bGroup = document.createElement( + 'm-forms-button-group' + ) + bGroup.addPrimary(this.text.add, () => { + const path = edit.pageInput.value + const access = edit.accessSelect.value + const exists = localStorage.getItem(path) + if (!exists) { + edit.error = 'doesntExist' + return + } else if (path === this.path) { + edit.error = 'samePage' + return + } else if (path in this.data) { + edit.error = 'alreadyConnected' + return + } + this.data = { + ...this.data, + [path]: access, + } + dialog.close() + }) + bGroup.addCancel(this.text.cancel, () => { + dialog.close() + }) + dialog.footerEl.appendChild(bGroup) + this.shadowRoot.append(dialog) + dialog.open() + } + + display() { + const entries = Object.entries(this.data) + const content = entries.map(([path, access]) => { + const el = document.createElement('div') + el.innerText = `${path}: ${access}` + return el + }) + this.content.replaceChildren(...content) + } + + set type(value) { + this._type = value + } + + get type() { + return this._type + } + + get data() { + return this._data + } + + set data(value) { + this._data = value + this.display() + } + + get language() { + return this._language + } + + set language(language) { + this._language = language + this.text = this.langEs ? this.textEs : this.textEn + } + + get langEs() { + return /^es\b/.test(this.language) + } + + get lang() { + return this.language.split('-')[0] + } +} \ No newline at end of file diff --git a/page-settings.js b/page-settings.js index b7ce49a..d494920 100644 --- a/page-settings.js +++ b/page-settings.js @@ -1,9 +1,13 @@ export class PageSettings extends HTMLElement { textEn = { + outbound: 'Outbound connections', + inbound: 'Inbound connections', netAccess: 'Direct network access (CSP)', } textEs = { + outbound: 'Conexiones salientes', + inbound: 'Conexiones entrantes', netAccess: 'Acceso directo a la red (CSP)', } @@ -11,6 +15,20 @@ export class PageSettings extends HTMLElement { super() this.attachShadow({mode: 'open'}) this.language = navigator.language + const outboundHeading = document.createElement('div') + outboundHeading.classList.add('heading') + outboundHeading.innerText = this.text.outbound + this.outbound = document.createElement( + 'm-settings-connections' + ) + this.outbound.type = 'outbound' + const inboundHeading = document.createElement('div') + inboundHeading.classList.add('heading') + inboundHeading.innerText = this.text.inbound + this.inbound = document.createElement( + 'm-settings-connections' + ) + this.inbound.type = 'inbound' const netSelectHeading = document.createElement('div') netSelectHeading.classList.add('heading') netSelectHeading.innerText = this.text.netAccess @@ -18,6 +36,10 @@ export class PageSettings extends HTMLElement { 'm-settings-network-settings' ) this.shadowRoot.append( + outboundHeading, + this.outbound, + inboundHeading, + this.inbound, netSelectHeading, this.network, ) @@ -42,7 +64,8 @@ export class PageSettings extends HTMLElement { justify-content: flex-start; background: #f2dbd8; padding: 3px; - margin-bottom: 5px; + margin-bottom: 10px; + margin-top: 10px; font-weight: bold; } ` @@ -52,15 +75,29 @@ export class PageSettings extends HTMLElement { get data() { return { ...this.network.data, + outbound: this.outbound.data, + inbound: this.inbound.data, } } set data(value) { + this.outbound.data = value.connections?.outbound || {} + this.inbound.data = value.connections?.inbound || {} this.network.data = { networkAccess: value.networkAccess } } + set path(value) { + this._path = value + this.outbound.path = value + this.inbound.path = value + } + + get path() { + return this._path + } + set cspProfiles(value) { this.network.cspProfiles = value }