main
html 255 lines 9.28 KB
Raw
1 <html>
2 <head>
3 <title>Restore Backup</title>
4 <script type="module">
5 import { store } from "/components/settings/backup/backup-store.js";
6 </script>
7 </head>
8 <body>
9 <div x-data>
10 <template x-if="$store.backupStore">
11 <div x-init="$store.backupStore.initRestore()" x-destroy="$store.backupStore.onClose()">
12
13 <!-- File Upload Section -->
14 <div class="upload-section">
15 <label for="backup-file" class="upload-label">
16 Select Backup File (.zip)
17 </label>
18 <input type="file" id="backup-file" accept=".zip"
19 @change="$store.backupStore.handleFileUpload($event)">
20 </div>
21
22 <!-- Warning Message (only show when backup file is loaded) -->
23 <div x-show="$store.backupStore.backupMetadata" class="restore-warning">
24 <span class="warning-icon">⚠️</span>
25 <span class="warning-text">After restoring a backup you will have to restart Agent-Zero to fully load the backed-up configuration (button in the left pane).</span>
26 <span class="warning-icon">⚠️</span>
27 </div>
28
29 <!-- File Conflict Policy (Dropdown) -->
30 <div x-show="$store.backupStore.backupMetadata" class="overwrite-policy">
31 <label class="policy-label">
32 <span class="policy-label-text">File Conflict Policy:</span>
33 <select x-model="$store.backupStore.overwritePolicy" class="policy-dropdown">
34 <option value="overwrite">Overwrite existing files</option>
35 <option value="skip">Skip existing files</option>
36 <option value="backup">Backup existing files (.backup.timestamp)</option>
37 </select>
38 </label>
39 </div>
40
41 <!-- Clean Before Restore Option -->
42 <div x-show="$store.backupStore.backupMetadata" class="clean-before-restore">
43 <label class="checkbox-label">
44 <input type="checkbox" x-model="$store.backupStore.cleanBeforeRestore">
45 <span class="checkbox-text">Clean before restore (delete existing files matching original backup patterns)</span>
46 </label>
47 <div class="clean-description">
48 When enabled, all existing files matching the original backup patterns will be deleted before restoring files from the archive. This ensures a completely clean restore state.
49 </div>
50 </div>
51
52 <!-- Loading indicator -->
53 <div x-show="$store.backupStore.loading" class="restore-loading">
54 <span x-text="$store.backupStore.loadingMessage || 'Processing...'"></span>
55 </div>
56
57 <!-- Error display -->
58 <div x-show="$store.backupStore.error" class="restore-error">
59 <span x-text="$store.backupStore.error"></span>
60 </div>
61
62 <!-- Success display -->
63 <div x-show="$store.backupStore.restoreResult" class="restore-result">
64 <h4>Restore Complete</h4>
65 <div class="result-stats">
66 <div x-show="$store.backupStore.restoreResult?.deleted_files?.length > 0">Deleted: <span x-text="$store.backupStore.restoreResult?.deleted_files?.length || 0"></span></div>
67 <div>Restored: <span x-text="$store.backupStore.restoreResult?.restored_files?.length || 0"></span></div>
68 <div>Skipped: <span x-text="$store.backupStore.restoreResult?.skipped_files?.length || 0"></span></div>
69 <div>Errors: <span x-text="$store.backupStore.restoreResult?.errors?.length || 0"></span></div>
70 </div>
71 </div>
72
73 <!-- Header with buttons (following MCP servers pattern) -->
74 <h3 x-show="$store.backupStore.backupMetadata">Restore Configuration JSON
75 <button class="btn slim" style="margin-left: 0.5em;"
76 @click="$store.backupStore.formatJson()">Format</button>
77 <button class="btn slim" style="margin-left: 0.5em;"
78 @click="$store.backupStore.resetToOriginalMetadata()">Reset</button>
79 <button class="btn slim" style="margin-left: 0.5em;"
80 @click="$store.backupStore.dryRun()" :disabled="$store.backupStore.loading">Dry Run</button>
81 <button class="btn slim primary" style="margin-left: 0.5em;"
82 @click="$store.backupStore.performRestore()" :disabled="$store.backupStore.loading">Restore Files</button>
83 </h3>
84
85 <!-- JSON Editor (upper part) -->
86 <div x-show="$store.backupStore.backupMetadata" id="restore-metadata-editor"></div>
87
88 <!-- File Operations Display (lower part) -->
89 <h3 x-show="$store.backupStore.backupMetadata" id="restore-operations">File Operations</h3>
90
91 <!-- File listing textarea -->
92 <div x-show="$store.backupStore.backupMetadata" class="file-operations-container">
93 <textarea id="restore-file-list"
94 x-model="$store.backupStore.fileOperationsLog"
95 readonly
96 placeholder="File operations will be displayed here..."></textarea>
97 </div>
98
99 </div>
100 </template>
101 </div>
102
103 <style>
104 .upload-section {
105 margin-bottom: 1.5rem;
106 padding: 1rem;
107 border: 2px dashed var(--color-border);
108 border-radius: 4px;
109 text-align: center;
110 }
111
112 .upload-label {
113 display: block;
114 margin-bottom: 0.5rem;
115 font-weight: 600;
116 }
117
118 .restore-loading {
119 width: 100%;
120 text-align: center;
121 margin-top: 2rem;
122 margin-bottom: 2rem;
123 color: var(--color-secondary);
124 }
125
126 #restore-metadata-editor {
127 width: 100%;
128 height: 25em;
129 }
130
131 .file-operations-container {
132 margin-top: 0.5em;
133 margin-bottom: 1em;
134 }
135
136 #restore-file-list {
137 width: 100%;
138 height: 15em;
139 font-family: monospace;
140 font-size: 0.85em;
141 background: var(--color-input);
142 color: var(--color-text);
143 border: 1px solid var(--color-border);
144 border-radius: 4px;
145 padding: 0.5em;
146 resize: vertical;
147 }
148
149 .overwrite-policy {
150 margin: 1rem 0;
151 }
152
153 .policy-label {
154 display: flex;
155 align-items: center;
156 gap: 0.5rem;
157 margin: 0.5rem 0;
158 }
159
160 .clean-before-restore {
161 margin: 1rem 0;
162 padding: 0.75rem;
163 background: var(--color-input);
164 border: 1px solid var(--color-border);
165 border-radius: 4px;
166 }
167
168 .checkbox-label {
169 display: flex;
170 align-items: center;
171 gap: 0.5rem;
172 margin-bottom: 0.5rem;
173 cursor: pointer;
174 }
175
176 .checkbox-label input[type="checkbox"] {
177 width: 1rem;
178 height: 1rem;
179 }
180
181 .checkbox-text {
182 font-weight: 600;
183 color: var(--color-text);
184 }
185
186 .clean-description {
187 font-size: 0.85rem;
188 color: var(--color-secondary);
189 line-height: 1.4;
190 margin-left: 1.5rem;
191 }
192
193 .policy-label-text {
194 font-weight: 600;
195 white-space: nowrap;
196 }
197
198 .policy-dropdown {
199 flex: 1;
200 padding: 0.5rem;
201 border: 1px solid var(--color-border);
202 border-radius: 4px;
203 background: var(--color-input);
204 color: var(--color-text);
205 font-size: 0.9rem;
206 }
207
208 .restore-error {
209 color: var(--color-error);
210 margin: 0.5rem 0;
211 padding: 0.5rem;
212 background: var(--color-input);
213 border: 1px solid var(--color-error);
214 border-radius: 4px;
215 }
216
217 .restore-result {
218 margin: 1rem 0;
219 padding: 1rem;
220 background: var(--color-secondary);
221 border-radius: 4px;
222 }
223
224 .result-stats {
225 display: flex;
226 gap: 1rem;
227 margin-top: 0.5rem;
228 }
229
230 .restore-warning {
231 display: flex;
232 align-items: center;
233 justify-content: center;
234 margin: 1rem 0;
235 padding: 1rem;
236 background: var(--color-background);
237 border: 2px solid #f1c40f;
238 border-radius: 4px;
239 color: var(--color-text);
240 }
241
242 .warning-icon {
243 font-size: 1.2em;
244 margin: 0 1rem;
245 color: #f39c12;
246 }
247
248 .warning-text {
249 text-align: center;
250 font-weight: 500;
251 flex: 1;
252 }
253 </style>
254 </body>
255 </html>