mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 17:45:42 +00:00
1320457e56
Updated the build scripts to include the server library in the agent build process. Introduced new environment variables for Go module and build caches to improve build efficiency. Enhanced the generator route to support multiple languages and added locale labels for better user experience. Updated the generator view to dynamically populate language options based on supported languages.
293 lines
19 KiB
HTML
293 lines
19 KiB
HTML
<%- include('layouts/main', {
|
|
title: _('nav.generator'),
|
|
pageStyles: ['pages', 'generator'],
|
|
pageScripts: ['generator'],
|
|
currentPage: 'generator',
|
|
breadcrumb: [{ label: _('nav.generator') }],
|
|
body: `
|
|
<div class="page-header">
|
|
<h1 class="page-title">
|
|
<span class="material-icons">tune</span>
|
|
${_('generator.title')}
|
|
</h1>
|
|
<p class="page-subtitle">${_('generator.subtitle')}</p>
|
|
</div>
|
|
|
|
<div class="generator-layout">
|
|
<!-- Left column: bundle list -->
|
|
<aside class="generator-bundles card">
|
|
<div class="card-header">
|
|
<h2 class="card-title">
|
|
<span class="material-icons">inventory_2</span>
|
|
${_('generator.bundles_title')}
|
|
</h2>
|
|
<button id="gen-new-bundle" class="btn btn-primary btn-sm">
|
|
<span class="material-icons">add</span>
|
|
${_('generator.new_bundle')}
|
|
</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="gen-bundle-list" class="bundle-list">
|
|
<p class="text-muted">${_('generator.loading')}</p>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Right column: editor + preview -->
|
|
<section class="generator-editor card">
|
|
<div class="card-header">
|
|
<h2 class="card-title" id="gen-editor-title">
|
|
<span class="material-icons">edit</span>
|
|
${_('generator.editor_title')}
|
|
</h2>
|
|
<div class="editor-actions">
|
|
<button id="gen-revoke-btn" class="btn btn-warning btn-sm hidden">
|
|
<span class="material-icons">block</span>
|
|
${_('generator.revoke')}
|
|
</button>
|
|
<button id="gen-delete-btn" class="btn btn-danger btn-sm hidden">
|
|
<span class="material-icons">delete</span>
|
|
${_('common.delete')}
|
|
</button>
|
|
<button id="gen-save-btn" class="btn btn-primary btn-sm" disabled>
|
|
<span class="material-icons">save</span>
|
|
${_('common.save')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="gen-empty-state" class="empty-state">
|
|
<span class="material-icons">touch_app</span>
|
|
<p>${_('generator.empty_state')}</p>
|
|
</div>
|
|
|
|
<div id="gen-editor-form" class="editor-form hidden">
|
|
<div class="editor-grid">
|
|
<div class="editor-fields">
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-name">${_('generator.bundle_name')}</label>
|
|
<input type="text" id="gen-name" class="form-input" maxlength="100" required>
|
|
<p class="form-hint">${_('generator.bundle_name_hint')}</p>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-slug">${_('generator.short_link')}</label>
|
|
<div class="download-link-row">
|
|
<span class="input-prefix">/d/</span>
|
|
<input type="text" id="gen-slug" class="form-input" maxlength="32"
|
|
pattern="[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?"
|
|
autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<p class="form-hint">${_('generator.short_link_hint')}</p>
|
|
</div>
|
|
|
|
<h3 class="section-title">${_('generator.connection_section')}</h3>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-server-host">${_('generator.server_host')}</label>
|
|
<input type="text" id="gen-server-host" class="form-input" maxlength="253"
|
|
placeholder="${_('generator.server_host_placeholder')}" required>
|
|
<p class="form-hint">${_('generator.server_host_hint')}</p>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group form-group-checkbox">
|
|
<label class="form-label">
|
|
<input type="checkbox" id="gen-use-https" checked>
|
|
${_('generator.use_https')}
|
|
</label>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">${_('generator.enrollment_token')}</label>
|
|
<input type="text" id="gen-token-mask" class="form-input" readonly
|
|
placeholder="${_('generator.enrollment_token_pending')}">
|
|
<p class="form-hint">${_('generator.enrollment_token_hint')}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="section-title">${_('generator.branding_section')}</h3>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-company">${_('generator.company_name')}</label>
|
|
<input type="text" id="gen-company" class="form-input" maxlength="100" required>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-short-text">${_('generator.short_text')}</label>
|
|
<textarea id="gen-short-text" class="form-input" rows="2" maxlength="500"></textarea>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-email">${_('generator.contact_email')}</label>
|
|
<input type="email" id="gen-email" class="form-input" maxlength="200">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-phone">${_('generator.contact_phone')}</label>
|
|
<input type="text" id="gen-phone" class="form-input" maxlength="200">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-url">${_('generator.contact_url')}</label>
|
|
<input type="url" id="gen-url" class="form-input" maxlength="200" placeholder="https://example.com">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-logo">${_('generator.logo')}</label>
|
|
<input type="file" id="gen-logo" class="form-input" accept="image/png,image/jpeg,image/svg+xml,image/webp">
|
|
<p class="form-hint">${_('generator.logo_hint')}</p>
|
|
<button type="button" id="gen-logo-clear" class="btn btn-ghost btn-sm hidden">
|
|
<span class="material-icons">close</span>
|
|
${_('generator.logo_clear')}
|
|
</button>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-primary">${_('generator.primary_color')}</label>
|
|
<input type="color" id="gen-primary" class="form-input form-color" value="#2563eb">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-accent">${_('generator.accent_color')}</label>
|
|
<input type="color" id="gen-accent" class="form-input form-color" value="#1e293b">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row color-grid">
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-bg">${_('generator.background_color')}</label>
|
|
<input type="color" id="gen-bg" class="form-input form-color" value="#0f172a">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-surface">${_('generator.surface_color')}</label>
|
|
<input type="color" id="gen-surface" class="form-input form-color" value="#1e293b">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-text">${_('generator.text_color')}</label>
|
|
<input type="color" id="gen-text" class="form-input form-color" value="#e2e8f0">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-text-muted">${_('generator.text_muted_color')}</label>
|
|
<input type="color" id="gen-text-muted" class="form-input form-color" value="#94a3b8">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-status-ready">${_('generator.status_ready_color')}</label>
|
|
<input type="color" id="gen-status-ready" class="form-input form-color" value="#22c55e">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-header-text">${_('generator.header_text_color')}</label>
|
|
<input type="color" id="gen-header-text" class="form-input form-color" value="#ffffff">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label" for="gen-lang">${_('generator.default_lang')}</label>
|
|
<select id="gen-lang" class="form-input">
|
|
${(typeof supportedLangs !== 'undefined' ? supportedLangs : ['en', 'pl', 'zh-TW']).map(function(code) {
|
|
const label = (typeof localeLabels !== 'undefined' && localeLabels[code]) ? localeLabels[code] : code;
|
|
return '<option value="' + code + '">' + label + '</option>';
|
|
}).join('')}
|
|
</select>
|
|
</div>
|
|
<div class="form-group form-group-checkbox">
|
|
<label class="form-label">
|
|
<input type="checkbox" id="gen-unattended">
|
|
${_('generator.allow_unattended')}
|
|
</label>
|
|
<p class="form-hint">${_('generator.allow_unattended_hint')}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="gen-download-info" class="download-info hidden">
|
|
<div class="builds-section" id="gen-builds-section">
|
|
<div class="builds-section-header">
|
|
<h3 class="section-title">${_('generator.builds_title')}</h3>
|
|
<button type="button" id="gen-rebuild-btn" class="btn btn-secondary btn-sm">
|
|
<span class="material-icons">sync</span>
|
|
${_('generator.rebuild_all')}
|
|
</button>
|
|
</div>
|
|
<p class="form-hint">${_('generator.builds_hint')}</p>
|
|
<div id="gen-builds-summary" class="builds-summary hidden"></div>
|
|
<div id="gen-builds-list" class="builds-list">
|
|
<p class="text-muted">${_('generator.builds_loading')}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="section-title">${_('generator.download_link_title')}</h3>
|
|
<div class="download-link-row">
|
|
<input type="text" id="gen-download-url" class="form-input" readonly>
|
|
<button type="button" id="gen-copy-link" class="btn btn-secondary">
|
|
<span class="material-icons">content_copy</span>
|
|
${_('copy')}
|
|
</button>
|
|
<a id="gen-open-link" class="btn btn-ghost" target="_blank" rel="noopener">
|
|
<span class="material-icons">open_in_new</span>
|
|
${_('generator.open_portal')}
|
|
</a>
|
|
</div>
|
|
<p class="form-hint">${_('generator.download_link_hint')}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Live preview -->
|
|
<div class="editor-preview">
|
|
<h3 class="section-title">${_('generator.preview_title')}</h3>
|
|
<p class="form-hint">${_('generator.preview_hint')}</p>
|
|
<div class="agent-preview" id="gen-preview">
|
|
<div class="agent-preview-frame" style="--brand-primary: #2563eb; --brand-accent: #1e293b;">
|
|
<div class="ap-header">
|
|
<div class="ap-brand ap-brand-only">
|
|
<div class="ap-brand-name" id="gen-prev-name">${_('generator.preview_default_name')}</div>
|
|
<div class="ap-brand-text" id="gen-prev-text"></div>
|
|
</div>
|
|
</div>
|
|
<div class="ap-body">
|
|
<div class="ap-body-logo" id="gen-prev-body-logo">
|
|
<span class="material-icons">support_agent</span>
|
|
</div>
|
|
<div class="ap-status">
|
|
<span class="ap-status-dot"></span>
|
|
<span class="ap-status-text">${_('generator.preview_status_ready')}</span>
|
|
</div>
|
|
<div class="ap-id-row">
|
|
<span class="ap-id-label">${_('generator.preview_id')}</span>
|
|
<span class="ap-id-value">123 456 789</span>
|
|
</div>
|
|
<div class="ap-pw-row" id="gen-prev-pw-row">
|
|
<span class="ap-id-label">${_('generator.preview_password')}</span>
|
|
<span class="ap-id-value ap-pw">a B 3 # K 9</span>
|
|
</div>
|
|
<button class="ap-help" type="button" disabled>
|
|
<span class="material-icons">contact_support</span>
|
|
${_('generator.preview_help')}
|
|
</button>
|
|
<button class="ap-chat" type="button" disabled>
|
|
<span class="material-icons">chat</span>
|
|
${_('generator.preview_chat')}
|
|
</button>
|
|
</div>
|
|
<div class="ap-footer">
|
|
<button class="ap-icon-btn" type="button" disabled title="${_('generator.preview_settings')}">
|
|
<span class="material-icons">settings</span>
|
|
</button>
|
|
<div class="ap-contact" id="gen-prev-contact"></div>
|
|
<button class="ap-icon-btn" type="button" disabled title="${_('generator.preview_quit')}">
|
|
<span class="material-icons">power_settings_new</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="gen-validation-errors" class="validation-errors hidden"></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
`
|
|
}) %>
|