@noya-app/noya-file-explorer 0.0.2
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/.eslintrc.js +11 -0
- package/.turbo/turbo-build.log +24 -0
- package/CHANGELOG.md +14 -0
- package/README.md +3 -0
- package/dist/index.css +1811 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +23279 -0
- package/dist/index.d.ts +23279 -0
- package/dist/index.js +1854 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1857 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +37 -0
- package/src/MediaCollection.tsx +839 -0
- package/src/__tests__/deleteMediaItems.test.ts +125 -0
- package/src/__tests__/getDepthMap.test.ts +84 -0
- package/src/__tests__/getParentDirectories.test.ts +68 -0
- package/src/__tests__/getVisibleItems.test.ts +184 -0
- package/src/__tests__/moveMediaInsideFolder.test.ts +348 -0
- package/src/__tests__/movePathsIntoTarget.test.ts +229 -0
- package/src/__tests__/moveUpAFolder.test.ts +179 -0
- package/src/__tests__/updateExpandedMap.test.ts +157 -0
- package/src/__tests__/validateMediaItemRename.test.ts +200 -0
- package/src/index.css +1 -0
- package/src/index.ts +4 -0
- package/src/utils/files.ts +274 -0
- package/src/utils/mediaItemTree.ts +110 -0
- package/tsconfig.json +3 -0
- package/tsup.config.ts +13 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { MediaMap } from "@noya-app/noya-schemas";
|
|
2
|
+
import { expect, it } from "bun:test";
|
|
3
|
+
import { moveUpAFolder } from "../utils/files";
|
|
4
|
+
import {
|
|
5
|
+
createMediaAsset,
|
|
6
|
+
createMediaFolder,
|
|
7
|
+
createMediaItemTree,
|
|
8
|
+
} from "../utils/mediaItemTree";
|
|
9
|
+
|
|
10
|
+
it("should move an item up one level in the folder hierarchy", () => {
|
|
11
|
+
// Create a folder structure:
|
|
12
|
+
// Root
|
|
13
|
+
// └── Folder 1
|
|
14
|
+
// └── Folder 2
|
|
15
|
+
// └── Asset 1
|
|
16
|
+
const folder1 = createMediaFolder();
|
|
17
|
+
const folder2 = createMediaFolder();
|
|
18
|
+
const asset1 = createMediaAsset({
|
|
19
|
+
assetId: "asset1",
|
|
20
|
+
});
|
|
21
|
+
const media: MediaMap = {
|
|
22
|
+
folder1,
|
|
23
|
+
"folder1/folder2": folder2,
|
|
24
|
+
"folder1/folder2/asset1": asset1,
|
|
25
|
+
};
|
|
26
|
+
const tree = createMediaItemTree(media);
|
|
27
|
+
|
|
28
|
+
// Move Asset 1 up from Folder 2 to Folder 1
|
|
29
|
+
const result = moveUpAFolder({
|
|
30
|
+
tree,
|
|
31
|
+
media: media,
|
|
32
|
+
selectedIds: [asset1.id],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Asset 1 should now have Folder 1 as its parent
|
|
36
|
+
expect(result).toBeDefined();
|
|
37
|
+
expect(result?.["folder1/asset1"]).toEqual(asset1);
|
|
38
|
+
|
|
39
|
+
// Other items should remain unchanged
|
|
40
|
+
expect(result?.["folder1"]).toEqual(folder1);
|
|
41
|
+
expect(result?.["folder1/folder2"]).toEqual(folder2);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should move multiple items up one level at once", () => {
|
|
45
|
+
// Create a folder structure:
|
|
46
|
+
// Root
|
|
47
|
+
// └── Folder 1
|
|
48
|
+
// └── Folder 2
|
|
49
|
+
// ├── Asset 1
|
|
50
|
+
// └── Asset 2
|
|
51
|
+
const folder1 = createMediaFolder();
|
|
52
|
+
const folder2 = createMediaFolder();
|
|
53
|
+
const asset1 = createMediaAsset({
|
|
54
|
+
assetId: "asset1",
|
|
55
|
+
});
|
|
56
|
+
const asset2 = createMediaAsset({
|
|
57
|
+
assetId: "asset2",
|
|
58
|
+
});
|
|
59
|
+
const media: MediaMap = {
|
|
60
|
+
folder1,
|
|
61
|
+
"folder1/folder2": folder2,
|
|
62
|
+
"folder1/folder2/asset1": asset1,
|
|
63
|
+
"folder1/folder2/asset2": asset2,
|
|
64
|
+
};
|
|
65
|
+
const tree = createMediaItemTree(media);
|
|
66
|
+
|
|
67
|
+
// Move both assets up from Folder 2 to Folder 1
|
|
68
|
+
const result = moveUpAFolder({
|
|
69
|
+
tree,
|
|
70
|
+
media: media,
|
|
71
|
+
selectedIds: [asset1.id, asset2.id],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Both assets should now have Folder 1 as their parent
|
|
75
|
+
expect(result).toBeDefined();
|
|
76
|
+
|
|
77
|
+
expect(result?.["folder1/asset1"]).toEqual(asset1);
|
|
78
|
+
expect(result?.["folder1/asset2"]).toEqual(asset2);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should return undefined if the selected item is not found", () => {
|
|
82
|
+
const folder1 = createMediaFolder();
|
|
83
|
+
|
|
84
|
+
const media: MediaMap = {
|
|
85
|
+
folder1,
|
|
86
|
+
};
|
|
87
|
+
const tree = createMediaItemTree(media);
|
|
88
|
+
|
|
89
|
+
const result = moveUpAFolder({
|
|
90
|
+
tree,
|
|
91
|
+
media: media,
|
|
92
|
+
selectedIds: ["nonexistent"],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
expect(result).toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should not move items at root level", () => {
|
|
99
|
+
// Create a folder structure with only one level:
|
|
100
|
+
// Root
|
|
101
|
+
// └── Asset 1
|
|
102
|
+
const asset1 = createMediaAsset({
|
|
103
|
+
assetId: "asset1",
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const media: MediaMap = {
|
|
107
|
+
asset1: asset1,
|
|
108
|
+
};
|
|
109
|
+
const tree = createMediaItemTree(media);
|
|
110
|
+
|
|
111
|
+
// Try to move Asset 1 up, but it's already at the root
|
|
112
|
+
const result = moveUpAFolder({
|
|
113
|
+
tree,
|
|
114
|
+
media: media,
|
|
115
|
+
selectedIds: [asset1.id],
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// The function should still return a result, with the asset having undefined parentId
|
|
119
|
+
expect(result).toBeDefined();
|
|
120
|
+
expect(result?.["asset1"]).toEqual(asset1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should move items from a subfolder to root if parent is at root level", () => {
|
|
124
|
+
// Create a folder structure:
|
|
125
|
+
// Root
|
|
126
|
+
// └── Folder 1
|
|
127
|
+
// └── Asset 1
|
|
128
|
+
const folder1 = createMediaFolder();
|
|
129
|
+
const asset1 = createMediaAsset({
|
|
130
|
+
assetId: "asset1",
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const media: MediaMap = {
|
|
134
|
+
folder1,
|
|
135
|
+
"folder1/asset1": asset1,
|
|
136
|
+
};
|
|
137
|
+
const tree = createMediaItemTree(media);
|
|
138
|
+
|
|
139
|
+
// Move Asset 1 up from Folder 1 to Root
|
|
140
|
+
const result = moveUpAFolder({
|
|
141
|
+
tree,
|
|
142
|
+
media: media,
|
|
143
|
+
selectedIds: [asset1.id],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(result).toBeDefined();
|
|
147
|
+
expect(result?.["asset1"]).toEqual(asset1);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should move a folders descendants up a folder", () => {
|
|
151
|
+
// Create a folder structure:
|
|
152
|
+
// Root
|
|
153
|
+
// └── Folder 1
|
|
154
|
+
// └── Folder 2
|
|
155
|
+
// └── Asset 1
|
|
156
|
+
const folder1 = createMediaFolder();
|
|
157
|
+
const folder2 = createMediaFolder();
|
|
158
|
+
const asset1 = createMediaAsset({
|
|
159
|
+
assetId: "asset1",
|
|
160
|
+
});
|
|
161
|
+
const media: MediaMap = {
|
|
162
|
+
folder1,
|
|
163
|
+
"folder1/folder2": folder2,
|
|
164
|
+
"folder1/folder2/asset1": asset1,
|
|
165
|
+
};
|
|
166
|
+
const tree = createMediaItemTree(media);
|
|
167
|
+
|
|
168
|
+
const result = moveUpAFolder({
|
|
169
|
+
tree,
|
|
170
|
+
media: media,
|
|
171
|
+
selectedIds: [folder2.id],
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
expect(result).toBeDefined();
|
|
175
|
+
expect(result?.["folder2/asset1"]).toEqual(asset1);
|
|
176
|
+
expect(result?.["folder2"]).toEqual(folder2);
|
|
177
|
+
expect(result?.["folder1"]).toEqual(folder1);
|
|
178
|
+
expect(result?.["folder1/folder2"]).toBeUndefined();
|
|
179
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { MediaMap } from "@noya-app/noya-schemas";
|
|
2
|
+
import { expect, it } from "bun:test";
|
|
3
|
+
import { updateExpandedMap } from "../utils/files";
|
|
4
|
+
import {
|
|
5
|
+
createMediaFolder,
|
|
6
|
+
createMediaItemTree,
|
|
7
|
+
rootMediaItem,
|
|
8
|
+
} from "../utils/mediaItemTree";
|
|
9
|
+
|
|
10
|
+
it("should expand a folder", () => {
|
|
11
|
+
const dir1 = createMediaFolder();
|
|
12
|
+
const media: MediaMap = { dir1 };
|
|
13
|
+
const tree = createMediaItemTree(media);
|
|
14
|
+
const expandedMap = {};
|
|
15
|
+
|
|
16
|
+
const result = updateExpandedMap({
|
|
17
|
+
item: dir1,
|
|
18
|
+
expanded: true,
|
|
19
|
+
tree,
|
|
20
|
+
expandable: true,
|
|
21
|
+
expandedMap,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(result).toEqual({ [dir1.id]: true });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should collapse a folder and all its children", () => {
|
|
28
|
+
const dir1 = createMediaFolder();
|
|
29
|
+
const dir2 = createMediaFolder();
|
|
30
|
+
const dir3 = createMediaFolder();
|
|
31
|
+
const media: MediaMap = {
|
|
32
|
+
dir1,
|
|
33
|
+
"dir1/dir2": dir2,
|
|
34
|
+
"dir1/dir3": dir3,
|
|
35
|
+
};
|
|
36
|
+
const tree = createMediaItemTree(media);
|
|
37
|
+
const expandedMap = { [dir1.id]: true, [dir2.id]: true, [dir3.id]: true };
|
|
38
|
+
|
|
39
|
+
const result = updateExpandedMap({
|
|
40
|
+
item: dir1,
|
|
41
|
+
expanded: false,
|
|
42
|
+
tree,
|
|
43
|
+
expandable: true,
|
|
44
|
+
expandedMap,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(result).toEqual({
|
|
48
|
+
[dir1.id]: false,
|
|
49
|
+
[dir2.id]: false,
|
|
50
|
+
[dir3.id]: false,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should not modify map if expandable is false", () => {
|
|
55
|
+
const item = createMediaFolder();
|
|
56
|
+
const media: MediaMap = { folder: item };
|
|
57
|
+
const tree = createMediaItemTree(media);
|
|
58
|
+
const expandedMap = { someOtherId: true };
|
|
59
|
+
|
|
60
|
+
const result = updateExpandedMap({
|
|
61
|
+
item,
|
|
62
|
+
expanded: true,
|
|
63
|
+
tree,
|
|
64
|
+
expandable: false,
|
|
65
|
+
expandedMap,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(result).toEqual(expandedMap);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should not modify root item expansion state", () => {
|
|
72
|
+
const media: MediaMap = { rootMediaItem };
|
|
73
|
+
const tree = createMediaItemTree(media);
|
|
74
|
+
const expandedMap = { someOtherId: true };
|
|
75
|
+
|
|
76
|
+
const result = updateExpandedMap({
|
|
77
|
+
item: rootMediaItem,
|
|
78
|
+
expanded: true,
|
|
79
|
+
tree,
|
|
80
|
+
expandable: true,
|
|
81
|
+
expandedMap,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(result).toEqual(expandedMap);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should handle deeply nested folder structure", () => {
|
|
88
|
+
const dir1 = createMediaFolder();
|
|
89
|
+
const dir2 = createMediaFolder();
|
|
90
|
+
const dir3 = createMediaFolder();
|
|
91
|
+
const media: MediaMap = {
|
|
92
|
+
dir1,
|
|
93
|
+
"dir1/dir2": dir2,
|
|
94
|
+
"dir1/dir2/dir3": dir3,
|
|
95
|
+
};
|
|
96
|
+
const tree = createMediaItemTree(media);
|
|
97
|
+
const expandedMap = { [dir1.id]: true, [dir2.id]: true, [dir3.id]: true };
|
|
98
|
+
|
|
99
|
+
const result = updateExpandedMap({
|
|
100
|
+
item: dir1,
|
|
101
|
+
expanded: false,
|
|
102
|
+
tree,
|
|
103
|
+
expandable: true,
|
|
104
|
+
expandedMap,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(result).toEqual({
|
|
108
|
+
[dir1.id]: false,
|
|
109
|
+
[dir2.id]: false,
|
|
110
|
+
[dir3.id]: false,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should preserve other expanded states when modifying one folder", () => {
|
|
115
|
+
const dir1 = createMediaFolder();
|
|
116
|
+
const dir2 = createMediaFolder();
|
|
117
|
+
const media: MediaMap = { dir1, dir2 };
|
|
118
|
+
const tree = createMediaItemTree(media);
|
|
119
|
+
const expandedMap = { [dir1.id]: false, [dir2.id]: true };
|
|
120
|
+
|
|
121
|
+
const result = updateExpandedMap({
|
|
122
|
+
item: dir1,
|
|
123
|
+
expanded: true,
|
|
124
|
+
tree,
|
|
125
|
+
expandable: true,
|
|
126
|
+
expandedMap,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
expect(result).toEqual({ [dir1.id]: true, [dir2.id]: true });
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should handle collapsing with missing children in media array", () => {
|
|
133
|
+
const dir1 = createMediaFolder();
|
|
134
|
+
const media: MediaMap = { dir1 };
|
|
135
|
+
const tree = createMediaItemTree(media);
|
|
136
|
+
// Expanded map contains children that don't exist in media array
|
|
137
|
+
const expandedMap = {
|
|
138
|
+
[dir1.id]: true,
|
|
139
|
+
missingChild1: true,
|
|
140
|
+
missingChild2: true,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const result = updateExpandedMap({
|
|
144
|
+
item: dir1,
|
|
145
|
+
expanded: false,
|
|
146
|
+
tree,
|
|
147
|
+
expandable: true,
|
|
148
|
+
expandedMap,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Should only modify the existing parent's state
|
|
152
|
+
expect(result).toEqual({
|
|
153
|
+
[dir1.id]: false,
|
|
154
|
+
missingChild1: true,
|
|
155
|
+
missingChild2: true,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { MediaMap } from "@noya-app/noya-schemas";
|
|
2
|
+
import { expect, it } from "bun:test";
|
|
3
|
+
import { validateMediaItemRename } from "../utils/files";
|
|
4
|
+
import { createMediaAsset, createMediaFolder } from "../utils/mediaItemTree";
|
|
5
|
+
|
|
6
|
+
it("should return true for valid rename with no conflicts", () => {
|
|
7
|
+
const dir1 = createMediaFolder();
|
|
8
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
9
|
+
const mediaMap: MediaMap = {
|
|
10
|
+
dir1,
|
|
11
|
+
"dir1/file1.jpg": file1,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const result = validateMediaItemRename({
|
|
15
|
+
basename: "newname.jpg",
|
|
16
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
17
|
+
media: mediaMap,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(result).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return false when a file with the same name already exists", () => {
|
|
24
|
+
const dir1 = createMediaFolder();
|
|
25
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
26
|
+
const file2 = createMediaAsset({ assetId: "2" });
|
|
27
|
+
const mediaMap: MediaMap = {
|
|
28
|
+
dir1,
|
|
29
|
+
"dir1/file1.jpg": file1,
|
|
30
|
+
"dir1/file2.jpg": file2,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const result = validateMediaItemRename({
|
|
34
|
+
basename: "file2.jpg",
|
|
35
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
36
|
+
media: mediaMap,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(result).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should return false when renaming a file to its own name", () => {
|
|
43
|
+
const dir1 = createMediaFolder();
|
|
44
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
45
|
+
const mediaMap: MediaMap = {
|
|
46
|
+
dir1,
|
|
47
|
+
"dir1/file1.jpg": file1,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const result = validateMediaItemRename({
|
|
51
|
+
basename: "file1.jpg",
|
|
52
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
53
|
+
media: mediaMap,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(result).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should return true when renaming a folder with no conflicts", () => {
|
|
60
|
+
const dir1 = createMediaFolder();
|
|
61
|
+
const dir2 = createMediaFolder();
|
|
62
|
+
const mediaMap: MediaMap = {
|
|
63
|
+
dir1,
|
|
64
|
+
"dir1/dir2": dir2,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const result = validateMediaItemRename({
|
|
68
|
+
basename: "newdir",
|
|
69
|
+
selectedItemPath: "dir1/dir2",
|
|
70
|
+
media: mediaMap,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(result).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should return false when a folder with the same name already exists", () => {
|
|
77
|
+
const dir1 = createMediaFolder();
|
|
78
|
+
const dir2 = createMediaFolder();
|
|
79
|
+
const dir3 = createMediaFolder();
|
|
80
|
+
const mediaMap: MediaMap = {
|
|
81
|
+
dir1,
|
|
82
|
+
"dir1/dir2": dir2,
|
|
83
|
+
"dir1/dir3": dir3,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const result = validateMediaItemRename({
|
|
87
|
+
basename: "dir3",
|
|
88
|
+
selectedItemPath: "dir1/dir2",
|
|
89
|
+
media: mediaMap,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(result).toBe(false);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("should handle special characters in basename", () => {
|
|
96
|
+
const dir1 = createMediaFolder();
|
|
97
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
98
|
+
const mediaMap: MediaMap = {
|
|
99
|
+
dir1,
|
|
100
|
+
"dir1/file1.jpg": file1,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const result = validateMediaItemRename({
|
|
104
|
+
basename: "new-file@name.jpg",
|
|
105
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
106
|
+
media: mediaMap,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expect(result).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should return true when renaming to a name that exists in a different directory", () => {
|
|
113
|
+
const dir1 = createMediaFolder();
|
|
114
|
+
const dir2 = createMediaFolder();
|
|
115
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
116
|
+
const file2 = createMediaAsset({ assetId: "2" });
|
|
117
|
+
const mediaMap: MediaMap = {
|
|
118
|
+
dir1,
|
|
119
|
+
dir2,
|
|
120
|
+
"dir1/file1.jpg": file1,
|
|
121
|
+
"dir2/file2.jpg": file2,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const result = validateMediaItemRename({
|
|
125
|
+
basename: "file2.jpg",
|
|
126
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
127
|
+
media: mediaMap,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(result).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("should return false when trying to rename to an empty basename", () => {
|
|
134
|
+
const dir1 = createMediaFolder();
|
|
135
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
136
|
+
const mediaMap: MediaMap = {
|
|
137
|
+
dir1,
|
|
138
|
+
"dir1/file1.jpg": file1,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const result = validateMediaItemRename({
|
|
142
|
+
basename: "",
|
|
143
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
144
|
+
media: mediaMap,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
expect(result).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should handle deep nested directories", () => {
|
|
151
|
+
const dir1 = createMediaFolder();
|
|
152
|
+
const dir2 = createMediaFolder();
|
|
153
|
+
const dir3 = createMediaFolder();
|
|
154
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
155
|
+
const mediaMap: MediaMap = {
|
|
156
|
+
dir1,
|
|
157
|
+
"dir1/dir2": dir2,
|
|
158
|
+
"dir1/dir2/dir3": dir3,
|
|
159
|
+
"dir1/dir2/dir3/file1.jpg": file1,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const result = validateMediaItemRename({
|
|
163
|
+
basename: "renamed.jpg",
|
|
164
|
+
selectedItemPath: "dir1/dir2/dir3/file1.jpg",
|
|
165
|
+
media: mediaMap,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
expect(result).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should return false when basename contains invalid filesystem characters", () => {
|
|
172
|
+
const dir1 = createMediaFolder();
|
|
173
|
+
const file1 = createMediaAsset({ assetId: "1" });
|
|
174
|
+
const mediaMap: MediaMap = {
|
|
175
|
+
dir1,
|
|
176
|
+
"dir1/file1.jpg": file1,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const invalidNames = [
|
|
180
|
+
"file/name.jpg",
|
|
181
|
+
"file\\name.jpg",
|
|
182
|
+
"file<name.jpg",
|
|
183
|
+
"file>name.jpg",
|
|
184
|
+
'file"name.jpg',
|
|
185
|
+
"file:name.jpg",
|
|
186
|
+
"file|name.jpg",
|
|
187
|
+
"file?name.jpg",
|
|
188
|
+
"file*name.jpg",
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
invalidNames.forEach((basename) => {
|
|
192
|
+
const result = validateMediaItemRename({
|
|
193
|
+
basename,
|
|
194
|
+
selectedItemPath: "dir1/file1.jpg",
|
|
195
|
+
media: mediaMap,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(result).toBe(false);
|
|
199
|
+
});
|
|
200
|
+
});
|
package/src/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "@noya-app/noya-designsystem/index.css";
|
package/src/index.ts
ADDED