Adopt the shopdb-flask visual language across the PXE webapp (presentation only, Flask/Jinja logic unchanged): - New static/pxe-theme.css: GE Aerospace palette (atmosphere-blue sidebar, sky-blue primary, avionics-green), Inter font stack, light/dark theming via data-theme + localStorage (key pxe-theme) with system-pref fallback, and card/button/table/form/badge/alert component styles layered over Bootstrap. - base.html: shopdb-style sidebar (logo + title, nav sections, footer light/dark toggle) + theme boot script. - All 13 content templates restyled to the new page-header + card/table/badge vocabulary; unattend_editor grouped per unattend-UX research. - Fixed a pre-existing CRITICAL bug found during review: nested <form>s in image_config.html made Adopt submit the delete form and Delete-selected post every orphan filename regardless of checkboxes; split into standalone forms wired via the form= attribute. Built by a Fable-orchestrated Opus workflow (17 agents). All 14 templates parse clean under Jinja2.
571 lines
23 KiB
HTML
571 lines
23 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}{{ friendly_name }} - Unattend Editor{% endblock %}
|
|
|
|
{% block extra_head %}
|
|
<style>
|
|
/* Group dividers that organize the sections in configuration-pass order */
|
|
.group-heading {
|
|
font-size: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1.5px;
|
|
font-weight: 600;
|
|
color: var(--text-light);
|
|
margin: 1.9rem 0 0.9rem;
|
|
padding-bottom: 0.4rem;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
.group-heading:first-of-type { margin-top: 0.5rem; }
|
|
.group-heading .bi { color: var(--primary); }
|
|
|
|
/* Command-list feedback while dragging to reorder */
|
|
.command-table tbody tr { transition: background-color 0.15s; }
|
|
.command-table tbody tr.dragging {
|
|
opacity: 0.5;
|
|
background-color: rgba(65, 129, 255, 0.12);
|
|
}
|
|
|
|
.raw-xml-editor {
|
|
font-family: 'SF Mono', 'Consolas', 'Monaco', 'Courier New', monospace;
|
|
font-size: 0.85rem;
|
|
min-height: 600px;
|
|
height: 70vh;
|
|
tab-size: 2;
|
|
white-space: pre;
|
|
resize: vertical;
|
|
}
|
|
|
|
.order-num {
|
|
width: 40px;
|
|
text-align: center;
|
|
font-weight: 600;
|
|
color: var(--text-light);
|
|
}
|
|
.drag-handle { text-align: center; user-select: none; }
|
|
|
|
/* Count pill sitting next to a card title */
|
|
.count-pill {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
background: var(--bg);
|
|
color: var(--text-light);
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
padding: 1px 9px;
|
|
}
|
|
.card-header .title-group { display: flex; align-items: center; gap: 0.5rem; font-weight: 600; }
|
|
.card-header .title-group .bi { color: var(--primary); }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="page-header">
|
|
<div>
|
|
<h1>{{ friendly_name }}</h1>
|
|
<small class="mono" style="color: var(--text-light);">{{ image_type }}/Deploy/FlatUnattendW10.xml</small>
|
|
</div>
|
|
<div class="header-actions">
|
|
<button type="button" class="btn btn-success" id="saveFormBtn">
|
|
<i class="bi bi-floppy"></i> Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form / Raw XML toggle (ids read by app.js) -->
|
|
<ul class="nav nav-tabs editor-tabs mb-3" role="tablist">
|
|
<li class="nav-item">
|
|
<a class="nav-link active" id="form-tab" data-bs-toggle="tab"
|
|
href="#formView" role="tab">
|
|
<i class="bi bi-ui-checks-grid"></i> Form Editor
|
|
</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" id="raw-tab" data-bs-toggle="tab"
|
|
href="#rawView" role="tab">
|
|
<i class="bi bi-code-slash"></i> Raw XML
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<form method="POST" id="unattendForm">
|
|
<input type="hidden" name="_csrf_token" value="{{ csrf_token() }}">
|
|
<div class="tab-content">
|
|
|
|
<!-- ==================== FORM VIEW ==================== -->
|
|
<div class="tab-pane fade show active" id="formView" role="tabpanel">
|
|
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle"></i>
|
|
Edit this image's answer file below. Fields are grouped by Windows setup stage.
|
|
The <strong>Form Editor</strong> is the source of truth; switch to <strong>Raw XML</strong>
|
|
only for changes the form does not cover.
|
|
</div>
|
|
|
|
<!-- ============= GROUP 1: SYSTEM & REGIONAL ============= -->
|
|
<div class="group-heading"><i class="bi bi-pc-display-horizontal"></i> System & Regional</div>
|
|
|
|
<!-- Machine Settings -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group"><i class="bi bi-hdd-network"></i> Machine Settings</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Computer Name</label>
|
|
<input type="text" class="form-control" name="computer_name"
|
|
value="{{ data.computer_name }}" placeholder="* (auto-generate)">
|
|
<div class="form-text">Use <code>*</code> to let Windows auto-generate a name.</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Time Zone</label>
|
|
<input type="text" class="form-control" name="time_zone"
|
|
value="{{ data.time_zone }}" placeholder="Eastern Standard Time">
|
|
<div class="form-text">Applied during the specialize pass.</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Registered Organization</label>
|
|
<input type="text" class="form-control" name="registered_organization"
|
|
value="{{ data.registered_organization }}" placeholder="GE Aerospace">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Registered Owner</label>
|
|
<input type="text" class="form-control" name="registered_owner"
|
|
value="{{ data.registered_owner }}" placeholder="GE Aerospace">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- International Settings (collapsible) -->
|
|
<div class="card">
|
|
<div class="card-header" data-bs-toggle="collapse" data-bs-target="#intlCollapse"
|
|
role="button" style="cursor:pointer">
|
|
<span class="title-group"><i class="bi bi-globe2"></i> International Settings</span>
|
|
<small style="color: var(--text-light);"><i class="bi bi-chevron-expand"></i> click to expand</small>
|
|
</div>
|
|
<div class="collapse {% if data.intl.input_locale or data.intl.system_locale or data.intl.ui_language or data.intl.user_locale %}show{% endif %}"
|
|
id="intlCollapse">
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-3">
|
|
<label class="form-label">Input Locale</label>
|
|
<input type="text" class="form-control" name="intl_input_locale"
|
|
value="{{ data.intl.input_locale }}" placeholder="e.g. en-US">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">System Locale</label>
|
|
<input type="text" class="form-control" name="intl_system_locale"
|
|
value="{{ data.intl.system_locale }}" placeholder="e.g. en-US">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">UI Language</label>
|
|
<input type="text" class="form-control" name="intl_ui_language"
|
|
value="{{ data.intl.ui_language }}" placeholder="e.g. en-US">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">User Locale</label>
|
|
<input type="text" class="form-control" name="intl_user_locale"
|
|
value="{{ data.intl.user_locale }}" placeholder="e.g. en-US">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Driver Paths -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group">
|
|
<i class="bi bi-usb-drive"></i> Driver Paths
|
|
<span class="count-pill">{{ data.driver_paths|length }}</span>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="addDriverPath">
|
|
<i class="bi bi-plus-lg"></i> Add
|
|
</button>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-container">
|
|
<table class="table table-sm mb-0 align-middle" id="driverPathsTable">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">#</th>
|
|
<th>Path</th>
|
|
<th style="width:60px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for dp in data.driver_paths %}
|
|
<tr>
|
|
<td class="order-num">{{ loop.index }}</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm mono"
|
|
name="driver_path[]" value="{{ dp }}">
|
|
</td>
|
|
<td>
|
|
<button type="button" class="btn btn-outline-danger btn-row-action remove-row" title="Remove">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if not data.driver_paths %}
|
|
<div class="text-center py-3 empty-message" id="driverPathsEmpty" style="color: var(--text-light);">
|
|
No driver paths configured. Click <strong>Add</strong> to add one.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============= GROUP 2: ACCOUNTS & SIGN-IN ============= -->
|
|
<div class="group-heading"><i class="bi bi-people"></i> Accounts & Sign-in</div>
|
|
|
|
<!-- User Accounts -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group">
|
|
<i class="bi bi-person-badge"></i> User Accounts (Local)
|
|
<span class="count-pill">{{ data.user_accounts|length }}</span>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="addUserAccount">
|
|
<i class="bi bi-plus-lg"></i> Add
|
|
</button>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-container">
|
|
<table class="table table-sm mb-0 align-middle" id="userAccountsTable">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:40px">#</th>
|
|
<th>Name</th>
|
|
<th>Password</th>
|
|
<th>Group</th>
|
|
<th>Display Name</th>
|
|
<th style="width:60px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for acct in data.user_accounts %}
|
|
<tr>
|
|
<td class="order-num">{{ loop.index }}</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="account_name_{{ loop.index0 }}" value="{{ acct.name }}">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="account_password_{{ loop.index0 }}" value="{{ acct.password }}">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="account_group_{{ loop.index0 }}" value="{{ acct.group }}">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="account_display_{{ loop.index0 }}" value="{{ acct.display_name }}">
|
|
</td>
|
|
<td>
|
|
<input type="hidden" name="account_plaintext_{{ loop.index0 }}" value="{{ acct.plain_text }}">
|
|
<button type="button" class="btn btn-outline-danger btn-row-action remove-account-row" title="Remove">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if not data.user_accounts %}
|
|
<div class="text-center py-3 empty-message" id="userAccountsEmpty" style="color: var(--text-light);">
|
|
No local accounts configured. Click <strong>Add</strong> to add one.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-footer">
|
|
<small style="color: var(--text-light);">
|
|
<i class="bi bi-shield-lock"></i> Passwords are stored in the answer file. Handle this image config as sensitive.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- AutoLogon -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group"><i class="bi bi-box-arrow-in-right"></i> AutoLogon</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3 align-items-end">
|
|
<div class="col-md-3">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="autologonEnabledToggle"
|
|
{% if data.autologon.enabled|lower == 'true' %}checked{% endif %}>
|
|
<label class="form-check-label" for="autologonEnabledToggle">Enabled</label>
|
|
<input type="hidden" name="autologon_enabled" id="autologon_enabled_val"
|
|
value="{{ data.autologon.enabled }}">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Username</label>
|
|
<input type="text" class="form-control" name="autologon_username"
|
|
value="{{ data.autologon.username }}" placeholder="e.g. SupportUser">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Password</label>
|
|
<input type="text" class="form-control" name="autologon_password"
|
|
value="{{ data.autologon.password }}">
|
|
<input type="hidden" name="autologon_plaintext" value="{{ data.autologon.plain_text }}">
|
|
</div>
|
|
<div class="col-md-3">
|
|
<label class="form-label">Logon Count</label>
|
|
<input type="text" class="form-control" name="autologon_logoncount"
|
|
value="{{ data.autologon.logon_count }}" placeholder="e.g. 2 or 999">
|
|
<div class="form-text">Number of auto-logon attempts.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============= GROUP 3: OUT-OF-BOX EXPERIENCE ============= -->
|
|
<div class="group-heading"><i class="bi bi-window-desktop"></i> Out-of-Box Experience (OOBE)</div>
|
|
|
|
<!-- OOBE Settings -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group"><i class="bi bi-toggles"></i> OOBE Settings</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
{% set bool_oobe_fields = [
|
|
("HideEULAPage", "Hide EULA Page"),
|
|
("HideOEMRegistrationScreen", "Hide OEM Registration Screen"),
|
|
("HideOnlineAccountScreens", "Hide Online Account Screens"),
|
|
("HideWirelessSetupInOOBE", "Hide Wireless Setup in OOBE"),
|
|
("HideLocalAccountScreen", "Hide Local Account Screen"),
|
|
("SkipUserOOBE", "Skip User OOBE"),
|
|
("SkipMachineOOBE", "Skip Machine OOBE"),
|
|
] %}
|
|
{% for key, label in bool_oobe_fields %}
|
|
<div class="col-md-4">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input oobe-toggle" type="checkbox"
|
|
id="oobe_{{ key }}"
|
|
data-field="oobe_{{ key }}"
|
|
{% if data.oobe[key]|lower == 'true' %}checked{% endif %}>
|
|
<label class="form-check-label" for="oobe_{{ key }}">{{ label }}</label>
|
|
<input type="hidden" name="oobe_{{ key }}" id="oobe_{{ key }}_val"
|
|
value="{{ data.oobe[key] }}">
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
<div class="col-md-4">
|
|
<label class="form-label">Network Location</label>
|
|
<select class="form-select form-select-sm" name="oobe_NetworkLocation">
|
|
{% for opt in ["Home", "Work", "Other"] %}
|
|
<option value="{{ opt }}" {% if data.oobe.NetworkLocation == opt %}selected{% endif %}>
|
|
{{ opt }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label">ProtectYourPC</label>
|
|
<select class="form-select form-select-sm" name="oobe_ProtectYourPC">
|
|
{% for opt in ["1", "2", "3"] %}
|
|
<option value="{{ opt }}" {% if data.oobe.ProtectYourPC == opt %}selected{% endif %}>
|
|
{{ opt }}{% if opt == "1" %} (Recommended){% elif opt == "3" %} (Skip){% endif %}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
<div class="form-text">1 = Recommended, 2 = Install only updates, 3 = Skip</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- OOBE Time Zone -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group"><i class="bi bi-clock-history"></i> OOBE Time Zone</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Time Zone (oobeSystem pass)</label>
|
|
<input type="text" class="form-control" name="oobe_timezone"
|
|
value="{{ data.oobe_timezone }}" placeholder="e.g. Eastern Standard Time">
|
|
<div class="form-text">Separate from the specialize-pass time zone in Machine Settings above.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============= GROUP 4: SETUP COMMANDS ============= -->
|
|
<div class="group-heading"><i class="bi bi-terminal"></i> Setup Commands (RunSynchronous)</div>
|
|
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
These commands run as a validated golden sequence. <strong>Order matters within each list.</strong>
|
|
Reorder with the arrows or by dragging the <i class="bi bi-grip-vertical"></i> handle only when you are sure.
|
|
</div>
|
|
|
|
<!-- Specialize Commands -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group">
|
|
<i class="bi bi-gear-wide-connected"></i> Specialize Commands
|
|
<span class="count-pill">{{ data.specialize_commands|length }}</span>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="addSpecCmd">
|
|
<i class="bi bi-plus-lg"></i> Add
|
|
</button>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-container">
|
|
<table class="table table-sm mb-0 align-middle command-table" id="specCmdTable">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:30px"></th>
|
|
<th style="width:50px">Order</th>
|
|
<th>Path / Command</th>
|
|
<th>Description</th>
|
|
<th style="width:120px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for cmd in data.specialize_commands %}
|
|
<tr draggable="true">
|
|
<td class="drag-handle"><i class="bi bi-grip-vertical"></i></td>
|
|
<td class="order-num">{{ loop.index }}</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm mono"
|
|
name="spec_cmd_path[]" value="{{ cmd.path }}">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="spec_cmd_desc[]" value="{{ cmd.description }}">
|
|
</td>
|
|
<td class="text-nowrap">
|
|
<button type="button" class="btn btn-outline-secondary btn-row-action move-up" title="Move up">
|
|
<i class="bi bi-arrow-up"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-row-action move-down" title="Move down">
|
|
<i class="bi bi-arrow-down"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-outline-danger btn-row-action remove-row" title="Remove">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if not data.specialize_commands %}
|
|
<div class="text-center py-3 empty-message" id="specCmdEmpty" style="color: var(--text-light);">
|
|
No specialize commands configured. Click <strong>Add</strong> to add one.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- First Logon Commands -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group">
|
|
<i class="bi bi-play-circle"></i> First Logon Commands
|
|
<span class="count-pill">{{ data.firstlogon_commands|length }}</span>
|
|
</span>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" id="addFlCmd">
|
|
<i class="bi bi-plus-lg"></i> Add
|
|
</button>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-container">
|
|
<table class="table table-sm mb-0 align-middle command-table" id="flCmdTable">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:30px"></th>
|
|
<th style="width:50px">Order</th>
|
|
<th>Command Line</th>
|
|
<th>Description</th>
|
|
<th style="width:120px"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for cmd in data.firstlogon_commands %}
|
|
<tr draggable="true">
|
|
<td class="drag-handle"><i class="bi bi-grip-vertical"></i></td>
|
|
<td class="order-num">{{ loop.index }}</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm mono"
|
|
name="fl_cmd_commandline[]" value="{{ cmd.commandline }}">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm"
|
|
name="fl_cmd_desc[]" value="{{ cmd.description }}">
|
|
</td>
|
|
<td class="text-nowrap">
|
|
<button type="button" class="btn btn-outline-secondary btn-row-action move-up" title="Move up">
|
|
<i class="bi bi-arrow-up"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-outline-secondary btn-row-action move-down" title="Move down">
|
|
<i class="bi bi-arrow-down"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-outline-danger btn-row-action remove-row" title="Remove">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if not data.firstlogon_commands %}
|
|
<div class="text-center py-3 empty-message" id="flCmdEmpty" style="color: var(--text-light);">
|
|
No first logon commands configured. Click <strong>Add</strong> to add one.
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- end formView -->
|
|
|
|
<!-- ==================== RAW XML VIEW ==================== -->
|
|
<div class="tab-pane fade" id="rawView" role="tabpanel">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<span class="title-group"><i class="bi bi-filetype-xml"></i> Raw XML</span>
|
|
<button type="button" class="btn btn-sm btn-success" id="saveRawBtn">
|
|
<i class="bi bi-floppy"></i> Save Raw XML
|
|
</button>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
Editing raw XML bypasses the form. Save here to write your changes directly.
|
|
</div>
|
|
<textarea class="form-control raw-xml-editor" name="raw_xml"
|
|
id="rawXmlEditor">{{ data.raw_xml }}</textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- end tab-content -->
|
|
|
|
<input type="hidden" name="save_mode" id="saveMode" value="form">
|
|
</form>
|
|
{% endblock %}
|
|
|
|
{% block extra_scripts %}
|
|
<script>
|
|
// Pass the image_type and API URL to JavaScript
|
|
window.PXE_IMAGE_TYPE = "{{ image_type }}";
|
|
window.PXE_API_URL = "{{ url_for('api_save_unattend', image_type=image_type) }}";
|
|
</script>
|
|
{% endblock %}
|