@axium/storage 0.19.1 → 0.19.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/db.json +10 -0
- package/dist/common.d.ts +2 -0
- package/dist/server/item.js +8 -1
- package/lib/List.svelte +48 -5
- package/package.json +1 -1
package/db.json
CHANGED
|
@@ -79,6 +79,16 @@
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"delta": true,
|
|
85
|
+
"alter_tables": {
|
|
86
|
+
"storage": {
|
|
87
|
+
"add_constraints": {
|
|
88
|
+
"unique_name_parentId": { "type": "unique", "on": ["name", "parentId"] }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
82
92
|
}
|
|
83
93
|
],
|
|
84
94
|
"wipe": ["storage", "acl.storage"],
|
package/dist/common.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export declare const StorageItemSorting: z.ZodObject<{
|
|
|
61
61
|
descending: z.ZodOptional<z.ZodBoolean>;
|
|
62
62
|
by: z.ZodLiteral<"name" | "createdAt" | "modifiedAt" | "size">;
|
|
63
63
|
}, z.core.$strip>;
|
|
64
|
+
export interface StorageItemSorting extends z.infer<typeof StorageItemSorting> {
|
|
65
|
+
}
|
|
64
66
|
export declare const syncProtocolVersion = 0;
|
|
65
67
|
export declare const StorageLimits: z.ZodObject<{
|
|
66
68
|
item_size: z.ZodInt;
|
package/dist/server/item.js
CHANGED
|
@@ -77,7 +77,14 @@ export async function createNewItem(init, userId, writeContent) {
|
|
|
77
77
|
hash,
|
|
78
78
|
})
|
|
79
79
|
.returningAll()
|
|
80
|
-
.executeTakeFirstOrThrow()
|
|
80
|
+
.executeTakeFirstOrThrow()
|
|
81
|
+
.catch(e => {
|
|
82
|
+
if (!(e instanceof Error))
|
|
83
|
+
throw e;
|
|
84
|
+
if (e.message.includes('unique_name_parentId') && e.message.includes('duplicate'))
|
|
85
|
+
error(409, 'A file with that name already exists in this folder.');
|
|
86
|
+
throw e;
|
|
87
|
+
}));
|
|
81
88
|
const path = join(dataDir, item.id);
|
|
82
89
|
if (existing)
|
|
83
90
|
linkSync(join(dataDir, existing.id), path);
|
package/lib/List.svelte
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import type { AccessControllable, UserPublic } from '@axium/core';
|
|
8
8
|
import { formatBytes } from '@axium/core/format';
|
|
9
9
|
import { forMime as iconForMime } from '@axium/core/icons';
|
|
10
|
+
import { errorText } from '@axium/core/io';
|
|
10
11
|
import { getDirectoryMetadata, updateItemMetadata } from '@axium/storage/client';
|
|
11
12
|
import { copyShortURL, formatItemName } from '@axium/storage/client/frontend';
|
|
12
|
-
import type
|
|
13
|
+
import { StorageItemSorting, type StorageItemMetadata } from '@axium/storage/common';
|
|
13
14
|
import Preview from './Preview.svelte';
|
|
14
15
|
|
|
15
16
|
let {
|
|
@@ -23,6 +24,31 @@
|
|
|
23
24
|
const activeItem = $derived(items[activeIndex]);
|
|
24
25
|
const activeItemName = $derived(formatItemName(activeItem));
|
|
25
26
|
const dialogs = $state<Record<string, HTMLDialogElement>>({});
|
|
27
|
+
|
|
28
|
+
const search = new URLSearchParams(location.search);
|
|
29
|
+
let sort = $state<StorageItemSorting | null>();
|
|
30
|
+
try {
|
|
31
|
+
sort = StorageItemSorting.parse({
|
|
32
|
+
by: search.get('sortBy'),
|
|
33
|
+
descending: search.has('descending'),
|
|
34
|
+
});
|
|
35
|
+
} catch (e) {
|
|
36
|
+
console.log('Ignoring invalid sorting parameters', errorText(e));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const sortedItems = $derived(
|
|
40
|
+
items
|
|
41
|
+
.map((item, i) => [item, i] as const)
|
|
42
|
+
.toSorted(
|
|
43
|
+
sort
|
|
44
|
+
? ([_a], [_b]) => {
|
|
45
|
+
const [a, b] = sort?.descending ? [_b, _a] : [_a, _b];
|
|
46
|
+
// @ts-expect-error 2362 — `Date`s have a `valueOf` and can be treated like numbers
|
|
47
|
+
return sort.by == 'name' ? a.name.localeCompare(b.name) : a[sort.by] - b[sort.by];
|
|
48
|
+
}
|
|
49
|
+
: undefined
|
|
50
|
+
)
|
|
51
|
+
);
|
|
26
52
|
</script>
|
|
27
53
|
|
|
28
54
|
{#snippet action(name: string, icon: string, i: number, preview: boolean = false)}
|
|
@@ -40,11 +66,19 @@
|
|
|
40
66
|
<div class="list">
|
|
41
67
|
<div class="list-item list-header">
|
|
42
68
|
<span></span>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
69
|
+
{#each [['name', 'storage.generic.name'], ['modifiedAt', 'storage.List.last_modified'], ['size', 'storage.List.size']] as const as [key, translation]}
|
|
70
|
+
<span
|
|
71
|
+
class="header-column"
|
|
72
|
+
onclick={() => (sort = sort?.descending === false ? null : { by: key, descending: !sort?.descending })}
|
|
73
|
+
>
|
|
74
|
+
{#if sort?.by == key}
|
|
75
|
+
<Icon i="sort-{sort.descending ? 'down' : 'up'}" />
|
|
76
|
+
{/if}
|
|
77
|
+
<span>{text(translation)}</span>
|
|
78
|
+
</span>
|
|
79
|
+
{/each}
|
|
46
80
|
</div>
|
|
47
|
-
{#each
|
|
81
|
+
{#each sortedItems as [item, i] (item.id)}
|
|
48
82
|
<div
|
|
49
83
|
class="list-item"
|
|
50
84
|
onclick={async () => {
|
|
@@ -167,6 +201,15 @@
|
|
|
167
201
|
grid-template-columns: 1em 4fr 15em 5em repeat(4, 1em);
|
|
168
202
|
}
|
|
169
203
|
|
|
204
|
+
.header-column {
|
|
205
|
+
display: inline-flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
|
|
208
|
+
&:hover {
|
|
209
|
+
cursor: pointer;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
170
213
|
@media (width < 700px) {
|
|
171
214
|
.item-actions {
|
|
172
215
|
display: none;
|