@tulip-systems/drive 0.8.1 → 0.8.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/client.d.mts +5 -0
- package/dist/client.mjs +6 -0
- package/dist/components/content.d.mts +13 -0
- package/dist/components/content.mjs +17 -0
- package/dist/components/context.client.d.mts +13 -0
- package/dist/components/dnd.client.d.mts +16 -0
- package/dist/components/dnd.client.mjs +29 -0
- package/dist/components/grid-card.client.d.mts +46 -0
- package/dist/components/grid-card.client.mjs +173 -0
- package/dist/components/grid.client.d.mts +53 -0
- package/dist/components/grid.client.mjs +53 -0
- package/dist/components/navigation/breadcrumbs.client.d.mts +25 -0
- package/dist/components/navigation/breadcrumbs.client.mjs +51 -0
- package/dist/components/navigation/header.client.d.mts +27 -0
- package/dist/components/navigation/header.client.mjs +40 -0
- package/dist/components/navigation/toolbar.client.d.mts +23 -0
- package/dist/components/navigation/toolbar.client.mjs +34 -0
- package/dist/components/navigation/view-switcher.client.d.mts +9 -0
- package/dist/components/navigation/view-switcher.client.mjs +35 -0
- package/dist/components/selection.client.d.mts +27 -0
- package/dist/components/selection.client.mjs +36 -0
- package/dist/components/view.client.d.mts +25 -0
- package/dist/components/view.client.mjs +43 -0
- package/dist/config/filters.mjs +14 -0
- package/dist/config/types.mjs +60 -0
- package/dist/google/client.d.mts +8 -0
- package/dist/google/client.mjs +9 -0
- package/dist/google/server.d.mts +3 -0
- package/dist/google/server.mjs +4 -0
- package/dist/google.d.mts +6 -0
- package/dist/google.mjs +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +7 -0
- package/dist/lib/constants.d.mts +11 -0
- package/dist/lib/constants.mjs +20 -0
- package/dist/lib/contracts.d.mts +100 -0
- package/dist/lib/dto.d.mts +117 -0
- package/dist/lib/dto.mjs +57 -0
- package/dist/lib/helpers.d.mts +17 -0
- package/dist/lib/helpers.mjs +36 -0
- package/dist/lib/helpers.server.d.mts +13 -0
- package/dist/lib/helpers.server.mjs +15 -0
- package/dist/lib/search-params.d.mts +8 -0
- package/dist/lib/search-params.mjs +7 -0
- package/dist/lib/validators.d.mts +157 -0
- package/dist/lib/validators.mjs +65 -0
- package/dist/local/client.d.mts +13 -0
- package/dist/local/client.mjs +13 -0
- package/dist/local/server.d.mts +4 -0
- package/dist/local/server.mjs +5 -0
- package/dist/local.d.mts +8 -0
- package/dist/local.mjs +9 -0
- package/dist/providers/google/components/command-file-update.d.mts +21 -0
- package/dist/providers/google/components/command-file-update.mjs +51 -0
- package/dist/providers/google/components/command-folder-create.d.mts +21 -0
- package/dist/providers/google/components/command-folder-create.mjs +58 -0
- package/dist/providers/google/components/command-folder-update.d.mts +21 -0
- package/dist/providers/google/components/command-folder-update.mjs +51 -0
- package/dist/providers/google/components/content.client.d.mts +9 -0
- package/dist/providers/google/components/content.client.mjs +10 -0
- package/dist/providers/google/components/navigation.client.d.mts +15 -0
- package/dist/providers/google/components/navigation.client.mjs +17 -0
- package/dist/providers/google/components/provider.client.d.mts +32 -0
- package/dist/providers/google/components/provider.client.mjs +42 -0
- package/dist/providers/google/components/view.client.d.mts +40 -0
- package/dist/providers/google/components/view.client.mjs +96 -0
- package/dist/providers/google/config/columns-data.d.mts +7 -0
- package/dist/providers/google/config/columns-data.mjs +69 -0
- package/dist/providers/google/config/filters.d.mts +15 -0
- package/dist/providers/google/config/filters.mjs +7 -0
- package/dist/providers/google/lib/constants.mjs +12 -0
- package/dist/providers/google/lib/dto.d.mts +38 -0
- package/dist/providers/google/lib/dto.mjs +65 -0
- package/dist/providers/google/lib/helpers.mjs +38 -0
- package/dist/providers/google/lib/router.server.d.mts +611 -0
- package/dist/providers/google/lib/router.server.mjs +39 -0
- package/dist/providers/google/lib/search-params.d.mts +14 -0
- package/dist/providers/google/lib/search-params.mjs +11 -0
- package/dist/providers/google/lib/service.server.d.mts +185 -0
- package/dist/providers/google/lib/service.server.mjs +610 -0
- package/dist/providers/google/lib/validators.d.mts +302 -0
- package/dist/providers/google/lib/validators.mjs +58 -0
- package/dist/providers/local/components/command-file-update.d.mts +17 -0
- package/dist/providers/local/components/command-file-update.mjs +47 -0
- package/dist/providers/local/components/command-file-upload.d.mts +10 -0
- package/dist/providers/local/components/command-file-upload.mjs +34 -0
- package/dist/providers/local/components/command-folder-create.d.mts +17 -0
- package/dist/providers/local/components/command-folder-create.mjs +54 -0
- package/dist/providers/local/components/command-folder-update.d.mts +17 -0
- package/dist/providers/local/components/command-folder-update.mjs +47 -0
- package/dist/providers/local/components/content.client.d.mts +6 -0
- package/dist/providers/local/components/content.client.mjs +7 -0
- package/dist/providers/local/components/navigation.client.d.mts +15 -0
- package/dist/providers/local/components/navigation.client.mjs +17 -0
- package/dist/providers/local/components/provider.client.d.mts +39 -0
- package/dist/providers/local/components/provider.client.mjs +60 -0
- package/dist/providers/local/components/upload-zone-context.client.d.mts +37 -0
- package/dist/providers/local/components/upload-zone-context.client.mjs +22 -0
- package/dist/providers/local/components/upload-zone.client.d.mts +29 -0
- package/dist/providers/local/components/upload-zone.client.mjs +146 -0
- package/dist/providers/local/components/view.client.d.mts +31 -0
- package/dist/providers/local/components/view.client.mjs +90 -0
- package/dist/providers/local/config/columns-data.d.mts +7 -0
- package/dist/providers/local/config/columns-data.mjs +69 -0
- package/dist/providers/local/config/filters.d.mts +25 -0
- package/dist/providers/local/config/filters.mjs +14 -0
- package/dist/providers/local/lib/constants.d.mts +11 -0
- package/dist/providers/local/lib/constants.mjs +28 -0
- package/dist/providers/local/lib/helpers.d.mts +44 -0
- package/dist/providers/local/lib/helpers.mjs +109 -0
- package/dist/providers/local/lib/route-handler.server.d.mts +33 -0
- package/dist/providers/local/lib/route-handler.server.mjs +113 -0
- package/dist/providers/local/lib/router.server.d.mts +41647 -0
- package/dist/providers/local/lib/router.server.mjs +51 -0
- package/dist/providers/local/lib/schema.d.mts +1112 -0
- package/dist/providers/local/lib/schema.mjs +70 -0
- package/dist/providers/local/lib/search-params.d.mts +13 -0
- package/dist/providers/local/lib/search-params.mjs +8 -0
- package/dist/providers/local/lib/service.server.d.mts +488 -0
- package/dist/providers/local/lib/service.server.mjs +667 -0
- package/dist/providers/local/lib/upload.client.d.mts +61 -0
- package/dist/providers/local/lib/upload.client.mjs +99 -0
- package/dist/providers/local/lib/validators.d.mts +453 -0
- package/dist/providers/local/lib/validators.mjs +95 -0
- package/dist/server.d.mts +2 -0
- package/dist/server.mjs +3 -0
- package/package.json +45 -46
- package/src/components/grid-card.client.tsx +17 -12
- package/src/components/selection.client.tsx +1 -2
- package/src/config/types.tsx +1 -1
- package/src/providers/google/components/command-file-update.tsx +2 -2
- package/src/providers/google/components/command-folder-create.tsx +2 -2
- package/src/providers/google/components/command-folder-update.tsx +2 -2
- package/src/providers/google/components/view.client.tsx +1 -7
- package/src/providers/google/lib/helpers.ts +0 -9
- package/src/providers/google/lib/service.server.ts +1 -3
- package/src/providers/local/components/command-file-update.tsx +2 -2
- package/src/providers/local/components/command-folder-create.tsx +2 -2
- package/src/providers/local/components/command-folder-update.tsx +2 -2
- package/src/providers/local/components/upload-zone.client.tsx +1 -1
- package/src/providers/local/lib/helpers.ts +0 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DriveSelectionContextValue } from "../../../components/selection.client.mjs";
|
|
2
|
+
import { DriveViewProviderProps } from "../../../components/view.client.mjs";
|
|
3
|
+
import { DriveContextValue } from "../../../components/context.client.mjs";
|
|
4
|
+
import { DriveDragDropProviderProps } from "../../../components/dnd.client.mjs";
|
|
5
|
+
import { LocalDriveUploadZoneProps } from "./upload-zone.client.mjs";
|
|
6
|
+
import * as react from "react";
|
|
7
|
+
import { PropsWithChildren } from "react";
|
|
8
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
9
|
+
|
|
10
|
+
//#region src/providers/local/components/provider.client.d.ts
|
|
11
|
+
type LocalDriveContextValue = DriveContextValue & {
|
|
12
|
+
readonly?: boolean;
|
|
13
|
+
};
|
|
14
|
+
declare const LocalDriveContext: react.Context<LocalDriveContextValue>;
|
|
15
|
+
declare function useLocalDriveContext(): LocalDriveContextValue;
|
|
16
|
+
type LocalDriveProviderProps = PropsWithChildren<LocalDriveContextValue & Partial<DriveSelectionContextValue> & Pick<DriveViewProviderProps, "initialView"> & Pick<DriveDragDropProviderProps, "onMove"> & Pick<LocalDriveUploadZoneProps, "driveUploadClient" | "uploadHooks" | "onUploadCompleted" | "onUploadFailed" | "optimistic" | "disabled" | "className"> & {
|
|
17
|
+
parentId?: string | null;
|
|
18
|
+
}>;
|
|
19
|
+
declare function LocalDriveProvider({
|
|
20
|
+
initialView,
|
|
21
|
+
namespace,
|
|
22
|
+
parentId,
|
|
23
|
+
permission,
|
|
24
|
+
meta,
|
|
25
|
+
readonly,
|
|
26
|
+
selection,
|
|
27
|
+
selectionConditions,
|
|
28
|
+
onMove,
|
|
29
|
+
driveUploadClient,
|
|
30
|
+
uploadHooks,
|
|
31
|
+
onUploadCompleted,
|
|
32
|
+
onUploadFailed,
|
|
33
|
+
optimistic,
|
|
34
|
+
disabled,
|
|
35
|
+
className,
|
|
36
|
+
children
|
|
37
|
+
}: LocalDriveProviderProps): react_jsx_runtime0.JSX.Element;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { LocalDriveContext, LocalDriveContextValue, LocalDriveProvider, LocalDriveProviderProps, useLocalDriveContext };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { DriveSelectionProvider } from "../../../components/selection.client.mjs";
|
|
4
|
+
import { DriveViewProvider } from "../../../components/view.client.mjs";
|
|
5
|
+
import { DriveDragDropProvider } from "../../../components/dnd.client.mjs";
|
|
6
|
+
import { LocalDriveUploadZone } from "./upload-zone.client.mjs";
|
|
7
|
+
import { cn } from "@tulip-systems/core/lib";
|
|
8
|
+
import { createContext, use } from "react";
|
|
9
|
+
import { jsx } from "react/jsx-runtime";
|
|
10
|
+
import { Allowed } from "@tulip-systems/core/auth/client";
|
|
11
|
+
|
|
12
|
+
//#region src/providers/local/components/provider.client.tsx
|
|
13
|
+
const LocalDriveContext = createContext({});
|
|
14
|
+
function useLocalDriveContext() {
|
|
15
|
+
const context = use(LocalDriveContext);
|
|
16
|
+
if (!context) throw new Error("LocalDriveContext not found!");
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
function LocalDriveProvider({ initialView = "grid", namespace, parentId, permission, meta, readonly = false, selection, selectionConditions, onMove, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, optimistic, disabled, className, children }) {
|
|
20
|
+
const isDisabled = disabled ?? readonly;
|
|
21
|
+
return /* @__PURE__ */ jsx(Allowed, {
|
|
22
|
+
permission,
|
|
23
|
+
children: /* @__PURE__ */ jsx(DriveSelectionProvider, {
|
|
24
|
+
selection,
|
|
25
|
+
selectionConditions,
|
|
26
|
+
children: /* @__PURE__ */ jsx(DriveViewProvider, {
|
|
27
|
+
initialView,
|
|
28
|
+
children: /* @__PURE__ */ jsx(DriveDragDropProvider, {
|
|
29
|
+
disabled: isDisabled,
|
|
30
|
+
onMove,
|
|
31
|
+
children: /* @__PURE__ */ jsx(LocalDriveContext, {
|
|
32
|
+
value: {
|
|
33
|
+
namespace,
|
|
34
|
+
permission,
|
|
35
|
+
meta,
|
|
36
|
+
readonly
|
|
37
|
+
},
|
|
38
|
+
children: /* @__PURE__ */ jsx(LocalDriveUploadZone, {
|
|
39
|
+
disabled: isDisabled,
|
|
40
|
+
className: cn("flex min-h-dvh flex-col", className),
|
|
41
|
+
variables: {
|
|
42
|
+
namespace,
|
|
43
|
+
parentId
|
|
44
|
+
},
|
|
45
|
+
driveUploadClient,
|
|
46
|
+
uploadHooks,
|
|
47
|
+
onUploadCompleted,
|
|
48
|
+
onUploadFailed,
|
|
49
|
+
optimistic,
|
|
50
|
+
children
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { LocalDriveContext, LocalDriveProvider, useLocalDriveContext };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { LocalDriveFileNode, LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { LocalDriveUploadClient } from "../lib/upload.client.mjs";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/local/components/upload-zone-context.client.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Upload Zone Context Value
|
|
8
|
+
*/
|
|
9
|
+
type LocalDriveUploadZoneContextValue = {
|
|
10
|
+
driveUploadClient: LocalDriveUploadClient;
|
|
11
|
+
onUpload: (file: File) => Promise<LocalDriveFileNode>;
|
|
12
|
+
onRemove: (ids: string[]) => Promise<void>;
|
|
13
|
+
optimistic?: {
|
|
14
|
+
add?: (newValue: LocalDriveNodeWithAsset) => Promise<void> | void;
|
|
15
|
+
replace?: (input: {
|
|
16
|
+
id: string;
|
|
17
|
+
newValue: LocalDriveNodeWithAsset;
|
|
18
|
+
}) => Promise<void> | void;
|
|
19
|
+
remove?: (ids: string[]) => Promise<void> | void;
|
|
20
|
+
invalidate?: () => Promise<void> | void;
|
|
21
|
+
cancel?: () => Promise<void> | void;
|
|
22
|
+
};
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Upload Zone Context
|
|
27
|
+
*/
|
|
28
|
+
declare const LocalDriveUploadZoneContext: React.Context<LocalDriveUploadZoneContextValue | null>;
|
|
29
|
+
type DriveUploadZoneContextValue = LocalDriveUploadZoneContextValue;
|
|
30
|
+
declare const DriveUploadZoneContext: React.Context<LocalDriveUploadZoneContextValue | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Upload Zone Hook
|
|
33
|
+
*/
|
|
34
|
+
declare function useLocalDriveUploadZone(): LocalDriveUploadZoneContextValue;
|
|
35
|
+
declare const useDriveUploadZone: typeof useLocalDriveUploadZone;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { DriveUploadZoneContext, DriveUploadZoneContextValue, LocalDriveUploadZoneContext, LocalDriveUploadZoneContextValue, useDriveUploadZone, useLocalDriveUploadZone };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/local/components/upload-zone-context.client.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Upload Zone Context
|
|
8
|
+
*/
|
|
9
|
+
const LocalDriveUploadZoneContext = React.createContext(null);
|
|
10
|
+
const DriveUploadZoneContext = LocalDriveUploadZoneContext;
|
|
11
|
+
/**
|
|
12
|
+
* Upload Zone Hook
|
|
13
|
+
*/
|
|
14
|
+
function useLocalDriveUploadZone() {
|
|
15
|
+
const context = React.useContext(LocalDriveUploadZoneContext);
|
|
16
|
+
if (!context) throw new Error("useUploadZone must be used within an UploadZoneContext provider");
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
const useDriveUploadZone = useLocalDriveUploadZone;
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { DriveUploadZoneContext, LocalDriveUploadZoneContext, useDriveUploadZone, useLocalDriveUploadZone };
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/providers/local/components/upload-zone.client.d.ts
|
|
8
|
+
type LocalDriveUploadZoneProps = ComponentProps<"div"> & Pick<LocalDriveUploadZoneContextValue, "optimistic" | "driveUploadClient" | "disabled"> & {
|
|
9
|
+
variables: Pick<PrepareLocalDriveUploadInput, "namespace" | "parentId" | "readonly" | "hidden" | "visibility">;
|
|
10
|
+
uploadHooks?: LocalDriveUploadHooks;
|
|
11
|
+
onUploadCompleted?: (node: LocalDriveFileNode) => Promise<void> | void;
|
|
12
|
+
onUploadFailed?: (error: unknown) => Promise<void> | void;
|
|
13
|
+
};
|
|
14
|
+
type DriveUploadZoneProps = LocalDriveUploadZoneProps;
|
|
15
|
+
declare function LocalDriveUploadZone({
|
|
16
|
+
variables,
|
|
17
|
+
optimistic,
|
|
18
|
+
driveUploadClient,
|
|
19
|
+
uploadHooks,
|
|
20
|
+
onUploadCompleted,
|
|
21
|
+
onUploadFailed,
|
|
22
|
+
disabled,
|
|
23
|
+
children,
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: LocalDriveUploadZoneProps): react_jsx_runtime0.JSX.Element;
|
|
27
|
+
declare const DriveUploadZone: typeof LocalDriveUploadZone;
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DriveUploadZone, DriveUploadZoneProps, LocalDriveUploadZone, LocalDriveUploadZoneProps };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { inferLocalDriveNodeSubtype } from "../lib/helpers.mjs";
|
|
4
|
+
import { LocalDriveUploadZoneContext } from "./upload-zone-context.client.mjs";
|
|
5
|
+
import { cn } from "@tulip-systems/core/lib";
|
|
6
|
+
import { useCallback } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { toast } from "@tulip-systems/core/components/client";
|
|
9
|
+
import { useAction } from "@tulip-systems/core/lib/client";
|
|
10
|
+
import { useDropzone } from "react-dropzone";
|
|
11
|
+
|
|
12
|
+
//#region src/providers/local/components/upload-zone.client.tsx
|
|
13
|
+
function LocalDriveUploadZone({ variables, optimistic, driveUploadClient, uploadHooks, onUploadCompleted, onUploadFailed, disabled = false, children, className, ...props }) {
|
|
14
|
+
/**
|
|
15
|
+
* Delete mutation
|
|
16
|
+
*/
|
|
17
|
+
const deleteMutation = useAction({
|
|
18
|
+
mutationFn: async (ids) => driveUploadClient.deleteFiles(ids),
|
|
19
|
+
onMutate: async (ids) => {
|
|
20
|
+
await optimistic?.cancel?.();
|
|
21
|
+
await optimistic?.remove?.(ids);
|
|
22
|
+
},
|
|
23
|
+
onError: async (error) => {
|
|
24
|
+
console.error("Delete failed upload error: ", error);
|
|
25
|
+
await onUploadFailed?.(error);
|
|
26
|
+
},
|
|
27
|
+
onSettled: () => {
|
|
28
|
+
optimistic?.invalidate?.();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Upload mutation
|
|
33
|
+
*/
|
|
34
|
+
const uploadMutation = useAction({
|
|
35
|
+
mutationFn: async (params) => driveUploadClient.upload(params, uploadHooks),
|
|
36
|
+
onMutate: async (variables) => {
|
|
37
|
+
await optimistic?.cancel?.();
|
|
38
|
+
const newNode = {
|
|
39
|
+
id: variables.uploadId,
|
|
40
|
+
provider: "local",
|
|
41
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
42
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
43
|
+
type: "file",
|
|
44
|
+
name: variables.file.name,
|
|
45
|
+
namespace: variables.namespace,
|
|
46
|
+
parentId: variables.parentId ?? null,
|
|
47
|
+
size: variables.file.size,
|
|
48
|
+
contentType: variables.file.type || "application/octet-stream",
|
|
49
|
+
readonly: variables.readonly ?? false,
|
|
50
|
+
hidden: variables.hidden ?? false,
|
|
51
|
+
archivedAt: null,
|
|
52
|
+
assetId: null,
|
|
53
|
+
subtype: inferLocalDriveNodeSubtype({
|
|
54
|
+
name: variables.file.name,
|
|
55
|
+
contentType: variables.file.type || "application/octet-stream"
|
|
56
|
+
}),
|
|
57
|
+
links: {
|
|
58
|
+
view: null,
|
|
59
|
+
download: null,
|
|
60
|
+
preview: null,
|
|
61
|
+
thumbnail: null
|
|
62
|
+
},
|
|
63
|
+
availability: "pending",
|
|
64
|
+
asset: {
|
|
65
|
+
status: "pending",
|
|
66
|
+
name: variables.file.name,
|
|
67
|
+
contentType: variables.file.type || "application/octet-stream",
|
|
68
|
+
size: variables.file.size,
|
|
69
|
+
visibility: variables.visibility || "private"
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
await optimistic?.add?.(newNode);
|
|
73
|
+
},
|
|
74
|
+
onSuccess: async (data, variables) => {
|
|
75
|
+
await optimistic?.replace?.({
|
|
76
|
+
id: variables.uploadId ?? "",
|
|
77
|
+
newValue: {
|
|
78
|
+
...data,
|
|
79
|
+
asset: {
|
|
80
|
+
status: "ready",
|
|
81
|
+
name: data.name,
|
|
82
|
+
contentType: data.contentType,
|
|
83
|
+
size: data.size,
|
|
84
|
+
visibility: variables.visibility || "private"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
await onUploadCompleted?.(data);
|
|
89
|
+
toast.success(`Succesvol geupload: ${data.name}`);
|
|
90
|
+
},
|
|
91
|
+
onError: async (error) => {
|
|
92
|
+
await onUploadFailed?.(error);
|
|
93
|
+
console.error("Upload error: ", error);
|
|
94
|
+
toast.error("Bestand uploaden mislukt", { description: error instanceof Error ? error.message : void 0 });
|
|
95
|
+
},
|
|
96
|
+
onSettled: () => {
|
|
97
|
+
optimistic?.invalidate?.();
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* Upload file handler
|
|
102
|
+
*/
|
|
103
|
+
const onUpload = useCallback(async (file) => {
|
|
104
|
+
console.info("Uploading file", file);
|
|
105
|
+
const req = driveUploadClient.prepareUpload({
|
|
106
|
+
...variables,
|
|
107
|
+
file
|
|
108
|
+
});
|
|
109
|
+
return await uploadMutation.mutateAsync(req);
|
|
110
|
+
}, [
|
|
111
|
+
driveUploadClient,
|
|
112
|
+
variables,
|
|
113
|
+
uploadMutation
|
|
114
|
+
]);
|
|
115
|
+
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
116
|
+
onDrop: useCallback(async (acceptedFiles) => {
|
|
117
|
+
if (acceptedFiles.length === 0) return;
|
|
118
|
+
await Promise.allSettled(acceptedFiles.map(onUpload));
|
|
119
|
+
}, [onUpload]),
|
|
120
|
+
noClick: true,
|
|
121
|
+
disabled
|
|
122
|
+
});
|
|
123
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
124
|
+
...props,
|
|
125
|
+
...getRootProps(),
|
|
126
|
+
className: cn("relative z-0", className),
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx("input", { ...getInputProps() }),
|
|
129
|
+
isDragActive && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 rounded-md bg-primary/20 opacity-70 backdrop-blur-3xl" }),
|
|
130
|
+
/* @__PURE__ */ jsx(LocalDriveUploadZoneContext, {
|
|
131
|
+
value: {
|
|
132
|
+
driveUploadClient,
|
|
133
|
+
onUpload,
|
|
134
|
+
onRemove: deleteMutation.mutateAsync,
|
|
135
|
+
optimistic,
|
|
136
|
+
disabled
|
|
137
|
+
},
|
|
138
|
+
children
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const DriveUploadZone = LocalDriveUploadZone;
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { DriveUploadZone, LocalDriveUploadZone };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { TableColumnDef } from "@tulip-systems/core/data-tables";
|
|
3
|
+
import { ComponentProps } from "react";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
+
import { useInfiniteStrategy } from "@tulip-systems/core/data-tables/client";
|
|
6
|
+
import { CommandDef } from "@tulip-systems/core/commands";
|
|
7
|
+
import { VisibilityState } from "@tanstack/react-table";
|
|
8
|
+
|
|
9
|
+
//#region src/providers/local/components/view.client.d.ts
|
|
10
|
+
type LocalDriveViewProviderProps<TData extends LocalDriveNodeWithAsset = LocalDriveNodeWithAsset> = ComponentProps<"div"> & {
|
|
11
|
+
queryData: TData[];
|
|
12
|
+
columns?: TableColumnDef<TData>[];
|
|
13
|
+
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
14
|
+
commands?: CommandDef<TData>[];
|
|
15
|
+
columnVisibility?: VisibilityState;
|
|
16
|
+
};
|
|
17
|
+
declare function LocalDriveViewProvider<TData extends LocalDriveNodeWithAsset = LocalDriveNodeWithAsset>({
|
|
18
|
+
queryData,
|
|
19
|
+
columns,
|
|
20
|
+
strategy,
|
|
21
|
+
commands,
|
|
22
|
+
columnVisibility,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}: LocalDriveViewProviderProps<TData>): react_jsx_runtime0.JSX.Element;
|
|
26
|
+
declare function LocalDriveView(): react_jsx_runtime0.JSX.Element | null;
|
|
27
|
+
declare function LocalDriveViewLoading({
|
|
28
|
+
...props
|
|
29
|
+
}: ComponentProps<"div">): react_jsx_runtime0.JSX.Element;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { LocalDriveView, LocalDriveViewLoading, LocalDriveViewProvider };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useDriveSelectionContext } from "../../../components/selection.client.mjs";
|
|
4
|
+
import { DriveGridCard, DriveGridCardSkeleton } from "../../../components/grid-card.client.mjs";
|
|
5
|
+
import { DriveGrid, DriveGridBottombar, DriveGridEmpty, DriveGridLoading } from "../../../components/grid.client.mjs";
|
|
6
|
+
import { useDriveViewContext } from "../../../components/view.client.mjs";
|
|
7
|
+
import { localDriveColumns } from "../config/columns-data.mjs";
|
|
8
|
+
import { localDriveImageLoader } from "../lib/helpers.mjs";
|
|
9
|
+
import { useLocalDriveUploadZone } from "./upload-zone-context.client.mjs";
|
|
10
|
+
import { useLocalDriveContext } from "./provider.client.mjs";
|
|
11
|
+
import { TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
|
|
12
|
+
import { useMemo } from "react";
|
|
13
|
+
import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
|
|
14
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
import { DataTable, TableConfigProvider, createTableConfig, useTableConfigContext } from "@tulip-systems/core/data-tables/client";
|
|
16
|
+
|
|
17
|
+
//#region src/providers/local/components/view.client.tsx
|
|
18
|
+
function LocalDriveViewProvider({ queryData, columns = localDriveColumns, strategy, commands, columnVisibility, children, ...props }) {
|
|
19
|
+
const { meta } = useLocalDriveContext();
|
|
20
|
+
const { selection } = useDriveSelectionContext();
|
|
21
|
+
return /* @__PURE__ */ jsx(TableConfigProvider, {
|
|
22
|
+
config: createTableConfig({
|
|
23
|
+
queryData,
|
|
24
|
+
columns,
|
|
25
|
+
strategy,
|
|
26
|
+
commands,
|
|
27
|
+
meta,
|
|
28
|
+
columnVisibility,
|
|
29
|
+
selection
|
|
30
|
+
}),
|
|
31
|
+
children: /* @__PURE__ */ jsx(TableLayout, {
|
|
32
|
+
...props,
|
|
33
|
+
children
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function LocalDriveView() {
|
|
38
|
+
const { view } = useDriveViewContext();
|
|
39
|
+
if (view === "grid") return /* @__PURE__ */ jsx(LocalDriveGrid, {});
|
|
40
|
+
if (view === "list") return /* @__PURE__ */ jsx(LocalDriveList, {});
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
function LocalDriveGrid(props) {
|
|
44
|
+
const { queryData, strategy, commands, selection, meta } = useTableConfigContext();
|
|
45
|
+
const { optimistic } = useLocalDriveUploadZone();
|
|
46
|
+
const { rowCount, paginationState } = strategy;
|
|
47
|
+
const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta;
|
|
48
|
+
const hasNextPage = rowCount == null ? false : queryData.length < rowCount;
|
|
49
|
+
const selectedData = useMemo(() => queryData.filter((node) => selection?.rowSelection?.[node.id] === true), [queryData, selection?.rowSelection]);
|
|
50
|
+
return /* @__PURE__ */ jsxs(DriveGrid, {
|
|
51
|
+
...props,
|
|
52
|
+
children: [
|
|
53
|
+
queryData.length > 0 ? queryData.filter((node) => !node.hidden).map((node) => /* @__PURE__ */ jsx(DriveGridCard, {
|
|
54
|
+
node,
|
|
55
|
+
commands,
|
|
56
|
+
imageLoader: localDriveImageLoader
|
|
57
|
+
}, node.id)) : /* @__PURE__ */ jsx(DriveGridEmpty, { title: "Geen resultaten gevonden" }),
|
|
58
|
+
isFetchingNextPage && Array.from({ length: paginationState?.pageSize ?? 0 }).map((_, index) => /* @__PURE__ */ jsx(DriveGridCardSkeleton, {}, index)),
|
|
59
|
+
/* @__PURE__ */ jsx(DriveGridBottombar, {
|
|
60
|
+
hasNextPage,
|
|
61
|
+
fetchNextPage,
|
|
62
|
+
isFetching,
|
|
63
|
+
isFetchingNextPage
|
|
64
|
+
}),
|
|
65
|
+
commands && commands.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
66
|
+
data: selectedData,
|
|
67
|
+
commands,
|
|
68
|
+
meta,
|
|
69
|
+
state: selectedData.length > 0 ? "open" : "closed",
|
|
70
|
+
onSuccess: () => {
|
|
71
|
+
selection?.setRowSelection?.({});
|
|
72
|
+
optimistic?.invalidate?.();
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function LocalDriveList(props) {
|
|
79
|
+
return /* @__PURE__ */ jsx(DataTable, { ...props });
|
|
80
|
+
}
|
|
81
|
+
function LocalDriveViewLoading({ ...props }) {
|
|
82
|
+
const { view } = useDriveViewContext();
|
|
83
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
84
|
+
...props,
|
|
85
|
+
children: [view === "grid" && /* @__PURE__ */ jsx(DriveGridLoading, { ...props }), view === "list" && /* @__PURE__ */ jsx(TableSkeleton, { ...props })]
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//#endregion
|
|
90
|
+
export { LocalDriveView, LocalDriveViewLoading, LocalDriveViewProvider };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
|
+
import { TableColumnDef } from "@tulip-systems/core/data-tables";
|
|
3
|
+
|
|
4
|
+
//#region src/providers/local/config/columns-data.d.ts
|
|
5
|
+
declare const localDriveColumns: TableColumnDef<LocalDriveNodeWithAsset>[];
|
|
6
|
+
//#endregion
|
|
7
|
+
export { localDriveColumns };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { driveTreeSearchParams } from "../../../lib/search-params.mjs";
|
|
4
|
+
import { nodeSubtypeConfig, nodeSubtypeVariants } from "../../../config/types.mjs";
|
|
5
|
+
import { TableColumnHeader } from "@tulip-systems/core/data-tables";
|
|
6
|
+
import { findStatus } from "@tulip-systems/core/components";
|
|
7
|
+
import { FolderIcon } from "lucide-react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/core/components/client";
|
|
10
|
+
import { TableTextCell, createTableSelectCell } from "@tulip-systems/core/data-tables/client";
|
|
11
|
+
import Link from "next/link";
|
|
12
|
+
import { createSerializer, useQueryStates } from "nuqs";
|
|
13
|
+
|
|
14
|
+
//#region src/providers/local/config/columns-data.tsx
|
|
15
|
+
const localDriveColumns = [
|
|
16
|
+
createTableSelectCell(),
|
|
17
|
+
{
|
|
18
|
+
id: "icon",
|
|
19
|
+
accessorKey: "icon",
|
|
20
|
+
header: () => null,
|
|
21
|
+
cell: ({ row }) => {
|
|
22
|
+
if (row.original.type === "file") {
|
|
23
|
+
const subtype = findStatus(nodeSubtypeConfig, row.original.subtype);
|
|
24
|
+
if (!subtype) return null;
|
|
25
|
+
return /* @__PURE__ */ jsx(TableTextCell, {
|
|
26
|
+
className: "w-4",
|
|
27
|
+
children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(subtype.icon, { className: nodeSubtypeVariants({
|
|
28
|
+
status: row.original.subtype,
|
|
29
|
+
className: "size-4"
|
|
30
|
+
}) }) }), /* @__PURE__ */ jsx(TooltipContent, { children: subtype.label })] })
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (row.original.type === "folder") return /* @__PURE__ */ jsx(TableTextCell, {
|
|
34
|
+
className: "w-4",
|
|
35
|
+
children: /* @__PURE__ */ jsx(FolderIcon, { className: "w-4 min-w-4" })
|
|
36
|
+
});
|
|
37
|
+
return null;
|
|
38
|
+
},
|
|
39
|
+
enableSorting: false
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: "name",
|
|
43
|
+
accessorKey: "name",
|
|
44
|
+
header: ({ column }) => /* @__PURE__ */ jsx(TableColumnHeader, {
|
|
45
|
+
column,
|
|
46
|
+
title: "Naam"
|
|
47
|
+
}),
|
|
48
|
+
cell: ({ row }) => {
|
|
49
|
+
const [query] = useQueryStates(driveTreeSearchParams);
|
|
50
|
+
const serialize = createSerializer(driveTreeSearchParams);
|
|
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 ?? "#" : serialize({
|
|
55
|
+
...query,
|
|
56
|
+
parentId: row.original.id
|
|
57
|
+
}),
|
|
58
|
+
className: "truncate hover:underline",
|
|
59
|
+
target: row.original.type === "file" ? "_blank" : "_self",
|
|
60
|
+
children: row.getValue("name")
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
enableSorting: false
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { localDriveColumns };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import z$1 from "zod";
|
|
2
|
+
import * as _tulip_systems_core_data_tables0 from "@tulip-systems/core/data-tables";
|
|
3
|
+
|
|
4
|
+
//#region src/providers/local/config/filters.d.ts
|
|
5
|
+
declare const localDriveFilters: {
|
|
6
|
+
subtypes: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodArray<z$1.ZodEnum<{
|
|
7
|
+
image: "image";
|
|
8
|
+
document: "document";
|
|
9
|
+
spreadsheet: "spreadsheet";
|
|
10
|
+
video: "video";
|
|
11
|
+
audio: "audio";
|
|
12
|
+
archive: "archive";
|
|
13
|
+
other: "other";
|
|
14
|
+
}>>>;
|
|
15
|
+
hidden: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodBoolean>;
|
|
16
|
+
types: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodArray<z$1.ZodEnum<{
|
|
17
|
+
file: "file";
|
|
18
|
+
folder: "folder";
|
|
19
|
+
}>>>;
|
|
20
|
+
contentTypes: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodArray<z$1.ZodString>>;
|
|
21
|
+
nodeIds: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodArray<z$1.ZodString>>;
|
|
22
|
+
isArchived: _tulip_systems_core_data_tables0.ParseFilter<z$1.ZodBoolean>;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { localDriveFilters };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { driveTreeFilters } from "../../../config/filters.mjs";
|
|
2
|
+
import { nodeSubtypes } from "../lib/constants.mjs";
|
|
3
|
+
import z$1 from "zod";
|
|
4
|
+
import { createTableFilters, parseFilterArray, parseFilterBoolean } from "@tulip-systems/core/data-tables";
|
|
5
|
+
|
|
6
|
+
//#region src/providers/local/config/filters.ts
|
|
7
|
+
const localDriveFilters = createTableFilters({
|
|
8
|
+
...driveTreeFilters,
|
|
9
|
+
subtypes: parseFilterArray(z$1.array(z$1.enum(nodeSubtypes))),
|
|
10
|
+
hidden: parseFilterBoolean(z$1.boolean())
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { localDriveFilters };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/providers/local/lib/constants.d.ts
|
|
2
|
+
declare const deviceSizes: number[];
|
|
3
|
+
declare const imageSizes: number[];
|
|
4
|
+
declare const imageVariants: readonly ["main", ...`preview-${number}`[]];
|
|
5
|
+
type ImageVariant = (typeof imageVariants)[number];
|
|
6
|
+
/**
|
|
7
|
+
* Node subtype
|
|
8
|
+
*/
|
|
9
|
+
declare const nodeSubtypes: readonly ["image", "document", "spreadsheet", "video", "audio", "archive", "other"];
|
|
10
|
+
//#endregion
|
|
11
|
+
export { ImageVariant, deviceSizes, imageSizes, imageVariants, nodeSubtypes };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/providers/local/lib/constants.ts
|
|
2
|
+
const deviceSizes = [
|
|
3
|
+
640,
|
|
4
|
+
750,
|
|
5
|
+
828,
|
|
6
|
+
1080,
|
|
7
|
+
1200,
|
|
8
|
+
1920,
|
|
9
|
+
2048,
|
|
10
|
+
3840
|
|
11
|
+
];
|
|
12
|
+
const imageSizes = deviceSizes;
|
|
13
|
+
const imageVariants = ["main", ...deviceSizes.map((size) => `preview-${size}`)];
|
|
14
|
+
/**
|
|
15
|
+
* Node subtype
|
|
16
|
+
*/
|
|
17
|
+
const nodeSubtypes = [
|
|
18
|
+
"image",
|
|
19
|
+
"document",
|
|
20
|
+
"spreadsheet",
|
|
21
|
+
"video",
|
|
22
|
+
"audio",
|
|
23
|
+
"archive",
|
|
24
|
+
"other"
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { deviceSizes, imageSizes, imageVariants, nodeSubtypes };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { GetLocalFileURLSchema, LocalDriveNode, LocalNode } from "./validators.mjs";
|
|
2
|
+
import { nodeSubtypes } from "./constants.mjs";
|
|
3
|
+
import { ImageLoaderProps } from "next/image";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/local/lib/helpers.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Convert a LocalNode to LocalDriveNode by adding provider and links
|
|
8
|
+
* @param node The LocalNode to convert
|
|
9
|
+
* @returns The converted LocalDriveNode
|
|
10
|
+
*/
|
|
11
|
+
declare function toLocalDriveNode<TNode extends LocalNode>(node: TNode): LocalDriveNode;
|
|
12
|
+
/**
|
|
13
|
+
* Check if the node is a file
|
|
14
|
+
*/
|
|
15
|
+
declare function isLocalDriveFile(node: Pick<LocalNode, "type">): node is LocalNode;
|
|
16
|
+
/**
|
|
17
|
+
* Check if the node is a folder
|
|
18
|
+
*/
|
|
19
|
+
declare function isLocalDriveFolder(node: Pick<LocalNode, "type">): node is LocalNode;
|
|
20
|
+
/**
|
|
21
|
+
* Get file url
|
|
22
|
+
*/
|
|
23
|
+
declare function getLocalDriveFileUrl(id: string, options?: Partial<GetLocalFileURLSchema>): string;
|
|
24
|
+
/**
|
|
25
|
+
* Image loader
|
|
26
|
+
*/
|
|
27
|
+
declare function localDriveImageLoader({
|
|
28
|
+
src,
|
|
29
|
+
width
|
|
30
|
+
}: ImageLoaderProps): string;
|
|
31
|
+
/**
|
|
32
|
+
* Node subtype inference
|
|
33
|
+
*/
|
|
34
|
+
type LocalDriveNodeSubtype = (typeof nodeSubtypes)[number];
|
|
35
|
+
declare function inferLocalDriveNodeSubtype({
|
|
36
|
+
name,
|
|
37
|
+
contentType
|
|
38
|
+
}: Partial<Pick<LocalDriveNode, "name" | "contentType">>): LocalDriveNodeSubtype;
|
|
39
|
+
/**
|
|
40
|
+
* Render bytes
|
|
41
|
+
*/
|
|
42
|
+
declare function renderBytes(bytes: number): string;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { LocalDriveNodeSubtype, getLocalDriveFileUrl, inferLocalDriveNodeSubtype, isLocalDriveFile, isLocalDriveFolder, localDriveImageLoader, renderBytes, toLocalDriveNode };
|