@leogps/file-uploader 2.0.3 → 2.0.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.
@@ -1912,36 +1912,6 @@ module.exports = setup;
1912
1912
  })));
1913
1913
 
1914
1914
 
1915
- /***/ }),
1916
-
1917
- /***/ 791:
1918
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1919
-
1920
- "use strict";
1921
-
1922
- Object.defineProperty(exports, "__esModule", ({ value: true }));
1923
- exports.computeSHA1 = void 0;
1924
- const js_sha1_1 = __webpack_require__(9668);
1925
- const computeSHA1 = async (blob) => {
1926
- if (window.crypto && crypto.subtle && crypto.subtle.digest) {
1927
- try {
1928
- const buffer = await blob.arrayBuffer();
1929
- const hashBuffer = await crypto.subtle.digest("SHA-1", buffer);
1930
- const hashArray = Array.from(new Uint8Array(hashBuffer));
1931
- return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
1932
- }
1933
- catch (err) {
1934
- console.warn("WebCrypto SHA-1 failed, falling back to js-sha1:", err);
1935
- }
1936
- }
1937
- // Fallback to js-sha1
1938
- const arrayBuffer = await blob.arrayBuffer();
1939
- const bytes = new Uint8Array(arrayBuffer);
1940
- return (0, js_sha1_1.sha1)(bytes);
1941
- };
1942
- exports.computeSHA1 = computeSHA1;
1943
-
1944
-
1945
1915
  /***/ }),
1946
1916
 
1947
1917
  /***/ 838:
@@ -6096,229 +6066,6 @@ const decode = (base64) => {
6096
6066
  exports.decode = decode;
6097
6067
 
6098
6068
 
6099
- /***/ }),
6100
-
6101
- /***/ 2844:
6102
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6103
-
6104
- "use strict";
6105
- /* provided dependency */ var $ = __webpack_require__(4692);
6106
- /* provided dependency */ var jQuery = __webpack_require__(4692);
6107
-
6108
- var __importDefault = (this && this.__importDefault) || function (mod) {
6109
- return (mod && mod.__esModule) ? mod : { "default": mod };
6110
- };
6111
- Object.defineProperty(exports, "__esModule", ({ value: true }));
6112
- exports.ProgressHandler = void 0;
6113
- const socket_io_client_1 = __webpack_require__(8007);
6114
- const progress_utils_1 = __webpack_require__(4753);
6115
- const moment_1 = __importDefault(__webpack_require__(5093));
6116
- const pretty_bytes_1 = __importDefault(__webpack_require__(281));
6117
- const _progressDivCache = new Map();
6118
- const stateColorMap = {
6119
- COMPLETE: "is-success",
6120
- FAILED: "is-danger",
6121
- };
6122
- class ProgressHandler {
6123
- addToDomCache(progressId, $panel) {
6124
- _progressDivCache.set(progressId, $panel);
6125
- this.updateCollapseAllVisibility();
6126
- }
6127
- getFromDomCache(progressId) {
6128
- return _progressDivCache.get(progressId);
6129
- }
6130
- domCacheSize() {
6131
- return _progressDivCache.size;
6132
- }
6133
- registerHandler() {
6134
- console.log("Registering Progress Handler...");
6135
- const socket = (0, socket_io_client_1.io)();
6136
- socket.emit("message", "Connected.");
6137
- socket.on("progresses", (progresses) => {
6138
- this.handleProgresses(progresses);
6139
- });
6140
- this.registerAllDetailToggleEventHandler();
6141
- console.log("Progress handler registration complete.");
6142
- }
6143
- updateCollapseAllVisibility() {
6144
- const $control = $(".all-progress-detail-control");
6145
- if (this.domCacheSize() > 0) {
6146
- $control.removeClass("is-hidden");
6147
- }
6148
- else {
6149
- $control.addClass("is-hidden");
6150
- }
6151
- const $parentElem = jQuery(".single-progress-container");
6152
- const $btn = jQuery(".all-progress-detail-control button");
6153
- const $progressDetailElems = $parentElem
6154
- .find("[id^='progressTableContainer-']");
6155
- const $hiddenProgressDetailElems = $parentElem
6156
- .find("[id^='progressTableContainer-'].is-hidden");
6157
- const allHidden = $hiddenProgressDetailElems.length === $progressDetailElems.length;
6158
- const buttonLabel = allHidden ? "Expand All" : "Collapse All";
6159
- $btn.text(buttonLabel);
6160
- }
6161
- registerAllDetailToggleEventHandler() {
6162
- const $btn = jQuery(".all-progress-detail-control button");
6163
- $btn.on("click", () => {
6164
- const collapseAll = $btn.text().trim() === "Collapse All";
6165
- const newLabel = collapseAll ? "Expand All" : "Collapse All";
6166
- $btn.text(newLabel);
6167
- // Loop through every progress panel
6168
- jQuery(".single-progress-container").each((_, panel) => {
6169
- const $panel = jQuery(panel);
6170
- const $toggle = $panel.find(".progress-detail-control");
6171
- const $icon = $toggle.find("i");
6172
- // table container selector
6173
- const panelId = $panel.attr("id");
6174
- const tableContainerId = `progressTableContainer-${panelId}`;
6175
- const $tableContainer = jQuery(`#${tableContainerId}`);
6176
- if (collapseAll) {
6177
- // collapse everything
6178
- $toggle.removeClass("is-active");
6179
- $tableContainer.addClass("is-hidden");
6180
- $icon.removeClass("fa-minus-circle").addClass("fa-plus-circle")
6181
- .attr("title", "expand");
6182
- }
6183
- else {
6184
- // expand everything
6185
- $toggle.addClass("is-active");
6186
- $tableContainer.removeClass("is-hidden");
6187
- $icon.removeClass("fa-plus-circle").addClass("fa-minus-circle")
6188
- .attr("title", "collapse");
6189
- }
6190
- });
6191
- });
6192
- }
6193
- registerDetailToggleEventHandler($panel, tableContainerId) {
6194
- $panel.on("click", ".progress-detail-control", (event) => {
6195
- const $btn = jQuery(event.currentTarget);
6196
- const $tableContainer = jQuery(`#${tableContainerId}`);
6197
- // toggle active class
6198
- const isActive = $btn.toggleClass("is-active").hasClass("is-active");
6199
- // toggle content visibility
6200
- if (isActive) {
6201
- $tableContainer.removeClass("is-hidden");
6202
- }
6203
- else {
6204
- $tableContainer.addClass("is-hidden");
6205
- }
6206
- // toggle icon
6207
- const $icon = $btn.find("i");
6208
- if (isActive) {
6209
- // expanded → show minus
6210
- $icon.removeClass("fa-plus-circle").addClass("fa-minus-circle");
6211
- $icon.attr("title", "collapse");
6212
- }
6213
- else {
6214
- // collapsed → show plus
6215
- $icon.removeClass("fa-minus-circle").addClass("fa-plus-circle");
6216
- $icon.attr("title", "expand");
6217
- }
6218
- // no need for _this alias
6219
- this.updateCollapseAllVisibility();
6220
- });
6221
- }
6222
- handleProgresses(progresses) {
6223
- const $progressContainer = jQuery("div#progress-container");
6224
- progresses.forEach(progress => {
6225
- const progressId = `progress-${progress.uuid}`;
6226
- const uploaded = progress.uploadedChunks?.length ?? 0;
6227
- const uploading = progress.uploadingChunks?.length ?? 0;
6228
- const totalChunks = progress.totalChunks ?? 1;
6229
- const colorKey = progress.lastState;
6230
- const stateColor = stateColorMap[colorKey] || "";
6231
- // Container box
6232
- let $panel = this.getFromDomCache(progressId);
6233
- const tableContainerId = `progressTableContainer-${progressId}`;
6234
- if (!$panel) {
6235
- $panel = jQuery(`<article id="${progressId}" class="progress-panel panel is-bordered single-progress-container mb-4"></article>`);
6236
- $progressContainer.prepend($panel);
6237
- this.addToDomCache(progressId, $panel);
6238
- this.registerDetailToggleEventHandler($panel, tableContainerId);
6239
- }
6240
- // Remove existing progress colors
6241
- $panel.removeClass("is-success is-danger is-info is-warning");
6242
- $panel.addClass(stateColor || "is-info");
6243
- // Add file name as a heading above the table
6244
- const panelHeadingId = `panelHeading-${progressId}`;
6245
- let $panelHeading = $panel.find(`#${panelHeadingId}`);
6246
- if (!$panelHeading.length) {
6247
- $panelHeading = jQuery(`<div id="${panelHeadingId}" class="panel-heading wrap-text is-flex-wrap-wrap p-2 has-text-weight-normal is-size-6 mb-1">
6248
- <a class="progress-detail-control is-active ml-1 mr-1">
6249
- <span class="panel-icon m-0 p-0">
6250
- <i class="fas fa-minus-circle m-0 p-0" aria-hidden="true" title="collapse"></i>
6251
- </span>
6252
- </a>
6253
- <span class="upload-file-name ml-0 pl-0">
6254
- ${progress.fileName}
6255
- </span>
6256
- </div>`);
6257
- $panel.append($panelHeading);
6258
- }
6259
- $panelHeading.find(".upload-file-name").text(progress.fileName || "");
6260
- // Main progress bar (bytes)
6261
- let $progressElem = $panel.find(`progress#${progressId}`);
6262
- if (!$progressElem.length) {
6263
- $progressElem = jQuery(`<progress id="${progressId}" class="progress is-info is-small">`);
6264
- $panel.append($progressElem);
6265
- }
6266
- $progressElem.attr("max", (progress.bytesExpected || 100));
6267
- $progressElem.attr("value", (progress.bytesReceived || 0));
6268
- // Remove existing progress colors
6269
- $progressElem.removeClass("is-success is-danger is-info is-warning");
6270
- $progressElem.addClass(stateColor || "is-info");
6271
- let $tableContainer = $panel.find(`#${tableContainerId}`);
6272
- if (!$tableContainer.length) {
6273
- $tableContainer = jQuery(`<div id="${tableContainerId}" class="panel-block table-container m-0 p-0"></div>`);
6274
- $panel.append($tableContainer);
6275
- }
6276
- const tableId = `progressTable-${progressId}`;
6277
- let $table = $tableContainer.find(`#${tableId}`);
6278
- if (!$table.length) {
6279
- $table = jQuery(`<table id="${tableId}" class="table is-fullwidth is-bordered is-striped"></table>`);
6280
- $tableContainer.append($table);
6281
- }
6282
- // Clear previous rows
6283
- $table.empty();
6284
- let progressPercent = 0;
6285
- if (progress.bytesReceived !== undefined && progress.bytesExpected !== undefined) {
6286
- progressPercent = (progress.bytesReceived / progress.bytesExpected) * 100;
6287
- }
6288
- // Define table rows
6289
- const rows = [
6290
- // ["File Name", progress.fileName || "-"],
6291
- // ["Location", progress.savedLocation || "-"],
6292
- ["Started", (0, moment_1.default)(progress.timestamp).format("MMMM Do YYYY, h:mm:ss a")],
6293
- ["Transferred", `${(0, pretty_bytes_1.default)(progress.bytesReceived || 0)} / ${(0, pretty_bytes_1.default)(progress.bytesExpected || 0)}`],
6294
- ["Chunks", `Verified ${progress.chunkVerificationCount || 0}
6295
- <b>|</b> Uploading: ${uploading}
6296
- <b>|</b> Uploaded: ${uploaded}/${totalChunks}`],
6297
- ["Speed", `${(0, pretty_bytes_1.default)(progress_utils_1.ProgressUtils.calculateTransferRate(progress))}/s`],
6298
- ["Status", `${progress.lastState || "-"}`],
6299
- ["Progress", `${progressPercent.toFixed(2)}%`],
6300
- ];
6301
- if (progress.completed) {
6302
- const timeTaken = ((progress.completed - (progress.timestamp || 0)) / 1000).toFixed(2);
6303
- rows.push(["Completed in", `${timeTaken} sec`]);
6304
- }
6305
- // Append rows
6306
- for (const [key, value] of rows) {
6307
- $table.append(`<tr><th class="is-narrow">${key}</th><td>${value}</td></tr>`);
6308
- }
6309
- const horizontalRulerId = `horizontalRuler-${progressId}`;
6310
- let $horizontalRuler = $panel.find(`#${horizontalRulerId}`);
6311
- if (!$horizontalRuler.length) {
6312
- $horizontalRuler = jQuery(`<hr id="${horizontalRulerId}" class="is-one-third mt-3 mb-1">`);
6313
- $panel.append($horizontalRuler);
6314
- }
6315
- this.updateCollapseAllVisibility();
6316
- });
6317
- }
6318
- }
6319
- exports.ProgressHandler = ProgressHandler;
6320
-
6321
-
6322
6069
  /***/ }),
6323
6070
 
6324
6071
  /***/ 2934:
@@ -6581,6 +6328,48 @@ exports.ProgressHandler = ProgressHandler;
6581
6328
  })));
6582
6329
 
6583
6330
 
6331
+ /***/ }),
6332
+
6333
+ /***/ 3037:
6334
+ /***/ ((__unused_webpack_module, exports) => {
6335
+
6336
+ "use strict";
6337
+
6338
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
6339
+ exports.ProgressUtils = void 0;
6340
+ class ProgressUtils {
6341
+ static calculateTransferRate(progress) {
6342
+ const samples = progress.transferSamples;
6343
+ if (!samples || samples.length < 2) {
6344
+ return 0;
6345
+ }
6346
+ let totalBytes = 0;
6347
+ let totalTimeMs = 0;
6348
+ // Case vs Reason for skipping
6349
+ // bytes === 0 idle / waiting / verification
6350
+ // bytes < 0 possibly corrupted or reset counter
6351
+ // timeMs === 0 divide-by-zero risk
6352
+ // timeMs < 0 invalid timestamp
6353
+ // To prevent idle gaps from dragging the rate down artificially.
6354
+ for (let i = 1; i < samples.length; i++) {
6355
+ const prev = samples[i - 1];
6356
+ const curr = samples[i];
6357
+ const bytes = curr.bytesReceived - prev.bytesReceived;
6358
+ const timeMs = curr.timestamp - prev.timestamp;
6359
+ if (bytes > 0 && timeMs > 0) {
6360
+ totalBytes += bytes;
6361
+ totalTimeMs += timeMs;
6362
+ }
6363
+ }
6364
+ if (totalTimeMs === 0) {
6365
+ return 0;
6366
+ }
6367
+ return totalBytes / (totalTimeMs / 1000);
6368
+ }
6369
+ }
6370
+ exports.ProgressUtils = ProgressUtils;
6371
+
6372
+
6584
6373
  /***/ }),
6585
6374
 
6586
6375
  /***/ 3164:
@@ -21009,48 +20798,6 @@ return jQuery;
21009
20798
  })));
21010
20799
 
21011
20800
 
21012
- /***/ }),
21013
-
21014
- /***/ 4753:
21015
- /***/ ((__unused_webpack_module, exports) => {
21016
-
21017
- "use strict";
21018
-
21019
- Object.defineProperty(exports, "__esModule", ({ value: true }));
21020
- exports.ProgressUtils = void 0;
21021
- class ProgressUtils {
21022
- static calculateTransferRate(progress) {
21023
- const samples = progress.transferSamples;
21024
- if (!samples || samples.length < 2) {
21025
- return 0;
21026
- }
21027
- let totalBytes = 0;
21028
- let totalTimeMs = 0;
21029
- // Case vs Reason for skipping
21030
- // bytes === 0 idle / waiting / verification
21031
- // bytes < 0 possibly corrupted or reset counter
21032
- // timeMs === 0 divide-by-zero risk
21033
- // timeMs < 0 invalid timestamp
21034
- // To prevent idle gaps from dragging the rate down artificially.
21035
- for (let i = 1; i < samples.length; i++) {
21036
- const prev = samples[i - 1];
21037
- const curr = samples[i];
21038
- const bytes = curr.bytesReceived - prev.bytesReceived;
21039
- const timeMs = curr.timestamp - prev.timestamp;
21040
- if (bytes > 0 && timeMs > 0) {
21041
- totalBytes += bytes;
21042
- totalTimeMs += timeMs;
21043
- }
21044
- }
21045
- if (totalTimeMs === 0) {
21046
- return 0;
21047
- }
21048
- return totalBytes / (totalTimeMs / 1000);
21049
- }
21050
- }
21051
- exports.ProgressUtils = ProgressUtils;
21052
-
21053
-
21054
20801
  /***/ }),
21055
20802
 
21056
20803
  /***/ 4903:
@@ -27191,6 +26938,36 @@ Object.defineProperty(exports, "nextTick", ({ enumerable: true, get: function ()
27191
26938
  })));
27192
26939
 
27193
26940
 
26941
+ /***/ }),
26942
+
26943
+ /***/ 5131:
26944
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
26945
+
26946
+ "use strict";
26947
+
26948
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
26949
+ exports.computeSHA1 = void 0;
26950
+ const js_sha1_1 = __webpack_require__(9668);
26951
+ const computeSHA1 = async (blob) => {
26952
+ if (window.crypto && crypto.subtle && crypto.subtle.digest) {
26953
+ try {
26954
+ const buffer = await blob.arrayBuffer();
26955
+ const hashBuffer = await crypto.subtle.digest("SHA-1", buffer);
26956
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
26957
+ return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
26958
+ }
26959
+ catch (err) {
26960
+ console.warn("WebCrypto SHA-1 failed, falling back to js-sha1:", err);
26961
+ }
26962
+ }
26963
+ // Fallback to js-sha1
26964
+ const arrayBuffer = await blob.arrayBuffer();
26965
+ const bytes = new Uint8Array(arrayBuffer);
26966
+ return (0, js_sha1_1.sha1)(bytes);
26967
+ };
26968
+ exports.computeSHA1 = computeSHA1;
26969
+
26970
+
27194
26971
  /***/ }),
27195
26972
 
27196
26973
  /***/ 5177:
@@ -27966,7 +27743,7 @@ function utf8Length(str) {
27966
27743
 
27967
27744
  /***/ }),
27968
27745
 
27969
- /***/ 5600:
27746
+ /***/ 5668:
27970
27747
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
27971
27748
 
27972
27749
  "use strict";
@@ -27977,11 +27754,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27977
27754
  return (mod && mod.__esModule) ? mod : { "default": mod };
27978
27755
  };
27979
27756
  Object.defineProperty(exports, "__esModule", ({ value: true }));
27980
- const progress_handler_1 = __webpack_require__(2844);
27757
+ const progress_handler_1 = __webpack_require__(5792);
27981
27758
  __webpack_require__(5838);
27982
27759
  __webpack_require__(9968);
27983
27760
  const toastify_js_1 = __importDefault(__webpack_require__(7736));
27984
- const sha1_1 = __webpack_require__(791);
27761
+ const sha1_1 = __webpack_require__(5131);
27985
27762
  const MAX_COMPLETE_CHECK_RETRIES = 20;
27986
27763
  const COMPLETE_CHECK_RETRY_DELAY_MS = 1000;
27987
27764
  jQuery(() => {
@@ -27990,6 +27767,19 @@ jQuery(() => {
27990
27767
  const pageEventRegistrar = new PageEventRegistrar();
27991
27768
  pageEventRegistrar.registerEvents();
27992
27769
  });
27770
+ const asyncPool = async (poolLimit, array, iteratorFn) => {
27771
+ const executing = new Set();
27772
+ for (const item of array) {
27773
+ const p = Promise.resolve().then(() => iteratorFn(item));
27774
+ executing.add(p);
27775
+ const clean = () => executing.delete(p);
27776
+ p.then(clean).catch(clean);
27777
+ if (executing.size >= poolLimit) {
27778
+ await Promise.race(executing);
27779
+ }
27780
+ }
27781
+ await Promise.all(executing);
27782
+ };
27993
27783
  class PageEventRegistrar {
27994
27784
  registerEvents() {
27995
27785
  this.registerThemeSelectionEventHandler();
@@ -28062,35 +27852,40 @@ class PageEventRegistrar {
28062
27852
  }).showToast();
28063
27853
  return;
28064
27854
  }
28065
- const disableChunked = (jQuery("#disableChunkedUpload").prop("checked") === true);
28066
27855
  // Block form before uploading
28067
27856
  $uploadForm.block({
28068
27857
  message: '<h1 class="upload-block-modal p-2 m-0">Uploading...</h1>'
28069
27858
  });
28070
- try {
28071
- // Upload all files sequentially
28072
- for (const file of Array.from(files)) {
28073
- if (disableChunked) {
28074
- await this.uploadFileNonChunked(file);
28075
- }
28076
- else {
28077
- await this.uploadFile(file);
28078
- }
27859
+ const disableChunked = (jQuery("#disableChunkedUpload").prop("checked") === true);
27860
+ console.log("disableChunked?", disableChunked);
27861
+ const serverConfigResponse = await this.retrieveConfig();
27862
+ const errorMessage = serverConfigResponse.error;
27863
+ if (errorMessage) {
27864
+ let errorText = errorMessage;
27865
+ const errorObject = serverConfigResponse.errorObject;
27866
+ const errorObjectMessage = errorObject instanceof Error ? errorObject.message : String(errorObject);
27867
+ if (serverConfigResponse.errorObject) {
27868
+ errorText = `${errorText}. ${errorObjectMessage}`;
28079
27869
  }
27870
+ console.error(errorText);
27871
+ (0, toastify_js_1.default)({
27872
+ text: errorText,
27873
+ duration: -1,
27874
+ close: true,
27875
+ style: { background: "linear-gradient(to right, #F39454, #FF6600)" }
27876
+ }).showToast();
28080
27877
  }
28081
- finally {
28082
- // Unblock and reset form after all files finish
28083
- $uploadForm.trigger("reset");
28084
- const $fileDiv = jQuery("#file-div");
28085
- const $fileNameDiv = $fileDiv.find("#file-name");
28086
- const $fileInput = jQuery("form#uploadForm input[name='file']");
28087
- this.onFilesChange($fileNameDiv, $fileInput);
28088
- $uploadForm.unblock();
28089
- }
27878
+ const serverConfigJson = serverConfigResponse.response;
27879
+ await this.doUpload(files, {
27880
+ $uploadForm,
27881
+ serverConfig: serverConfigJson,
27882
+ disableChunkedUpload: disableChunked,
27883
+ });
28090
27884
  })().catch(err => {
27885
+ const message = err instanceof Error ? err.message : String(err);
28091
27886
  console.error("Error during upload:", err);
28092
27887
  (0, toastify_js_1.default)({
28093
- text: `Upload error: ${err}`,
27888
+ text: `Upload failed: ${message}`,
28094
27889
  duration: -1,
28095
27890
  close: true,
28096
27891
  style: { background: "linear-gradient(to right, #F39454, #FF6600)" }
@@ -28098,6 +27893,40 @@ class PageEventRegistrar {
28098
27893
  });
28099
27894
  });
28100
27895
  }
27896
+ async doUpload(files, { disableChunkedUpload = false, serverConfig, $uploadForm, }) {
27897
+ try {
27898
+ let maxParallelFileUploads = 1;
27899
+ if (serverConfig != null) {
27900
+ maxParallelFileUploads = serverConfig.maxParallelFileUploads;
27901
+ }
27902
+ console.log(`Max parallel file uploads: ${maxParallelFileUploads}`);
27903
+ await asyncPool(maxParallelFileUploads, Array.from(files), async (file) => {
27904
+ if (disableChunkedUpload) {
27905
+ await this.uploadFileNonChunked(file);
27906
+ }
27907
+ else {
27908
+ await this.uploadFile(file);
27909
+ }
27910
+ }).catch(err => {
27911
+ console.error("Error during upload:", err);
27912
+ (0, toastify_js_1.default)({
27913
+ text: `Upload failed: ${err}`,
27914
+ duration: -1,
27915
+ close: true,
27916
+ style: { background: "linear-gradient(to right, #F39454, #FF6600)" }
27917
+ }).showToast();
27918
+ });
27919
+ }
27920
+ finally {
27921
+ // Unblock and reset form after all files finish
27922
+ $uploadForm.trigger("reset");
27923
+ const $fileDiv = jQuery("#file-div");
27924
+ const $fileNameDiv = $fileDiv.find("#file-name");
27925
+ const $fileInput = jQuery("form#uploadForm input[name='file']");
27926
+ this.onFilesChange($fileNameDiv, $fileInput);
27927
+ $uploadForm.unblock();
27928
+ }
27929
+ }
28101
27930
  async uploadFileNonChunked(file) {
28102
27931
  const formData = new FormData();
28103
27932
  // Server-side uses formidable({ multiples: true }) so using the same field name is fine
@@ -28135,7 +27964,7 @@ class PageEventRegistrar {
28135
27964
  const initData = await initResp.json();
28136
27965
  const fileId = initData.fileId;
28137
27966
  const chunkSize = initData.chunkSize;
28138
- const maxParallel = initData.maxParallel || 3;
27967
+ const maxParallelChunkUploads = initData.maxParallelChunkUploads || 3;
28139
27968
  const totalChunks = Math.ceil(file.size / chunkSize);
28140
27969
  // Active upload pool
28141
27970
  const pool = [];
@@ -28175,7 +28004,7 @@ class PageEventRegistrar {
28175
28004
  });
28176
28005
  pool.push(taskPromise);
28177
28006
  // If pool is full, wait for at least one to finish
28178
- if (pool.length >= maxParallel) {
28007
+ if (pool.length >= maxParallelChunkUploads) {
28179
28008
  await Promise.race(pool).catch((err) => {
28180
28009
  console.warn(`Pool full, but one task failed, err: ${err}`);
28181
28010
  }); // don't block other tasks
@@ -28251,6 +28080,28 @@ class PageEventRegistrar {
28251
28080
  }
28252
28081
  }
28253
28082
  }
28083
+ async retrieveConfig() {
28084
+ try {
28085
+ const response = await fetch(`/config`);
28086
+ if (response.ok) {
28087
+ const serverConfigJson = await response.json();
28088
+ return {
28089
+ response: serverConfigJson
28090
+ };
28091
+ }
28092
+ return {
28093
+ "error": `Could not retrieve config: ${response.status}`
28094
+ };
28095
+ }
28096
+ catch (error) {
28097
+ const errorMessage = error instanceof Error ? error.message : String(error);
28098
+ console.error(`Could not retrieve config: ${errorMessage}`);
28099
+ return {
28100
+ error: `Failed to retrieve config: ${errorMessage}`,
28101
+ errorObject: error,
28102
+ };
28103
+ }
28104
+ }
28254
28105
  }
28255
28106
 
28256
28107
 
@@ -28701,6 +28552,229 @@ class PageEventRegistrar {
28701
28552
  })));
28702
28553
 
28703
28554
 
28555
+ /***/ }),
28556
+
28557
+ /***/ 5792:
28558
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
28559
+
28560
+ "use strict";
28561
+ /* provided dependency */ var $ = __webpack_require__(4692);
28562
+ /* provided dependency */ var jQuery = __webpack_require__(4692);
28563
+
28564
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28565
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28566
+ };
28567
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
28568
+ exports.ProgressHandler = void 0;
28569
+ const socket_io_client_1 = __webpack_require__(8007);
28570
+ const progress_utils_1 = __webpack_require__(3037);
28571
+ const moment_1 = __importDefault(__webpack_require__(5093));
28572
+ const pretty_bytes_1 = __importDefault(__webpack_require__(281));
28573
+ const _progressDivCache = new Map();
28574
+ const stateColorMap = {
28575
+ COMPLETE: "is-success",
28576
+ FAILED: "is-danger",
28577
+ };
28578
+ class ProgressHandler {
28579
+ addToDomCache(progressId, $panel) {
28580
+ _progressDivCache.set(progressId, $panel);
28581
+ this.updateCollapseAllVisibility();
28582
+ }
28583
+ getFromDomCache(progressId) {
28584
+ return _progressDivCache.get(progressId);
28585
+ }
28586
+ domCacheSize() {
28587
+ return _progressDivCache.size;
28588
+ }
28589
+ registerHandler() {
28590
+ console.log("Registering Progress Handler...");
28591
+ const socket = (0, socket_io_client_1.io)();
28592
+ socket.emit("message", "Connected.");
28593
+ socket.on("progresses", (progresses) => {
28594
+ this.handleProgresses(progresses);
28595
+ });
28596
+ this.registerAllDetailToggleEventHandler();
28597
+ console.log("Progress handler registration complete.");
28598
+ }
28599
+ updateCollapseAllVisibility() {
28600
+ const $control = $(".all-progress-detail-control");
28601
+ if (this.domCacheSize() > 0) {
28602
+ $control.removeClass("is-hidden");
28603
+ }
28604
+ else {
28605
+ $control.addClass("is-hidden");
28606
+ }
28607
+ const $parentElem = jQuery(".single-progress-container");
28608
+ const $btn = jQuery(".all-progress-detail-control button");
28609
+ const $progressDetailElems = $parentElem
28610
+ .find("[id^='progressTableContainer-']");
28611
+ const $hiddenProgressDetailElems = $parentElem
28612
+ .find("[id^='progressTableContainer-'].is-hidden");
28613
+ const allHidden = $hiddenProgressDetailElems.length === $progressDetailElems.length;
28614
+ const buttonLabel = allHidden ? "Expand All" : "Collapse All";
28615
+ $btn.text(buttonLabel);
28616
+ }
28617
+ registerAllDetailToggleEventHandler() {
28618
+ const $btn = jQuery(".all-progress-detail-control button");
28619
+ $btn.on("click", () => {
28620
+ const collapseAll = $btn.text().trim() === "Collapse All";
28621
+ const newLabel = collapseAll ? "Expand All" : "Collapse All";
28622
+ $btn.text(newLabel);
28623
+ // Loop through every progress panel
28624
+ jQuery(".single-progress-container").each((_, panel) => {
28625
+ const $panel = jQuery(panel);
28626
+ const $toggle = $panel.find(".progress-detail-control");
28627
+ const $icon = $toggle.find("i");
28628
+ // table container selector
28629
+ const panelId = $panel.attr("id");
28630
+ const tableContainerId = `progressTableContainer-${panelId}`;
28631
+ const $tableContainer = jQuery(`#${tableContainerId}`);
28632
+ if (collapseAll) {
28633
+ // collapse everything
28634
+ $toggle.removeClass("is-active");
28635
+ $tableContainer.addClass("is-hidden");
28636
+ $icon.removeClass("fa-minus-circle").addClass("fa-plus-circle")
28637
+ .attr("title", "expand");
28638
+ }
28639
+ else {
28640
+ // expand everything
28641
+ $toggle.addClass("is-active");
28642
+ $tableContainer.removeClass("is-hidden");
28643
+ $icon.removeClass("fa-plus-circle").addClass("fa-minus-circle")
28644
+ .attr("title", "collapse");
28645
+ }
28646
+ });
28647
+ });
28648
+ }
28649
+ registerDetailToggleEventHandler($panel, tableContainerId) {
28650
+ $panel.on("click", ".progress-detail-control", (event) => {
28651
+ const $btn = jQuery(event.currentTarget);
28652
+ const $tableContainer = jQuery(`#${tableContainerId}`);
28653
+ // toggle active class
28654
+ const isActive = $btn.toggleClass("is-active").hasClass("is-active");
28655
+ // toggle content visibility
28656
+ if (isActive) {
28657
+ $tableContainer.removeClass("is-hidden");
28658
+ }
28659
+ else {
28660
+ $tableContainer.addClass("is-hidden");
28661
+ }
28662
+ // toggle icon
28663
+ const $icon = $btn.find("i");
28664
+ if (isActive) {
28665
+ // expanded → show minus
28666
+ $icon.removeClass("fa-plus-circle").addClass("fa-minus-circle");
28667
+ $icon.attr("title", "collapse");
28668
+ }
28669
+ else {
28670
+ // collapsed → show plus
28671
+ $icon.removeClass("fa-minus-circle").addClass("fa-plus-circle");
28672
+ $icon.attr("title", "expand");
28673
+ }
28674
+ // no need for _this alias
28675
+ this.updateCollapseAllVisibility();
28676
+ });
28677
+ }
28678
+ handleProgresses(progresses) {
28679
+ const $progressContainer = jQuery("div#progress-container");
28680
+ progresses.forEach(progress => {
28681
+ const progressId = `progress-${progress.uuid}`;
28682
+ const uploaded = progress.uploadedChunks?.length ?? 0;
28683
+ const uploading = progress.uploadingChunks?.length ?? 0;
28684
+ const totalChunks = progress.totalChunks ?? 1;
28685
+ const colorKey = progress.lastState;
28686
+ const stateColor = stateColorMap[colorKey] || "";
28687
+ // Container box
28688
+ let $panel = this.getFromDomCache(progressId);
28689
+ const tableContainerId = `progressTableContainer-${progressId}`;
28690
+ if (!$panel) {
28691
+ $panel = jQuery(`<article id="${progressId}" class="progress-panel panel is-bordered single-progress-container mb-4"></article>`);
28692
+ $progressContainer.prepend($panel);
28693
+ this.addToDomCache(progressId, $panel);
28694
+ this.registerDetailToggleEventHandler($panel, tableContainerId);
28695
+ }
28696
+ // Remove existing progress colors
28697
+ $panel.removeClass("is-success is-danger is-info is-warning");
28698
+ $panel.addClass(stateColor || "is-info");
28699
+ // Add file name as a heading above the table
28700
+ const panelHeadingId = `panelHeading-${progressId}`;
28701
+ let $panelHeading = $panel.find(`#${panelHeadingId}`);
28702
+ if (!$panelHeading.length) {
28703
+ $panelHeading = jQuery(`<div id="${panelHeadingId}" class="panel-heading wrap-text is-flex-wrap-wrap p-2 has-text-weight-normal is-size-6 mb-1">
28704
+ <a class="progress-detail-control is-active ml-1 mr-1">
28705
+ <span class="panel-icon m-0 p-0">
28706
+ <i class="fas fa-minus-circle m-0 p-0" aria-hidden="true" title="collapse"></i>
28707
+ </span>
28708
+ </a>
28709
+ <span class="upload-file-name ml-0 pl-0">
28710
+ ${progress.fileName}
28711
+ </span>
28712
+ </div>`);
28713
+ $panel.append($panelHeading);
28714
+ }
28715
+ $panelHeading.find(".upload-file-name").text(progress.fileName || "");
28716
+ // Main progress bar (bytes)
28717
+ let $progressElem = $panel.find(`progress#${progressId}`);
28718
+ if (!$progressElem.length) {
28719
+ $progressElem = jQuery(`<progress id="${progressId}" class="progress is-info is-small">`);
28720
+ $panel.append($progressElem);
28721
+ }
28722
+ $progressElem.attr("max", (progress.bytesExpected || 100));
28723
+ $progressElem.attr("value", (progress.bytesReceived || 0));
28724
+ // Remove existing progress colors
28725
+ $progressElem.removeClass("is-success is-danger is-info is-warning");
28726
+ $progressElem.addClass(stateColor || "is-info");
28727
+ let $tableContainer = $panel.find(`#${tableContainerId}`);
28728
+ if (!$tableContainer.length) {
28729
+ $tableContainer = jQuery(`<div id="${tableContainerId}" class="panel-block table-container m-0 p-0"></div>`);
28730
+ $panel.append($tableContainer);
28731
+ }
28732
+ const tableId = `progressTable-${progressId}`;
28733
+ let $table = $tableContainer.find(`#${tableId}`);
28734
+ if (!$table.length) {
28735
+ $table = jQuery(`<table id="${tableId}" class="table is-fullwidth is-bordered is-striped"></table>`);
28736
+ $tableContainer.append($table);
28737
+ }
28738
+ // Clear previous rows
28739
+ $table.empty();
28740
+ let progressPercent = 0;
28741
+ if (progress.bytesReceived !== undefined && progress.bytesExpected !== undefined) {
28742
+ progressPercent = (progress.bytesReceived / progress.bytesExpected) * 100;
28743
+ }
28744
+ // Define table rows
28745
+ const rows = [
28746
+ // ["File Name", progress.fileName || "-"],
28747
+ // ["Location", progress.savedLocation || "-"],
28748
+ ["Started", (0, moment_1.default)(progress.timestamp).format("MMMM Do YYYY, h:mm:ss a")],
28749
+ ["Transferred", `${(0, pretty_bytes_1.default)(progress.bytesReceived || 0)} / ${(0, pretty_bytes_1.default)(progress.bytesExpected || 0)}`],
28750
+ ["Chunks", `Verified ${progress.chunkVerificationCount || 0}
28751
+ <b>|</b> Uploading: ${uploading}
28752
+ <b>|</b> Uploaded: ${uploaded}/${totalChunks}`],
28753
+ ["Speed", `${(0, pretty_bytes_1.default)(progress_utils_1.ProgressUtils.calculateTransferRate(progress))}/s`],
28754
+ ["Status", `${progress.lastState || "-"}`],
28755
+ ["Progress", `${progressPercent.toFixed(2)}%`],
28756
+ ];
28757
+ if (progress.completed) {
28758
+ const timeTaken = ((progress.completed - (progress.timestamp || 0)) / 1000).toFixed(2);
28759
+ rows.push(["Completed in", `${timeTaken} sec`]);
28760
+ }
28761
+ // Append rows
28762
+ for (const [key, value] of rows) {
28763
+ $table.append(`<tr><th class="is-narrow">${key}</th><td>${value}</td></tr>`);
28764
+ }
28765
+ const horizontalRulerId = `horizontalRuler-${progressId}`;
28766
+ let $horizontalRuler = $panel.find(`#${horizontalRulerId}`);
28767
+ if (!$horizontalRuler.length) {
28768
+ $horizontalRuler = jQuery(`<hr id="${horizontalRulerId}" class="is-one-third mt-3 mb-1">`);
28769
+ $panel.append($horizontalRuler);
28770
+ }
28771
+ this.updateCollapseAllVisibility();
28772
+ });
28773
+ }
28774
+ }
28775
+ exports.ProgressHandler = ProgressHandler;
28776
+
28777
+
28704
28778
  /***/ }),
28705
28779
 
28706
28780
  /***/ 5802:
@@ -39556,7 +39630,7 @@ __webpack_require__.r(__webpack_exports__);
39556
39630
  /******/ // startup
39557
39631
  /******/ // Load entry module and return exports
39558
39632
  /******/ // This entry module is referenced by other modules so it can't be inlined
39559
- /******/ var __webpack_exports__ = __webpack_require__(5600);
39633
+ /******/ var __webpack_exports__ = __webpack_require__(5668);
39560
39634
  /******/
39561
39635
  /******/ })()
39562
39636
  ;