@design.estate/dees-catalog 3.47.1 → 3.48.3
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/dist_bundle/bundle.js +4903 -2056
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.d.ts +50 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.demo.d.ts +2 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.demo.js +148 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.js +520 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-columns.d.ts +99 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-columns.js +1731 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-keys.d.ts +64 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-keys.js +1232 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-preview.d.ts +37 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-preview.js +626 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/index.d.ts +6 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/index.js +7 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/interfaces.d.ts +48 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/interfaces.js +5 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/utilities.d.ts +39 -0
- package/dist_ts_web/elements/00group-dataview/dees-storage-browser/utilities.js +109 -0
- package/dist_ts_web/elements/00group-dataview/index.d.ts +1 -0
- package/dist_ts_web/elements/00group-dataview/index.js +2 -1
- package/dist_watch/bundle.js +4928 -2090
- package/dist_watch/bundle.js.map +4 -4
- package/package.json +3 -3
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.demo.ts +156 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-browser.ts +439 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-columns.ts +1652 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-keys.ts +1094 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/dees-storage-preview.ts +540 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/index.ts +6 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/interfaces.ts +37 -0
- package/ts_web/elements/00group-dataview/dees-storage-browser/utilities.ts +120 -0
- package/ts_web/elements/00group-dataview/index.ts +1 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 Data Provider interface - implement this to connect the S3 browser to your backend
|
|
3
|
+
*/
|
|
4
|
+
export interface IS3Object {
|
|
5
|
+
key: string;
|
|
6
|
+
size?: number;
|
|
7
|
+
lastModified?: string;
|
|
8
|
+
isPrefix?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface IS3ChangeEvent {
|
|
11
|
+
type: 'add' | 'modify' | 'delete';
|
|
12
|
+
key: string;
|
|
13
|
+
bucket: string;
|
|
14
|
+
size?: number;
|
|
15
|
+
lastModified?: Date;
|
|
16
|
+
}
|
|
17
|
+
export interface IS3DataProvider {
|
|
18
|
+
listObjects(bucket: string, prefix?: string, delimiter?: string): Promise<{
|
|
19
|
+
objects: IS3Object[];
|
|
20
|
+
prefixes: string[];
|
|
21
|
+
}>;
|
|
22
|
+
getObject(bucket: string, key: string): Promise<{
|
|
23
|
+
content: string;
|
|
24
|
+
contentType: string;
|
|
25
|
+
size: number;
|
|
26
|
+
lastModified: string;
|
|
27
|
+
}>;
|
|
28
|
+
putObject(bucket: string, key: string, base64Content: string, contentType: string): Promise<boolean>;
|
|
29
|
+
deleteObject(bucket: string, key: string): Promise<boolean>;
|
|
30
|
+
deletePrefix(bucket: string, prefix: string): Promise<boolean>;
|
|
31
|
+
getObjectUrl(bucket: string, key: string): Promise<string>;
|
|
32
|
+
moveObject(bucket: string, sourceKey: string, destKey: string): Promise<{
|
|
33
|
+
success: boolean;
|
|
34
|
+
error?: string;
|
|
35
|
+
}>;
|
|
36
|
+
movePrefix(bucket: string, sourcePrefix: string, destPrefix: string): Promise<{
|
|
37
|
+
success: boolean;
|
|
38
|
+
movedCount?: number;
|
|
39
|
+
error?: string;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
export interface IColumn {
|
|
43
|
+
prefix: string;
|
|
44
|
+
objects: IS3Object[];
|
|
45
|
+
prefixes: string[];
|
|
46
|
+
selectedItem: string | null;
|
|
47
|
+
width: number;
|
|
48
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 Data Provider interface - implement this to connect the S3 browser to your backend
|
|
3
|
+
*/
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzX3dlYi9lbGVtZW50cy8wMGdyb3VwLWRhdGF2aWV3L2RlZXMtc3RvcmFnZS1icm93c2VyL2ludGVyZmFjZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUcifQ==
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for S3 browser components
|
|
3
|
+
*/
|
|
4
|
+
export interface IMoveValidation {
|
|
5
|
+
valid: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Format a byte size into a human-readable string
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatSize(bytes?: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* Format a count into a compact human-readable string
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatCount(count?: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* Extract the file name from a path
|
|
18
|
+
*/
|
|
19
|
+
export declare function getFileName(path: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Validates if a move operation is allowed
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateMove(sourceKey: string, destPrefix: string): IMoveValidation;
|
|
24
|
+
/**
|
|
25
|
+
* Gets the parent prefix (directory) of a given key
|
|
26
|
+
*/
|
|
27
|
+
export declare function getParentPrefix(key: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Get content type from file extension
|
|
30
|
+
*/
|
|
31
|
+
export declare function getContentType(ext: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Get default content for a new file based on extension
|
|
34
|
+
*/
|
|
35
|
+
export declare function getDefaultContent(ext: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Parse a prefix into cumulative path segments
|
|
38
|
+
*/
|
|
39
|
+
export declare function getPathSegments(prefix: string): string[];
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for S3 browser components
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Format a byte size into a human-readable string
|
|
6
|
+
*/
|
|
7
|
+
export function formatSize(bytes) {
|
|
8
|
+
if (bytes === undefined || bytes === null)
|
|
9
|
+
return '-';
|
|
10
|
+
if (bytes === 0)
|
|
11
|
+
return '0 B';
|
|
12
|
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
13
|
+
let size = bytes;
|
|
14
|
+
let unitIndex = 0;
|
|
15
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
16
|
+
size /= 1024;
|
|
17
|
+
unitIndex++;
|
|
18
|
+
}
|
|
19
|
+
return `${size.toFixed(unitIndex > 0 ? 1 : 0)} ${units[unitIndex]}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Format a count into a compact human-readable string
|
|
23
|
+
*/
|
|
24
|
+
export function formatCount(count) {
|
|
25
|
+
if (count === undefined || count === null)
|
|
26
|
+
return '';
|
|
27
|
+
if (count >= 1000000)
|
|
28
|
+
return `${(count / 1000000).toFixed(1)}M`;
|
|
29
|
+
if (count >= 1000)
|
|
30
|
+
return `${(count / 1000).toFixed(1)}K`;
|
|
31
|
+
return count.toString();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract the file name from a path
|
|
35
|
+
*/
|
|
36
|
+
export function getFileName(path) {
|
|
37
|
+
const parts = path.replace(/\/$/, '').split('/');
|
|
38
|
+
return parts[parts.length - 1] || path;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates if a move operation is allowed
|
|
42
|
+
*/
|
|
43
|
+
export function validateMove(sourceKey, destPrefix) {
|
|
44
|
+
if (sourceKey.endsWith('/')) {
|
|
45
|
+
if (destPrefix.startsWith(sourceKey)) {
|
|
46
|
+
return { valid: false, error: 'Cannot move a folder into itself' };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const sourceParent = getParentPrefix(sourceKey);
|
|
50
|
+
if (sourceParent === destPrefix) {
|
|
51
|
+
return { valid: false, error: 'Item is already in this location' };
|
|
52
|
+
}
|
|
53
|
+
return { valid: true };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Gets the parent prefix (directory) of a given key
|
|
57
|
+
*/
|
|
58
|
+
export function getParentPrefix(key) {
|
|
59
|
+
const trimmed = key.endsWith('/') ? key.slice(0, -1) : key;
|
|
60
|
+
const lastSlash = trimmed.lastIndexOf('/');
|
|
61
|
+
return lastSlash >= 0 ? trimmed.substring(0, lastSlash + 1) : '';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get content type from file extension
|
|
65
|
+
*/
|
|
66
|
+
export function getContentType(ext) {
|
|
67
|
+
const contentTypes = {
|
|
68
|
+
json: 'application/json',
|
|
69
|
+
txt: 'text/plain',
|
|
70
|
+
html: 'text/html',
|
|
71
|
+
css: 'text/css',
|
|
72
|
+
js: 'application/javascript',
|
|
73
|
+
ts: 'text/typescript',
|
|
74
|
+
md: 'text/markdown',
|
|
75
|
+
xml: 'application/xml',
|
|
76
|
+
yaml: 'text/yaml',
|
|
77
|
+
yml: 'text/yaml',
|
|
78
|
+
csv: 'text/csv',
|
|
79
|
+
};
|
|
80
|
+
return contentTypes[ext] || 'application/octet-stream';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get default content for a new file based on extension
|
|
84
|
+
*/
|
|
85
|
+
export function getDefaultContent(ext) {
|
|
86
|
+
const defaults = {
|
|
87
|
+
json: '{\n \n}',
|
|
88
|
+
html: '<!DOCTYPE html>\n<html>\n<head>\n <title></title>\n</head>\n<body>\n \n</body>\n</html>',
|
|
89
|
+
md: '# Title\n\n',
|
|
90
|
+
txt: '',
|
|
91
|
+
};
|
|
92
|
+
return defaults[ext] || '';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Parse a prefix into cumulative path segments
|
|
96
|
+
*/
|
|
97
|
+
export function getPathSegments(prefix) {
|
|
98
|
+
if (!prefix)
|
|
99
|
+
return [];
|
|
100
|
+
const parts = prefix.split('/').filter(p => p);
|
|
101
|
+
const segments = [];
|
|
102
|
+
let cumulative = '';
|
|
103
|
+
for (const part of parts) {
|
|
104
|
+
cumulative += part + '/';
|
|
105
|
+
segments.push(cumulative);
|
|
106
|
+
}
|
|
107
|
+
return segments;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbGl0aWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHNfd2ViL2VsZW1lbnRzLzAwZ3JvdXAtZGF0YXZpZXcvZGVlcy1zdG9yYWdlLWJyb3dzZXIvdXRpbGl0aWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBT0g7O0dBRUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLEtBQWM7SUFDdkMsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxHQUFHLENBQUM7SUFDdEQsSUFBSSxLQUFLLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBRTlCLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzVDLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNqQixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFFbEIsT0FBTyxJQUFJLElBQUksSUFBSSxJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BELElBQUksSUFBSSxJQUFJLENBQUM7UUFDYixTQUFTLEVBQUUsQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO0FBQ3RFLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBYztJQUN4QyxJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUk7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNyRCxJQUFJLEtBQUssSUFBSSxPQUFPO1FBQUUsT0FBTyxHQUFHLENBQUMs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
|
|
@@ -3,4 +3,5 @@ export * from './dees-dataview-codebox/index.js';
|
|
|
3
3
|
export * from './dees-dataview-statusobject/index.js';
|
|
4
4
|
export * from './dees-table/index.js';
|
|
5
5
|
export * from './dees-statsgrid/index.js';
|
|
6
|
-
|
|
6
|
+
export * from './dees-storage-browser/index.js';
|
|
7
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1kYXRhdmlldy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1QkFBdUI7QUFDdkIsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYywyQkFBMkIsQ0FBQztBQUMxQyxjQUFjLGlDQUFpQyxDQUFDIn0=
|