@tulip-systems/drive-local 0.11.1
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/LICENSE +662 -0
- package/dist/client.d.mts +12 -0
- package/dist/client.mjs +12 -0
- package/dist/database/drizzle/lib/adapter.d.mts +310 -0
- package/dist/database/drizzle/lib/adapter.mjs +520 -0
- package/dist/database/drizzle/lib/compilers.d.mts +395 -0
- package/dist/database/drizzle/lib/compilers.mjs +21 -0
- package/dist/database/drizzle/lib/schema.d.mts +61 -0
- package/dist/drizzle.d.mts +4 -0
- package/dist/drizzle.mjs +3 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +8 -0
- package/dist/root/components/command-file-update.d.mts +11 -0
- package/dist/root/components/command-file-update.mjs +44 -0
- package/dist/root/components/command-file-upload.d.mts +5 -0
- package/dist/root/components/command-file-upload.mjs +31 -0
- package/dist/root/components/command-folder-create.d.mts +11 -0
- package/dist/root/components/command-folder-create.mjs +50 -0
- package/dist/root/components/command-folder-update.d.mts +11 -0
- package/dist/root/components/command-folder-update.mjs +44 -0
- package/dist/root/components/content.client.d.mts +5 -0
- package/dist/root/components/content.client.mjs +5 -0
- package/dist/root/components/navigation.client.d.mts +11 -0
- package/dist/root/components/navigation.client.mjs +12 -0
- package/dist/root/components/provider.client.d.mts +16 -0
- package/dist/root/components/provider.client.mjs +65 -0
- package/dist/root/components/upload-zone-context.client.d.mts +36 -0
- package/dist/root/components/upload-zone-context.client.mjs +19 -0
- package/dist/root/components/upload-zone.client.d.mts +16 -0
- package/dist/root/components/upload-zone.client.mjs +147 -0
- package/dist/root/components/view.client.d.mts +20 -0
- package/dist/root/components/view.client.mjs +86 -0
- package/dist/root/config/columns-data.d.mts +6 -0
- package/dist/root/config/columns-data.mjs +62 -0
- package/dist/root/config/filters.d.mts +404 -0
- package/dist/root/config/filters.mjs +122 -0
- package/dist/root/config/sorting.d.mts +38 -0
- package/dist/root/config/sorting.mjs +26 -0
- package/dist/root/lib/constants.d.mts +12 -0
- package/dist/root/lib/constants.mjs +27 -0
- package/dist/root/lib/database/contracts.d.mts +112 -0
- package/dist/root/lib/database/filters.d.mts +28 -0
- package/dist/root/lib/database/filters.mjs +73 -0
- package/dist/root/lib/helpers.d.mts +33 -0
- package/dist/root/lib/helpers.mjs +78 -0
- package/dist/root/lib/route-handler.server.d.mts +36 -0
- package/dist/root/lib/route-handler.server.mjs +111 -0
- package/dist/root/lib/router.server.d.mts +819 -0
- package/dist/root/lib/router.server.mjs +87 -0
- package/dist/root/lib/search-params.d.mts +15 -0
- package/dist/root/lib/search-params.mjs +6 -0
- package/dist/root/lib/service.server.d.mts +522 -0
- package/dist/root/lib/service.server.mjs +613 -0
- package/dist/root/lib/upload.client.d.mts +60 -0
- package/dist/root/lib/upload.client.mjs +97 -0
- package/dist/root/lib/validators.d.mts +710 -0
- package/dist/root/lib/validators.mjs +116 -0
- package/dist/server.d.mts +5 -0
- package/dist/server.mjs +4 -0
- package/package.json +83 -0
- package/styles.css +1 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createLocalDriveFolderInputSchema } from "../lib/validators.mjs";
|
|
3
|
+
import { useDriveNavigation } from "@tulip-systems/drive/client";
|
|
4
|
+
import { FolderPlus } from "lucide-react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
|
7
|
+
import { CommandFormDialog, CommandFormDialogCancel, CommandFormDialogContent, CommandFormDialogFields, CommandFormDialogFooter, CommandFormDialogHeader, CommandFormDialogSubmit, CommandFormDialogTitle, CommandFormDialogTrigger, CommandLabel } from "@tulip-systems/commands/client";
|
|
8
|
+
import { Input } from "@tulip-systems/ui/input";
|
|
9
|
+
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@tulip-systems/ui/react-hook-form";
|
|
10
|
+
import { useForm } from "react-hook-form";
|
|
11
|
+
//#region src/root/components/command-folder-create.tsx
|
|
12
|
+
function LocalDriveFoldersCreateCommand({ defaultValues, variables, mutation }) {
|
|
13
|
+
const { parentId } = useDriveNavigation();
|
|
14
|
+
const form = useForm({
|
|
15
|
+
resolver: standardSchemaResolver(createLocalDriveFolderInputSchema),
|
|
16
|
+
defaultValues: {
|
|
17
|
+
...defaultValues,
|
|
18
|
+
parentId
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return /* @__PURE__ */ jsx(Form, {
|
|
22
|
+
...form,
|
|
23
|
+
children: /* @__PURE__ */ jsxs(CommandFormDialog, { children: [/* @__PURE__ */ jsxs(CommandFormDialogTrigger, {
|
|
24
|
+
label: "Folder toevoegen",
|
|
25
|
+
hotkey: "mod+i",
|
|
26
|
+
children: [/* @__PURE__ */ jsx(FolderPlus, { className: "size-4" }), /* @__PURE__ */ jsx(CommandLabel, {})]
|
|
27
|
+
}), /* @__PURE__ */ jsxs(CommandFormDialogContent, {
|
|
28
|
+
variables,
|
|
29
|
+
mutation,
|
|
30
|
+
children: [
|
|
31
|
+
/* @__PURE__ */ jsx(CommandFormDialogHeader, { children: /* @__PURE__ */ jsx(CommandFormDialogTitle, { children: "Folder toevoegen" }) }),
|
|
32
|
+
/* @__PURE__ */ jsx(CommandFormDialogFields, { children: /* @__PURE__ */ jsx(FormField, {
|
|
33
|
+
control: form.control,
|
|
34
|
+
name: "name",
|
|
35
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
36
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Naam" }),
|
|
37
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
38
|
+
...field,
|
|
39
|
+
value: field.value ?? ""
|
|
40
|
+
}) }),
|
|
41
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
42
|
+
] })
|
|
43
|
+
}) }),
|
|
44
|
+
/* @__PURE__ */ jsxs(CommandFormDialogFooter, { children: [/* @__PURE__ */ jsx(CommandFormDialogCancel, { children: "Annuleren" }), /* @__PURE__ */ jsx(CommandFormDialogSubmit, { children: "Toevoegen" })] })
|
|
45
|
+
]
|
|
46
|
+
})] })
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { LocalDriveFoldersCreateCommand };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { UpdateLocalDriveNodeInput } from "../lib/validators.mjs";
|
|
2
|
+
import { DefaultError, MutationOptions } from "@tanstack/react-query";
|
|
3
|
+
//#region src/root/components/command-folder-update.d.ts
|
|
4
|
+
type LocalDriveFoldersUpdateCommandProps<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> = {
|
|
5
|
+
defaultValues: Partial<UpdateLocalDriveNodeInput>;
|
|
6
|
+
variables: (values: UpdateLocalDriveNodeInput) => TVariables;
|
|
7
|
+
mutation: MutationOptions<TData, TError, TVariables, TOnMutateResult>;
|
|
8
|
+
};
|
|
9
|
+
declare function LocalDriveFoldersUpdateCommand<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown>({ defaultValues, variables, mutation }: LocalDriveFoldersUpdateCommandProps<TData, TError, TVariables, TOnMutateResult>): import("react").JSX.Element;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { LocalDriveFoldersUpdateCommand, LocalDriveFoldersUpdateCommandProps };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { updateLocalDriveNodeInputSchema } from "../lib/validators.mjs";
|
|
3
|
+
import { FolderPen } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
|
6
|
+
import { CommandFormDialog, CommandFormDialogCancel, CommandFormDialogContent, CommandFormDialogFields, CommandFormDialogFooter, CommandFormDialogHeader, CommandFormDialogSubmit, CommandFormDialogTitle, CommandFormDialogTrigger, CommandLabel } from "@tulip-systems/commands/client";
|
|
7
|
+
import { Input } from "@tulip-systems/ui/input";
|
|
8
|
+
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@tulip-systems/ui/react-hook-form";
|
|
9
|
+
import { useForm } from "react-hook-form";
|
|
10
|
+
//#region src/root/components/command-folder-update.tsx
|
|
11
|
+
function LocalDriveFoldersUpdateCommand({ defaultValues, variables, mutation }) {
|
|
12
|
+
const form = useForm({
|
|
13
|
+
resolver: standardSchemaResolver(updateLocalDriveNodeInputSchema),
|
|
14
|
+
defaultValues
|
|
15
|
+
});
|
|
16
|
+
return /* @__PURE__ */ jsx(Form, {
|
|
17
|
+
...form,
|
|
18
|
+
children: /* @__PURE__ */ jsxs(CommandFormDialog, { children: [/* @__PURE__ */ jsxs(CommandFormDialogTrigger, {
|
|
19
|
+
label: "Wijzigen",
|
|
20
|
+
children: [/* @__PURE__ */ jsx(FolderPen, { className: "size-4" }), /* @__PURE__ */ jsx(CommandLabel, {})]
|
|
21
|
+
}), /* @__PURE__ */ jsxs(CommandFormDialogContent, {
|
|
22
|
+
variables,
|
|
23
|
+
mutation,
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ jsx(CommandFormDialogHeader, { children: /* @__PURE__ */ jsx(CommandFormDialogTitle, { children: "Folder wijzigen" }) }),
|
|
26
|
+
/* @__PURE__ */ jsx(CommandFormDialogFields, { children: /* @__PURE__ */ jsx(FormField, {
|
|
27
|
+
control: form.control,
|
|
28
|
+
name: "name",
|
|
29
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
30
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Naam" }),
|
|
31
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
32
|
+
...field,
|
|
33
|
+
value: field.value ?? ""
|
|
34
|
+
}) }),
|
|
35
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
36
|
+
] })
|
|
37
|
+
}) }),
|
|
38
|
+
/* @__PURE__ */ jsxs(CommandFormDialogFooter, { children: [/* @__PURE__ */ jsx(CommandFormDialogCancel, { children: "Annuleren" }), /* @__PURE__ */ jsx(CommandFormDialogSubmit, { children: "Opslaan" })] })
|
|
39
|
+
]
|
|
40
|
+
})] })
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { LocalDriveFoldersUpdateCommand };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DriveBreadcrumb, DriveHeader, DriveHeaderBreadcrumbs, DriveHeaderTools, DriveToolbar, DriveToolbarTools, DriveViewSwitcher } from "@tulip-systems/drive/client";
|
|
2
|
+
//#region src/root/components/navigation.client.d.ts
|
|
3
|
+
declare const LocalDriveHeader: typeof DriveHeader;
|
|
4
|
+
declare const LocalDriveHeaderBreadcrumbs: typeof DriveHeaderBreadcrumbs;
|
|
5
|
+
declare const LocalDriveHeaderTools: typeof DriveHeaderTools;
|
|
6
|
+
declare const LocalDriveToolbar: typeof DriveToolbar;
|
|
7
|
+
declare const LocalDriveToolbarBreadcrumbs: typeof import("@tulip-systems/drive/client").DriveBreadcrumbs;
|
|
8
|
+
declare const LocalDriveToolbarTools: typeof DriveToolbarTools;
|
|
9
|
+
declare const LocalDriveViewSwitcher: typeof DriveViewSwitcher;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type DriveBreadcrumb, LocalDriveHeader, LocalDriveHeaderBreadcrumbs, LocalDriveHeaderTools, LocalDriveToolbar, LocalDriveToolbarBreadcrumbs, LocalDriveToolbarTools, LocalDriveViewSwitcher };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { DriveHeader, DriveHeaderBreadcrumbs, DriveHeaderTools, DriveToolbar, DriveToolbarBreadcrumbs, DriveToolbarTools, DriveViewSwitcher } from "@tulip-systems/drive/client";
|
|
3
|
+
//#region src/root/components/navigation.client.tsx
|
|
4
|
+
const LocalDriveHeader = DriveHeader;
|
|
5
|
+
const LocalDriveHeaderBreadcrumbs = DriveHeaderBreadcrumbs;
|
|
6
|
+
const LocalDriveHeaderTools = DriveHeaderTools;
|
|
7
|
+
const LocalDriveToolbar = DriveToolbar;
|
|
8
|
+
const LocalDriveToolbarBreadcrumbs = DriveToolbarBreadcrumbs;
|
|
9
|
+
const LocalDriveToolbarTools = DriveToolbarTools;
|
|
10
|
+
const LocalDriveViewSwitcher = DriveViewSwitcher;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { LocalDriveHeader, LocalDriveHeaderBreadcrumbs, LocalDriveHeaderTools, LocalDriveToolbar, LocalDriveToolbarBreadcrumbs, LocalDriveToolbarTools, LocalDriveViewSwitcher };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LocalDriveUploadZoneProps } from "./upload-zone.client.mjs";
|
|
2
|
+
import { DriveContextValue, DriveDragDropProviderProps, DriveNavigationConfig, DriveSelectionContextValue, DriveViewProviderProps } from "@tulip-systems/drive/client";
|
|
3
|
+
import { PropsWithChildren } from "react";
|
|
4
|
+
//#region src/root/components/provider.client.d.ts
|
|
5
|
+
type LocalDriveContextValue = DriveContextValue & {
|
|
6
|
+
readonly?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const LocalDriveContext: import("react").Context<LocalDriveContextValue>;
|
|
9
|
+
declare function useLocalDriveContext(): LocalDriveContextValue;
|
|
10
|
+
type LocalDriveProviderProps = PropsWithChildren<LocalDriveContextValue & Partial<DriveSelectionContextValue> & Pick<DriveViewProviderProps, "defaultView"> & Pick<DriveDragDropProviderProps, "onMove"> & Pick<LocalDriveUploadZoneProps, "driveUploadClient" | "uploadHooks" | "onUploadCompleted" | "onUploadFailed" | "optimistic" | "disabled" | "className"> & {
|
|
11
|
+
parentId: string | null;
|
|
12
|
+
navigation: DriveNavigationConfig;
|
|
13
|
+
}>;
|
|
14
|
+
declare function LocalDriveProvider({ defaultView, namespace, parentId, permission, meta, readonly, selection, selectionConditions, onMove, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, optimistic, disabled, className, navigation, children }: LocalDriveProviderProps): import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { LocalDriveContext, LocalDriveContextValue, LocalDriveProvider, LocalDriveProviderProps, useLocalDriveContext };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { LocalDriveUploadZone } from "./upload-zone.client.mjs";
|
|
3
|
+
import { DriveDragDropProvider, DriveNavigationProvider, DriveSelectionProvider, DriveViewProvider } from "@tulip-systems/drive/client";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { cn } from "@tulip-systems/ui/cn";
|
|
6
|
+
import { createContext, use, useMemo } from "react";
|
|
7
|
+
import { Allowed } from "@tulip-systems/auth/permissions/client";
|
|
8
|
+
//#region src/root/components/provider.client.tsx
|
|
9
|
+
const LocalDriveContext = createContext({});
|
|
10
|
+
function useLocalDriveContext() {
|
|
11
|
+
const context = use(LocalDriveContext);
|
|
12
|
+
if (!context) throw new Error("LocalDriveContext not found!");
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function LocalDriveProvider({ defaultView, namespace, parentId, permission, meta, readonly = false, selection, selectionConditions, onMove, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, optimistic, disabled, className, navigation, children }) {
|
|
16
|
+
const isDisabled = disabled ?? readonly;
|
|
17
|
+
const context = useMemo(() => ({
|
|
18
|
+
namespace,
|
|
19
|
+
permission,
|
|
20
|
+
meta,
|
|
21
|
+
readonly
|
|
22
|
+
}), [
|
|
23
|
+
namespace,
|
|
24
|
+
permission,
|
|
25
|
+
meta,
|
|
26
|
+
readonly
|
|
27
|
+
]);
|
|
28
|
+
return /* @__PURE__ */ jsx(DriveNavigationProvider, {
|
|
29
|
+
parentId,
|
|
30
|
+
navigation,
|
|
31
|
+
children: /* @__PURE__ */ jsx(Allowed, {
|
|
32
|
+
permission,
|
|
33
|
+
children: /* @__PURE__ */ jsx(DriveSelectionProvider, {
|
|
34
|
+
selection,
|
|
35
|
+
selectionConditions,
|
|
36
|
+
children: /* @__PURE__ */ jsx(DriveViewProvider, {
|
|
37
|
+
defaultView,
|
|
38
|
+
children: /* @__PURE__ */ jsx(DriveDragDropProvider, {
|
|
39
|
+
disabled: isDisabled,
|
|
40
|
+
onMove,
|
|
41
|
+
children: /* @__PURE__ */ jsx(LocalDriveContext, {
|
|
42
|
+
value: context,
|
|
43
|
+
children: /* @__PURE__ */ jsx(LocalDriveUploadZone, {
|
|
44
|
+
disabled: isDisabled,
|
|
45
|
+
className: cn("flex min-h-dvh flex-col", className),
|
|
46
|
+
variables: {
|
|
47
|
+
namespace,
|
|
48
|
+
parentId
|
|
49
|
+
},
|
|
50
|
+
driveUploadClient,
|
|
51
|
+
uploadHooks,
|
|
52
|
+
onUploadCompleted,
|
|
53
|
+
onUploadFailed,
|
|
54
|
+
optimistic,
|
|
55
|
+
children
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { LocalDriveContext, LocalDriveProvider, useLocalDriveContext };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { LocalDriveFileNode, LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { LocalDriveUploadClient } from "../lib/upload.client.mjs";
|
|
3
|
+
import React from "react";
|
|
4
|
+
//#region src/root/components/upload-zone-context.client.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Upload Zone Context Value
|
|
7
|
+
*/
|
|
8
|
+
type LocalDriveUploadZoneContextValue = {
|
|
9
|
+
driveUploadClient: LocalDriveUploadClient;
|
|
10
|
+
onUpload: (file: File) => Promise<LocalDriveFileNode>;
|
|
11
|
+
onRemove: (ids: string[]) => Promise<void>;
|
|
12
|
+
optimistic?: {
|
|
13
|
+
add?: (newValue: LocalDriveNodeWithAsset) => Promise<void> | void;
|
|
14
|
+
replace?: (input: {
|
|
15
|
+
id: string;
|
|
16
|
+
newValue: LocalDriveNodeWithAsset;
|
|
17
|
+
}) => Promise<void> | void;
|
|
18
|
+
remove?: (ids: string[]) => Promise<void> | void;
|
|
19
|
+
invalidate?: () => Promise<void> | void;
|
|
20
|
+
cancel?: () => Promise<void> | void;
|
|
21
|
+
};
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Upload Zone Context
|
|
26
|
+
*/
|
|
27
|
+
declare const LocalDriveUploadZoneContext: React.Context<LocalDriveUploadZoneContextValue | null>;
|
|
28
|
+
type DriveUploadZoneContextValue = LocalDriveUploadZoneContextValue;
|
|
29
|
+
declare const DriveUploadZoneContext: React.Context<LocalDriveUploadZoneContextValue | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Upload Zone Hook
|
|
32
|
+
*/
|
|
33
|
+
declare function useLocalDriveUploadZone(): LocalDriveUploadZoneContextValue;
|
|
34
|
+
declare const useDriveUploadZone: typeof useLocalDriveUploadZone;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { DriveUploadZoneContext, DriveUploadZoneContextValue, LocalDriveUploadZoneContext, LocalDriveUploadZoneContextValue, useDriveUploadZone, useLocalDriveUploadZone };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React from "react";
|
|
3
|
+
//#region src/root/components/upload-zone-context.client.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Upload Zone Context
|
|
6
|
+
*/
|
|
7
|
+
const LocalDriveUploadZoneContext = React.createContext(null);
|
|
8
|
+
const DriveUploadZoneContext = LocalDriveUploadZoneContext;
|
|
9
|
+
/**
|
|
10
|
+
* Upload Zone Hook
|
|
11
|
+
*/
|
|
12
|
+
function useLocalDriveUploadZone() {
|
|
13
|
+
const context = React.useContext(LocalDriveUploadZoneContext);
|
|
14
|
+
if (!context) throw new Error("useUploadZone must be used within an UploadZoneContext provider");
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
const useDriveUploadZone = useLocalDriveUploadZone;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { DriveUploadZoneContext, LocalDriveUploadZoneContext, useDriveUploadZone, useLocalDriveUploadZone };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LocalDriveFileNode } from "../lib/validators.mjs";
|
|
2
|
+
import { LocalDriveUploadHooks, PrepareLocalDriveUploadInput } from "../lib/upload.client.mjs";
|
|
3
|
+
import { LocalDriveUploadZoneContextValue } from "./upload-zone-context.client.mjs";
|
|
4
|
+
import { ComponentProps } from "react";
|
|
5
|
+
//#region src/root/components/upload-zone.client.d.ts
|
|
6
|
+
type LocalDriveUploadZoneProps = ComponentProps<"div"> & Pick<LocalDriveUploadZoneContextValue, "optimistic" | "driveUploadClient" | "disabled"> & {
|
|
7
|
+
variables: Pick<PrepareLocalDriveUploadInput, "namespace" | "parentId" | "readonly" | "hidden" | "visibility">;
|
|
8
|
+
uploadHooks?: LocalDriveUploadHooks;
|
|
9
|
+
onUploadCompleted?: (node: LocalDriveFileNode) => Promise<void> | void;
|
|
10
|
+
onUploadFailed?: (error: unknown) => Promise<void> | void;
|
|
11
|
+
};
|
|
12
|
+
type DriveUploadZoneProps = LocalDriveUploadZoneProps;
|
|
13
|
+
declare function LocalDriveUploadZone({ variables, optimistic, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, disabled, children, className, ...props }: LocalDriveUploadZoneProps): import("react").JSX.Element;
|
|
14
|
+
declare const DriveUploadZone: typeof LocalDriveUploadZone;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DriveUploadZone, DriveUploadZoneProps, LocalDriveUploadZone, LocalDriveUploadZoneProps };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { inferLocalDriveNodeSubtype } from "../lib/helpers.mjs";
|
|
3
|
+
import { LocalDriveUploadZoneContext } from "./upload-zone-context.client.mjs";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { cn } from "@tulip-systems/ui/cn";
|
|
6
|
+
import { useCallback } from "react";
|
|
7
|
+
import { useAction } from "@tulip-systems/core/client";
|
|
8
|
+
import { toast } from "@tulip-systems/ui/sonner";
|
|
9
|
+
import { useDropzone } from "react-dropzone";
|
|
10
|
+
//#region src/root/components/upload-zone.client.tsx
|
|
11
|
+
function LocalDriveUploadZone({ variables, optimistic, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, disabled = false, children, className, ...props }) {
|
|
12
|
+
/**
|
|
13
|
+
* Delete mutation
|
|
14
|
+
*/
|
|
15
|
+
const deleteMutation = useAction({
|
|
16
|
+
mutationFn: async (ids) => driveUploadClient.deleteFiles(ids),
|
|
17
|
+
onMutate: async (ids) => {
|
|
18
|
+
await optimistic?.cancel?.();
|
|
19
|
+
await optimistic?.remove?.(ids);
|
|
20
|
+
},
|
|
21
|
+
onError: async (error) => {
|
|
22
|
+
console.error("Delete failed upload error: ", error);
|
|
23
|
+
await onUploadFailed?.(error);
|
|
24
|
+
},
|
|
25
|
+
onSettled: () => {
|
|
26
|
+
optimistic?.invalidate?.();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Upload mutation
|
|
31
|
+
*/
|
|
32
|
+
const uploadMutation = useAction({
|
|
33
|
+
mutationFn: async (params) => driveUploadClient.upload(params, uploadHooks),
|
|
34
|
+
onMutate: async (variables) => {
|
|
35
|
+
await optimistic?.cancel?.();
|
|
36
|
+
const newNode = {
|
|
37
|
+
id: variables.uploadId,
|
|
38
|
+
provider: "local",
|
|
39
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
40
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
41
|
+
type: "file",
|
|
42
|
+
name: variables.file.name,
|
|
43
|
+
namespace: variables.namespace,
|
|
44
|
+
parentId: variables.parentId ?? null,
|
|
45
|
+
size: variables.file.size,
|
|
46
|
+
contentType: variables.file.type || "application/octet-stream",
|
|
47
|
+
readonly: variables.readonly ?? false,
|
|
48
|
+
hidden: variables.hidden ?? false,
|
|
49
|
+
archivedAt: null,
|
|
50
|
+
assetId: null,
|
|
51
|
+
subtype: inferLocalDriveNodeSubtype({
|
|
52
|
+
name: variables.file.name,
|
|
53
|
+
contentType: variables.file.type || "application/octet-stream"
|
|
54
|
+
}),
|
|
55
|
+
links: {
|
|
56
|
+
view: null,
|
|
57
|
+
download: null,
|
|
58
|
+
preview: null,
|
|
59
|
+
thumbnail: null
|
|
60
|
+
},
|
|
61
|
+
availability: "pending",
|
|
62
|
+
asset: {
|
|
63
|
+
status: "pending",
|
|
64
|
+
name: variables.file.name,
|
|
65
|
+
contentType: variables.file.type || "application/octet-stream",
|
|
66
|
+
size: variables.file.size,
|
|
67
|
+
visibility: variables.visibility || "private"
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
await optimistic?.add?.(newNode);
|
|
71
|
+
},
|
|
72
|
+
onSuccess: async (data, variables) => {
|
|
73
|
+
await optimistic?.replace?.({
|
|
74
|
+
id: variables.uploadId ?? "",
|
|
75
|
+
newValue: {
|
|
76
|
+
...data,
|
|
77
|
+
asset: {
|
|
78
|
+
status: "ready",
|
|
79
|
+
name: data.name,
|
|
80
|
+
contentType: data.contentType,
|
|
81
|
+
size: data.size,
|
|
82
|
+
visibility: variables.visibility || "private"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
await onUploadCompleted?.(data);
|
|
87
|
+
toast.success(`Succesvol geupload: ${data.name}`);
|
|
88
|
+
},
|
|
89
|
+
onError: async (error) => {
|
|
90
|
+
await onUploadFailed?.(error);
|
|
91
|
+
console.error("Upload error: ", error);
|
|
92
|
+
toast.error("Bestand uploaden mislukt", { description: error instanceof Error ? error.message : void 0 });
|
|
93
|
+
},
|
|
94
|
+
onSettled: () => {
|
|
95
|
+
optimistic?.invalidate?.();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
/**
|
|
99
|
+
* Upload file handler
|
|
100
|
+
*/
|
|
101
|
+
const onUpload = useCallback(async (file) => {
|
|
102
|
+
console.info("Uploading file", file);
|
|
103
|
+
const req = driveUploadClient.prepareUpload({
|
|
104
|
+
...variables,
|
|
105
|
+
file
|
|
106
|
+
});
|
|
107
|
+
return await uploadMutation.mutateAsync(req);
|
|
108
|
+
}, [
|
|
109
|
+
driveUploadClient,
|
|
110
|
+
variables,
|
|
111
|
+
uploadMutation
|
|
112
|
+
]);
|
|
113
|
+
/**
|
|
114
|
+
* Drop handler
|
|
115
|
+
*/
|
|
116
|
+
const onDrop = useCallback(async (acceptedFiles) => {
|
|
117
|
+
if (acceptedFiles.length === 0) return;
|
|
118
|
+
await Promise.allSettled(acceptedFiles.map(onUpload));
|
|
119
|
+
}, [onUpload]);
|
|
120
|
+
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
121
|
+
onDrop,
|
|
122
|
+
noClick: true,
|
|
123
|
+
disabled
|
|
124
|
+
});
|
|
125
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
126
|
+
...props,
|
|
127
|
+
...getRootProps(),
|
|
128
|
+
className: cn("relative z-0", className),
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsx("input", { ...getInputProps() }),
|
|
131
|
+
isDragActive && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 rounded-md bg-primary/20 opacity-70 backdrop-blur-3xl" }),
|
|
132
|
+
/* @__PURE__ */ jsx(LocalDriveUploadZoneContext, {
|
|
133
|
+
value: {
|
|
134
|
+
driveUploadClient,
|
|
135
|
+
onUpload,
|
|
136
|
+
onRemove: deleteMutation.mutateAsync,
|
|
137
|
+
optimistic,
|
|
138
|
+
disabled
|
|
139
|
+
},
|
|
140
|
+
children
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
const DriveUploadZone = LocalDriveUploadZone;
|
|
146
|
+
//#endregion
|
|
147
|
+
export { DriveUploadZone, LocalDriveUploadZone };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { TableColumnDef } from "@tulip-systems/data-tables";
|
|
3
|
+
import { useInfiniteStrategy } from "@tulip-systems/data-tables/client";
|
|
4
|
+
import { DriveViewCommands, createDriveViewConfig } from "@tulip-systems/drive/client";
|
|
5
|
+
import { ComponentProps } from "react";
|
|
6
|
+
import { VisibilityState } from "@tanstack/react-table";
|
|
7
|
+
//#region src/root/components/view.client.d.ts
|
|
8
|
+
type LocalDriveViewProviderProps<TData extends LocalDriveNodeWithAsset = LocalDriveNodeWithAsset> = ComponentProps<"div"> & {
|
|
9
|
+
queryData: TData[];
|
|
10
|
+
columns?: TableColumnDef<TData>[];
|
|
11
|
+
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
12
|
+
commands?: DriveViewCommands<TData>;
|
|
13
|
+
columnVisibility?: VisibilityState;
|
|
14
|
+
sorting?: Parameters<typeof createDriveViewConfig<TData>>[0]["sorting"];
|
|
15
|
+
};
|
|
16
|
+
declare function LocalDriveViewProvider<TData extends LocalDriveNodeWithAsset = LocalDriveNodeWithAsset>({ queryData, columns, strategy, commands, columnVisibility, sorting, children, ...props }: LocalDriveViewProviderProps<TData>): import("react").JSX.Element;
|
|
17
|
+
declare function LocalDriveView(): import("react").JSX.Element | null;
|
|
18
|
+
declare function LocalDriveViewLoading({ ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { LocalDriveView, LocalDriveViewLoading, LocalDriveViewProvider };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { localDriveColumns } from "../config/columns-data.mjs";
|
|
3
|
+
import { localDriveImageLoader } from "../lib/helpers.mjs";
|
|
4
|
+
import { useLocalDriveUploadZone } from "./upload-zone-context.client.mjs";
|
|
5
|
+
import { useLocalDriveContext } from "./provider.client.mjs";
|
|
6
|
+
import { TableLayout, TableSkeleton } from "@tulip-systems/data-tables";
|
|
7
|
+
import { DataTable } from "@tulip-systems/data-tables/client";
|
|
8
|
+
import { DriveGrid, DriveGridBottombar, DriveGridCard, DriveGridCardSkeleton, DriveGridEmpty, DriveGridLoading, DriveViewConfigProvider, createDriveViewConfig, useDriveSelectionContext, useDriveViewConfig, useDriveViewContext } from "@tulip-systems/drive/client";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { FloatingCommandMenu } from "@tulip-systems/commands/client";
|
|
11
|
+
import { useMemo } from "react";
|
|
12
|
+
//#region src/root/components/view.client.tsx
|
|
13
|
+
function LocalDriveViewProvider({ queryData, columns = localDriveColumns, strategy, commands, columnVisibility, sorting, children, ...props }) {
|
|
14
|
+
const { meta } = useLocalDriveContext();
|
|
15
|
+
const selectionContext = useDriveSelectionContext();
|
|
16
|
+
const config = createDriveViewConfig({
|
|
17
|
+
queryData,
|
|
18
|
+
columns,
|
|
19
|
+
strategy,
|
|
20
|
+
commands,
|
|
21
|
+
meta,
|
|
22
|
+
columnVisibility,
|
|
23
|
+
selection: selectionContext?.selection,
|
|
24
|
+
sorting
|
|
25
|
+
});
|
|
26
|
+
return /* @__PURE__ */ jsx(DriveViewConfigProvider, {
|
|
27
|
+
config,
|
|
28
|
+
children: /* @__PURE__ */ jsx(TableLayout, {
|
|
29
|
+
...props,
|
|
30
|
+
children
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function LocalDriveView() {
|
|
35
|
+
const { view } = useDriveViewContext();
|
|
36
|
+
if (view === "grid") return /* @__PURE__ */ jsx(LocalDriveGrid, {});
|
|
37
|
+
if (view === "list") return /* @__PURE__ */ jsx(LocalDriveList, {});
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function LocalDriveGrid(props) {
|
|
41
|
+
const { queryData, strategy, commands, selection, meta } = useDriveViewConfig();
|
|
42
|
+
const { optimistic } = useLocalDriveUploadZone();
|
|
43
|
+
const { rowCount, paginationState } = strategy;
|
|
44
|
+
const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta;
|
|
45
|
+
const hasNextPage = rowCount == null ? false : queryData.length < rowCount;
|
|
46
|
+
const selectedData = useMemo(() => queryData.filter((node) => selection?.rowSelection?.[node.id] === true), [queryData, selection?.rowSelection]);
|
|
47
|
+
return /* @__PURE__ */ jsxs(DriveGrid, {
|
|
48
|
+
...props,
|
|
49
|
+
children: [
|
|
50
|
+
queryData.length > 0 ? queryData.filter((node) => !node.hidden).map((node) => /* @__PURE__ */ jsx(DriveGridCard, {
|
|
51
|
+
node,
|
|
52
|
+
commands: commands?.node,
|
|
53
|
+
imageLoader: localDriveImageLoader
|
|
54
|
+
}, node.id)) : /* @__PURE__ */ jsx(DriveGridEmpty, { title: "Geen resultaten gevonden" }),
|
|
55
|
+
isFetchingNextPage && Array.from({ length: paginationState?.pageSize ?? 0 }).map((_, index) => /* @__PURE__ */ jsx(DriveGridCardSkeleton, {}, index)),
|
|
56
|
+
/* @__PURE__ */ jsx(DriveGridBottombar, {
|
|
57
|
+
hasNextPage,
|
|
58
|
+
fetchNextPage,
|
|
59
|
+
isFetching,
|
|
60
|
+
isFetchingNextPage
|
|
61
|
+
}),
|
|
62
|
+
commands?.selectedNodes && commands?.selectedNodes.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
63
|
+
data: selectedData,
|
|
64
|
+
commands: commands.selectedNodes,
|
|
65
|
+
meta,
|
|
66
|
+
state: selectedData.length > 0 ? "open" : "closed",
|
|
67
|
+
onSuccess: () => {
|
|
68
|
+
selection?.setRowSelection?.({});
|
|
69
|
+
optimistic?.invalidate?.();
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function LocalDriveList(props) {
|
|
76
|
+
return /* @__PURE__ */ jsx(DataTable, { ...props });
|
|
77
|
+
}
|
|
78
|
+
function LocalDriveViewLoading({ ...props }) {
|
|
79
|
+
const { view } = useDriveViewContext();
|
|
80
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
81
|
+
...props,
|
|
82
|
+
children: [view === "grid" && /* @__PURE__ */ jsx(DriveGridLoading, { ...props }), view === "list" && /* @__PURE__ */ jsx(TableSkeleton, { ...props })]
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { LocalDriveView, LocalDriveViewLoading, LocalDriveViewProvider };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { TableColumnDef } from "@tulip-systems/data-tables";
|
|
3
|
+
//#region src/root/config/columns-data.d.ts
|
|
4
|
+
declare const localDriveColumns: TableColumnDef<LocalDriveNodeWithAsset>[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { localDriveColumns };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { TableColumnHeader } from "@tulip-systems/data-tables";
|
|
3
|
+
import { TableTextCell, createTableSelectCell } from "@tulip-systems/data-tables/client";
|
|
4
|
+
import { nodeSubtypeConfig, nodeSubtypeVariants } from "@tulip-systems/drive";
|
|
5
|
+
import { useDriveNavigation } from "@tulip-systems/drive/client";
|
|
6
|
+
import { findStatus } from "@tulip-systems/ui/status";
|
|
7
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/ui/tooltip";
|
|
8
|
+
import { FolderIcon } from "lucide-react";
|
|
9
|
+
import Link from "next/link";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
//#region src/root/config/columns-data.tsx
|
|
12
|
+
const localDriveColumns = [
|
|
13
|
+
createTableSelectCell(),
|
|
14
|
+
{
|
|
15
|
+
id: "icon",
|
|
16
|
+
accessorKey: "icon",
|
|
17
|
+
header: () => null,
|
|
18
|
+
cell: ({ row }) => {
|
|
19
|
+
if (row.original.type === "file") {
|
|
20
|
+
const subtype = findStatus(nodeSubtypeConfig, row.original.subtype);
|
|
21
|
+
const Icon = subtype?.icon;
|
|
22
|
+
if (!subtype || !Icon) return null;
|
|
23
|
+
return /* @__PURE__ */ jsx(TableTextCell, {
|
|
24
|
+
className: "w-4",
|
|
25
|
+
children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Icon, { className: nodeSubtypeVariants({
|
|
26
|
+
status: row.original.subtype,
|
|
27
|
+
className: "size-4"
|
|
28
|
+
}) }) }), /* @__PURE__ */ jsx(TooltipContent, { children: subtype.label })] })
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (row.original.type === "folder") return /* @__PURE__ */ jsx(TableTextCell, {
|
|
32
|
+
className: "w-4",
|
|
33
|
+
children: /* @__PURE__ */ jsx(FolderIcon, { className: "w-4 min-w-4" })
|
|
34
|
+
});
|
|
35
|
+
return null;
|
|
36
|
+
},
|
|
37
|
+
enableSorting: false
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "name",
|
|
41
|
+
accessorKey: "name",
|
|
42
|
+
header: ({ column }) => /* @__PURE__ */ jsx(TableColumnHeader, {
|
|
43
|
+
column,
|
|
44
|
+
title: "Naam"
|
|
45
|
+
}),
|
|
46
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(LocalDriveNameCell, { row })
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
function LocalDriveNameCell({ row }) {
|
|
50
|
+
const navigation = useDriveNavigation();
|
|
51
|
+
return /* @__PURE__ */ jsx(TableTextCell, {
|
|
52
|
+
className: "w-full min-w-64",
|
|
53
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
54
|
+
href: row.original.type === "file" ? row.original.links.view ?? "#" : navigation.getFolderHref(row.original.id),
|
|
55
|
+
className: "truncate hover:underline",
|
|
56
|
+
target: row.original.type === "file" ? "_blank" : "_self",
|
|
57
|
+
children: row.getValue("name")
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { localDriveColumns };
|