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.
@@ -102,8 +102,8 @@ const Input = {
102
102
  </div>
103
103
  `
104
104
  : options?.placeholderIcon
105
- ? html` <div class="fl input-row-${id}">${options.placeholderIcon} ${inputElement}</div> `
106
- : inputElement}
105
+ ? html` <div class="fl input-row-${id}">${options.placeholderIcon} ${inputElement}</div> `
106
+ : inputElement}
107
107
  <div class="in input-info input-info-${id}">&nbsp</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
- RichText.Tokens[inputData.id].easyMDE.value(fileObj[inputData.model].mdPlain);
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
- options.heightBottomBar = 50;
58
- options.heightTopBar = 50;
59
- let originHeightBottomBar = options.heightBottomBar ? newInstance(options.heightBottomBar) : 0;
60
- let originHeightTopBar = options.heightTopBar ? newInstance(options.heightTopBar) : 0;
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
- heightBottomBar: 0,
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
- // barMode: options.barMode,
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
- Input.setValues(
112
- formData,
113
- obj,
114
- options.originData().find((d) => d._id === obj._id || d.id === obj.id),
115
- options.filesData().find((d) => d._id === obj._id || d.id === obj.id),
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
- for (const file of filesData) {
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
- mdFileId = data[0]._id;
251
- if (data[1]) fileId = data[1]._id;
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) return;
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
- const {
369
- data: [file],
370
- } = await FileService.get({ id: documentObject.mdFileId });
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
- // const ext = file.name.split('.')[file.name.split('.').length - 1];
383
- fileBlob = file;
384
- filePlain = undefined;
385
- fileId = getSrcFromFileData(file);
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
- panelData.filesData.push({
389
- id: documentObject._id,
390
- _id: documentObject._id,
391
- mdFileId: { mdBlob, mdPlain },
392
- fileId: { fileBlob, filePlain },
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
- panelData.data.push({
396
- id: documentObject._id,
397
- title: documentObject.title,
398
- createdAt: documentObject.createdAt,
399
- tags: documentObject.tags.filter((t) => !prefixTags.includes(t)),
400
- mdFileId: marked.parse(mdFileId),
401
- userId: documentObject.userId._id,
402
- fileId,
403
- tools: Elements.Data.user.main.model.user._id === documentObject.userId._id,
404
- _id: documentObject._id,
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
- if (loadingGetData || (lastCid === cid && !forceUpdate)) return;
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
- PanelForm.Data[idPanel] = {
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.0';
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
- if (ssrBodyComponent.match('SplashScreen')) {
523
- if (backgroundImage)
524
- ssrBodyComponents += SrrComponent({
525
- ...metadata,
526
- backgroundImage: (path === '/' ? path : `${path}/`) + backgroundImage,
527
- });
528
- else ssrBodyComponents += SrrComponent({ metadata });
529
- } else
530
- ssrBodyComponents += SrrComponent({
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