@leadertechie/personal-site-kit 0.1.0-alpha.4 → 0.1.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/handlers/auth-handler.d.ts +2 -0
- package/dist/api/handlers/auth-handler.d.ts.map +1 -0
- package/dist/api/handlers/auth.d.ts +23 -0
- package/dist/api/handlers/auth.d.ts.map +1 -0
- package/dist/api/handlers/content.d.ts.map +1 -1
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/website-api.d.ts +1 -1
- package/dist/api/website-api.d.ts.map +1 -1
- package/dist/api.js +17 -2
- package/dist/chunks/{index-VimKeB5W.js → index-C3wLSCKU.js} +236 -93
- package/dist/chunks/{website-api-CVsi-OLc.js → website-api-DI3muo2s.js} +335 -23
- package/dist/index.js +27 -13
- package/dist/ui/admin/index.d.ts +12 -3
- package/dist/ui/admin/index.d.ts.map +1 -1
- package/dist/ui.js +1 -1
- package/package.json +1 -1
- package/src/api/handlers/auth-handler.ts +181 -0
- package/src/api/handlers/auth.ts +157 -0
- package/src/api/handlers/content.ts +81 -14
- package/src/api/index.ts +2 -0
- package/src/api/website-api.ts +22 -16
- package/src/ui/admin/index.ts +254 -91
package/src/ui/admin/index.ts
CHANGED
|
@@ -3,8 +3,6 @@ import { customElement, state } from 'lit/decorators.js';
|
|
|
3
3
|
|
|
4
4
|
import { adminStyles } from './styles';
|
|
5
5
|
|
|
6
|
-
console.log('[AdminPortal] Module loading');
|
|
7
|
-
|
|
8
6
|
interface ContentItem {
|
|
9
7
|
key: string;
|
|
10
8
|
size: number;
|
|
@@ -19,17 +17,23 @@ interface StaticDetails {
|
|
|
19
17
|
email?: string;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
interface AuthStatus {
|
|
21
|
+
configured: boolean;
|
|
22
|
+
username: string | null;
|
|
23
|
+
}
|
|
23
24
|
|
|
24
25
|
@customElement('admin-portal')
|
|
25
26
|
export class AdminPortal extends LitElement {
|
|
26
27
|
static styles = adminStyles;
|
|
27
28
|
|
|
28
29
|
@state()
|
|
29
|
-
accessor
|
|
30
|
+
accessor isAuthenticated = false;
|
|
30
31
|
|
|
31
32
|
@state()
|
|
32
|
-
accessor
|
|
33
|
+
accessor isSetup = false;
|
|
34
|
+
|
|
35
|
+
@state()
|
|
36
|
+
accessor isLoading = true;
|
|
33
37
|
|
|
34
38
|
@state()
|
|
35
39
|
accessor contentList: ContentItem[] = [];
|
|
@@ -43,26 +47,157 @@ export class AdminPortal extends LitElement {
|
|
|
43
47
|
@state()
|
|
44
48
|
accessor staticDetails: StaticDetails = {};
|
|
45
49
|
|
|
50
|
+
@state()
|
|
51
|
+
accessor loginError = '';
|
|
52
|
+
|
|
46
53
|
get apiUrl() {
|
|
47
54
|
return (window as any).__VITE_API_URL__ || import.meta.env.VITE_API_URL || 'http://localhost:8787';
|
|
48
55
|
}
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
async connectedCallback() {
|
|
58
|
+
super.connectedCallback();
|
|
59
|
+
await this.checkAuthStatus();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async checkAuthStatus() {
|
|
63
|
+
try {
|
|
64
|
+
const res = await fetch(`${this.apiUrl}/auth/status`, {
|
|
65
|
+
credentials: 'include'
|
|
66
|
+
});
|
|
67
|
+
if (res.ok) {
|
|
68
|
+
const status: AuthStatus = await res.json();
|
|
69
|
+
this.isSetup = status.configured;
|
|
70
|
+
|
|
71
|
+
if (status.configured) {
|
|
72
|
+
await this.tryAutoLogin();
|
|
73
|
+
} else {
|
|
74
|
+
this.isLoading = false;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
this.isSetup = false;
|
|
78
|
+
this.isLoading = false;
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
this.isSetup = false;
|
|
82
|
+
this.isLoading = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async tryAutoLogin() {
|
|
87
|
+
try {
|
|
88
|
+
const res = await fetch(`${this.apiUrl}/content`, {
|
|
89
|
+
credentials: 'include'
|
|
90
|
+
});
|
|
91
|
+
if (res.ok) {
|
|
92
|
+
this.contentList = await res.json();
|
|
93
|
+
this.isAuthenticated = true;
|
|
94
|
+
}
|
|
95
|
+
} catch (e) {}
|
|
96
|
+
this.isLoading = false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async handleLogin(e: Event) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
this.loginError = '';
|
|
102
|
+
|
|
103
|
+
const usernameInput = this.shadowRoot?.querySelector('#username') as HTMLInputElement;
|
|
104
|
+
const passwordInput = this.shadowRoot?.querySelector('#password') as HTMLInputElement;
|
|
105
|
+
|
|
106
|
+
if (!usernameInput?.value || !passwordInput?.value) {
|
|
107
|
+
this.loginError = 'Username and password required';
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
const res = await fetch(`${this.apiUrl}/auth/login`, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
credentials: 'include',
|
|
115
|
+
headers: { 'Content-Type': 'application/json' },
|
|
116
|
+
body: JSON.stringify({
|
|
117
|
+
username: usernameInput.value,
|
|
118
|
+
password: passwordInput.value
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (res.ok) {
|
|
123
|
+
this.isAuthenticated = true;
|
|
124
|
+
await this.fetchContent();
|
|
125
|
+
} else {
|
|
126
|
+
const data = await res.json();
|
|
127
|
+
this.loginError = data.error || 'Login failed';
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
this.loginError = 'Connection error';
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async handleSetup(e: Event) {
|
|
51
135
|
e.preventDefault();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
136
|
+
this.loginError = '';
|
|
137
|
+
|
|
138
|
+
const usernameInput = this.shadowRoot?.querySelector('#username') as HTMLInputElement;
|
|
139
|
+
const passwordInput = this.shadowRoot?.querySelector('#password') as HTMLInputElement;
|
|
140
|
+
const confirmInput = this.shadowRoot?.querySelector('#confirmPassword') as HTMLInputElement;
|
|
141
|
+
|
|
142
|
+
if (!usernameInput?.value || !passwordInput?.value) {
|
|
143
|
+
this.loginError = 'Username and password required';
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (usernameInput.value.length < 3) {
|
|
148
|
+
this.loginError = 'Username must be at least 3 characters';
|
|
149
|
+
return;
|
|
57
150
|
}
|
|
151
|
+
|
|
152
|
+
if (passwordInput.value.length < 8) {
|
|
153
|
+
this.loginError = 'Password must be at least 8 characters';
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (passwordInput.value !== confirmInput?.value) {
|
|
158
|
+
this.loginError = 'Passwords do not match';
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const res = await fetch(`${this.apiUrl}/auth/setup`, {
|
|
164
|
+
method: 'POST',
|
|
165
|
+
credentials: 'include',
|
|
166
|
+
headers: { 'Content-Type': 'application/json' },
|
|
167
|
+
body: JSON.stringify({
|
|
168
|
+
username: usernameInput.value,
|
|
169
|
+
password: passwordInput.value
|
|
170
|
+
})
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (res.ok) {
|
|
174
|
+
this.isAuthenticated = true;
|
|
175
|
+
this.isSetup = true;
|
|
176
|
+
await this.fetchContent();
|
|
177
|
+
} else {
|
|
178
|
+
const data = await res.json();
|
|
179
|
+
this.loginError = data.error || 'Setup failed';
|
|
180
|
+
}
|
|
181
|
+
} catch (e) {
|
|
182
|
+
this.loginError = 'Connection error';
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async handleLogout() {
|
|
187
|
+
try {
|
|
188
|
+
await fetch(`${this.apiUrl}/auth/logout`, {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
credentials: 'include'
|
|
191
|
+
});
|
|
192
|
+
} catch (e) {}
|
|
193
|
+
this.isAuthenticated = false;
|
|
194
|
+
this.contentList = [];
|
|
58
195
|
}
|
|
59
196
|
|
|
60
197
|
async fetchContent() {
|
|
61
198
|
try {
|
|
62
199
|
const res = await fetch(`${this.apiUrl}/content`, {
|
|
63
|
-
|
|
64
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
65
|
-
}
|
|
200
|
+
credentials: 'include'
|
|
66
201
|
});
|
|
67
202
|
if (res.ok) {
|
|
68
203
|
this.contentList = await res.json();
|
|
@@ -76,13 +211,13 @@ export class AdminPortal extends LitElement {
|
|
|
76
211
|
|
|
77
212
|
async fetchStaticDetails() {
|
|
78
213
|
try {
|
|
79
|
-
const res = await fetch(`${this.apiUrl}/
|
|
214
|
+
const res = await fetch(`${this.apiUrl}/static`, {
|
|
215
|
+
credentials: 'include'
|
|
216
|
+
});
|
|
80
217
|
if (res.ok) {
|
|
81
218
|
this.staticDetails = await res.json();
|
|
82
219
|
}
|
|
83
|
-
} catch (e) {
|
|
84
|
-
// Ignore errors
|
|
85
|
-
}
|
|
220
|
+
} catch (e) {}
|
|
86
221
|
}
|
|
87
222
|
|
|
88
223
|
async handleUpload(key: string, file: File) {
|
|
@@ -90,9 +225,7 @@ export class AdminPortal extends LitElement {
|
|
|
90
225
|
this.statusMessage = 'Uploading...';
|
|
91
226
|
const res = await fetch(`${this.apiUrl}/content/${key}`, {
|
|
92
227
|
method: 'PUT',
|
|
93
|
-
|
|
94
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
95
|
-
},
|
|
228
|
+
credentials: 'include',
|
|
96
229
|
body: file
|
|
97
230
|
});
|
|
98
231
|
|
|
@@ -112,9 +245,7 @@ export class AdminPortal extends LitElement {
|
|
|
112
245
|
this.statusMessage = 'Clearing cache...';
|
|
113
246
|
const res = await fetch(`${this.apiUrl}/cache-clear`, {
|
|
114
247
|
method: 'POST',
|
|
115
|
-
|
|
116
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
117
|
-
}
|
|
248
|
+
credentials: 'include'
|
|
118
249
|
});
|
|
119
250
|
|
|
120
251
|
if (res.ok) {
|
|
@@ -133,9 +264,7 @@ export class AdminPortal extends LitElement {
|
|
|
133
264
|
try {
|
|
134
265
|
const res = await fetch(`${this.apiUrl}/content/${key}`, {
|
|
135
266
|
method: 'DELETE',
|
|
136
|
-
|
|
137
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
138
|
-
}
|
|
267
|
+
credentials: 'include'
|
|
139
268
|
});
|
|
140
269
|
|
|
141
270
|
if (res.ok) {
|
|
@@ -156,6 +285,41 @@ export class AdminPortal extends LitElement {
|
|
|
156
285
|
return this.contentList.filter(c => c.key.startsWith(prefix));
|
|
157
286
|
}
|
|
158
287
|
|
|
288
|
+
renderLoginForm() {
|
|
289
|
+
return html`
|
|
290
|
+
<div class="container">
|
|
291
|
+
<div class="login-box">
|
|
292
|
+
<h2>Admin Setup</h2>
|
|
293
|
+
<p>Create your admin credentials</p>
|
|
294
|
+
<form @submit=${this.handleSetup}>
|
|
295
|
+
<input type="text" id="username" placeholder="Username (3+ chars)" />
|
|
296
|
+
<input type="password" id="password" placeholder="Password (8+ chars)" />
|
|
297
|
+
<input type="password" id="confirmPassword" placeholder="Confirm Password" />
|
|
298
|
+
${this.loginError ? html`<div class="error-message">${this.loginError}</div>` : ''}
|
|
299
|
+
<button type="submit" class="btn-primary">Create Account</button>
|
|
300
|
+
</form>
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
renderLogin() {
|
|
307
|
+
return html`
|
|
308
|
+
<div class="container">
|
|
309
|
+
<div class="login-box">
|
|
310
|
+
<h2>Admin Login</h2>
|
|
311
|
+
<p>Enter your credentials</p>
|
|
312
|
+
<form @submit=${this.handleLogin}>
|
|
313
|
+
<input type="text" id="username" placeholder="Username" autocomplete="username" />
|
|
314
|
+
<input type="password" id="password" placeholder="Password" autocomplete="current-password" />
|
|
315
|
+
${this.loginError ? html`<div class="error-message">${this.loginError}</div>` : ''}
|
|
316
|
+
<button type="submit" class="btn-primary">Login</button>
|
|
317
|
+
</form>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
`;
|
|
321
|
+
}
|
|
322
|
+
|
|
159
323
|
renderHomeSection() {
|
|
160
324
|
const home = this.getContent('home.md');
|
|
161
325
|
return html`
|
|
@@ -361,69 +525,6 @@ export class AdminPortal extends LitElement {
|
|
|
361
525
|
`;
|
|
362
526
|
}
|
|
363
527
|
|
|
364
|
-
render() {
|
|
365
|
-
if (!this.isAuthenticated) {
|
|
366
|
-
return html`
|
|
367
|
-
<div class="container">
|
|
368
|
-
<div class="login-box">
|
|
369
|
-
<h2>Admin Login</h2>
|
|
370
|
-
<p>Enter your API key to manage content</p>
|
|
371
|
-
<form @submit=${this.handleLogin}>
|
|
372
|
-
<input type="password" id="apiKey" placeholder="API Key" />
|
|
373
|
-
<button type="submit" class="btn-primary">Login</button>
|
|
374
|
-
</form>
|
|
375
|
-
</div>
|
|
376
|
-
</div>
|
|
377
|
-
`;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
return html`
|
|
381
|
-
<div class="container">
|
|
382
|
-
<div class="header">
|
|
383
|
-
<h1>Content Manager</h1>
|
|
384
|
-
<button class="btn-secondary" @click=${() => this.handleClearCache()}>Clear Cache</button>
|
|
385
|
-
</div>
|
|
386
|
-
|
|
387
|
-
<div class="nav-tabs">
|
|
388
|
-
<button class="nav-tab ${this.activeSection === 'home' ? 'active' : ''}"
|
|
389
|
-
@click=${() => this.activeSection = 'home'}>Home</button>
|
|
390
|
-
<button class="nav-tab ${this.activeSection === 'profile' ? 'active' : ''}"
|
|
391
|
-
@click=${() => this.activeSection = 'profile'}>Profile</button>
|
|
392
|
-
<button class="nav-tab ${this.activeSection === 'aboutme' ? 'active' : ''}"
|
|
393
|
-
@click=${() => this.activeSection = 'aboutme'}>About Me</button>
|
|
394
|
-
<button class="nav-tab ${this.activeSection === 'blogs' ? 'active' : ''}"
|
|
395
|
-
@click=${() => this.activeSection = 'blogs'}>Blogs</button>
|
|
396
|
-
<button class="nav-tab ${this.activeSection === 'stories' ? 'active' : ''}"
|
|
397
|
-
@click=${() => this.activeSection = 'stories'}>Stories</button>
|
|
398
|
-
<button class="nav-tab ${this.activeSection === 'images' ? 'active' : ''}"
|
|
399
|
-
@click=${() => this.activeSection = 'images'}>Images</button>
|
|
400
|
-
<button class="nav-tab ${this.activeSection === 'logo' ? 'active' : ''}"
|
|
401
|
-
@click=${() => this.activeSection = 'logo'}>Logo</button>
|
|
402
|
-
<button class="nav-tab ${this.activeSection === 'static' ? 'active' : ''}"
|
|
403
|
-
@click=${() => {
|
|
404
|
-
this.activeSection = 'static';
|
|
405
|
-
this.fetchStaticDetails();
|
|
406
|
-
}}>Site Settings</button>
|
|
407
|
-
</div>
|
|
408
|
-
|
|
409
|
-
${this.statusMessage ? html`
|
|
410
|
-
<div class="status-message ${this.statusMessage.includes('successful') || this.statusMessage.includes('cleared') ? 'success' : this.statusMessage.includes('failed') || this.statusMessage.includes('Error') ? 'error' : ''}">
|
|
411
|
-
${this.statusMessage}
|
|
412
|
-
</div>
|
|
413
|
-
` : ''}
|
|
414
|
-
|
|
415
|
-
${this.activeSection === 'home' ? this.renderHomeSection() : ''}
|
|
416
|
-
${this.activeSection === 'profile' ? this.renderProfileSection() : ''}
|
|
417
|
-
${this.activeSection === 'aboutme' ? this.renderAboutMeSection() : ''}
|
|
418
|
-
${this.activeSection === 'blogs' ? this.renderBlogsSection() : ''}
|
|
419
|
-
${this.activeSection === 'stories' ? this.renderStoriesSection() : ''}
|
|
420
|
-
${this.activeSection === 'images' ? this.renderImagesSection() : ''}
|
|
421
|
-
${this.activeSection === 'logo' ? this.renderLogoSection() : ''}
|
|
422
|
-
${this.activeSection === 'static' ? this.renderStaticSection() : ''}
|
|
423
|
-
</div>
|
|
424
|
-
`;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
528
|
renderStaticSection() {
|
|
428
529
|
return html`
|
|
429
530
|
<div class="section">
|
|
@@ -473,7 +574,8 @@ export class AdminPortal extends LitElement {
|
|
|
473
574
|
const url = `${this.apiUrl}/content/staticdetails.json`;
|
|
474
575
|
const res = await fetch(url, {
|
|
475
576
|
method: 'PUT',
|
|
476
|
-
|
|
577
|
+
credentials: 'include',
|
|
578
|
+
headers: { 'Content-Type': 'application/json' },
|
|
477
579
|
body: JSON.stringify(data)
|
|
478
580
|
});
|
|
479
581
|
if (res.ok) {
|
|
@@ -489,4 +591,65 @@ export class AdminPortal extends LitElement {
|
|
|
489
591
|
</div>
|
|
490
592
|
`;
|
|
491
593
|
}
|
|
594
|
+
|
|
595
|
+
render() {
|
|
596
|
+
if (this.isLoading) {
|
|
597
|
+
return html`<div class="container"><div class="loading">Loading...</div></div>`;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (!this.isSetup) {
|
|
601
|
+
return this.renderLoginForm();
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (!this.isAuthenticated) {
|
|
605
|
+
return this.renderLogin();
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return html`
|
|
609
|
+
<div class="container">
|
|
610
|
+
<div class="header">
|
|
611
|
+
<h1>Content Manager</h1>
|
|
612
|
+
<button class="btn-secondary" @click=${() => this.handleLogout()}>Logout</button>
|
|
613
|
+
<button class="btn-secondary" @click=${() => this.handleClearCache()}>Clear Cache</button>
|
|
614
|
+
</div>
|
|
615
|
+
|
|
616
|
+
<div class="nav-tabs">
|
|
617
|
+
<button class="nav-tab ${this.activeSection === 'home' ? 'active' : ''}"
|
|
618
|
+
@click=${() => this.activeSection = 'home'}>Home</button>
|
|
619
|
+
<button class="nav-tab ${this.activeSection === 'profile' ? 'active' : ''}"
|
|
620
|
+
@click=${() => this.activeSection = 'profile'}>Profile</button>
|
|
621
|
+
<button class="nav-tab ${this.activeSection === 'aboutme' ? 'active' : ''}"
|
|
622
|
+
@click=${() => this.activeSection = 'aboutme'}>About Me</button>
|
|
623
|
+
<button class="nav-tab ${this.activeSection === 'blogs' ? 'active' : ''}"
|
|
624
|
+
@click=${() => this.activeSection = 'blogs'}>Blogs</button>
|
|
625
|
+
<button class="nav-tab ${this.activeSection === 'stories' ? 'active' : ''}"
|
|
626
|
+
@click=${() => this.activeSection = 'stories'}>Stories</button>
|
|
627
|
+
<button class="nav-tab ${this.activeSection === 'images' ? 'active' : ''}"
|
|
628
|
+
@click=${() => this.activeSection = 'images'}>Images</button>
|
|
629
|
+
<button class="nav-tab ${this.activeSection === 'logo' ? 'active' : ''}"
|
|
630
|
+
@click=${() => this.activeSection = 'logo'}>Logo</button>
|
|
631
|
+
<button class="nav-tab ${this.activeSection === 'static' ? 'active' : ''}"
|
|
632
|
+
@click=${() => {
|
|
633
|
+
this.activeSection = 'static';
|
|
634
|
+
this.fetchStaticDetails();
|
|
635
|
+
}}>Site Settings</button>
|
|
636
|
+
</div>
|
|
637
|
+
|
|
638
|
+
${this.statusMessage ? html`
|
|
639
|
+
<div class="status-message ${this.statusMessage.includes('successful') || this.statusMessage.includes('cleared') ? 'success' : this.statusMessage.includes('failed') || this.statusMessage.includes('Error') ? 'error' : ''}">
|
|
640
|
+
${this.statusMessage}
|
|
641
|
+
</div>
|
|
642
|
+
` : ''}
|
|
643
|
+
|
|
644
|
+
${this.activeSection === 'home' ? this.renderHomeSection() : ''}
|
|
645
|
+
${this.activeSection === 'profile' ? this.renderProfileSection() : ''}
|
|
646
|
+
${this.activeSection === 'aboutme' ? this.renderAboutMeSection() : ''}
|
|
647
|
+
${this.activeSection === 'blogs' ? this.renderBlogsSection() : ''}
|
|
648
|
+
${this.activeSection === 'stories' ? this.renderStoriesSection() : ''}
|
|
649
|
+
${this.activeSection === 'images' ? this.renderImagesSection() : ''}
|
|
650
|
+
${this.activeSection === 'logo' ? this.renderLogoSection() : ''}
|
|
651
|
+
${this.activeSection === 'static' ? this.renderStaticSection() : ''}
|
|
652
|
+
</div>
|
|
653
|
+
`;
|
|
654
|
+
}
|
|
492
655
|
}
|