import * as plugins from '../plugins.js'; import * as shared from './shared/index.js'; import * as appstate from '../appstate.js'; import { DeesElement, customElement, html, state, css, cssManager, type TemplateResult, } from '@design.estate/dees-element'; @customElement('ob-view-settings') export class ObViewSettings extends DeesElement { @state() accessor settingsState: appstate.ISettingsState = { settings: null, backupPasswordConfigured: false, }; @state() accessor loginState: appstate.ILoginState = { identity: null, isLoggedIn: false, }; constructor() { super(); const settingsSub = appstate.settingsStatePart .select((s) => s) .subscribe((newState) => { this.settingsState = newState; }); this.rxSubscriptions.push(settingsSub); const loginSub = appstate.loginStatePart .select((s) => s) .subscribe((newState) => { this.loginState = newState; }); this.rxSubscriptions.push(loginSub); } public static styles = [ cssManager.defaultStyles, shared.viewHostCss, css` .gateway-card { margin-bottom: 24px; border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')}; border-radius: 12px; background: ${cssManager.bdTheme('#ffffff', '#09090b')}; overflow: hidden; box-shadow: 0 1px 2px ${cssManager.bdTheme('rgba(0,0,0,0.04)', 'rgba(0,0,0,0.2)')}; } .gateway-header { padding: 16px 20px; border-bottom: 1px solid ${cssManager.bdTheme('#f4f4f5', '#27272a')}; background: ${cssManager.bdTheme('#fafafa', '#101013')}; } .gateway-title { font-size: 15px; font-weight: 600; color: ${cssManager.bdTheme('#18181b', '#fafafa')}; } .gateway-subtitle { margin-top: 4px; font-size: 13px; color: ${cssManager.bdTheme('#71717a', '#a1a1aa')}; } .gateway-content { padding: 20px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; } .gateway-field.full { grid-column: 1 / -1; } dees-input-text { width: 100%; } .gateway-footer { display: flex; justify-content: flex-end; padding: 0 20px 20px; } @media (max-width: 700px) { .gateway-content { grid-template-columns: 1fr; } } `, ]; async connectedCallback() { super.connectedCallback(); await appstate.settingsStatePart.dispatchAction(appstate.fetchSettingsAction, null); } public render(): TemplateResult { return html` Settings ${this.renderExternalGatewaySettings()} { const { key, value } = e.detail; appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, { settings: { [key]: value }, }); }} @save=${(e: CustomEvent) => { appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, { settings: e.detail, }); }} @change-password=${(e: CustomEvent) => { console.log('Change password requested:', e.detail); }} @reset=${() => { appstate.settingsStatePart.dispatchAction(appstate.fetchSettingsAction, null); }} > `; } private renderExternalGatewaySettings(): TemplateResult { const settings = this.settingsState.settings; return html`
Delegate Routing
Delegate public app routing, DNS, and certificates to a dcrouter edge authority.
${this.renderGatewayInput('dcrouterGatewayUrl', 'Gateway URL', settings?.dcrouterGatewayUrl || '', 'Base URL of the dcrouter OpsServer.')} ${this.renderGatewayInput('dcrouterGatewayApiToken', 'API Token', settings?.dcrouterGatewayApiToken || '', 'Requires gateway-client access in dcrouter.', true)} ${this.renderGatewayInput('dcrouterGatewayClientId', 'Gateway Client ID', settings?.dcrouterGatewayClientId || settings?.dcrouterWorkHosterId || '', 'Leave empty to let Onebox create a stable ID.')} ${this.renderGatewayInput('dcrouterTargetHost', 'Target Host', settings?.dcrouterTargetHost || '', 'Defaults to the configured server IP when empty.')} ${this.renderGatewayInput('dcrouterTargetPort', 'Target Port', String(settings?.dcrouterTargetPort || 80), 'Internal HTTP port dcrouter forwards to.')}
`; } private renderGatewayInput( key: keyof NonNullable, label: string, value: string, hint: string, isPassword = false, ): TemplateResult { return html`
this.updateGatewayDraft(key, (event.target as HTMLInputElement).value)} >
`; } private updateGatewayDraft( key: keyof NonNullable, value: string, ): void { const currentSettings = this.settingsState.settings || {} as NonNullable; const nextValue = key === 'dcrouterTargetPort' ? Number(value) || 0 : value; this.settingsState = { ...this.settingsState, settings: { ...currentSettings, [key]: nextValue, }, }; } private async saveExternalGatewaySettings(): Promise { const settings = this.settingsState.settings; if (!settings) return; await appstate.settingsStatePart.dispatchAction(appstate.updateSettingsAction, { settings: { dcrouterGatewayUrl: settings.dcrouterGatewayUrl || '', dcrouterGatewayApiToken: settings.dcrouterGatewayApiToken || '', dcrouterGatewayClientId: settings.dcrouterGatewayClientId || settings.dcrouterWorkHosterId || '', dcrouterTargetHost: settings.dcrouterTargetHost || '', dcrouterTargetPort: Number(settings.dcrouterTargetPort) || 80, }, }); } }