@leadertechie/personal-site-kit 0.1.0-alpha.5 → 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/chunks/{index-VimKeB5W.js → index-C3wLSCKU.js} +236 -93
- package/dist/index.js +1 -1
- 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/ui/admin/index.ts +254 -91
|
@@ -564,38 +564,151 @@ var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "rea
|
|
|
564
564
|
var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
565
565
|
var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
566
566
|
var __privateMethod$3 = (obj, member, method) => (__accessCheck$3(obj, member, "access private method"), method);
|
|
567
|
-
var _staticDetails_dec, _activeSection_dec, _statusMessage_dec, _contentList_dec,
|
|
568
|
-
console.log("[AdminPortal] Module loading");
|
|
569
|
-
console.log("[AdminPortal] About to define custom element");
|
|
567
|
+
var _loginError_dec, _staticDetails_dec, _activeSection_dec, _statusMessage_dec, _contentList_dec, _isLoading_dec, _isSetup_dec, _isAuthenticated_dec, _a$4, _AdminPortal_decorators, _init$4, _isAuthenticated, _isSetup, _isLoading, _contentList, _statusMessage, _activeSection, _staticDetails, _loginError;
|
|
570
568
|
_AdminPortal_decorators = [customElement("admin-portal")];
|
|
571
|
-
class AdminPortal extends (_a$4 = LitElement,
|
|
569
|
+
class AdminPortal extends (_a$4 = LitElement, _isAuthenticated_dec = [state()], _isSetup_dec = [state()], _isLoading_dec = [state()], _contentList_dec = [state()], _statusMessage_dec = [state()], _activeSection_dec = [state()], _staticDetails_dec = [state()], _loginError_dec = [state()], _a$4) {
|
|
572
570
|
constructor() {
|
|
573
571
|
super(...arguments);
|
|
574
|
-
__privateAdd$3(this,
|
|
575
|
-
__privateAdd$3(this,
|
|
576
|
-
__privateAdd$3(this,
|
|
577
|
-
__privateAdd$3(this,
|
|
578
|
-
__privateAdd$3(this,
|
|
579
|
-
__privateAdd$3(this,
|
|
572
|
+
__privateAdd$3(this, _isAuthenticated, __runInitializers$4(_init$4, 8, this, false)), __runInitializers$4(_init$4, 11, this);
|
|
573
|
+
__privateAdd$3(this, _isSetup, __runInitializers$4(_init$4, 12, this, false)), __runInitializers$4(_init$4, 15, this);
|
|
574
|
+
__privateAdd$3(this, _isLoading, __runInitializers$4(_init$4, 16, this, true)), __runInitializers$4(_init$4, 19, this);
|
|
575
|
+
__privateAdd$3(this, _contentList, __runInitializers$4(_init$4, 20, this, [])), __runInitializers$4(_init$4, 23, this);
|
|
576
|
+
__privateAdd$3(this, _statusMessage, __runInitializers$4(_init$4, 24, this, "")), __runInitializers$4(_init$4, 27, this);
|
|
577
|
+
__privateAdd$3(this, _activeSection, __runInitializers$4(_init$4, 28, this, "profile")), __runInitializers$4(_init$4, 31, this);
|
|
578
|
+
__privateAdd$3(this, _staticDetails, __runInitializers$4(_init$4, 32, this, {})), __runInitializers$4(_init$4, 35, this);
|
|
579
|
+
__privateAdd$3(this, _loginError, __runInitializers$4(_init$4, 36, this, "")), __runInitializers$4(_init$4, 39, this);
|
|
580
580
|
}
|
|
581
581
|
get apiUrl() {
|
|
582
582
|
return window.__VITE_API_URL__ || void 0 || "http://localhost:8787";
|
|
583
583
|
}
|
|
584
|
-
|
|
584
|
+
async connectedCallback() {
|
|
585
|
+
super.connectedCallback();
|
|
586
|
+
await this.checkAuthStatus();
|
|
587
|
+
}
|
|
588
|
+
async checkAuthStatus() {
|
|
589
|
+
try {
|
|
590
|
+
const res = await fetch(`${this.apiUrl}/auth/status`, {
|
|
591
|
+
credentials: "include"
|
|
592
|
+
});
|
|
593
|
+
if (res.ok) {
|
|
594
|
+
const status = await res.json();
|
|
595
|
+
this.isSetup = status.configured;
|
|
596
|
+
if (status.configured) {
|
|
597
|
+
await this.tryAutoLogin();
|
|
598
|
+
} else {
|
|
599
|
+
this.isLoading = false;
|
|
600
|
+
}
|
|
601
|
+
} else {
|
|
602
|
+
this.isSetup = false;
|
|
603
|
+
this.isLoading = false;
|
|
604
|
+
}
|
|
605
|
+
} catch (e2) {
|
|
606
|
+
this.isSetup = false;
|
|
607
|
+
this.isLoading = false;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
async tryAutoLogin() {
|
|
611
|
+
try {
|
|
612
|
+
const res = await fetch(`${this.apiUrl}/content`, {
|
|
613
|
+
credentials: "include"
|
|
614
|
+
});
|
|
615
|
+
if (res.ok) {
|
|
616
|
+
this.contentList = await res.json();
|
|
617
|
+
this.isAuthenticated = true;
|
|
618
|
+
}
|
|
619
|
+
} catch (e2) {
|
|
620
|
+
}
|
|
621
|
+
this.isLoading = false;
|
|
622
|
+
}
|
|
623
|
+
async handleLogin(e2) {
|
|
585
624
|
e2.preventDefault();
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
this.
|
|
625
|
+
this.loginError = "";
|
|
626
|
+
const usernameInput = this.shadowRoot?.querySelector("#username");
|
|
627
|
+
const passwordInput = this.shadowRoot?.querySelector("#password");
|
|
628
|
+
if (!usernameInput?.value || !passwordInput?.value) {
|
|
629
|
+
this.loginError = "Username and password required";
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
try {
|
|
633
|
+
const res = await fetch(`${this.apiUrl}/auth/login`, {
|
|
634
|
+
method: "POST",
|
|
635
|
+
credentials: "include",
|
|
636
|
+
headers: { "Content-Type": "application/json" },
|
|
637
|
+
body: JSON.stringify({
|
|
638
|
+
username: usernameInput.value,
|
|
639
|
+
password: passwordInput.value
|
|
640
|
+
})
|
|
641
|
+
});
|
|
642
|
+
if (res.ok) {
|
|
643
|
+
this.isAuthenticated = true;
|
|
644
|
+
await this.fetchContent();
|
|
645
|
+
} else {
|
|
646
|
+
const data = await res.json();
|
|
647
|
+
this.loginError = data.error || "Login failed";
|
|
648
|
+
}
|
|
649
|
+
} catch (e22) {
|
|
650
|
+
this.loginError = "Connection error";
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
async handleSetup(e2) {
|
|
654
|
+
e2.preventDefault();
|
|
655
|
+
this.loginError = "";
|
|
656
|
+
const usernameInput = this.shadowRoot?.querySelector("#username");
|
|
657
|
+
const passwordInput = this.shadowRoot?.querySelector("#password");
|
|
658
|
+
const confirmInput = this.shadowRoot?.querySelector("#confirmPassword");
|
|
659
|
+
if (!usernameInput?.value || !passwordInput?.value) {
|
|
660
|
+
this.loginError = "Username and password required";
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (usernameInput.value.length < 3) {
|
|
664
|
+
this.loginError = "Username must be at least 3 characters";
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
if (passwordInput.value.length < 8) {
|
|
668
|
+
this.loginError = "Password must be at least 8 characters";
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
if (passwordInput.value !== confirmInput?.value) {
|
|
672
|
+
this.loginError = "Passwords do not match";
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
try {
|
|
676
|
+
const res = await fetch(`${this.apiUrl}/auth/setup`, {
|
|
677
|
+
method: "POST",
|
|
678
|
+
credentials: "include",
|
|
679
|
+
headers: { "Content-Type": "application/json" },
|
|
680
|
+
body: JSON.stringify({
|
|
681
|
+
username: usernameInput.value,
|
|
682
|
+
password: passwordInput.value
|
|
683
|
+
})
|
|
684
|
+
});
|
|
685
|
+
if (res.ok) {
|
|
686
|
+
this.isAuthenticated = true;
|
|
687
|
+
this.isSetup = true;
|
|
688
|
+
await this.fetchContent();
|
|
689
|
+
} else {
|
|
690
|
+
const data = await res.json();
|
|
691
|
+
this.loginError = data.error || "Setup failed";
|
|
692
|
+
}
|
|
693
|
+
} catch (e22) {
|
|
694
|
+
this.loginError = "Connection error";
|
|
591
695
|
}
|
|
592
696
|
}
|
|
697
|
+
async handleLogout() {
|
|
698
|
+
try {
|
|
699
|
+
await fetch(`${this.apiUrl}/auth/logout`, {
|
|
700
|
+
method: "POST",
|
|
701
|
+
credentials: "include"
|
|
702
|
+
});
|
|
703
|
+
} catch (e2) {
|
|
704
|
+
}
|
|
705
|
+
this.isAuthenticated = false;
|
|
706
|
+
this.contentList = [];
|
|
707
|
+
}
|
|
593
708
|
async fetchContent() {
|
|
594
709
|
try {
|
|
595
710
|
const res = await fetch(`${this.apiUrl}/content`, {
|
|
596
|
-
|
|
597
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
598
|
-
}
|
|
711
|
+
credentials: "include"
|
|
599
712
|
});
|
|
600
713
|
if (res.ok) {
|
|
601
714
|
this.contentList = await res.json();
|
|
@@ -608,7 +721,9 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
608
721
|
}
|
|
609
722
|
async fetchStaticDetails() {
|
|
610
723
|
try {
|
|
611
|
-
const res = await fetch(`${this.apiUrl}/
|
|
724
|
+
const res = await fetch(`${this.apiUrl}/static`, {
|
|
725
|
+
credentials: "include"
|
|
726
|
+
});
|
|
612
727
|
if (res.ok) {
|
|
613
728
|
this.staticDetails = await res.json();
|
|
614
729
|
}
|
|
@@ -620,9 +735,7 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
620
735
|
this.statusMessage = "Uploading...";
|
|
621
736
|
const res = await fetch(`${this.apiUrl}/content/${key}`, {
|
|
622
737
|
method: "PUT",
|
|
623
|
-
|
|
624
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
625
|
-
},
|
|
738
|
+
credentials: "include",
|
|
626
739
|
body: file
|
|
627
740
|
});
|
|
628
741
|
if (res.ok) {
|
|
@@ -640,9 +753,7 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
640
753
|
this.statusMessage = "Clearing cache...";
|
|
641
754
|
const res = await fetch(`${this.apiUrl}/cache-clear`, {
|
|
642
755
|
method: "POST",
|
|
643
|
-
|
|
644
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
645
|
-
}
|
|
756
|
+
credentials: "include"
|
|
646
757
|
});
|
|
647
758
|
if (res.ok) {
|
|
648
759
|
this.statusMessage = "Cache cleared!";
|
|
@@ -658,9 +769,7 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
658
769
|
try {
|
|
659
770
|
const res = await fetch(`${this.apiUrl}/content/${key}`, {
|
|
660
771
|
method: "DELETE",
|
|
661
|
-
|
|
662
|
-
"Authorization": `Bearer ${this.apiKey}`
|
|
663
|
-
}
|
|
772
|
+
credentials: "include"
|
|
664
773
|
});
|
|
665
774
|
if (res.ok) {
|
|
666
775
|
this.fetchContent();
|
|
@@ -677,6 +786,39 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
677
786
|
getSectionFiles(prefix) {
|
|
678
787
|
return this.contentList.filter((c2) => c2.key.startsWith(prefix));
|
|
679
788
|
}
|
|
789
|
+
renderLoginForm() {
|
|
790
|
+
return html`
|
|
791
|
+
<div class="container">
|
|
792
|
+
<div class="login-box">
|
|
793
|
+
<h2>Admin Setup</h2>
|
|
794
|
+
<p>Create your admin credentials</p>
|
|
795
|
+
<form @submit=${this.handleSetup}>
|
|
796
|
+
<input type="text" id="username" placeholder="Username (3+ chars)" />
|
|
797
|
+
<input type="password" id="password" placeholder="Password (8+ chars)" />
|
|
798
|
+
<input type="password" id="confirmPassword" placeholder="Confirm Password" />
|
|
799
|
+
${this.loginError ? html`<div class="error-message">${this.loginError}</div>` : ""}
|
|
800
|
+
<button type="submit" class="btn-primary">Create Account</button>
|
|
801
|
+
</form>
|
|
802
|
+
</div>
|
|
803
|
+
</div>
|
|
804
|
+
`;
|
|
805
|
+
}
|
|
806
|
+
renderLogin() {
|
|
807
|
+
return html`
|
|
808
|
+
<div class="container">
|
|
809
|
+
<div class="login-box">
|
|
810
|
+
<h2>Admin Login</h2>
|
|
811
|
+
<p>Enter your credentials</p>
|
|
812
|
+
<form @submit=${this.handleLogin}>
|
|
813
|
+
<input type="text" id="username" placeholder="Username" autocomplete="username" />
|
|
814
|
+
<input type="password" id="password" placeholder="Password" autocomplete="current-password" />
|
|
815
|
+
${this.loginError ? html`<div class="error-message">${this.loginError}</div>` : ""}
|
|
816
|
+
<button type="submit" class="btn-primary">Login</button>
|
|
817
|
+
</form>
|
|
818
|
+
</div>
|
|
819
|
+
</div>
|
|
820
|
+
`;
|
|
821
|
+
}
|
|
680
822
|
renderHomeSection() {
|
|
681
823
|
const home = this.getContent("home.md");
|
|
682
824
|
return html`
|
|
@@ -875,67 +1017,6 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
875
1017
|
</div>
|
|
876
1018
|
`;
|
|
877
1019
|
}
|
|
878
|
-
render() {
|
|
879
|
-
if (!this.isAuthenticated) {
|
|
880
|
-
return html`
|
|
881
|
-
<div class="container">
|
|
882
|
-
<div class="login-box">
|
|
883
|
-
<h2>Admin Login</h2>
|
|
884
|
-
<p>Enter your API key to manage content</p>
|
|
885
|
-
<form @submit=${this.handleLogin}>
|
|
886
|
-
<input type="password" id="apiKey" placeholder="API Key" />
|
|
887
|
-
<button type="submit" class="btn-primary">Login</button>
|
|
888
|
-
</form>
|
|
889
|
-
</div>
|
|
890
|
-
</div>
|
|
891
|
-
`;
|
|
892
|
-
}
|
|
893
|
-
return html`
|
|
894
|
-
<div class="container">
|
|
895
|
-
<div class="header">
|
|
896
|
-
<h1>Content Manager</h1>
|
|
897
|
-
<button class="btn-secondary" @click=${() => this.handleClearCache()}>Clear Cache</button>
|
|
898
|
-
</div>
|
|
899
|
-
|
|
900
|
-
<div class="nav-tabs">
|
|
901
|
-
<button class="nav-tab ${this.activeSection === "home" ? "active" : ""}"
|
|
902
|
-
@click=${() => this.activeSection = "home"}>Home</button>
|
|
903
|
-
<button class="nav-tab ${this.activeSection === "profile" ? "active" : ""}"
|
|
904
|
-
@click=${() => this.activeSection = "profile"}>Profile</button>
|
|
905
|
-
<button class="nav-tab ${this.activeSection === "aboutme" ? "active" : ""}"
|
|
906
|
-
@click=${() => this.activeSection = "aboutme"}>About Me</button>
|
|
907
|
-
<button class="nav-tab ${this.activeSection === "blogs" ? "active" : ""}"
|
|
908
|
-
@click=${() => this.activeSection = "blogs"}>Blogs</button>
|
|
909
|
-
<button class="nav-tab ${this.activeSection === "stories" ? "active" : ""}"
|
|
910
|
-
@click=${() => this.activeSection = "stories"}>Stories</button>
|
|
911
|
-
<button class="nav-tab ${this.activeSection === "images" ? "active" : ""}"
|
|
912
|
-
@click=${() => this.activeSection = "images"}>Images</button>
|
|
913
|
-
<button class="nav-tab ${this.activeSection === "logo" ? "active" : ""}"
|
|
914
|
-
@click=${() => this.activeSection = "logo"}>Logo</button>
|
|
915
|
-
<button class="nav-tab ${this.activeSection === "static" ? "active" : ""}"
|
|
916
|
-
@click=${() => {
|
|
917
|
-
this.activeSection = "static";
|
|
918
|
-
this.fetchStaticDetails();
|
|
919
|
-
}}>Site Settings</button>
|
|
920
|
-
</div>
|
|
921
|
-
|
|
922
|
-
${this.statusMessage ? html`
|
|
923
|
-
<div class="status-message ${this.statusMessage.includes("successful") || this.statusMessage.includes("cleared") ? "success" : this.statusMessage.includes("failed") || this.statusMessage.includes("Error") ? "error" : ""}">
|
|
924
|
-
${this.statusMessage}
|
|
925
|
-
</div>
|
|
926
|
-
` : ""}
|
|
927
|
-
|
|
928
|
-
${this.activeSection === "home" ? this.renderHomeSection() : ""}
|
|
929
|
-
${this.activeSection === "profile" ? this.renderProfileSection() : ""}
|
|
930
|
-
${this.activeSection === "aboutme" ? this.renderAboutMeSection() : ""}
|
|
931
|
-
${this.activeSection === "blogs" ? this.renderBlogsSection() : ""}
|
|
932
|
-
${this.activeSection === "stories" ? this.renderStoriesSection() : ""}
|
|
933
|
-
${this.activeSection === "images" ? this.renderImagesSection() : ""}
|
|
934
|
-
${this.activeSection === "logo" ? this.renderLogoSection() : ""}
|
|
935
|
-
${this.activeSection === "static" ? this.renderStaticSection() : ""}
|
|
936
|
-
</div>
|
|
937
|
-
`;
|
|
938
|
-
}
|
|
939
1020
|
renderStaticSection() {
|
|
940
1021
|
return html`
|
|
941
1022
|
<div class="section">
|
|
@@ -983,7 +1064,8 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
983
1064
|
const url = `${this.apiUrl}/content/staticdetails.json`;
|
|
984
1065
|
const res = await fetch(url, {
|
|
985
1066
|
method: "PUT",
|
|
986
|
-
|
|
1067
|
+
credentials: "include",
|
|
1068
|
+
headers: { "Content-Type": "application/json" },
|
|
987
1069
|
body: JSON.stringify(data)
|
|
988
1070
|
});
|
|
989
1071
|
if (res.ok) {
|
|
@@ -999,20 +1081,81 @@ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthen
|
|
|
999
1081
|
</div>
|
|
1000
1082
|
`;
|
|
1001
1083
|
}
|
|
1084
|
+
render() {
|
|
1085
|
+
if (this.isLoading) {
|
|
1086
|
+
return html`<div class="container"><div class="loading">Loading...</div></div>`;
|
|
1087
|
+
}
|
|
1088
|
+
if (!this.isSetup) {
|
|
1089
|
+
return this.renderLoginForm();
|
|
1090
|
+
}
|
|
1091
|
+
if (!this.isAuthenticated) {
|
|
1092
|
+
return this.renderLogin();
|
|
1093
|
+
}
|
|
1094
|
+
return html`
|
|
1095
|
+
<div class="container">
|
|
1096
|
+
<div class="header">
|
|
1097
|
+
<h1>Content Manager</h1>
|
|
1098
|
+
<button class="btn-secondary" @click=${() => this.handleLogout()}>Logout</button>
|
|
1099
|
+
<button class="btn-secondary" @click=${() => this.handleClearCache()}>Clear Cache</button>
|
|
1100
|
+
</div>
|
|
1101
|
+
|
|
1102
|
+
<div class="nav-tabs">
|
|
1103
|
+
<button class="nav-tab ${this.activeSection === "home" ? "active" : ""}"
|
|
1104
|
+
@click=${() => this.activeSection = "home"}>Home</button>
|
|
1105
|
+
<button class="nav-tab ${this.activeSection === "profile" ? "active" : ""}"
|
|
1106
|
+
@click=${() => this.activeSection = "profile"}>Profile</button>
|
|
1107
|
+
<button class="nav-tab ${this.activeSection === "aboutme" ? "active" : ""}"
|
|
1108
|
+
@click=${() => this.activeSection = "aboutme"}>About Me</button>
|
|
1109
|
+
<button class="nav-tab ${this.activeSection === "blogs" ? "active" : ""}"
|
|
1110
|
+
@click=${() => this.activeSection = "blogs"}>Blogs</button>
|
|
1111
|
+
<button class="nav-tab ${this.activeSection === "stories" ? "active" : ""}"
|
|
1112
|
+
@click=${() => this.activeSection = "stories"}>Stories</button>
|
|
1113
|
+
<button class="nav-tab ${this.activeSection === "images" ? "active" : ""}"
|
|
1114
|
+
@click=${() => this.activeSection = "images"}>Images</button>
|
|
1115
|
+
<button class="nav-tab ${this.activeSection === "logo" ? "active" : ""}"
|
|
1116
|
+
@click=${() => this.activeSection = "logo"}>Logo</button>
|
|
1117
|
+
<button class="nav-tab ${this.activeSection === "static" ? "active" : ""}"
|
|
1118
|
+
@click=${() => {
|
|
1119
|
+
this.activeSection = "static";
|
|
1120
|
+
this.fetchStaticDetails();
|
|
1121
|
+
}}>Site Settings</button>
|
|
1122
|
+
</div>
|
|
1123
|
+
|
|
1124
|
+
${this.statusMessage ? html`
|
|
1125
|
+
<div class="status-message ${this.statusMessage.includes("successful") || this.statusMessage.includes("cleared") ? "success" : this.statusMessage.includes("failed") || this.statusMessage.includes("Error") ? "error" : ""}">
|
|
1126
|
+
${this.statusMessage}
|
|
1127
|
+
</div>
|
|
1128
|
+
` : ""}
|
|
1129
|
+
|
|
1130
|
+
${this.activeSection === "home" ? this.renderHomeSection() : ""}
|
|
1131
|
+
${this.activeSection === "profile" ? this.renderProfileSection() : ""}
|
|
1132
|
+
${this.activeSection === "aboutme" ? this.renderAboutMeSection() : ""}
|
|
1133
|
+
${this.activeSection === "blogs" ? this.renderBlogsSection() : ""}
|
|
1134
|
+
${this.activeSection === "stories" ? this.renderStoriesSection() : ""}
|
|
1135
|
+
${this.activeSection === "images" ? this.renderImagesSection() : ""}
|
|
1136
|
+
${this.activeSection === "logo" ? this.renderLogoSection() : ""}
|
|
1137
|
+
${this.activeSection === "static" ? this.renderStaticSection() : ""}
|
|
1138
|
+
</div>
|
|
1139
|
+
`;
|
|
1140
|
+
}
|
|
1002
1141
|
}
|
|
1003
1142
|
_init$4 = __decoratorStart$4(_a$4);
|
|
1004
|
-
_apiKey = /* @__PURE__ */ new WeakMap();
|
|
1005
1143
|
_isAuthenticated = /* @__PURE__ */ new WeakMap();
|
|
1144
|
+
_isSetup = /* @__PURE__ */ new WeakMap();
|
|
1145
|
+
_isLoading = /* @__PURE__ */ new WeakMap();
|
|
1006
1146
|
_contentList = /* @__PURE__ */ new WeakMap();
|
|
1007
1147
|
_statusMessage = /* @__PURE__ */ new WeakMap();
|
|
1008
1148
|
_activeSection = /* @__PURE__ */ new WeakMap();
|
|
1009
1149
|
_staticDetails = /* @__PURE__ */ new WeakMap();
|
|
1010
|
-
|
|
1150
|
+
_loginError = /* @__PURE__ */ new WeakMap();
|
|
1011
1151
|
__decorateElement$4(_init$4, 4, "isAuthenticated", _isAuthenticated_dec, AdminPortal, _isAuthenticated);
|
|
1152
|
+
__decorateElement$4(_init$4, 4, "isSetup", _isSetup_dec, AdminPortal, _isSetup);
|
|
1153
|
+
__decorateElement$4(_init$4, 4, "isLoading", _isLoading_dec, AdminPortal, _isLoading);
|
|
1012
1154
|
__decorateElement$4(_init$4, 4, "contentList", _contentList_dec, AdminPortal, _contentList);
|
|
1013
1155
|
__decorateElement$4(_init$4, 4, "statusMessage", _statusMessage_dec, AdminPortal, _statusMessage);
|
|
1014
1156
|
__decorateElement$4(_init$4, 4, "activeSection", _activeSection_dec, AdminPortal, _activeSection);
|
|
1015
1157
|
__decorateElement$4(_init$4, 4, "staticDetails", _staticDetails_dec, AdminPortal, _staticDetails);
|
|
1158
|
+
__decorateElement$4(_init$4, 4, "loginError", _loginError_dec, AdminPortal, _loginError);
|
|
1016
1159
|
AdminPortal = __decorateElement$4(_init$4, 0, "AdminPortal", _AdminPortal_decorators, AdminPortal);
|
|
1017
1160
|
AdminPortal.styles = adminStyles;
|
|
1018
1161
|
__runInitializers$4(_init$4, 1, AdminPortal);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { A, B, M, R, W, c, a, g, b, d, h, e, r, s, v } from "./chunks/website-api-DI3muo2s.js";
|
|
2
2
|
import { WebsitePrerender } from "./prerender.js";
|
|
3
|
-
import { A as A2, B as B2, F, M as M2, a as a2, S } from "./chunks/index-
|
|
3
|
+
import { A as A2, B as B2, F, M as M2, a as a2, S } from "./chunks/index-C3wLSCKU.js";
|
|
4
4
|
import { R as R2, S as S2, T, W as W2, b as b2, c as c2, g as g2, a as a3, i, r as r2 } from "./chunks/template-MawmknFQ.js";
|
|
5
5
|
export {
|
|
6
6
|
A as AUTH_KV,
|
package/dist/ui/admin/index.d.ts
CHANGED
|
@@ -13,14 +13,21 @@ interface StaticDetails {
|
|
|
13
13
|
}
|
|
14
14
|
export declare class AdminPortal extends LitElement {
|
|
15
15
|
static styles: import('lit').CSSResult;
|
|
16
|
-
accessor apiKey: string;
|
|
17
16
|
accessor isAuthenticated: boolean;
|
|
17
|
+
accessor isSetup: boolean;
|
|
18
|
+
accessor isLoading: boolean;
|
|
18
19
|
accessor contentList: ContentItem[];
|
|
19
20
|
accessor statusMessage: string;
|
|
20
21
|
accessor activeSection: string;
|
|
21
22
|
accessor staticDetails: StaticDetails;
|
|
23
|
+
accessor loginError: string;
|
|
22
24
|
get apiUrl(): any;
|
|
23
|
-
|
|
25
|
+
connectedCallback(): Promise<void>;
|
|
26
|
+
checkAuthStatus(): Promise<void>;
|
|
27
|
+
tryAutoLogin(): Promise<void>;
|
|
28
|
+
handleLogin(e: Event): Promise<void>;
|
|
29
|
+
handleSetup(e: Event): Promise<void>;
|
|
30
|
+
handleLogout(): Promise<void>;
|
|
24
31
|
fetchContent(): Promise<void>;
|
|
25
32
|
fetchStaticDetails(): Promise<void>;
|
|
26
33
|
handleUpload(key: string, file: File): Promise<void>;
|
|
@@ -28,6 +35,8 @@ export declare class AdminPortal extends LitElement {
|
|
|
28
35
|
handleDelete(key: string): Promise<void>;
|
|
29
36
|
getContent(key: string): ContentItem | undefined;
|
|
30
37
|
getSectionFiles(prefix: string): ContentItem[];
|
|
38
|
+
renderLoginForm(): import('lit-html').TemplateResult<1>;
|
|
39
|
+
renderLogin(): import('lit-html').TemplateResult<1>;
|
|
31
40
|
renderHomeSection(): import('lit-html').TemplateResult<1>;
|
|
32
41
|
renderProfileSection(): import('lit-html').TemplateResult<1>;
|
|
33
42
|
renderAboutMeSection(): import('lit-html').TemplateResult<1>;
|
|
@@ -35,8 +44,8 @@ export declare class AdminPortal extends LitElement {
|
|
|
35
44
|
renderStoriesSection(): import('lit-html').TemplateResult<1>;
|
|
36
45
|
renderImagesSection(): import('lit-html').TemplateResult<1>;
|
|
37
46
|
renderLogoSection(): import('lit-html').TemplateResult<1>;
|
|
38
|
-
render(): import('lit-html').TemplateResult<1>;
|
|
39
47
|
renderStaticSection(): import('lit-html').TemplateResult<1>;
|
|
48
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
40
49
|
}
|
|
41
50
|
export {};
|
|
42
51
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,qBACa,WAAY,SAAQ,UAAU;IACzC,MAAM,CAAC,MAAM,0BAAe;IAG5B,QAAQ,CAAC,eAAe,UAAS;IAGjC,QAAQ,CAAC,OAAO,UAAS;IAGzB,QAAQ,CAAC,SAAS,UAAQ;IAG1B,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,CAAM;IAGzC,QAAQ,CAAC,aAAa,SAAM;IAG5B,QAAQ,CAAC,aAAa,SAAa;IAGnC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAM;IAG3C,QAAQ,CAAC,UAAU,SAAM;IAEzB,IAAI,MAAM,QAET;IAEK,iBAAiB;IAKjB,eAAe;IAwBf,YAAY;IAaZ,WAAW,CAAC,CAAC,EAAE,KAAK;IAmCpB,WAAW,CAAC,CAAC,EAAE,KAAK;IAoDpB,YAAY;IAWZ,YAAY;IAeZ,kBAAkB;IAWlB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;IAoBpC,gBAAgB;IAkBhB,YAAY,CAAC,GAAG,EAAE,MAAM;IAmB9B,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIhD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE;IAI9C,eAAe;IAkBf,WAAW;IAiBX,iBAAiB;IAuBjB,oBAAoB;IAuBpB,oBAAoB;IAuBpB,kBAAkB;IAuClB,oBAAoB;IAuCpB,mBAAmB;IA+BnB,iBAAiB;IA2BjB,mBAAmB;IAmEnB,MAAM;CA4DP"}
|
package/dist/ui.js
CHANGED
package/package.json
CHANGED
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
|
}
|