Twan07 commited on
Commit
24761b1
·
verified ·
1 Parent(s): 50ae0b5

Create server/html.ts

Browse files
Files changed (1) hide show
  1. exocore-web/server/html.ts +233 -0
exocore-web/server/html.ts ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Request, Response, Application } from 'express';
2
+ import path from 'path';
3
+ import { readFileSync, existsSync } from 'fs';
4
+
5
+ function safeReadFile(filePath: string, encoding: BufferEncoding = 'utf-8'): string {
6
+ if (existsSync(filePath)) {
7
+ try {
8
+ return readFileSync(filePath, encoding);
9
+ } catch (e) {
10
+ console.error(`Error reading file ${filePath} (safeReadFile):`, e);
11
+ return '';
12
+ }
13
+ }
14
+ console.warn(`Warning: File not found at ${filePath} (safeReadFile). Returning empty string.`);
15
+ return '';
16
+ }
17
+
18
+ export function html(app: Application): void {
19
+ const fileSystemPublicBasePath = path.resolve(__dirname, '..', 'public');
20
+ const header = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'header.html'));
21
+ const chatheadai = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'chatheadai.html'));
22
+ const footer = safeReadFile(path.join(fileSystemPublicBasePath, 'templates', 'footer.html'));
23
+
24
+ function renderPage(title: string, scriptPath: string): string {
25
+ const hostScript = safeReadFile(path.join(fileSystemPublicBasePath, 'src', scriptPath));
26
+ const basePublicPath = '/private/server/exocore/web/public';
27
+
28
+ return `
29
+ <!DOCTYPE html>
30
+ <html lang="en">
31
+ <head>
32
+ <meta charset="UTF-8" />
33
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
34
+ <link rel="icon" type="image/jpeg" href="https://i.ibb.co/G4vDj7Fm/FB-IMG-1749809298614.jpg">
35
+ <title>${title}</title>
36
+ <script>
37
+ (function() {
38
+ const getToken = () => localStorage.getItem('exocore-token') || '';
39
+ const getCookies = () => localStorage.getItem('exocore-cookies') || '';
40
+ const baseRedirectPath = '/private/server/exocore/web/public';
41
+ const panelLoginLandingUrl = baseRedirectPath;
42
+ const accountLoginUrl = \`\${baseRedirectPath}/login\`;
43
+ const registerUrl = \`\${baseRedirectPath}/register\`;
44
+ const otpUrl = \`\${baseRedirectPath}/otp\`;
45
+ const forgotPasswordUrl = \`\${baseRedirectPath}/forgot-password\`;
46
+ const currentPathname = window.location.pathname;
47
+ const isPanelLoginSuccess = localStorage.getItem('panelLogin') === 'success';
48
+ const hasAccountAuthTokens = getToken() && getCookies();
49
+
50
+ if (!isPanelLoginSuccess) {
51
+ if (currentPathname !== panelLoginLandingUrl) {
52
+ console.log("'panelLogin' is not 'success'. Redirecting to panel login landing page...");
53
+ window.location.href = panelLoginLandingUrl;
54
+ throw new Error("Redirecting to panel login landing to halt script execution.");
55
+ }
56
+ return;
57
+ }
58
+
59
+ const postPanelLogin_AccountAuthPages = [accountLoginUrl, registerUrl, otpUrl, forgotPasswordUrl];
60
+
61
+ if (!hasAccountAuthTokens) {
62
+ if (!postPanelLogin_AccountAuthPages.includes(currentPathname)) {
63
+ console.log('User has panel access but no account session tokens. Redirecting to account login page...');
64
+ window.location.href = accountLoginUrl;
65
+ throw new Error("Redirecting to account login to halt script execution.");
66
+ }
67
+ return;
68
+ }
69
+ })();
70
+ </script>
71
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/ansi_up.min.js"></script>
72
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
73
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" />
74
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
75
+ <style>
76
+ html, body { height: 100%; margin: 0; }
77
+ .page-wrapper { min-height: 100%; display: flex; flex-direction: column; }
78
+ .page-content { flex: 1; }
79
+ #app { min-height: 100vh; }
80
+ h2, h3, h4 { color: #333; margin-top: 0.5rem; margin-bottom: 1rem; }
81
+ ul { list-style-type: none; padding: 0; margin: 0; }
82
+ li { padding: 0.2rem 0; }
83
+ .status-box { padding: 0.5rem; margin: 0.5rem 0; border: 1px solid #ddd; background: #f9f9f9; border-radius: 4px; display: flex; align-items: center; justify-content: space-between; }
84
+ input[type="file"] { display: none; }
85
+ @media (max-width: 767px) {
86
+ .main-content-flex { flex-direction: column; gap: 15px !important; }
87
+ .file-list-panel, .file-editor-panel { width: 100%; min-width: unset !important; }
88
+ }
89
+ pre { background: #1e1e1e; padding: 1em; overflow: auto; border-radius: 5px; color: #ccc; }
90
+ code { font-family: 'monospace'; display: block; }
91
+ </style>
92
+ </head>
93
+ <body>
94
+ <div class="page-wrapper">
95
+ ${header}
96
+ <div id="app" class="page-content"></div>
97
+ ${chatheadai}
98
+ ${footer}
99
+ </div>
100
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
101
+ <script>
102
+ document.addEventListener('DOMContentLoaded', () => {
103
+ if (typeof hljs !== 'undefined') {
104
+ hljs.highlightAll();
105
+ }
106
+ });
107
+ </script>
108
+ <script>
109
+ async function checkProjectStatusAndRedirect() {
110
+ const projectStatusUrl = '/private/server/exocore/web/project/status';
111
+ const redirectUrl = '${basePublicPath}/project';
112
+ if (window.location.pathname === redirectUrl) {
113
+ console.log('Currently on the project setup page. Status check will not redirect further from here.');
114
+ return;
115
+ }
116
+ try {
117
+ const response = await fetch(projectStatusUrl, {
118
+ method: 'POST',
119
+ headers: { 'Content-Type': 'application/json' },
120
+ });
121
+ if (!response.ok) {
122
+ console.error(\`Failed to fetch project status. Server responded with \${response.status}: \${response.statusText}\`);
123
+ return;
124
+ }
125
+ const statusData = await response.json();
126
+ if (statusData && typeof statusData.exists === 'boolean' && !statusData.exists) {
127
+ console.log('Project status indicates it does not exist or is not properly configured. Redirecting to project setup...');
128
+ window.location.href = redirectUrl;
129
+ } else if (statusData && statusData.exists === true) {
130
+ console.log('Project exists. No redirection necessary from project status check.');
131
+ } else {
132
+ console.warn('Received an unexpected or malformed response from the project status API:', statusData);
133
+ }
134
+ } catch (error) {
135
+ console.error('Error during project status check or processing:', error);
136
+ }
137
+ }
138
+ const currentPathnameForProjectCheck = window.location.pathname;
139
+ const baseRedirectPathForProjectCheck = '/private/server/exocore/web/public';
140
+ const accountLoginUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/login\`;
141
+ const registerUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/register\`;
142
+ const otpUrlForProjectCheck = \`\${baseRedirectPathForProjectCheck}/otp\`;
143
+ if ( localStorage.getItem('exocore-token') &&
144
+ localStorage.getItem('exocore-cookies') &&
145
+ localStorage.getItem('panelLogin') === 'success' &&
146
+ currentPathnameForProjectCheck !== accountLoginUrlForProjectCheck &&
147
+ currentPathnameForProjectCheck !== registerUrlForProjectCheck &&
148
+ currentPathnameForProjectCheck !== otpUrlForProjectCheck
149
+ ) {
150
+ checkProjectStatusAndRedirect();
151
+ }
152
+ </script>
153
+ <script type="module">${hostScript}</script>
154
+ </body>
155
+ </html>`;
156
+ }
157
+
158
+ const urlSegmentForPublicRoutes = '/private/server/exocore/web/public';
159
+
160
+ app.get(`${urlSegmentForPublicRoutes}/register`, (_req: Request, res: Response): void => {
161
+ res.setHeader('Content-Type', 'text/html');
162
+ res.send(renderPage('Signup', 'register.js'));
163
+ });
164
+
165
+ app.get(`${urlSegmentForPublicRoutes}/login`, (_req: Request, res: Response): void => {
166
+ res.setHeader('Content-Type', 'text/html');
167
+ res.send(renderPage('Login', 'login.js'));
168
+ });
169
+
170
+ app.get(`${urlSegmentForPublicRoutes}/project`, (_req: Request, res: Response): void => {
171
+ res.setHeader('Content-Type', 'text/html');
172
+ res.send(renderPage('Project', 'project.js'));
173
+ });
174
+
175
+ app.get(`${urlSegmentForPublicRoutes}/otp`, (_req: Request, res: Response): void => {
176
+ res.setHeader('Content-Type', 'text/html');
177
+ res.send(renderPage('Otp', 'otp.js'));
178
+ });
179
+
180
+ app.get(`${urlSegmentForPublicRoutes}/profile`, (_req: Request, res: Response): void => {
181
+ res.setHeader('Content-Type', 'text/html');
182
+ res.send(renderPage('Profile', 'profile.js'));
183
+ });
184
+
185
+ app.get(`${urlSegmentForPublicRoutes}/forgot-password`, (_req: Request, res: Response): void => {
186
+ res.setHeader('Content-Type', 'text/html');
187
+ res.send(renderPage('ForgotPass', 'forgot.js'));
188
+ });
189
+
190
+ app.get(`${urlSegmentForPublicRoutes}/dashboard`, (_req: Request, res: Response): void => {
191
+ res.setHeader('Content-Type', 'text/html');
192
+ res.send(renderPage('Dashboard', 'dashboard.js'));
193
+ });
194
+
195
+ app.get(`${urlSegmentForPublicRoutes}/plans`, (_req: Request, res: Response): void => {
196
+ res.setHeader('Content-Type', 'text/html');
197
+ res.send(renderPage('plans', 'plans.js'));
198
+ });
199
+
200
+ app.get(`${urlSegmentForPublicRoutes}/console`, (_req: Request, res: Response): void => {
201
+ res.setHeader('Content-Type', 'text/html');
202
+ res.send(renderPage('Console', 'console.js'));
203
+ });
204
+
205
+ app.get(`${urlSegmentForPublicRoutes}/shell`, (_req: Request, res: Response): void => {
206
+ res.setHeader('Content-Type', 'text/html');
207
+ res.send(renderPage('Shell', 'shell.js'));
208
+ });
209
+
210
+ app.get(`${urlSegmentForPublicRoutes}/manager`, (_req: Request, res: Response): void => {
211
+ res.setHeader('Content-Type', 'text/html');
212
+ res.send(renderPage('File Manager', 'FileManager.js'));
213
+ });
214
+
215
+ app.get(urlSegmentForPublicRoutes, (_req: Request, res: Response): void => {
216
+ const panelHtmlFilePath = path.join(fileSystemPublicBasePath, 'panel.html');
217
+
218
+ if (!existsSync(panelHtmlFilePath)) {
219
+ console.warn(`Static file not found: ${panelHtmlFilePath} for URL ${urlSegmentForPublicRoutes}. Sending 404.`);
220
+ res.status(404).send('Page not found.');
221
+ return;
222
+ }
223
+
224
+ try {
225
+ const fileContent = readFileSync(panelHtmlFilePath, 'utf-8');
226
+ res.setHeader('Content-Type', 'text/html');
227
+ res.send(fileContent);
228
+ } catch (error) {
229
+ console.error(`Error reading static file ${panelHtmlFilePath} for URL ${urlSegmentForPublicRoutes}:`, error);
230
+ res.status(500).send('Error loading page.');
231
+ }
232
+ });
233
+ }