blixify-ui-web 1.2.111 → 1.2.112
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/lib/components/data/dataTemplate/dataStateModel.d.ts +7 -0
- package/lib/components/data/dataTemplate/dataStateModel.d.ts.map +1 -1
- package/lib/components/data/dataTemplate/dataStateModel.js.map +1 -1
- package/lib/components/data/dataTemplate/driveUtils.d.ts +43 -0
- package/lib/components/data/dataTemplate/driveUtils.d.ts.map +1 -0
- package/lib/components/data/dataTemplate/driveUtils.js +153 -0
- package/lib/components/data/dataTemplate/driveUtils.js.map +1 -0
- package/lib/components/data/dataTemplate/driveView.d.ts +43 -0
- package/lib/components/data/dataTemplate/driveView.d.ts.map +1 -0
- package/lib/components/data/dataTemplate/driveView.js +877 -0
- package/lib/components/data/dataTemplate/driveView.js.map +1 -0
- package/lib/components/data/dataTemplate/index.d.ts.map +1 -1
- package/lib/components/data/dataTemplate/index.js +216 -179
- package/lib/components/data/dataTemplate/index.js.map +1 -1
- package/lib/components/data/dataTemplate/settingsModal.d.ts +9 -1
- package/lib/components/data/dataTemplate/settingsModal.d.ts.map +1 -1
- package/lib/components/data/dataTemplate/settingsModal.js +60 -1
- package/lib/components/data/dataTemplate/settingsModal.js.map +1 -1
- package/lib/components/data/dataTemplate/spaceModel.d.ts +24 -1
- package/lib/components/data/dataTemplate/spaceModel.d.ts.map +1 -1
- package/lib/tail.css +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
46
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
47
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
48
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49
|
+
function step(op) {
|
|
50
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
51
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
52
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
53
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
54
|
+
switch (op[0]) {
|
|
55
|
+
case 0: case 1: t = op; break;
|
|
56
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
57
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
58
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
59
|
+
default:
|
|
60
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
61
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
62
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
63
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
64
|
+
if (t[2]) _.ops.pop();
|
|
65
|
+
_.trys.pop(); continue;
|
|
66
|
+
}
|
|
67
|
+
op = body.call(thisArg, _);
|
|
68
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
69
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
73
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
74
|
+
if (ar || !(i in from)) {
|
|
75
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
76
|
+
ar[i] = from[i];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
80
|
+
};
|
|
81
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
82
|
+
exports.DriveView = void 0;
|
|
83
|
+
var react_1 = require("@headlessui/react");
|
|
84
|
+
var HeroIcons = __importStar(require("@heroicons/react/24/outline"));
|
|
85
|
+
var react_2 = __importStar(require("react"));
|
|
86
|
+
var popUp_1 = require("../../advanced/popUp");
|
|
87
|
+
var uuid_1 = require("uuid");
|
|
88
|
+
var button_1 = require("../../action/button");
|
|
89
|
+
var emptyState_1 = require("../../display/emptyState");
|
|
90
|
+
var filePreview_1 = require("../../display/filePreview");
|
|
91
|
+
var loading_1 = require("../../display/loading");
|
|
92
|
+
var modal_1 = require("../../display/modal");
|
|
93
|
+
var newList_1 = require("../../display/newList");
|
|
94
|
+
var textInput_1 = require("../../input/textInput");
|
|
95
|
+
var uploadInput_1 = require("../../input/uploadInput");
|
|
96
|
+
var blobModule_1 = require("../blobModule");
|
|
97
|
+
var driveUtils_1 = require("./driveUtils");
|
|
98
|
+
var LAYOUT_STORAGE_PREFIX = "blixify-dtw-drive-layout-";
|
|
99
|
+
/**
|
|
100
|
+
* A folder browser over a collection whose rows are files and folders.
|
|
101
|
+
*
|
|
102
|
+
* INFO: the rows of the open folder arrive from DataTemplate's own list query,
|
|
103
|
+
* so pagination, tab filters and permission filters behave as on any other
|
|
104
|
+
* view. This component adds the folder tree it needs for the breadcrumb, the
|
|
105
|
+
* move picker and search paths, and performs the drive's own writes.
|
|
106
|
+
*/
|
|
107
|
+
var DriveView = function (props) {
|
|
108
|
+
var _a, _b, _c;
|
|
109
|
+
var _d = (0, react_2.useState)(new Map()), folders = _d[0], setFolders = _d[1];
|
|
110
|
+
var _e = (0, react_2.useState)(function () {
|
|
111
|
+
try {
|
|
112
|
+
var stored = window.localStorage.getItem(LAYOUT_STORAGE_PREFIX + props.collectionId);
|
|
113
|
+
if (stored === "grid" || stored === "list")
|
|
114
|
+
return stored;
|
|
115
|
+
}
|
|
116
|
+
catch (err) { }
|
|
117
|
+
// INFO: a phone has no room for tiles and a menu per tile
|
|
118
|
+
return typeof window !== "undefined" && window.innerWidth < 640
|
|
119
|
+
? "list"
|
|
120
|
+
: "grid";
|
|
121
|
+
}), layout = _e[0], setLayout = _e[1];
|
|
122
|
+
var _f = (0, react_2.useState)(false), newFolderOpen = _f[0], setNewFolderOpen = _f[1];
|
|
123
|
+
var _g = (0, react_2.useState)(""), folderName = _g[0], setFolderName = _g[1];
|
|
124
|
+
var _h = (0, react_2.useState)(null), renameRow = _h[0], setRenameRow = _h[1];
|
|
125
|
+
var _j = (0, react_2.useState)(""), renameValue = _j[0], setRenameValue = _j[1];
|
|
126
|
+
var _k = (0, react_2.useState)(null), moveRow = _k[0], setMoveRow = _k[1];
|
|
127
|
+
var _l = (0, react_2.useState)(null), deleteRow = _l[0], setDeleteRow = _l[1];
|
|
128
|
+
var _m = (0, react_2.useState)(null), deleteIds = _m[0], setDeleteIds = _m[1];
|
|
129
|
+
var _o = (0, react_2.useState)(null), previewRow = _o[0], setPreviewRow = _o[1];
|
|
130
|
+
var _p = (0, react_2.useState)(false), uploadOpen = _p[0], setUploadOpen = _p[1];
|
|
131
|
+
var _q = (0, react_2.useState)({
|
|
132
|
+
data: [],
|
|
133
|
+
upload: [],
|
|
134
|
+
remove: [],
|
|
135
|
+
}), uploadFiles = _q[0], setUploadFiles = _q[1];
|
|
136
|
+
var _r = (0, react_2.useState)({}), uploadStatus = _r[0], setUploadStatus = _r[1];
|
|
137
|
+
var _s = (0, react_2.useState)(false), working = _s[0], setWorking = _s[1];
|
|
138
|
+
var _t = (0, react_2.useState)(false), dragging = _t[0], setDragging = _t[1];
|
|
139
|
+
var _u = (0, react_2.useState)(""), modalError = _u[0], setModalError = _u[1];
|
|
140
|
+
// INFO: dragenter and dragleave fire for every child the pointer crosses, so a
|
|
141
|
+
// plain boolean flickers off over each tile; a depth count only reaches zero
|
|
142
|
+
// when the drag has really left the drive
|
|
143
|
+
var dragDepthRef = (0, react_2.useRef)(0);
|
|
144
|
+
var settings = props.settings;
|
|
145
|
+
var fileColumn = props.structure.find(function (eachColumn) { return eachColumn.id === settings.fileColumnId; });
|
|
146
|
+
// INFO: the same folder a file column's uploads use everywhere else, so a
|
|
147
|
+
// row deleted from another view removes the same storage folder
|
|
148
|
+
var storageCollection = (_a = fileColumn === null || fileColumn === void 0 ? void 0 : fileColumn.imageCollectionName) !== null && _a !== void 0 ? _a : props.collectionId;
|
|
149
|
+
var sortedRows = (0, driveUtils_1.handleSortDriveRows)(props.rows, settings);
|
|
150
|
+
var path = (0, driveUtils_1.handleBuildFolderPath)(folders, props.folderId);
|
|
151
|
+
(0, react_2.useEffect)(function () {
|
|
152
|
+
handleLoadFolders();
|
|
153
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
154
|
+
}, [props.collectionId, JSON.stringify(props.baseQuery)]);
|
|
155
|
+
var handleLoadFolders = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
156
|
+
var res, err_1;
|
|
157
|
+
var _a;
|
|
158
|
+
return __generator(this, function (_b) {
|
|
159
|
+
switch (_b.label) {
|
|
160
|
+
case 0:
|
|
161
|
+
_b.trys.push([0, 2, , 3]);
|
|
162
|
+
return [4 /*yield*/, props.readQuery.call({
|
|
163
|
+
type: "list",
|
|
164
|
+
query: __spreadArray(__spreadArray([], props.baseQuery, true), [
|
|
165
|
+
{ type: "=", queryId: settings.kindColumnId, value: driveUtils_1.DRIVE_FOLDER },
|
|
166
|
+
], false),
|
|
167
|
+
stopLimit: true,
|
|
168
|
+
})];
|
|
169
|
+
case 1:
|
|
170
|
+
res = _b.sent();
|
|
171
|
+
setFolders((0, driveUtils_1.handleMapDriveFolders)((_a = res === null || res === void 0 ? void 0 : res.data) !== null && _a !== void 0 ? _a : [], settings));
|
|
172
|
+
return [3 /*break*/, 3];
|
|
173
|
+
case 2:
|
|
174
|
+
err_1 = _b.sent();
|
|
175
|
+
return [3 /*break*/, 3];
|
|
176
|
+
case 3: return [2 /*return*/];
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}); };
|
|
180
|
+
var handleChangeLayout = function (next) {
|
|
181
|
+
setLayout(next);
|
|
182
|
+
try {
|
|
183
|
+
window.localStorage.setItem(LAYOUT_STORAGE_PREFIX + props.collectionId, next);
|
|
184
|
+
}
|
|
185
|
+
catch (err) { }
|
|
186
|
+
};
|
|
187
|
+
var handleAfterWrite = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
188
|
+
return __generator(this, function (_a) {
|
|
189
|
+
switch (_a.label) {
|
|
190
|
+
case 0:
|
|
191
|
+
props.handleRefresh();
|
|
192
|
+
return [4 /*yield*/, handleLoadFolders()];
|
|
193
|
+
case 1:
|
|
194
|
+
_a.sent();
|
|
195
|
+
return [2 /*return*/];
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}); };
|
|
199
|
+
var handleResolveFile = function (row) {
|
|
200
|
+
var _a, _b;
|
|
201
|
+
var value = row === null || row === void 0 ? void 0 : row[settings.fileColumnId];
|
|
202
|
+
var entry = Array.isArray(value) ? value[0] : value;
|
|
203
|
+
if (!(entry === null || entry === void 0 ? void 0 : entry.token) || !(entry === null || entry === void 0 ? void 0 : entry.fileName))
|
|
204
|
+
return null;
|
|
205
|
+
return {
|
|
206
|
+
fileName: (0, blobModule_1.renderImageUrlFromPath)(props.imageEndpoint, storageCollection, (0, driveUtils_1.handleGetRowId)(row), entry.fileName, entry.token, props.bucketName),
|
|
207
|
+
label: String((_a = row === null || row === void 0 ? void 0 : row[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "") || undefined,
|
|
208
|
+
token: entry.token,
|
|
209
|
+
mimeType: (_b = entry.mimeType) !== null && _b !== void 0 ? _b : (0, filePreview_1.handleGuessMimeType)(entry.fileName),
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
var handleOpenRow = function (row) {
|
|
213
|
+
var _a;
|
|
214
|
+
if ((0, driveUtils_1.handleIsDriveFolder)(row, settings)) {
|
|
215
|
+
if (props.searching)
|
|
216
|
+
(_a = props.handleClearSearch) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
217
|
+
props.handleChangeFolder((0, driveUtils_1.handleGetRowId)(row));
|
|
218
|
+
}
|
|
219
|
+
else
|
|
220
|
+
setPreviewRow(row);
|
|
221
|
+
};
|
|
222
|
+
var handleCloseModals = function () {
|
|
223
|
+
setNewFolderOpen(false);
|
|
224
|
+
setFolderName("");
|
|
225
|
+
setRenameRow(null);
|
|
226
|
+
setRenameValue("");
|
|
227
|
+
setMoveRow(null);
|
|
228
|
+
setDeleteRow(null);
|
|
229
|
+
setDeleteIds(null);
|
|
230
|
+
setModalError("");
|
|
231
|
+
};
|
|
232
|
+
var handleCreateFolder = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
233
|
+
var name, err_2;
|
|
234
|
+
var _a;
|
|
235
|
+
return __generator(this, function (_b) {
|
|
236
|
+
switch (_b.label) {
|
|
237
|
+
case 0:
|
|
238
|
+
name = folderName.trim();
|
|
239
|
+
if (!name)
|
|
240
|
+
return [2 /*return*/, setModalError("Name the folder.")];
|
|
241
|
+
if ((0, driveUtils_1.handleIsDuplicateFolderName)(folders, props.folderId, name))
|
|
242
|
+
return [2 /*return*/, setModalError("A folder named \"".concat(name, "\" is already here."))];
|
|
243
|
+
setWorking(true);
|
|
244
|
+
_b.label = 1;
|
|
245
|
+
case 1:
|
|
246
|
+
_b.trys.push([1, 4, , 5]);
|
|
247
|
+
return [4 /*yield*/, props.writeQuery.call("create", {
|
|
248
|
+
data: (_a = {},
|
|
249
|
+
_a[props.serverId] = (0, uuid_1.v4)(),
|
|
250
|
+
_a[settings.nameColumnId] = name,
|
|
251
|
+
_a[settings.kindColumnId] = driveUtils_1.DRIVE_FOLDER,
|
|
252
|
+
_a[settings.parentColumnId] = props.folderId,
|
|
253
|
+
_a),
|
|
254
|
+
})];
|
|
255
|
+
case 2:
|
|
256
|
+
_b.sent();
|
|
257
|
+
handleCloseModals();
|
|
258
|
+
return [4 /*yield*/, handleAfterWrite()];
|
|
259
|
+
case 3:
|
|
260
|
+
_b.sent();
|
|
261
|
+
return [3 /*break*/, 5];
|
|
262
|
+
case 4:
|
|
263
|
+
err_2 = _b.sent();
|
|
264
|
+
setModalError("The folder could not be created.");
|
|
265
|
+
return [3 /*break*/, 5];
|
|
266
|
+
case 5:
|
|
267
|
+
setWorking(false);
|
|
268
|
+
return [2 /*return*/];
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}); };
|
|
272
|
+
var handleOpenRename = function (row) {
|
|
273
|
+
var _a;
|
|
274
|
+
setRenameRow(row);
|
|
275
|
+
setRenameValue(String((_a = row === null || row === void 0 ? void 0 : row[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""));
|
|
276
|
+
setModalError("");
|
|
277
|
+
};
|
|
278
|
+
var handleRename = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
279
|
+
var name, rowId, err_3;
|
|
280
|
+
var _a;
|
|
281
|
+
var _b;
|
|
282
|
+
return __generator(this, function (_c) {
|
|
283
|
+
switch (_c.label) {
|
|
284
|
+
case 0:
|
|
285
|
+
name = renameValue.trim();
|
|
286
|
+
if (!name)
|
|
287
|
+
return [2 /*return*/, setModalError("A name is required.")];
|
|
288
|
+
rowId = (0, driveUtils_1.handleGetRowId)(renameRow);
|
|
289
|
+
if ((0, driveUtils_1.handleIsDriveFolder)(renameRow, settings) &&
|
|
290
|
+
(0, driveUtils_1.handleIsDuplicateFolderName)(folders, String((_b = renameRow === null || renameRow === void 0 ? void 0 : renameRow[settings.parentColumnId]) !== null && _b !== void 0 ? _b : ""), name, rowId))
|
|
291
|
+
return [2 /*return*/, setModalError("A folder named \"".concat(name, "\" is already here."))];
|
|
292
|
+
setWorking(true);
|
|
293
|
+
_c.label = 1;
|
|
294
|
+
case 1:
|
|
295
|
+
_c.trys.push([1, 4, , 5]);
|
|
296
|
+
return [4 /*yield*/, props.writeQuery.call("update", {
|
|
297
|
+
id: rowId,
|
|
298
|
+
data: (_a = {}, _a[settings.nameColumnId] = name, _a),
|
|
299
|
+
})];
|
|
300
|
+
case 2:
|
|
301
|
+
_c.sent();
|
|
302
|
+
handleCloseModals();
|
|
303
|
+
return [4 /*yield*/, handleAfterWrite()];
|
|
304
|
+
case 3:
|
|
305
|
+
_c.sent();
|
|
306
|
+
return [3 /*break*/, 5];
|
|
307
|
+
case 4:
|
|
308
|
+
err_3 = _c.sent();
|
|
309
|
+
setModalError("The name could not be saved.");
|
|
310
|
+
return [3 /*break*/, 5];
|
|
311
|
+
case 5:
|
|
312
|
+
setWorking(false);
|
|
313
|
+
return [2 /*return*/];
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}); };
|
|
317
|
+
var handleMove = function (targetFolderId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
318
|
+
var rowId, err_4;
|
|
319
|
+
var _a;
|
|
320
|
+
var _b;
|
|
321
|
+
return __generator(this, function (_c) {
|
|
322
|
+
switch (_c.label) {
|
|
323
|
+
case 0:
|
|
324
|
+
rowId = (0, driveUtils_1.handleGetRowId)(moveRow);
|
|
325
|
+
if ((0, driveUtils_1.handleIsDriveFolder)(moveRow, settings) &&
|
|
326
|
+
(0, driveUtils_1.handleIsDuplicateFolderName)(folders, targetFolderId, String((_b = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.nameColumnId]) !== null && _b !== void 0 ? _b : ""), rowId))
|
|
327
|
+
return [2 /*return*/, setModalError("A folder with this name is already there.")];
|
|
328
|
+
setWorking(true);
|
|
329
|
+
_c.label = 1;
|
|
330
|
+
case 1:
|
|
331
|
+
_c.trys.push([1, 4, , 5]);
|
|
332
|
+
return [4 /*yield*/, props.writeQuery.call("update", {
|
|
333
|
+
id: rowId,
|
|
334
|
+
data: (_a = {}, _a[settings.parentColumnId] = targetFolderId, _a),
|
|
335
|
+
})];
|
|
336
|
+
case 2:
|
|
337
|
+
_c.sent();
|
|
338
|
+
handleCloseModals();
|
|
339
|
+
return [4 /*yield*/, handleAfterWrite()];
|
|
340
|
+
case 3:
|
|
341
|
+
_c.sent();
|
|
342
|
+
return [3 /*break*/, 5];
|
|
343
|
+
case 4:
|
|
344
|
+
err_4 = _c.sent();
|
|
345
|
+
setModalError("The item could not be moved.");
|
|
346
|
+
return [3 /*break*/, 5];
|
|
347
|
+
case 5:
|
|
348
|
+
setWorking(false);
|
|
349
|
+
return [2 /*return*/];
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}); };
|
|
353
|
+
/**
|
|
354
|
+
* INFO: a folder's contents are counted before anything is deleted, so the
|
|
355
|
+
* confirmation says what will go. Read from the whole collection, not the
|
|
356
|
+
* filtered list — a file hidden from this view would otherwise be left
|
|
357
|
+
* pointing at a folder that no longer exists.
|
|
358
|
+
*/
|
|
359
|
+
var handleOpenDelete = function (row) { return __awaiter(void 0, void 0, void 0, function () {
|
|
360
|
+
var res, rowId, err_5;
|
|
361
|
+
var _a;
|
|
362
|
+
return __generator(this, function (_b) {
|
|
363
|
+
switch (_b.label) {
|
|
364
|
+
case 0:
|
|
365
|
+
setDeleteRow(row);
|
|
366
|
+
setModalError("");
|
|
367
|
+
if (!(0, driveUtils_1.handleIsDriveFolder)(row, settings)) {
|
|
368
|
+
setDeleteIds([(0, driveUtils_1.handleGetRowId)(row)]);
|
|
369
|
+
return [2 /*return*/];
|
|
370
|
+
}
|
|
371
|
+
setDeleteIds(null);
|
|
372
|
+
_b.label = 1;
|
|
373
|
+
case 1:
|
|
374
|
+
_b.trys.push([1, 3, , 4]);
|
|
375
|
+
return [4 /*yield*/, props.readQuery.call({
|
|
376
|
+
type: "list",
|
|
377
|
+
query: [],
|
|
378
|
+
stopLimit: true,
|
|
379
|
+
})];
|
|
380
|
+
case 2:
|
|
381
|
+
res = _b.sent();
|
|
382
|
+
rowId = (0, driveUtils_1.handleGetRowId)(row);
|
|
383
|
+
setDeleteIds(__spreadArray([
|
|
384
|
+
rowId
|
|
385
|
+
], (0, driveUtils_1.handleCollectDescendantIds)((_a = res === null || res === void 0 ? void 0 : res.data) !== null && _a !== void 0 ? _a : [], settings, rowId), true));
|
|
386
|
+
return [3 /*break*/, 4];
|
|
387
|
+
case 3:
|
|
388
|
+
err_5 = _b.sent();
|
|
389
|
+
setModalError("The folder's contents could not be read.");
|
|
390
|
+
return [3 /*break*/, 4];
|
|
391
|
+
case 4: return [2 /*return*/];
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}); };
|
|
395
|
+
var handleDelete = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
396
|
+
var form, err_6;
|
|
397
|
+
return __generator(this, function (_a) {
|
|
398
|
+
switch (_a.label) {
|
|
399
|
+
case 0:
|
|
400
|
+
if (!(deleteIds === null || deleteIds === void 0 ? void 0 : deleteIds.length))
|
|
401
|
+
return [2 /*return*/];
|
|
402
|
+
setWorking(true);
|
|
403
|
+
_a.label = 1;
|
|
404
|
+
case 1:
|
|
405
|
+
_a.trys.push([1, 5, , 6]);
|
|
406
|
+
return [4 /*yield*/, props.writeQuery.call("batchDelete", { id: deleteIds })];
|
|
407
|
+
case 2:
|
|
408
|
+
_a.sent();
|
|
409
|
+
form = new FormData();
|
|
410
|
+
form.append("data[assetCollectionName]", storageCollection);
|
|
411
|
+
form.append("data[assetParentId]", JSON.stringify(deleteIds));
|
|
412
|
+
if (props.bucketName)
|
|
413
|
+
form.append("data[bucketName]", props.bucketName);
|
|
414
|
+
return [4 /*yield*/, props.lib
|
|
415
|
+
.axios({
|
|
416
|
+
data: form,
|
|
417
|
+
method: "post",
|
|
418
|
+
url: "".concat(props.uploadEndpoint, "/batchDeleteDirectory"),
|
|
419
|
+
headers: { "Content-Type": "multipart/form-data" },
|
|
420
|
+
})
|
|
421
|
+
.catch(function () { })];
|
|
422
|
+
case 3:
|
|
423
|
+
_a.sent();
|
|
424
|
+
handleCloseModals();
|
|
425
|
+
return [4 /*yield*/, handleAfterWrite()];
|
|
426
|
+
case 4:
|
|
427
|
+
_a.sent();
|
|
428
|
+
return [3 /*break*/, 6];
|
|
429
|
+
case 5:
|
|
430
|
+
err_6 = _a.sent();
|
|
431
|
+
setModalError("The item could not be deleted.");
|
|
432
|
+
return [3 /*break*/, 6];
|
|
433
|
+
case 6:
|
|
434
|
+
setWorking(false);
|
|
435
|
+
return [2 /*return*/];
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}); };
|
|
439
|
+
/**
|
|
440
|
+
* INFO: one row per file, each uploaded into its own row's storage folder
|
|
441
|
+
* first — a row is only created for a file that stored, and one failure does
|
|
442
|
+
* not stop the rest.
|
|
443
|
+
*/
|
|
444
|
+
var handleUploadFiles = function (queued) { return __awaiter(void 0, void 0, void 0, function () {
|
|
445
|
+
var failed, _loop_1, _i, queued_1, eachFile;
|
|
446
|
+
var _a;
|
|
447
|
+
return __generator(this, function (_b) {
|
|
448
|
+
switch (_b.label) {
|
|
449
|
+
case 0:
|
|
450
|
+
if (!queued.length)
|
|
451
|
+
return [2 /*return*/];
|
|
452
|
+
setWorking(true);
|
|
453
|
+
setModalError("");
|
|
454
|
+
failed = 0;
|
|
455
|
+
_loop_1 = function (eachFile) {
|
|
456
|
+
var file, rowId, storedName, res, token, err_7;
|
|
457
|
+
var _c, _d, _e;
|
|
458
|
+
return __generator(this, function (_f) {
|
|
459
|
+
switch (_f.label) {
|
|
460
|
+
case 0:
|
|
461
|
+
setUploadStatus(function (current) {
|
|
462
|
+
var _a;
|
|
463
|
+
return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "uploading", _a)));
|
|
464
|
+
});
|
|
465
|
+
_f.label = 1;
|
|
466
|
+
case 1:
|
|
467
|
+
_f.trys.push([1, 4, , 5]);
|
|
468
|
+
file = eachFile.fileName;
|
|
469
|
+
rowId = (0, uuid_1.v4)();
|
|
470
|
+
storedName = "".concat((0, uuid_1.v4)(), "-").concat(file.name);
|
|
471
|
+
return [4 /*yield*/, props.handleUpload(props.uploadEndpoint, rowId, storageCollection, storedName, file, props.bucketName)];
|
|
472
|
+
case 2:
|
|
473
|
+
res = _f.sent();
|
|
474
|
+
token = (_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data;
|
|
475
|
+
if (!token)
|
|
476
|
+
throw new Error("No token returned");
|
|
477
|
+
return [4 /*yield*/, props.writeQuery.call("create", {
|
|
478
|
+
data: __assign(__assign((_c = {}, _c[props.serverId] = rowId, _c[settings.nameColumnId] = file.name, _c[settings.kindColumnId] = driveUtils_1.DRIVE_FILE, _c[settings.parentColumnId] = props.folderId, _c[settings.fileColumnId] = [
|
|
479
|
+
{ token: token, fileName: storedName, mimeType: file.type || undefined },
|
|
480
|
+
], _c), (settings.sizeColumnId
|
|
481
|
+
? (_d = {}, _d[settings.sizeColumnId] = file.size, _d) : {})), (settings.mimeTypeColumnId
|
|
482
|
+
? (_e = {}, _e[settings.mimeTypeColumnId] = file.type, _e) : {})),
|
|
483
|
+
})];
|
|
484
|
+
case 3:
|
|
485
|
+
_f.sent();
|
|
486
|
+
setUploadStatus(function (current) {
|
|
487
|
+
var _a;
|
|
488
|
+
return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "done", _a)));
|
|
489
|
+
});
|
|
490
|
+
return [3 /*break*/, 5];
|
|
491
|
+
case 4:
|
|
492
|
+
err_7 = _f.sent();
|
|
493
|
+
failed += 1;
|
|
494
|
+
setUploadStatus(function (current) {
|
|
495
|
+
var _a;
|
|
496
|
+
return (__assign(__assign({}, current), (_a = {}, _a[eachFile.token] = "failed", _a)));
|
|
497
|
+
});
|
|
498
|
+
return [3 /*break*/, 5];
|
|
499
|
+
case 5: return [2 /*return*/];
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
};
|
|
503
|
+
_i = 0, queued_1 = queued;
|
|
504
|
+
_b.label = 1;
|
|
505
|
+
case 1:
|
|
506
|
+
if (!(_i < queued_1.length)) return [3 /*break*/, 4];
|
|
507
|
+
eachFile = queued_1[_i];
|
|
508
|
+
return [5 /*yield**/, _loop_1(eachFile)];
|
|
509
|
+
case 2:
|
|
510
|
+
_b.sent();
|
|
511
|
+
_b.label = 3;
|
|
512
|
+
case 3:
|
|
513
|
+
_i++;
|
|
514
|
+
return [3 /*break*/, 1];
|
|
515
|
+
case 4:
|
|
516
|
+
setWorking(false);
|
|
517
|
+
props.handleRefresh();
|
|
518
|
+
if (failed === 0)
|
|
519
|
+
handleCloseUpload();
|
|
520
|
+
else
|
|
521
|
+
setModalError("".concat(failed, " file(s) could not be uploaded."));
|
|
522
|
+
return [2 /*return*/];
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
}); };
|
|
526
|
+
var handleUploadAll = function () {
|
|
527
|
+
var _a;
|
|
528
|
+
return handleUploadFiles(((_a = uploadFiles.upload) !== null && _a !== void 0 ? _a : []).filter(function (eachFile) {
|
|
529
|
+
return uploadStatus[eachFile.token] !== "done" &&
|
|
530
|
+
eachFile.fileName instanceof File;
|
|
531
|
+
}));
|
|
532
|
+
};
|
|
533
|
+
/**
|
|
534
|
+
* INFO: a drop starts uploading at once — dragging files onto a folder is
|
|
535
|
+
* already the decision, so a confirm step would only be a second click. The
|
|
536
|
+
* dialog opens to show each file's progress and closes when all have stored.
|
|
537
|
+
*/
|
|
538
|
+
var handleDropFiles = function (files) {
|
|
539
|
+
if (working || !files.length)
|
|
540
|
+
return;
|
|
541
|
+
var queued = files.map(function (eachFile) { return ({
|
|
542
|
+
token: (0, uuid_1.v4)(),
|
|
543
|
+
fileName: eachFile,
|
|
544
|
+
}); });
|
|
545
|
+
setUploadFiles({ data: [], upload: queued, remove: [] });
|
|
546
|
+
setUploadStatus(Object.fromEntries(queued.map(function (eachFile) { return [eachFile.token, "waiting"]; })));
|
|
547
|
+
setModalError("");
|
|
548
|
+
setUploadOpen(true);
|
|
549
|
+
handleUploadFiles(queued);
|
|
550
|
+
};
|
|
551
|
+
var handleOpenUpload = function () {
|
|
552
|
+
setUploadFiles({ data: [], upload: [], remove: [] });
|
|
553
|
+
setUploadStatus({});
|
|
554
|
+
setModalError("");
|
|
555
|
+
setUploadOpen(true);
|
|
556
|
+
};
|
|
557
|
+
var handleCloseUpload = function () {
|
|
558
|
+
setUploadOpen(false);
|
|
559
|
+
setUploadFiles({ data: [], upload: [], remove: [] });
|
|
560
|
+
setUploadStatus({});
|
|
561
|
+
setModalError("");
|
|
562
|
+
};
|
|
563
|
+
// INFO: only a drag carrying files, only for someone who may create, and not
|
|
564
|
+
// while the upload dialog is open — it has its own drop zone
|
|
565
|
+
var handleIsFileDrag = function (event) {
|
|
566
|
+
var _a, _b;
|
|
567
|
+
return props.canCreate &&
|
|
568
|
+
!uploadOpen &&
|
|
569
|
+
Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes("Files");
|
|
570
|
+
};
|
|
571
|
+
var renderDropOverlay = function () {
|
|
572
|
+
if (!dragging)
|
|
573
|
+
return null;
|
|
574
|
+
var target = path.length ? path[path.length - 1].name : "Drive";
|
|
575
|
+
return (react_2.default.createElement("div", { "data-testid": "drive-drop-overlay", className: "pointer-events-none absolute inset-0 z-10 flex flex-col items-center justify-center gap-y-2 rounded-lg border-2 border-dashed border-primary-400 bg-primary-50/90" },
|
|
576
|
+
react_2.default.createElement(HeroIcons.ArrowUpTrayIcon, { className: "h-8 w-8 text-primary-500" }),
|
|
577
|
+
react_2.default.createElement("p", { className: "text-sm font-medium text-primary-700" },
|
|
578
|
+
"Drop to upload to ",
|
|
579
|
+
target)));
|
|
580
|
+
};
|
|
581
|
+
var renderMenu = function (row) { return (react_2.default.createElement(DriveItemMenu, { testId: "drive-menu-".concat((0, driveUtils_1.handleGetRowId)(row)), items: __spreadArray(__spreadArray([
|
|
582
|
+
{
|
|
583
|
+
text: "Details",
|
|
584
|
+
onClick: function () { return props.handleOpenDetails((0, driveUtils_1.handleGetRowId)(row)); },
|
|
585
|
+
}
|
|
586
|
+
], (props.canUpdate
|
|
587
|
+
? [
|
|
588
|
+
{ text: "Rename", onClick: function () { return handleOpenRename(row); } },
|
|
589
|
+
{
|
|
590
|
+
text: "Move to…",
|
|
591
|
+
onClick: function () {
|
|
592
|
+
setMoveRow(row);
|
|
593
|
+
setModalError("");
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
]
|
|
597
|
+
: []), true), (props.canDelete
|
|
598
|
+
? [{ text: "Delete", onClick: function () { return handleOpenDelete(row); } }]
|
|
599
|
+
: []), true) })); };
|
|
600
|
+
var renderRowPath = function (row) {
|
|
601
|
+
var _a;
|
|
602
|
+
if (!props.searching)
|
|
603
|
+
return "";
|
|
604
|
+
var parentId = String((_a = row === null || row === void 0 ? void 0 : row[settings.parentColumnId]) !== null && _a !== void 0 ? _a : "");
|
|
605
|
+
var rowPath = (0, driveUtils_1.handleFormatFolderPath)((0, driveUtils_1.handleBuildFolderPath)(folders, parentId));
|
|
606
|
+
return rowPath ? "In ".concat(rowPath) : "At the top level";
|
|
607
|
+
};
|
|
608
|
+
var renderToolbar = function () { return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3 sm:flex-row sm:items-center sm:gap-x-3" },
|
|
609
|
+
react_2.default.createElement("nav", { "aria-label": "Drive path", className: "flex min-w-0 flex-row flex-wrap items-center gap-x-1 text-sm" },
|
|
610
|
+
react_2.default.createElement("button", { type: "button", className: "font-medium ".concat(props.folderId ? "text-primary-600 hover:underline" : "text-gray-900"), onClick: function () { return props.handleChangeFolder(""); } }, "Drive"),
|
|
611
|
+
path.map(function (eachFolder, eachIndex) { return (react_2.default.createElement(react_2.default.Fragment, { key: eachFolder.id },
|
|
612
|
+
react_2.default.createElement(HeroIcons.ChevronRightIcon, { className: "h-4 w-4 shrink-0 text-gray-400" }),
|
|
613
|
+
react_2.default.createElement("button", { type: "button", className: "truncate font-medium ".concat(eachIndex === path.length - 1
|
|
614
|
+
? "text-gray-900"
|
|
615
|
+
: "text-primary-600 hover:underline"), onClick: function () { return props.handleChangeFolder(eachFolder.id); } }, eachFolder.name))); }),
|
|
616
|
+
props.searching && (react_2.default.createElement("span", { className: "ml-2 text-gray-500" }, "\u00B7 Search results"))),
|
|
617
|
+
react_2.default.createElement("div", { className: "grow" }),
|
|
618
|
+
react_2.default.createElement("div", { className: "flex flex-row flex-wrap items-center gap-2" },
|
|
619
|
+
react_2.default.createElement("div", { className: "flex flex-row overflow-hidden rounded-md border border-gray-200" }, ["grid", "list"].map(function (eachLayout) {
|
|
620
|
+
var Icon = eachLayout === "grid"
|
|
621
|
+
? HeroIcons.Squares2X2Icon
|
|
622
|
+
: HeroIcons.ListBulletIcon;
|
|
623
|
+
return (react_2.default.createElement("button", { key: eachLayout, type: "button", "aria-label": eachLayout === "grid" ? "Grid view" : "List view", "aria-pressed": layout === eachLayout, className: "p-1.5 ".concat(layout === eachLayout
|
|
624
|
+
? "bg-primary-50 text-primary-600"
|
|
625
|
+
: "bg-white text-gray-500 hover:bg-gray-50"), onClick: function () { return handleChangeLayout(eachLayout); } },
|
|
626
|
+
react_2.default.createElement(Icon, { className: "h-4 w-4" })));
|
|
627
|
+
})),
|
|
628
|
+
props.canCreate && (react_2.default.createElement(react_2.default.Fragment, null,
|
|
629
|
+
react_2.default.createElement(button_1.Button, { text: "New folder", type: "light", size: "extraSmall", className: "whitespace-nowrap sm:!px-3", icon: react_2.default.createElement(HeroIcons.FolderPlusIcon, { className: "mr-1 h-4 w-4" }), onClick: function () {
|
|
630
|
+
setFolderName("");
|
|
631
|
+
setModalError("");
|
|
632
|
+
setNewFolderOpen(true);
|
|
633
|
+
} }),
|
|
634
|
+
react_2.default.createElement(button_1.Button, { text: "Upload", type: "normal", size: "extraSmall", className: "whitespace-nowrap sm:!px-3", icon: react_2.default.createElement(HeroIcons.ArrowUpTrayIcon, { className: "mr-1 h-4 w-4" }), onClick: handleOpenUpload })))))); };
|
|
635
|
+
var renderFolderIcon = function (sizeClass) { return (react_2.default.createElement(HeroIcons.FolderIcon, { className: "".concat(sizeClass, " shrink-0 text-primary-400") })); };
|
|
636
|
+
// INFO: folders as compact rows above the file tiles, the way a file browser
|
|
637
|
+
// lays them out — a folder has no picture, so a tile-sized card for it is
|
|
638
|
+
// mostly empty space
|
|
639
|
+
var renderGrid = function () {
|
|
640
|
+
var folderRows = sortedRows.filter(function (eachRow) {
|
|
641
|
+
return (0, driveUtils_1.handleIsDriveFolder)(eachRow, settings);
|
|
642
|
+
});
|
|
643
|
+
var fileRows = sortedRows.filter(function (eachRow) { return !(0, driveUtils_1.handleIsDriveFolder)(eachRow, settings); });
|
|
644
|
+
return (react_2.default.createElement("div", { className: "flex flex-col gap-y-4" },
|
|
645
|
+
folderRows.length > 0 && (react_2.default.createElement("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4" }, folderRows.map(function (eachRow) {
|
|
646
|
+
var _a;
|
|
647
|
+
var rowId = (0, driveUtils_1.handleGetRowId)(eachRow);
|
|
648
|
+
return (react_2.default.createElement("div", { key: rowId, "data-testid": "drive-item-".concat(rowId), className: "flex min-w-0 flex-row items-center gap-x-2 rounded-lg border border-gray-200 bg-white pr-1 hover:bg-gray-50" },
|
|
649
|
+
react_2.default.createElement("button", { type: "button", onClick: function () { return handleOpenRow(eachRow); }, className: "flex min-w-0 grow flex-col items-start py-2 pl-3 text-left" },
|
|
650
|
+
react_2.default.createElement("span", { className: "flex w-full min-w-0 flex-row items-center gap-x-2" },
|
|
651
|
+
renderFolderIcon("h-5 w-5"),
|
|
652
|
+
react_2.default.createElement("span", { className: "truncate text-sm font-medium text-gray-900" }, String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""))),
|
|
653
|
+
props.searching && (react_2.default.createElement("span", { className: "w-full truncate pl-7 text-xs text-gray-500" }, renderRowPath(eachRow)))),
|
|
654
|
+
renderMenu(eachRow)));
|
|
655
|
+
}))),
|
|
656
|
+
fileRows.length > 0 && (react_2.default.createElement("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4" }, fileRows.map(function (eachRow) {
|
|
657
|
+
var _a;
|
|
658
|
+
var rowId = (0, driveUtils_1.handleGetRowId)(eachRow);
|
|
659
|
+
var file = handleResolveFile(eachRow);
|
|
660
|
+
return (react_2.default.createElement("div", { key: rowId, "data-testid": "drive-item-".concat(rowId), className: "relative min-w-0" },
|
|
661
|
+
file ? (react_2.default.createElement(filePreview_1.FilePreview, { variant: "tile", file: file, onClick: function () { return handleOpenRow(eachRow); } })) : (react_2.default.createElement("button", { type: "button", onClick: function () { return handleOpenRow(eachRow); }, className: "flex aspect-video w-full flex-col items-center justify-center gap-y-2 rounded-lg border border-gray-200" },
|
|
662
|
+
react_2.default.createElement(HeroIcons.DocumentIcon, { className: "h-8 w-8 text-gray-400" }),
|
|
663
|
+
react_2.default.createElement("span", { className: "w-full truncate px-2 text-sm text-gray-900" }, String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "")))),
|
|
664
|
+
props.searching && (react_2.default.createElement("p", { className: "mt-1 truncate text-xs text-gray-500" }, renderRowPath(eachRow))),
|
|
665
|
+
react_2.default.createElement("div", { className: "absolute right-1 top-1 rounded-md bg-white/90 shadow-sm" }, renderMenu(eachRow))));
|
|
666
|
+
})))));
|
|
667
|
+
};
|
|
668
|
+
var renderList = function () { return (react_2.default.createElement(newList_1.NewList, { list: sortedRows.map(function (eachRow) {
|
|
669
|
+
var _a;
|
|
670
|
+
var isFolder = (0, driveUtils_1.handleIsDriveFolder)(eachRow, settings);
|
|
671
|
+
var rowPath = renderRowPath(eachRow);
|
|
672
|
+
var size = !isFolder && settings.sizeColumnId
|
|
673
|
+
? eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.sizeColumnId]
|
|
674
|
+
: undefined;
|
|
675
|
+
var description = [
|
|
676
|
+
rowPath,
|
|
677
|
+
typeof size === "number" ? "".concat(Math.max(1, Math.round(size / 1024)), " KB") : "",
|
|
678
|
+
]
|
|
679
|
+
.filter(function (eachPart) { return !!eachPart; })
|
|
680
|
+
.join(" · ");
|
|
681
|
+
return __assign(__assign({ id: (0, driveUtils_1.handleGetRowId)(eachRow), title: String((_a = eachRow === null || eachRow === void 0 ? void 0 : eachRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : ""), icon: isFolder
|
|
682
|
+
? renderFolderIcon("h-6 w-6")
|
|
683
|
+
: react_2.default.createElement(HeroIcons.DocumentIcon, { className: "h-6 w-6 text-gray-400" }) }, (description ? { description: description } : {})), { action: renderMenu(eachRow) });
|
|
684
|
+
}), hidePagination: true, onClickItem: function (item) {
|
|
685
|
+
return handleOpenRow(sortedRows.find(function (eachRow) { return (0, driveUtils_1.handleGetRowId)(eachRow) === item.id; }));
|
|
686
|
+
}, darkMode: props.darkMode })); };
|
|
687
|
+
var renderContent = function () {
|
|
688
|
+
if (props.loading)
|
|
689
|
+
return (react_2.default.createElement("div", { className: "flex flex-col items-center py-10" },
|
|
690
|
+
react_2.default.createElement(loading_1.Loading, null)));
|
|
691
|
+
if (!sortedRows.length)
|
|
692
|
+
return (react_2.default.createElement(emptyState_1.EmptyState, { text: props.searching ? "Nothing matches the search" : "This folder is empty", icon: renderFolderIcon("h-10 w-10") }));
|
|
693
|
+
return layout === "grid" ? renderGrid() : renderList();
|
|
694
|
+
};
|
|
695
|
+
var renderNameForm = function (value, onChange, onSubmit, submitText, placeholder) { return (
|
|
696
|
+
// INFO: a form so Enter — and a phone keyboard's Done, which submits rather
|
|
697
|
+
// than sending a keydown — commits; stopPropagation keeps the submit from
|
|
698
|
+
// reaching a form this view sits inside
|
|
699
|
+
react_2.default.createElement("form", { onSubmit: function (event) {
|
|
700
|
+
event.preventDefault();
|
|
701
|
+
event.stopPropagation();
|
|
702
|
+
onSubmit();
|
|
703
|
+
}, className: "flex flex-col gap-y-3" },
|
|
704
|
+
react_2.default.createElement(textInput_1.TextInput, { id: "drive-name", type: "text", label: "", placeholder: placeholder, value: value, autoFocus: true, onChange: function (event) { return onChange(event.target.value); } }),
|
|
705
|
+
modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
|
|
706
|
+
react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
|
|
707
|
+
react_2.default.createElement(button_1.Button, { text: "Cancel", type: "light", size: "small", onClick: handleCloseModals }),
|
|
708
|
+
react_2.default.createElement(button_1.Button, { text: working ? "Saving…" : submitText, type: "normal", size: "small", disable: working, onClick: onSubmit })))); };
|
|
709
|
+
var renderMoveContent = function () {
|
|
710
|
+
var _a;
|
|
711
|
+
if (!moveRow)
|
|
712
|
+
return null;
|
|
713
|
+
var rowId = (0, driveUtils_1.handleGetRowId)(moveRow);
|
|
714
|
+
var currentParent = String((_a = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.parentColumnId]) !== null && _a !== void 0 ? _a : "");
|
|
715
|
+
var targets = (0, driveUtils_1.handleGetMoveTargets)(folders, rowId, (0, driveUtils_1.handleIsDriveFolder)(moveRow, settings))
|
|
716
|
+
.map(function (eachFolder) { return ({
|
|
717
|
+
folder: eachFolder,
|
|
718
|
+
label: (0, driveUtils_1.handleFormatFolderPath)((0, driveUtils_1.handleBuildFolderPath)(folders, eachFolder.id)),
|
|
719
|
+
}); })
|
|
720
|
+
.sort(function (a, b) {
|
|
721
|
+
return a.label.localeCompare(b.label, undefined, { numeric: true, sensitivity: "base" });
|
|
722
|
+
});
|
|
723
|
+
var options = __spreadArray([
|
|
724
|
+
{ id: "", label: "Drive (top level)" }
|
|
725
|
+
], targets.map(function (eachTarget) { return ({
|
|
726
|
+
id: eachTarget.folder.id,
|
|
727
|
+
label: eachTarget.label,
|
|
728
|
+
}); }), true).filter(function (eachOption) { return eachOption.id !== currentParent; });
|
|
729
|
+
return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
|
|
730
|
+
modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
|
|
731
|
+
react_2.default.createElement("div", { className: "max-h-80 overflow-y-auto" },
|
|
732
|
+
react_2.default.createElement(newList_1.NewList, { list: options.map(function (eachOption) { return ({
|
|
733
|
+
id: eachOption.id || "__root__",
|
|
734
|
+
title: eachOption.label,
|
|
735
|
+
icon: renderFolderIcon("h-5 w-5"),
|
|
736
|
+
}); }), hidePagination: true, onClickItem: function (item) {
|
|
737
|
+
return !working && handleMove(item.id === "__root__" ? "" : item.id);
|
|
738
|
+
} }))));
|
|
739
|
+
};
|
|
740
|
+
var renderDeleteContent = function () {
|
|
741
|
+
var _a, _b;
|
|
742
|
+
if (!deleteRow)
|
|
743
|
+
return null;
|
|
744
|
+
var isFolder = (0, driveUtils_1.handleIsDriveFolder)(deleteRow, settings);
|
|
745
|
+
var name = String((_a = deleteRow === null || deleteRow === void 0 ? void 0 : deleteRow[settings.nameColumnId]) !== null && _a !== void 0 ? _a : "");
|
|
746
|
+
var inside = ((_b = deleteIds === null || deleteIds === void 0 ? void 0 : deleteIds.length) !== null && _b !== void 0 ? _b : 1) - 1;
|
|
747
|
+
return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
|
|
748
|
+
react_2.default.createElement("p", { className: "text-sm text-gray-700" }, !isFolder
|
|
749
|
+
? "Delete \"".concat(name, "\"? This cannot be undone.")
|
|
750
|
+
: deleteIds === null
|
|
751
|
+
? "Counting what is inside…"
|
|
752
|
+
: inside > 0
|
|
753
|
+
? "Delete \"".concat(name, "\" and the ").concat(inside, " item(s) inside it? This cannot be undone.")
|
|
754
|
+
: "Delete the empty folder \"".concat(name, "\"?")),
|
|
755
|
+
modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
|
|
756
|
+
react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
|
|
757
|
+
react_2.default.createElement(button_1.Button, { text: "Cancel", type: "light", size: "small", onClick: handleCloseModals }),
|
|
758
|
+
react_2.default.createElement(button_1.Button, { text: working ? "Deleting…" : "Delete", type: "danger", size: "small", disable: working || deleteIds === null, onClick: handleDelete }))));
|
|
759
|
+
};
|
|
760
|
+
var renderUploadContent = function () {
|
|
761
|
+
var _a;
|
|
762
|
+
var queued = (_a = uploadFiles.upload) !== null && _a !== void 0 ? _a : [];
|
|
763
|
+
return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
|
|
764
|
+
react_2.default.createElement(uploadInput_1.UploadInput, { lib: props.lib, id: "drive-upload", label: "", type: "multi", files: uploadFiles, disabled: working, onChange: function (_a) {
|
|
765
|
+
var value = _a.value, action = _a.action;
|
|
766
|
+
if (action === "upload")
|
|
767
|
+
setUploadFiles(function (current) {
|
|
768
|
+
var _a;
|
|
769
|
+
return (__assign(__assign({}, current), { upload: __spreadArray(__spreadArray([], ((_a = current.upload) !== null && _a !== void 0 ? _a : []), true), value, true) }));
|
|
770
|
+
});
|
|
771
|
+
if (action === "remove")
|
|
772
|
+
setUploadFiles(function (current) {
|
|
773
|
+
var _a;
|
|
774
|
+
return (__assign(__assign({}, current), { upload: ((_a = current.upload) !== null && _a !== void 0 ? _a : []).filter(function (eachFile) { return eachFile.token !== value.token; }) }));
|
|
775
|
+
});
|
|
776
|
+
} }),
|
|
777
|
+
queued.length > 0 && Object.keys(uploadStatus).length > 0 && (react_2.default.createElement("ul", { className: "flex flex-col gap-y-1 text-sm" }, queued.map(function (eachFile) {
|
|
778
|
+
var _a, _b;
|
|
779
|
+
return (react_2.default.createElement("li", { key: eachFile.token, className: "flex flex-row gap-x-2" },
|
|
780
|
+
react_2.default.createElement("span", { className: "truncate text-gray-700" }, (_b = (_a = eachFile.fileName) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : ""),
|
|
781
|
+
react_2.default.createElement("span", { className: "grow" }),
|
|
782
|
+
react_2.default.createElement("span", { className: uploadStatus[eachFile.token] === "failed"
|
|
783
|
+
? "text-red-600"
|
|
784
|
+
: "text-gray-500" }, uploadStatus[eachFile.token] === "done"
|
|
785
|
+
? "Uploaded"
|
|
786
|
+
: uploadStatus[eachFile.token] === "uploading"
|
|
787
|
+
? "Uploading…"
|
|
788
|
+
: uploadStatus[eachFile.token] === "failed"
|
|
789
|
+
? "Failed"
|
|
790
|
+
: "Waiting")));
|
|
791
|
+
}))),
|
|
792
|
+
modalError && react_2.default.createElement("p", { className: "text-sm text-red-600" }, modalError),
|
|
793
|
+
react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
|
|
794
|
+
react_2.default.createElement(button_1.Button, { text: "Close", type: "light", size: "small", onClick: handleCloseUpload }),
|
|
795
|
+
react_2.default.createElement(button_1.Button, { text: working ? "Uploading…" : "Upload ".concat(queued.length || "").trim(), type: "normal", size: "small", disable: working || queued.length === 0, onClick: handleUploadAll }))));
|
|
796
|
+
};
|
|
797
|
+
var renderPreviewContent = function () {
|
|
798
|
+
var _a, _b;
|
|
799
|
+
var file = previewRow ? handleResolveFile(previewRow) : null;
|
|
800
|
+
if (!file)
|
|
801
|
+
return null;
|
|
802
|
+
var kind = (0, filePreview_1.handleResolveFileKind)(file);
|
|
803
|
+
return (react_2.default.createElement("div", { className: "flex flex-col gap-y-3" },
|
|
804
|
+
kind === "image" && (
|
|
805
|
+
// eslint-disable-next-line jsx-a11y/img-redundant-alt
|
|
806
|
+
react_2.default.createElement("img", { src: file.fileName, alt: (_a = file.label) !== null && _a !== void 0 ? _a : "", className: "max-h-[70vh] w-full object-contain" })),
|
|
807
|
+
kind === "pdf" && (react_2.default.createElement("iframe", { title: (_b = file.label) !== null && _b !== void 0 ? _b : "Preview", src: file.fileName, className: "h-[70vh] w-full" })),
|
|
808
|
+
kind === "video" && (react_2.default.createElement("video", { src: file.fileName, controls: true, className: "max-h-[70vh] w-full" })),
|
|
809
|
+
kind !== "image" && kind !== "pdf" && kind !== "video" && (react_2.default.createElement("p", { className: "text-sm text-gray-600" }, "This file has no preview.")),
|
|
810
|
+
react_2.default.createElement("div", { className: "flex flex-row justify-end gap-x-3" },
|
|
811
|
+
react_2.default.createElement(button_1.Button, { text: "Details", type: "light", size: "small", onClick: function () {
|
|
812
|
+
var rowId = (0, driveUtils_1.handleGetRowId)(previewRow);
|
|
813
|
+
setPreviewRow(null);
|
|
814
|
+
props.handleOpenDetails(rowId);
|
|
815
|
+
} }),
|
|
816
|
+
react_2.default.createElement("a", { href: file.fileName, target: "_blank", rel: "noopener noreferrer", className: "rounded-md bg-primary-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-primary-700" }, "Download"))));
|
|
817
|
+
};
|
|
818
|
+
return (react_2.default.createElement("div", {
|
|
819
|
+
// INFO: a minimum height so an empty or near-empty folder is still a
|
|
820
|
+
// drop target worth aiming at
|
|
821
|
+
className: "relative mt-4 flex min-h-[240px] flex-col gap-y-4 rounded-lg p-4 ".concat(props.darkMode ? "bg-white/5" : "bg-white"), "data-testid": "drive-view", onDragEnter: function (event) {
|
|
822
|
+
if (!handleIsFileDrag(event))
|
|
823
|
+
return;
|
|
824
|
+
event.preventDefault();
|
|
825
|
+
dragDepthRef.current += 1;
|
|
826
|
+
setDragging(true);
|
|
827
|
+
}, onDragOver: function (event) {
|
|
828
|
+
if (handleIsFileDrag(event))
|
|
829
|
+
event.preventDefault();
|
|
830
|
+
}, onDragLeave: function (event) {
|
|
831
|
+
if (!handleIsFileDrag(event))
|
|
832
|
+
return;
|
|
833
|
+
dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
|
|
834
|
+
if (dragDepthRef.current === 0)
|
|
835
|
+
setDragging(false);
|
|
836
|
+
}, onDrop: function (event) {
|
|
837
|
+
var _a, _b;
|
|
838
|
+
dragDepthRef.current = 0;
|
|
839
|
+
setDragging(false);
|
|
840
|
+
if (!handleIsFileDrag(event) || !((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b.length))
|
|
841
|
+
return;
|
|
842
|
+
event.preventDefault();
|
|
843
|
+
handleDropFiles(Array.from(event.dataTransfer.files));
|
|
844
|
+
} },
|
|
845
|
+
renderToolbar(),
|
|
846
|
+
renderContent(),
|
|
847
|
+
renderDropOverlay(),
|
|
848
|
+
react_2.default.createElement(modal_1.Modal, { open: newFolderOpen, title: "New folder", onClose: handleCloseModals, renderContent: function () {
|
|
849
|
+
return renderNameForm(folderName, setFolderName, handleCreateFolder, "Create", "Folder name");
|
|
850
|
+
} }),
|
|
851
|
+
react_2.default.createElement(modal_1.Modal, { open: !!renameRow, title: "Rename", onClose: handleCloseModals, renderContent: function () {
|
|
852
|
+
return renderNameForm(renameValue, setRenameValue, handleRename, "Save", "Name");
|
|
853
|
+
} }),
|
|
854
|
+
react_2.default.createElement(modal_1.Modal, { open: !!moveRow, title: "Move \"".concat(String((_b = moveRow === null || moveRow === void 0 ? void 0 : moveRow[settings.nameColumnId]) !== null && _b !== void 0 ? _b : ""), "\" to"), onClose: handleCloseModals, renderContent: renderMoveContent }),
|
|
855
|
+
react_2.default.createElement(modal_1.Modal, { open: !!deleteRow, title: "Delete", onClose: handleCloseModals, renderContent: renderDeleteContent }),
|
|
856
|
+
react_2.default.createElement(modal_1.Modal, { open: uploadOpen, title: "Upload files", maxWidth: "2xl", onClose: handleCloseUpload, renderContent: renderUploadContent }),
|
|
857
|
+
react_2.default.createElement(modal_1.Modal, { open: !!previewRow, title: String((_c = previewRow === null || previewRow === void 0 ? void 0 : previewRow[settings.nameColumnId]) !== null && _c !== void 0 ? _c : ""), maxWidth: "4xl", onClose: function () { return setPreviewRow(null); }, renderContent: renderPreviewContent })));
|
|
858
|
+
};
|
|
859
|
+
exports.DriveView = DriveView;
|
|
860
|
+
/**
|
|
861
|
+
* The per-item action menu.
|
|
862
|
+
*
|
|
863
|
+
* INFO: portalled — the list layout sits in NewList's rounded card, which clips
|
|
864
|
+
* overflow, so an in-place panel was cut off at the row's edge. Button's own
|
|
865
|
+
* popUpMenuItems has no portal and a full-size trigger, hence a small one here.
|
|
866
|
+
*/
|
|
867
|
+
var DriveItemMenu = function (props) {
|
|
868
|
+
var popUpRef = (0, react_2.useRef)(null);
|
|
869
|
+
return (react_2.default.createElement("div", { "data-testid": props.testId, onClick: function (event) { return event.stopPropagation(); } },
|
|
870
|
+
react_2.default.createElement(popUp_1.PopUp, { ref: popUpRef, portal: true, anchor: "right", direction: "bottom", lib: { Transition: react_1.Transition }, ctaComp: react_2.default.createElement("button", { type: "button", "aria-label": "Actions", className: "rounded-md p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700" },
|
|
871
|
+
react_2.default.createElement(HeroIcons.EllipsisVerticalIcon, { className: "h-4 w-4" })), renderComp: react_2.default.createElement("div", { className: "flex min-w-[140px] flex-col divide-y overflow-hidden rounded-md bg-white shadow-md" }, props.items.map(function (eachItem) { return (react_2.default.createElement("button", { key: eachItem.text, type: "button", className: "px-4 py-2 text-left text-sm hover:bg-gray-100 ".concat(eachItem.text === "Delete" ? "text-red-600" : "text-gray-900"), onClick: function () {
|
|
872
|
+
var _a;
|
|
873
|
+
(_a = popUpRef.current) === null || _a === void 0 ? void 0 : _a.handleOnClose();
|
|
874
|
+
eachItem.onClick();
|
|
875
|
+
} }, eachItem.text)); })) })));
|
|
876
|
+
};
|
|
877
|
+
//# sourceMappingURL=driveView.js.map
|