1+ < div class ="container-fluid ">
2+ < div class ="row ">
3+ < div class ="col-12 ">
4+ <!-- Header -->
5+ < div class ="d-flex justify-content-between align-items-center mb-4 ">
6+ < h2 >
7+ < i class ="fas fa-cogs me-2 "> </ i >
8+ {{ 'admin.update-config.title' | translate }}
9+ </ h2 >
10+ < button
11+ class ="btn btn-outline-secondary "
12+ (click) ="loadConfigFiles() "
13+ [disabled] ="loading "
14+ title ="{{ 'admin.update-config.refresh.tooltip' | translate }} ">
15+ < i class ="fas fa-sync-alt " [class.fa-spin] ="loading "> </ i >
16+ {{ 'admin.update-config.refresh' | translate }}
17+ </ button >
18+ </ div >
19+
20+ <!-- Loading indicator -->
21+ < div *ngIf ="loading && configFiles.length === 0 " class ="text-center py-4 ">
22+ < div class ="spinner-border " role ="status ">
23+ < span class ="visually-hidden "> {{ 'admin.update-config.loading' | translate }}</ span >
24+ </ div >
25+ < p class ="mt-2 "> {{ 'admin.update-config.loading-files' | translate }}</ p >
26+ </ div >
27+
28+ <!-- File Selection Card -->
29+ < div class ="card mb-4 ">
30+ < div class ="card-body ">
31+ < h5 class ="card-title ">
32+ < i class ="fas fa-folder-open me-2 "> </ i >
33+ {{ 'admin.update-config.file-selection.title' | translate }}
34+ </ h5 >
35+ < p class ="card-text text-muted ">
36+ {{ 'admin.update-config.description' | translate }}
37+ </ p >
38+
39+ < div class ="row align-items-center ">
40+ < div class ="col-md-6 ">
41+ < label for ="fileSelect " class ="form-label fw-bold ">
42+ < i class ="fas fa-file-code me-2 text-primary "> </ i >
43+ {{ 'admin.update-config.file-selection.label' | translate }}
44+ </ label >
45+ < select
46+ id ="fileSelect "
47+ class ="form-select form-select-lg "
48+ [(ngModel)] ="selectedFile "
49+ (ngModelChange) ="onFileSelect($event) "
50+ [disabled] ="loading || configFiles.length === 0 ">
51+ < option [ngValue] ="null "> {{ getFileSelectionText() }}</ option >
52+ < option *ngFor ="let file of configFiles " [ngValue] ="file ">
53+ < i class ="fas fa-file me-1 "> </ i > {{ file.fileName || '[No Name]' }}
54+ </ option >
55+ </ select >
56+ </ div >
57+ < div class ="col-md-6 " *ngIf ="selectedFile ">
58+ < div class ="file-info mt-3 mt-md-0 p-3 bg-light rounded ">
59+ < h6 class ="mb-2 ">
60+ < i class ="fas fa-info-circle text-info me-1 "> </ i >
61+ {{ 'admin.update-config.file-info.title' | translate }}
62+ </ h6 >
63+ < small class ="text-muted ">
64+ < strong > {{ 'admin.update-config.file-info.name' | translate }}:</ strong > {{ selectedFile.fileName }}< br >
65+ < strong > {{ 'admin.update-config.file-info.size' | translate }}:</ strong > {{ selectedFile.size | number }} {{ 'admin.update-config.file-info.bytes' | translate }}< br >
66+ < strong > {{ 'admin.update-config.file-info.modified' | translate }}:</ strong > {{ selectedFile.lastModified | date:'short' }}< br >
67+ < strong > {{ 'admin.update-config.file-info.status' | translate }}:</ strong >
68+ < span class ="badge bg-success "> {{ 'admin.update-config.file-info.ready' | translate }}</ span >
69+ </ small >
70+ </ div >
71+ </ div >
72+ </ div >
73+ </ div >
74+ </ div >
75+
76+ <!-- File Content Loading -->
77+ < div *ngIf ="loading && selectedFile " class ="text-center py-4 ">
78+ < div class ="spinner-border spinner-border-sm " role ="status ">
79+ < span class ="visually-hidden "> {{ 'admin.update-config.loading' | translate }}</ span >
80+ </ div >
81+ < p class ="mt-2 "> {{ 'admin.update-config.loading-content' | translate }}</ p >
82+ </ div >
83+
84+ <!-- Configuration Editor Card -->
85+ < div *ngIf ="selectedFile && !loading " class ="card ">
86+ < div class ="card-body ">
87+ < div class ="d-flex justify-content-between align-items-center mb-3 ">
88+ < h5 class ="card-title mb-0 ">
89+ < i class ="fas fa-code me-2 "> </ i >
90+ {{ 'admin.update-config.editor.title' | translate }}: {{ selectedFile.fileName }}
91+ </ h5 >
92+
93+ <!-- Action Buttons -->
94+ < div class ="d-flex flex-wrap gap-2 " role ="group ">
95+ < button
96+ class ="btn btn-outline-secondary btn-lg "
97+ (click) ="resetContent() "
98+ [disabled] ="!hasUnsavedChanges() || loading || saving "
99+ [title] ="'admin.update-config.buttons.undo.tooltip' | translate ">
100+ < i class ="fas fa-undo me-2 "> </ i >
101+ {{ 'admin.update-config.buttons.undo' | translate }}
102+ </ button >
103+ < button
104+ class ="btn btn-outline-warning btn-lg "
105+ (click) ="resetToOriginalFile() "
106+ [disabled] ="loading || saving "
107+ [title] ="'admin.update-config.buttons.reload.tooltip' | translate ">
108+ < i class ="fas fa-sync me-2 "> </ i >
109+ {{ 'admin.update-config.buttons.reload' | translate }}
110+ </ button >
111+ < button
112+ class ="btn btn-success btn-lg px-4 "
113+ (click) ="saveFile() "
114+ [disabled] ="!hasUnsavedChanges() || loading || saving "
115+ [title] ="'admin.update-config.buttons.save.tooltip' | translate ">
116+ < i class ="fas fa-save me-2 " *ngIf ="!saving "> </ i >
117+ < i class ="fas fa-spinner fa-spin me-2 " *ngIf ="saving "> </ i >
118+ < strong > {{ saving ? ('admin.update-config.buttons.saving' | translate) : ('admin.update-config.buttons.save' | translate) }}</ strong >
119+ </ button >
120+ </ div >
121+ </ div >
122+
123+ <!-- Config File Editor Notice -->
124+ < div class ="alert alert-info mb-3 d-flex align-items-center ">
125+ < i class ="fas fa-cogs me-2 text-primary "> </ i >
126+ < div >
127+ < strong > {{ 'admin.update-config.editor.notice.title' | translate }}</ strong > < br >
128+ < small > {{ 'admin.update-config.editor.notice.description' | translate:{ fileName: selectedFile?.fileName } }}</ small >
129+ </ div >
130+ </ div >
131+
132+ < div class ="mb-3 ">
133+ < div *ngIf ="hasUnsavedChanges() " class ="alert alert-warning py-2 ">
134+ < i class ="fas fa-edit me-1 "> </ i >
135+ {{ 'admin.update-config.validation.unsaved-changes' | translate }}
136+ </ div >
137+ </ div >
138+
139+ <!-- Text Editor -->
140+ < div class ="position-relative ">
141+ < label for ="xmlContent " class ="form-label ">
142+ {{ 'admin.update-config.editor.content' | translate }}
143+ </ label >
144+ < textarea
145+ id ="xmlContent "
146+ class ="form-control font-monospace config-editor "
147+ [(ngModel)] ="fileContent "
148+ (ngModelChange) ="onContentChange() "
149+ placeholder ="{{ 'admin.update-config.editor.placeholder' | translate }} "
150+ rows ="25 "
151+ [disabled] ="saving "
152+ spellcheck ="false ">
153+ </ textarea >
154+
155+ <!-- Character count -->
156+ < small class ="text-muted position-absolute " style ="bottom: 10px; right: 15px; background: rgba(255,255,255,0.8); padding: 2px 6px; border-radius: 3px; ">
157+ {{ fileContent.length }} {{ 'admin.update-config.editor.characters' | translate }}
158+ </ small >
159+ </ div >
160+ </ div >
161+ </ div >
162+
163+
164+ </ div >
165+ </ div >
166+ </ div >
0 commit comments