underpost 2.90.0 → 2.90.4
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/.env.production +2 -0
- package/README.md +3 -2
- package/bin/build.js +4 -0
- package/bin/deploy.js +16 -0
- package/cli.md +56 -2
- package/examples/QUICK-REFERENCE.md +499 -0
- package/examples/README.md +447 -0
- package/examples/STATIC-GENERATOR-GUIDE.md +807 -0
- package/examples/ssr-components/CustomPage.js +579 -0
- package/examples/static-config-example.json +183 -0
- package/examples/static-config-simple.json +57 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +1 -1
- package/src/api/document/document.model.js +7 -0
- package/src/api/document/document.service.js +4 -1
- package/src/cli/index.js +105 -1
- package/src/cli/run.js +1 -1
- package/src/cli/static.js +820 -0
- package/src/client/components/core/Input.js +6 -4
- package/src/client/components/core/Modal.js +13 -18
- package/src/client/components/core/Panel.js +26 -6
- package/src/client/components/core/PanelForm.js +67 -52
- package/src/index.js +10 -1
- package/src/server/client-build.js +9 -15
|
@@ -102,8 +102,8 @@ const Input = {
|
|
|
102
102
|
</div>
|
|
103
103
|
`
|
|
104
104
|
: options?.placeholderIcon
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
? html` <div class="fl input-row-${id}">${options.placeholderIcon} ${inputElement}</div> `
|
|
106
|
+
: inputElement}
|
|
107
107
|
<div class="in input-info input-info-${id}"> </div>
|
|
108
108
|
</div>
|
|
109
109
|
</div>`;
|
|
@@ -189,7 +189,7 @@ const Input = {
|
|
|
189
189
|
|
|
190
190
|
switch (inputData.inputType) {
|
|
191
191
|
case 'file':
|
|
192
|
-
if (fileObj[inputData.model] && s(`.${inputData.id}`)) {
|
|
192
|
+
if (fileObj && fileObj[inputData.model] && s(`.${inputData.id}`)) {
|
|
193
193
|
const dataTransfer = new DataTransfer();
|
|
194
194
|
|
|
195
195
|
if (fileObj[inputData.model].fileBlob)
|
|
@@ -207,7 +207,9 @@ const Input = {
|
|
|
207
207
|
continue;
|
|
208
208
|
break;
|
|
209
209
|
case 'md':
|
|
210
|
-
|
|
210
|
+
if (fileObj && fileObj[inputData.model] && fileObj[inputData.model].mdPlain) {
|
|
211
|
+
RichText.Tokens[inputData.id].easyMDE.value(fileObj[inputData.model].mdPlain);
|
|
212
|
+
}
|
|
211
213
|
continue;
|
|
212
214
|
break;
|
|
213
215
|
|
|
@@ -54,19 +54,18 @@ const Modal = {
|
|
|
54
54
|
disableBoxShadow: false,
|
|
55
55
|
},
|
|
56
56
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
const originHeightBottomBar = 50;
|
|
58
|
+
const originHeightTopBar = 50;
|
|
59
|
+
options.heightBottomBar = 0;
|
|
60
|
+
options.heightTopBar = 100;
|
|
61
|
+
if (options && options.barMode && options.barMode === 'top-bottom-bar') {
|
|
62
|
+
options.heightTopBar = 50;
|
|
63
|
+
options.heightBottomBar = 50;
|
|
64
|
+
}
|
|
61
65
|
let width = 300;
|
|
62
66
|
let height = 400;
|
|
63
67
|
let top = options.style?.top ? options.style.top : 0;
|
|
64
68
|
let left = options.style?.left ? options.style.left : 0;
|
|
65
|
-
const topBottomBarEnable = options && options.barMode && options.barMode === 'top-bottom-bar';
|
|
66
|
-
if (!topBottomBarEnable) {
|
|
67
|
-
options.heightTopBar = options.heightTopBar + options.heightBottomBar;
|
|
68
|
-
options.heightBottomBar = 0;
|
|
69
|
-
}
|
|
70
69
|
let transition = `opacity 0.3s, box-shadow 0.3s, bottom 0.3s`;
|
|
71
70
|
const originSlideMenuWidth = 320;
|
|
72
71
|
const collapseSlideMenuWidth = 50;
|
|
@@ -828,8 +827,7 @@ const Modal = {
|
|
|
828
827
|
},
|
|
829
828
|
dragDisabled: true,
|
|
830
829
|
maximize: true,
|
|
831
|
-
|
|
832
|
-
heightTopBar: options.heightTopBar,
|
|
830
|
+
barMode: options.barMode,
|
|
833
831
|
});
|
|
834
832
|
|
|
835
833
|
// Bind hover/focus and click-outside to dismiss
|
|
@@ -997,8 +995,6 @@ const Modal = {
|
|
|
997
995
|
dragDisabled: true,
|
|
998
996
|
maximize: true,
|
|
999
997
|
slideMenu: 'modal-menu',
|
|
1000
|
-
heightTopBar: originHeightTopBar,
|
|
1001
|
-
heightBottomBar: originHeightBottomBar,
|
|
1002
998
|
barMode: options.barMode,
|
|
1003
999
|
observer: true,
|
|
1004
1000
|
disableBoxShadow: true,
|
|
@@ -1150,7 +1146,7 @@ const Modal = {
|
|
|
1150
1146
|
dragDisabled: true,
|
|
1151
1147
|
disableCenter: true,
|
|
1152
1148
|
// maximize: true,
|
|
1153
|
-
|
|
1149
|
+
barMode: options.barMode,
|
|
1154
1150
|
});
|
|
1155
1151
|
Responsive.Event[`view-${id}`] = () => {
|
|
1156
1152
|
if (!this.Data[id] || !s(`.${id}`)) return delete Responsive.Event[`view-${id}`];
|
|
@@ -1259,8 +1255,6 @@ const Modal = {
|
|
|
1259
1255
|
},
|
|
1260
1256
|
dragDisabled: true,
|
|
1261
1257
|
maximize: true,
|
|
1262
|
-
heightBottomBar: 0,
|
|
1263
|
-
heightTopBar: originHeightTopBar,
|
|
1264
1258
|
barMode: options.barMode,
|
|
1265
1259
|
});
|
|
1266
1260
|
|
|
@@ -1319,8 +1313,6 @@ const Modal = {
|
|
|
1319
1313
|
},
|
|
1320
1314
|
dragDisabled: true,
|
|
1321
1315
|
maximize: true,
|
|
1322
|
-
heightTopBar: originHeightTopBar,
|
|
1323
|
-
heightBottomBar: originHeightBottomBar,
|
|
1324
1316
|
barMode: options.barMode,
|
|
1325
1317
|
});
|
|
1326
1318
|
|
|
@@ -2489,6 +2481,9 @@ const subMenuHandler = (routes, route) => {
|
|
|
2489
2481
|
}
|
|
2490
2482
|
setTimeout(() => {
|
|
2491
2483
|
let cid = getQueryParams().cid;
|
|
2484
|
+
if (cid && cid.includes(',')) {
|
|
2485
|
+
cid = cid.split(',')[0];
|
|
2486
|
+
}
|
|
2492
2487
|
if (s(`.main-sub-btn-active`)) s(`.main-sub-btn-active`).classList.remove('main-sub-btn-active');
|
|
2493
2488
|
if (cid && s(`.btn-${route}-${cid}`)) {
|
|
2494
2489
|
s(`.btn-${route}-${cid}`).classList.add('main-sub-btn-active');
|
|
@@ -108,12 +108,32 @@ const Panel = {
|
|
|
108
108
|
openPanelForm();
|
|
109
109
|
// s(`.btn-${idPanel}-add`).click();
|
|
110
110
|
s(`.${scrollClassContainer}`).scrollTop = 0;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
);
|
|
111
|
+
|
|
112
|
+
const originData = options.originData();
|
|
113
|
+
const filesData = options.filesData();
|
|
114
|
+
|
|
115
|
+
// Convert IDs to strings for comparison to handle ObjectId vs string issues
|
|
116
|
+
const searchId = String(obj._id || obj.id);
|
|
117
|
+
const foundOrigin = originData.find((d) => String(d._id || d.id) === searchId);
|
|
118
|
+
const foundFiles = filesData.find((d) => String(d._id || d.id) === searchId);
|
|
119
|
+
|
|
120
|
+
if (!foundOrigin) {
|
|
121
|
+
logger.error('Could not find origin data for ID:', searchId);
|
|
122
|
+
logger.error(
|
|
123
|
+
'Available originData IDs:',
|
|
124
|
+
originData.map((d) => String(d._id || d.id)),
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!foundFiles) {
|
|
129
|
+
logger.error('Could not find files data for ID:', searchId);
|
|
130
|
+
logger.error(
|
|
131
|
+
'Available filesData IDs:',
|
|
132
|
+
filesData.map((d) => String(d._id || d.id)),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Input.setValues(formData, obj, foundOrigin, foundFiles);
|
|
117
137
|
if (options.on.initEdit) await options.on.initEdit({ data: obj });
|
|
118
138
|
});
|
|
119
139
|
s(`.a-${payload._id}`).onclick = async (e) => {
|
|
@@ -230,9 +230,10 @@ const PanelForm = {
|
|
|
230
230
|
let message = '';
|
|
231
231
|
let status = 'success';
|
|
232
232
|
let indexFormDoc = -1;
|
|
233
|
-
const filesData = data.fileId ? data.fileId : [null];
|
|
234
233
|
|
|
235
|
-
|
|
234
|
+
const inputFiles = data.fileId ? data.fileId : [null];
|
|
235
|
+
|
|
236
|
+
for (const file of inputFiles) {
|
|
236
237
|
indexFormDoc++;
|
|
237
238
|
let fileId;
|
|
238
239
|
|
|
@@ -247,8 +248,17 @@ const PanelForm = {
|
|
|
247
248
|
status,
|
|
248
249
|
});
|
|
249
250
|
if (status === 'success') {
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
// Identify files by comparing filename instead of just mimetype
|
|
252
|
+
// This handles the case where an .md file is uploaded as the optional file
|
|
253
|
+
// - mdFileId: matches the generated mdFileName from the title
|
|
254
|
+
// - fileId: any other file (including other .md files)
|
|
255
|
+
for (const uploadedFile of data) {
|
|
256
|
+
if (uploadedFile.name === mdFileName) {
|
|
257
|
+
mdFileId = uploadedFile._id;
|
|
258
|
+
} else {
|
|
259
|
+
fileId = uploadedFile._id;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
252
262
|
}
|
|
253
263
|
})();
|
|
254
264
|
const body = {
|
|
@@ -329,8 +339,12 @@ const PanelForm = {
|
|
|
329
339
|
|
|
330
340
|
const getPanelData = async (isLoadMore = false) => {
|
|
331
341
|
const panelData = PanelForm.Data[idPanel];
|
|
342
|
+
logger.warn('getPanelData called, isLoadMore:', isLoadMore);
|
|
332
343
|
try {
|
|
333
|
-
if (panelData.loading || !panelData.hasMore)
|
|
344
|
+
if (panelData.loading || !panelData.hasMore) {
|
|
345
|
+
logger.warn('getPanelData early return - loading:', panelData.loading, 'hasMore:', panelData.hasMore);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
334
348
|
panelData.loading = true;
|
|
335
349
|
|
|
336
350
|
if (!isLoadMore) {
|
|
@@ -364,45 +378,51 @@ const PanelForm = {
|
|
|
364
378
|
let mdBlob, fileBlob;
|
|
365
379
|
let mdPlain, filePlain;
|
|
366
380
|
|
|
367
|
-
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
// const ext = file.name.split('.')[file.name.split('.').length - 1];
|
|
373
|
-
mdBlob = file;
|
|
374
|
-
mdPlain = await getRawContentFile(getBlobFromUint8ArrayFile(file.data.data, file.mimetype));
|
|
375
|
-
mdFileId = newInstance(mdPlain);
|
|
376
|
-
}
|
|
377
|
-
if (documentObject.fileId) {
|
|
378
|
-
const {
|
|
379
|
-
data: [file],
|
|
380
|
-
} = await FileService.get({ id: documentObject.fileId._id });
|
|
381
|
+
try {
|
|
382
|
+
{
|
|
383
|
+
const {
|
|
384
|
+
data: [file],
|
|
385
|
+
} = await FileService.get({ id: documentObject.mdFileId._id });
|
|
381
386
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
+
// const ext = file.name.split('.')[file.name.split('.').length - 1];
|
|
388
|
+
mdBlob = file;
|
|
389
|
+
mdPlain = await getRawContentFile(getBlobFromUint8ArrayFile(file.data.data, file.mimetype));
|
|
390
|
+
mdFileId = newInstance(mdPlain);
|
|
391
|
+
}
|
|
392
|
+
if (documentObject.fileId) {
|
|
393
|
+
const {
|
|
394
|
+
data: [file],
|
|
395
|
+
} = await FileService.get({ id: documentObject.fileId._id });
|
|
396
|
+
|
|
397
|
+
// const ext = file.name.split('.')[file.name.split('.').length - 1];
|
|
398
|
+
fileBlob = file;
|
|
399
|
+
filePlain = undefined;
|
|
400
|
+
fileId = getSrcFromFileData(file);
|
|
401
|
+
}
|
|
387
402
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
403
|
+
panelData.filesData.push({
|
|
404
|
+
id: documentObject._id,
|
|
405
|
+
_id: documentObject._id,
|
|
406
|
+
mdFileId: { mdBlob, mdPlain },
|
|
407
|
+
fileId: { fileBlob, filePlain },
|
|
408
|
+
});
|
|
394
409
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
410
|
+
panelData.data.push({
|
|
411
|
+
id: documentObject._id,
|
|
412
|
+
title: documentObject.title,
|
|
413
|
+
createdAt: documentObject.createdAt,
|
|
414
|
+
tags: documentObject.tags.filter((t) => !prefixTags.includes(t)),
|
|
415
|
+
mdFileId: marked.parse(mdFileId),
|
|
416
|
+
userId: documentObject.userId._id,
|
|
417
|
+
fileId,
|
|
418
|
+
tools: Elements.Data.user.main.model.user._id === documentObject.userId._id,
|
|
419
|
+
_id: documentObject._id,
|
|
420
|
+
});
|
|
421
|
+
} catch (fileError) {
|
|
422
|
+
logger.error('Error fetching files for document:', documentObject._id, fileError);
|
|
423
|
+
// Still add the document to originData even if file fetching fails
|
|
424
|
+
// but skip adding to data and filesData arrays
|
|
425
|
+
}
|
|
406
426
|
}
|
|
407
427
|
|
|
408
428
|
panelData.skip += result.data.data.length;
|
|
@@ -497,7 +517,11 @@ const PanelForm = {
|
|
|
497
517
|
JSON.stringify(Elements.Data.user.main.model.user, null, 4),
|
|
498
518
|
);
|
|
499
519
|
|
|
500
|
-
|
|
520
|
+
// Normalize empty values for comparison (undefined, null, '' should all be treated as empty)
|
|
521
|
+
const normalizedCid = cid || '';
|
|
522
|
+
const normalizedLastCid = lastCid || '';
|
|
523
|
+
|
|
524
|
+
if (loadingGetData || (normalizedLastCid === normalizedCid && !forceUpdate)) return;
|
|
501
525
|
loadingGetData = true;
|
|
502
526
|
lastUserId = newInstance(Elements.Data.user.main.model.user._id);
|
|
503
527
|
lastCid = cid;
|
|
@@ -579,16 +603,7 @@ const PanelForm = {
|
|
|
579
603
|
id: options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body',
|
|
580
604
|
routeId: options.route,
|
|
581
605
|
event: async (path) => {
|
|
582
|
-
|
|
583
|
-
...PanelForm.Data[idPanel],
|
|
584
|
-
originData: [],
|
|
585
|
-
data: [],
|
|
586
|
-
filesData: [],
|
|
587
|
-
// skip: 0,
|
|
588
|
-
limit: 3, // Load 5 items per page
|
|
589
|
-
hasMore: true,
|
|
590
|
-
loading: false,
|
|
591
|
-
};
|
|
606
|
+
// Don't manually clear arrays - updatePanel() will handle it if needed
|
|
592
607
|
await PanelForm.Data[idPanel].updatePanel();
|
|
593
608
|
},
|
|
594
609
|
});
|
package/src/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import UnderpostRun from './cli/run.js';
|
|
|
20
20
|
import UnderpostScript from './cli/script.js';
|
|
21
21
|
import UnderpostSecret from './cli/secrets.js';
|
|
22
22
|
import UnderpostSSH from './cli/ssh.js';
|
|
23
|
+
import UnderpostStatic from './cli/static.js';
|
|
23
24
|
import UnderpostTest from './cli/test.js';
|
|
24
25
|
import UnderpostStartUp from './server/start.js';
|
|
25
26
|
|
|
@@ -35,7 +36,7 @@ class Underpost {
|
|
|
35
36
|
* @type {String}
|
|
36
37
|
* @memberof Underpost
|
|
37
38
|
*/
|
|
38
|
-
static version = 'v2.90.
|
|
39
|
+
static version = 'v2.90.4';
|
|
39
40
|
/**
|
|
40
41
|
* Repository cli API
|
|
41
42
|
* @static
|
|
@@ -64,6 +65,14 @@ class Underpost {
|
|
|
64
65
|
* @memberof Underpost
|
|
65
66
|
*/
|
|
66
67
|
static start = UnderpostStartUp.API;
|
|
68
|
+
/**
|
|
69
|
+
* Static cli API
|
|
70
|
+
* @static
|
|
71
|
+
* @type {UnderpostStatic.API}
|
|
72
|
+
* @memberof Underpost
|
|
73
|
+
*/
|
|
74
|
+
static static = UnderpostStatic.API;
|
|
75
|
+
|
|
67
76
|
/**
|
|
68
77
|
* Cluster cli API
|
|
69
78
|
* @static
|
|
@@ -519,21 +519,15 @@ const buildClient = async (options = { liveClientBuildPaths: [], instances: [],
|
|
|
519
519
|
|
|
520
520
|
for (const ssrBodyComponent of confSSR[view.ssr].body) {
|
|
521
521
|
const SrrComponent = await ssrFactory(`./src/client/ssr/body/${ssrBodyComponent}.js`);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
ssrPath,
|
|
532
|
-
host,
|
|
533
|
-
path,
|
|
534
|
-
ttiLoadTimeLimit,
|
|
535
|
-
version: Underpost.version,
|
|
536
|
-
});
|
|
522
|
+
ssrBodyComponents += SrrComponent({
|
|
523
|
+
...metadata,
|
|
524
|
+
ssrPath,
|
|
525
|
+
host,
|
|
526
|
+
path,
|
|
527
|
+
ttiLoadTimeLimit,
|
|
528
|
+
version: Underpost.version,
|
|
529
|
+
backgroundImage: backgroundImage ? (path === '/' ? path : `${path}/`) + backgroundImage : undefined,
|
|
530
|
+
});
|
|
537
531
|
}
|
|
538
532
|
}
|
|
539
533
|
|