718 lines
23 KiB
TypeScript
718 lines
23 KiB
TypeScript
import * as plugins from '../../plugins.js';
|
|
import {
|
|
DeesElement,
|
|
property,
|
|
html,
|
|
customElement,
|
|
type TemplateResult,
|
|
css,
|
|
cssManager,
|
|
unsafeCSS,
|
|
state,
|
|
} from '@design.estate/dees-element';
|
|
import * as sharedStyles from '../../styles/shared.styles.js';
|
|
import type { IStatusPageConfig } from '../../interfaces/index.js';
|
|
import { demoFunc } from './upladmin-statuspage-config.demo.js';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'upladmin-statuspage-config': UpladminStatuspageConfig;
|
|
}
|
|
}
|
|
|
|
@customElement('upladmin-statuspage-config')
|
|
export class UpladminStatuspageConfig extends DeesElement {
|
|
public static demo = demoFunc;
|
|
|
|
@property({ type: Object })
|
|
accessor config: IStatusPageConfig = {};
|
|
|
|
@property({ type: Boolean })
|
|
accessor loading: boolean = false;
|
|
|
|
@state()
|
|
accessor formData: IStatusPageConfig = {};
|
|
|
|
@state()
|
|
accessor activeSection: string = 'branding';
|
|
|
|
@state()
|
|
accessor hasChanges: boolean = false;
|
|
|
|
public static styles = [
|
|
plugins.domtools.elementBasic.staticStyles,
|
|
sharedStyles.commonStyles,
|
|
css`
|
|
:host {
|
|
display: block;
|
|
font-family: ${unsafeCSS(sharedStyles.fonts.base)};
|
|
}
|
|
|
|
.config-container {
|
|
display: grid;
|
|
grid-template-columns: 220px 1fr;
|
|
gap: ${unsafeCSS(sharedStyles.spacing.lg)};
|
|
min-height: 500px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.config-container {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.config-nav {
|
|
background: ${sharedStyles.colors.background.secondary};
|
|
border: 1px solid ${sharedStyles.colors.border.default};
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.lg)};
|
|
padding: ${unsafeCSS(sharedStyles.spacing.sm)};
|
|
height: fit-content;
|
|
}
|
|
|
|
.nav-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
width: 100%;
|
|
padding: 14px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
font-family: ${unsafeCSS(sharedStyles.fonts.base)};
|
|
color: ${sharedStyles.colors.text.secondary};
|
|
background: transparent;
|
|
border: none;
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
|
|
cursor: pointer;
|
|
text-align: left;
|
|
transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
|
|
}
|
|
|
|
.nav-item:hover {
|
|
background: ${sharedStyles.colors.background.muted};
|
|
color: ${sharedStyles.colors.text.primary};
|
|
}
|
|
|
|
.nav-item.active {
|
|
background: ${sharedStyles.colors.accent.primary};
|
|
color: white;
|
|
}
|
|
|
|
.nav-item.active dees-icon {
|
|
--icon-color: white;
|
|
}
|
|
|
|
.nav-item dees-icon {
|
|
--icon-color: ${sharedStyles.colors.text.muted};
|
|
transition: color ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
|
|
}
|
|
|
|
.nav-item:hover dees-icon {
|
|
--icon-color: ${sharedStyles.colors.text.primary};
|
|
}
|
|
|
|
.config-content {
|
|
background: ${sharedStyles.colors.background.secondary};
|
|
border: 1px solid ${sharedStyles.colors.border.default};
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.lg)};
|
|
overflow: hidden;
|
|
}
|
|
|
|
.content-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.lg)};
|
|
border-bottom: 1px solid ${sharedStyles.colors.border.default};
|
|
background: ${sharedStyles.colors.background.muted};
|
|
}
|
|
|
|
.content-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: ${sharedStyles.colors.text.primary};
|
|
}
|
|
|
|
.content-subtitle {
|
|
font-size: 13px;
|
|
color: ${sharedStyles.colors.text.muted};
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.save-indicator {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 12px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: ${sharedStyles.colors.accent.warning};
|
|
background: ${cssManager.bdTheme('rgba(234, 179, 8, 0.1)', 'rgba(234, 179, 8, 0.15)')};
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
|
|
}
|
|
|
|
.save-indicator dees-icon {
|
|
--icon-color: ${sharedStyles.colors.accent.warning};
|
|
}
|
|
|
|
.content-body {
|
|
padding: ${unsafeCSS(sharedStyles.spacing.lg)};
|
|
}
|
|
|
|
dees-form {
|
|
display: contents;
|
|
}
|
|
|
|
.form-section {
|
|
margin-bottom: ${unsafeCSS(sharedStyles.spacing.xl)};
|
|
}
|
|
|
|
.form-section:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.section-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: ${sharedStyles.colors.text.primary};
|
|
margin-bottom: ${unsafeCSS(sharedStyles.spacing.md)};
|
|
padding-bottom: ${unsafeCSS(sharedStyles.spacing.xs)};
|
|
border-bottom: 1px solid ${sharedStyles.colors.border.light};
|
|
}
|
|
|
|
.section-title dees-icon {
|
|
--icon-color: ${sharedStyles.colors.text.muted};
|
|
}
|
|
|
|
.form-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
gap: ${unsafeCSS(sharedStyles.spacing.md)};
|
|
}
|
|
|
|
.content-actions {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: ${unsafeCSS(sharedStyles.spacing.sm)};
|
|
padding: ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.lg)};
|
|
border-top: 1px solid ${sharedStyles.colors.border.default};
|
|
background: ${sharedStyles.colors.background.muted};
|
|
}
|
|
|
|
.theme-options {
|
|
display: flex;
|
|
gap: ${unsafeCSS(sharedStyles.spacing.sm)};
|
|
}
|
|
|
|
.theme-option {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 18px;
|
|
background: ${sharedStyles.colors.background.primary};
|
|
border: 2px solid ${sharedStyles.colors.border.default};
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
|
|
cursor: pointer;
|
|
transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)};
|
|
}
|
|
|
|
.theme-option:hover {
|
|
border-color: ${sharedStyles.colors.border.strong};
|
|
}
|
|
|
|
.theme-option.selected {
|
|
border-color: ${sharedStyles.colors.accent.primary};
|
|
background: ${cssManager.bdTheme('rgba(59, 130, 246, 0.05)', 'rgba(96, 165, 250, 0.1)')};
|
|
}
|
|
|
|
.theme-option input {
|
|
display: none;
|
|
}
|
|
|
|
.theme-preview {
|
|
width: 56px;
|
|
height: 36px;
|
|
border-radius: 6px;
|
|
border: 1px solid ${sharedStyles.colors.border.default};
|
|
overflow: hidden;
|
|
}
|
|
|
|
.theme-preview.light {
|
|
background: linear-gradient(180deg, #f8fafc 0%, #e2e8f0 100%);
|
|
}
|
|
|
|
.theme-preview.dark {
|
|
background: linear-gradient(180deg, #1e293b 0%, #0f172a 100%);
|
|
}
|
|
|
|
.theme-preview.auto {
|
|
background: linear-gradient(135deg, #f8fafc 0%, #f8fafc 50%, #1e293b 50%, #1e293b 100%);
|
|
}
|
|
|
|
.theme-label {
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: ${sharedStyles.colors.text.primary};
|
|
}
|
|
|
|
.logo-preview {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: ${unsafeCSS(sharedStyles.spacing.md)};
|
|
padding: ${unsafeCSS(sharedStyles.spacing.md)};
|
|
background: ${sharedStyles.colors.background.primary};
|
|
border: 1px solid ${sharedStyles.colors.border.default};
|
|
border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)};
|
|
margin-top: ${unsafeCSS(sharedStyles.spacing.sm)};
|
|
}
|
|
|
|
.logo-preview img {
|
|
max-width: 140px;
|
|
max-height: 48px;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.logo-placeholder {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
color: ${sharedStyles.colors.text.muted};
|
|
font-size: 13px;
|
|
}
|
|
|
|
.logo-placeholder dees-icon {
|
|
--icon-color: ${sharedStyles.colors.text.muted};
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.toggle-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: ${unsafeCSS(sharedStyles.spacing.md)};
|
|
padding: ${unsafeCSS(sharedStyles.spacing.sm)} 0;
|
|
}
|
|
|
|
.toggle-label {
|
|
flex: 1;
|
|
}
|
|
|
|
.toggle-label-text {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: ${sharedStyles.colors.text.primary};
|
|
}
|
|
|
|
.toggle-label-hint {
|
|
font-size: 12px;
|
|
color: ${sharedStyles.colors.text.muted};
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* Style dees-input components */
|
|
dees-input-text,
|
|
dees-input-dropdown {
|
|
--dees-input-background: ${sharedStyles.colors.background.primary};
|
|
--dees-input-border-color: ${sharedStyles.colors.border.default};
|
|
}
|
|
`
|
|
];
|
|
|
|
async connectedCallback() {
|
|
await super.connectedCallback();
|
|
this.formData = { ...this.config };
|
|
}
|
|
|
|
updated(changedProperties: Map<string, unknown>) {
|
|
if (changedProperties.has('config')) {
|
|
this.formData = { ...this.config };
|
|
this.hasChanges = false;
|
|
}
|
|
}
|
|
|
|
public render(): TemplateResult {
|
|
const sections = [
|
|
{ id: 'branding', icon: 'lucide:Palette', label: 'Branding', subtitle: 'Logo, company name, colors' },
|
|
{ id: 'urls', icon: 'lucide:Link', label: 'URLs', subtitle: 'Links and endpoints' },
|
|
{ id: 'behavior', icon: 'lucide:Settings', label: 'Behavior', subtitle: 'Refresh, notifications, history' },
|
|
{ id: 'advanced', icon: 'lucide:Wrench', label: 'Advanced', subtitle: 'API, timezone, language' },
|
|
];
|
|
|
|
return html`
|
|
<div class="config-container">
|
|
<nav class="config-nav">
|
|
${sections.map(section => html`
|
|
<button
|
|
class="nav-item ${this.activeSection === section.id ? 'active' : ''}"
|
|
@click="${() => this.activeSection = section.id}"
|
|
>
|
|
<dees-icon .icon=${section.icon} .iconSize=${18}></dees-icon>
|
|
<span>${section.label}</span>
|
|
</button>
|
|
`)}
|
|
</nav>
|
|
|
|
<div class="config-content">
|
|
<div class="content-header">
|
|
<div>
|
|
<div class="content-title">${sections.find(s => s.id === this.activeSection)?.label}</div>
|
|
<div class="content-subtitle">${sections.find(s => s.id === this.activeSection)?.subtitle}</div>
|
|
</div>
|
|
${this.hasChanges ? html`
|
|
<div class="save-indicator">
|
|
<dees-icon .icon=${'lucide:AlertCircle'} .iconSize=${14}></dees-icon>
|
|
<span>Unsaved changes</span>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
|
|
<div class="content-body">
|
|
<dees-form>
|
|
${this.renderSection()}
|
|
</dees-form>
|
|
</div>
|
|
|
|
<div class="content-actions">
|
|
<dees-button type="discreet" @click="${this.handleReset}" ?disabled="${!this.hasChanges || this.loading}">
|
|
<dees-icon .icon=${'lucide:RotateCcw'} .iconSize=${14}></dees-icon>
|
|
Reset
|
|
</dees-button>
|
|
<dees-button type="highlighted" @click="${this.handleSave}" ?disabled="${!this.hasChanges || this.loading}">
|
|
${this.loading ? html`<dees-spinner .size=${16}></dees-spinner>` : html`<dees-icon .icon=${'lucide:Save'} .iconSize=${16}></dees-icon>`}
|
|
Save Changes
|
|
</dees-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private renderSection(): TemplateResult {
|
|
switch (this.activeSection) {
|
|
case 'branding':
|
|
return this.renderBrandingSection();
|
|
case 'urls':
|
|
return this.renderUrlsSection();
|
|
case 'behavior':
|
|
return this.renderBehaviorSection();
|
|
case 'advanced':
|
|
return this.renderAdvancedSection();
|
|
default:
|
|
return html``;
|
|
}
|
|
}
|
|
|
|
private renderBrandingSection(): TemplateResult {
|
|
const themeOptions: Array<{ value: 'light' | 'dark' | 'auto'; label: string; icon: string }> = [
|
|
{ value: 'light', label: 'Light', icon: 'lucide:Sun' },
|
|
{ value: 'dark', label: 'Dark', icon: 'lucide:Moon' },
|
|
{ value: 'auto', label: 'Auto', icon: 'lucide:Monitor' },
|
|
];
|
|
|
|
return html`
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Building'} .iconSize=${16}></dees-icon>
|
|
Company Information
|
|
</div>
|
|
<div class="form-grid">
|
|
<dees-input-text
|
|
key="companyName"
|
|
label="Company Name"
|
|
.value="${this.formData.companyName || ''}"
|
|
placeholder="Your Company"
|
|
description="Displayed in the header and footer"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('companyName', e.detail)}"
|
|
></dees-input-text>
|
|
|
|
<dees-input-text
|
|
key="supportEmail"
|
|
label="Support Email"
|
|
.value="${this.formData.supportEmail || ''}"
|
|
placeholder="support@example.com"
|
|
description="Contact email for users"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('supportEmail', e.detail)}"
|
|
></dees-input-text>
|
|
</div>
|
|
|
|
<dees-input-text
|
|
key="companyLogo"
|
|
label="Company Logo URL"
|
|
.value="${this.formData.companyLogo || ''}"
|
|
placeholder="https://example.com/logo.png"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('companyLogo', e.detail)}"
|
|
></dees-input-text>
|
|
|
|
${this.formData.companyLogo ? html`
|
|
<div class="logo-preview">
|
|
<img src="${this.formData.companyLogo}" alt="Company logo" @error="${this.handleLogoError}" />
|
|
</div>
|
|
` : html`
|
|
<div class="logo-preview">
|
|
<div class="logo-placeholder">
|
|
<dees-icon .icon=${'lucide:Image'} .iconSize=${20}></dees-icon>
|
|
No logo configured
|
|
</div>
|
|
</div>
|
|
`}
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Palette'} .iconSize=${16}></dees-icon>
|
|
Theme
|
|
</div>
|
|
<div class="theme-options">
|
|
${themeOptions.map(opt => html`
|
|
<label
|
|
class="theme-option ${this.formData.theme === opt.value ? 'selected' : ''}"
|
|
@click="${() => this.handleThemeChange(opt.value)}"
|
|
>
|
|
<input type="radio" name="theme" value="${opt.value}" ?checked="${this.formData.theme === opt.value}" />
|
|
<div class="theme-preview ${opt.value}"></div>
|
|
<span class="theme-label">${opt.label}</span>
|
|
</label>
|
|
`)}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="toggle-row">
|
|
<div class="toggle-label">
|
|
<div class="toggle-label-text">White Label Mode</div>
|
|
<div class="toggle-label-hint">Hide 'Powered by' branding</div>
|
|
</div>
|
|
<dees-input-checkbox
|
|
key="whitelabel"
|
|
.value="${this.formData.whitelabel || false}"
|
|
@changeSubject="${(e: CustomEvent) => this.handleBooleanChange('whitelabel', e.detail)}"
|
|
></dees-input-checkbox>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private renderUrlsSection(): TemplateResult {
|
|
return html`
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Globe'} .iconSize=${16}></dees-icon>
|
|
Status Page URLs
|
|
</div>
|
|
<div class="form-grid">
|
|
<dees-input-text
|
|
key="statusPageUrl"
|
|
label="Status Page URL"
|
|
.value="${this.formData.statusPageUrl || ''}"
|
|
placeholder="https://status.example.com"
|
|
description="Public URL of your status page"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('statusPageUrl', e.detail)}"
|
|
></dees-input-text>
|
|
|
|
<dees-input-text
|
|
key="legalUrl"
|
|
label="Legal / Terms URL"
|
|
.value="${this.formData.legalUrl || ''}"
|
|
placeholder="https://example.com/terms"
|
|
description="Link to terms of service or legal info"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('legalUrl', e.detail)}"
|
|
></dees-input-text>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Server'} .iconSize=${16}></dees-icon>
|
|
API Configuration
|
|
</div>
|
|
<dees-input-text
|
|
key="apiEndpoint"
|
|
label="API Endpoint"
|
|
.value="${this.formData.apiEndpoint || ''}"
|
|
placeholder="https://api.example.com/status"
|
|
description="Base URL for status API requests"
|
|
@changeSubject="${(e: CustomEvent) => this.handleTextChange('apiEndpoint', e.detail)}"
|
|
></dees-input-text>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private renderBehaviorSection(): TemplateResult {
|
|
return html`
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:RefreshCw'} .iconSize=${16}></dees-icon>
|
|
Auto-refresh
|
|
</div>
|
|
<dees-input-text
|
|
key="refreshInterval"
|
|
label="Refresh Interval (seconds)"
|
|
inputType="number"
|
|
.value="${String(this.formData.refreshInterval || 60)}"
|
|
placeholder="60"
|
|
description="How often to refresh status data (minimum 30 seconds)"
|
|
@changeSubject="${(e: CustomEvent) => this.handleNumberChange('refreshInterval', e.detail)}"
|
|
></dees-input-text>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:History'} .iconSize=${16}></dees-icon>
|
|
History
|
|
</div>
|
|
<dees-input-text
|
|
key="showHistoricalDays"
|
|
label="Historical Days to Show"
|
|
inputType="number"
|
|
.value="${String(this.formData.showHistoricalDays || 90)}"
|
|
placeholder="90"
|
|
description="Number of days of history to display"
|
|
@changeSubject="${(e: CustomEvent) => this.handleNumberChange('showHistoricalDays', e.detail)}"
|
|
></dees-input-text>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Zap'} .iconSize=${16}></dees-icon>
|
|
Features
|
|
</div>
|
|
<div class="toggle-row">
|
|
<div class="toggle-label">
|
|
<div class="toggle-label-text">WebSocket Updates</div>
|
|
<div class="toggle-label-hint">Enable real-time updates</div>
|
|
</div>
|
|
<dees-input-checkbox
|
|
key="enableWebSocket"
|
|
.value="${this.formData.enableWebSocket || false}"
|
|
@changeSubject="${(e: CustomEvent) => this.handleBooleanChange('enableWebSocket', e.detail)}"
|
|
></dees-input-checkbox>
|
|
</div>
|
|
|
|
<div class="toggle-row">
|
|
<div class="toggle-label">
|
|
<div class="toggle-label-text">Browser Notifications</div>
|
|
<div class="toggle-label-hint">Allow push notifications</div>
|
|
</div>
|
|
<dees-input-checkbox
|
|
key="enableNotifications"
|
|
.value="${this.formData.enableNotifications || false}"
|
|
@changeSubject="${(e: CustomEvent) => this.handleBooleanChange('enableNotifications', e.detail)}"
|
|
></dees-input-checkbox>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private renderAdvancedSection(): TemplateResult {
|
|
const timezoneOptions = [
|
|
{ key: 'UTC', option: 'UTC', payload: null },
|
|
{ key: 'America/New_York', option: 'Eastern Time (US)', payload: null },
|
|
{ key: 'America/Los_Angeles', option: 'Pacific Time (US)', payload: null },
|
|
{ key: 'Europe/London', option: 'London', payload: null },
|
|
{ key: 'Europe/Berlin', option: 'Berlin', payload: null },
|
|
{ key: 'Asia/Tokyo', option: 'Tokyo', payload: null },
|
|
{ key: 'Asia/Shanghai', option: 'Shanghai', payload: null },
|
|
];
|
|
|
|
const dateFormatOptions = [
|
|
{ key: 'relative', option: 'Relative (2 hours ago)', payload: null },
|
|
{ key: 'absolute', option: 'Absolute (Dec 23, 2024 14:30)', payload: null },
|
|
{ key: 'iso', option: 'ISO (2024-12-23T14:30:00)', payload: null },
|
|
];
|
|
|
|
const languageOptions = [
|
|
{ key: 'en', option: 'English', payload: null },
|
|
{ key: 'de', option: 'German', payload: null },
|
|
{ key: 'fr', option: 'French', payload: null },
|
|
{ key: 'es', option: 'Spanish', payload: null },
|
|
{ key: 'ja', option: 'Japanese', payload: null },
|
|
{ key: 'zh', option: 'Chinese', payload: null },
|
|
];
|
|
|
|
return html`
|
|
<div class="form-section">
|
|
<div class="section-title">
|
|
<dees-icon .icon=${'lucide:Globe2'} .iconSize=${16}></dees-icon>
|
|
Localization
|
|
</div>
|
|
<div class="form-grid">
|
|
<dees-input-dropdown
|
|
key="timeZone"
|
|
label="Timezone"
|
|
.options="${timezoneOptions}"
|
|
.selectedOption="${this.formData.timeZone || 'UTC'}"
|
|
@selectedOption="${(e: CustomEvent) => this.handleDropdownChange('timeZone', e.detail)}"
|
|
></dees-input-dropdown>
|
|
|
|
<dees-input-dropdown
|
|
key="language"
|
|
label="Language"
|
|
.options="${languageOptions}"
|
|
.selectedOption="${this.formData.language || 'en'}"
|
|
@selectedOption="${(e: CustomEvent) => this.handleDropdownChange('language', e.detail)}"
|
|
></dees-input-dropdown>
|
|
|
|
<dees-input-dropdown
|
|
key="dateFormat"
|
|
label="Date Format"
|
|
.options="${dateFormatOptions}"
|
|
.selectedOption="${this.formData.dateFormat || 'relative'}"
|
|
@selectedOption="${(e: CustomEvent) => this.handleDropdownChange('dateFormat', e.detail)}"
|
|
></dees-input-dropdown>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private handleTextChange(name: string, value: string) {
|
|
this.formData = { ...this.formData, [name]: value };
|
|
this.hasChanges = true;
|
|
}
|
|
|
|
private handleNumberChange(name: string, value: string) {
|
|
this.formData = { ...this.formData, [name]: parseInt(value, 10) || 0 };
|
|
this.hasChanges = true;
|
|
}
|
|
|
|
private handleBooleanChange(name: string, value: boolean) {
|
|
this.formData = { ...this.formData, [name]: value };
|
|
this.hasChanges = true;
|
|
}
|
|
|
|
private handleDropdownChange(name: string, value: string) {
|
|
this.formData = { ...this.formData, [name]: value };
|
|
this.hasChanges = true;
|
|
}
|
|
|
|
private handleThemeChange(theme: 'light' | 'dark' | 'auto') {
|
|
this.formData = { ...this.formData, theme };
|
|
this.hasChanges = true;
|
|
}
|
|
|
|
private handleLogoError(e: Event) {
|
|
const img = e.target as HTMLImageElement;
|
|
img.style.display = 'none';
|
|
}
|
|
|
|
private handleSave() {
|
|
this.dispatchEvent(new CustomEvent('configSave', {
|
|
detail: { config: { ...this.formData } },
|
|
bubbles: true,
|
|
composed: true
|
|
}));
|
|
}
|
|
|
|
private handleReset() {
|
|
this.formData = { ...this.config };
|
|
this.hasChanges = false;
|
|
}
|
|
|
|
public setConfig(config: IStatusPageConfig) {
|
|
this.formData = { ...config };
|
|
this.hasChanges = false;
|
|
}
|
|
}
|