@tulip-systems/drive 0.8.3 → 0.10.0
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 +2 -1
- package/dist/client.mjs +2 -1
- package/dist/components/grid-card.client.d.mts +2 -2
- package/dist/lib/view-config.client.d.mts +57 -0
- package/dist/lib/view-config.client.mjs +46 -0
- package/dist/providers/google/components/view.client.d.mts +2 -2
- package/dist/providers/google/components/view.client.mjs +9 -9
- package/dist/providers/google/config/columns-data.mjs +1 -1
- package/dist/providers/google/lib/router.server.d.mts +2 -2
- package/dist/providers/local/components/view.client.d.mts +2 -2
- package/dist/providers/local/components/view.client.mjs +9 -9
- package/dist/providers/local/config/columns-data.mjs +1 -1
- package/dist/providers/local/config/sorting.mjs +16 -0
- package/dist/providers/local/lib/router.server.d.mts +28 -28
- package/dist/providers/local/lib/service.server.d.mts +14 -14
- package/dist/providers/local/lib/service.server.mjs +9 -8
- package/package.json +2 -2
- package/src/components/grid-card.client.tsx +2 -2
- package/src/entry.client.ts +5 -0
- package/src/lib/view-config.client.tsx +116 -0
- package/src/providers/google/components/view.client.tsx +17 -20
- package/src/providers/local/components/view.client.tsx +17 -16
- package/src/providers/local/config/sorting.ts +16 -0
- package/src/providers/local/lib/service.server.ts +8 -19
package/dist/client.d.mts
CHANGED
|
@@ -2,4 +2,5 @@ import { DriveGrid, DriveGridBottombar, DriveGridEmpty, DriveGridEmptyProps, Dri
|
|
|
2
2
|
import { DriveGridCard, DriveGridCardSkeleton, DriveGridFileCard, DriveGridFolderCard } from "./components/grid-card.client.mjs";
|
|
3
3
|
import { DriveSelectionContextValue, DriveSelectionProvider, useDriveSelectionContext } from "./components/selection.client.mjs";
|
|
4
4
|
import { DriveViewContextValue, DriveViewMode, DriveViewProvider, DriveViewProviderProps, useDriveViewContext } from "./components/view.client.mjs";
|
|
5
|
-
|
|
5
|
+
import { CreateDriveViewConfigInput, DriveViewCommands, DriveViewConfig, DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig } from "./lib/view-config.client.mjs";
|
|
6
|
+
export { CreateDriveViewConfigInput, DriveGrid, DriveGridBottombar, DriveGridCard, DriveGridCardSkeleton, DriveGridEmpty, DriveGridEmptyProps, DriveGridFileCard, DriveGridFolderCard, DriveGridLoading, DriveGridLoadingProps, DriveGridProps, DriveSelectionContextValue, DriveSelectionProvider, DriveViewCommands, DriveViewConfig, DriveViewConfigProvider, DriveViewContextValue, DriveViewMode, DriveViewProvider, DriveViewProviderProps, createDriveViewConfig, useDriveSelectionContext, useDriveViewConfig, useDriveViewContext };
|
package/dist/client.mjs
CHANGED
|
@@ -2,5 +2,6 @@ import { DriveSelectionProvider, useDriveSelectionContext } from "./components/s
|
|
|
2
2
|
import { DriveGridCard, DriveGridCardSkeleton, DriveGridFileCard, DriveGridFolderCard } from "./components/grid-card.client.mjs";
|
|
3
3
|
import { DriveGrid, DriveGridBottombar, DriveGridEmpty, DriveGridLoading } from "./components/grid.client.mjs";
|
|
4
4
|
import { DriveViewProvider, useDriveViewContext } from "./components/view.client.mjs";
|
|
5
|
+
import { DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig } from "./lib/view-config.client.mjs";
|
|
5
6
|
|
|
6
|
-
export { DriveGrid, DriveGridBottombar, DriveGridCard, DriveGridCardSkeleton, DriveGridEmpty, DriveGridFileCard, DriveGridFolderCard, DriveGridLoading, DriveSelectionProvider, DriveViewProvider, useDriveSelectionContext, useDriveViewContext };
|
|
7
|
+
export { DriveGrid, DriveGridBottombar, DriveGridCard, DriveGridCardSkeleton, DriveGridEmpty, DriveGridFileCard, DriveGridFolderCard, DriveGridLoading, DriveSelectionProvider, DriveViewConfigProvider, DriveViewProvider, createDriveViewConfig, useDriveSelectionContext, useDriveViewConfig, useDriveViewContext };
|
|
@@ -2,7 +2,7 @@ import { DriveNode } from "../lib/dto.mjs";
|
|
|
2
2
|
import { ComponentProps } from "react";
|
|
3
3
|
import { ImageLoaderProps } from "next/image";
|
|
4
4
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
5
|
+
import { CommandFor } from "@tulip-systems/core/commands";
|
|
6
6
|
|
|
7
7
|
//#region src/components/grid-card.client.d.ts
|
|
8
8
|
/**
|
|
@@ -10,7 +10,7 @@ import { CommandDef } from "@tulip-systems/core/commands";
|
|
|
10
10
|
*/
|
|
11
11
|
type DriveGridCardProps<TData extends DriveNode> = ComponentProps<"div"> & {
|
|
12
12
|
node: TData;
|
|
13
|
-
commands?:
|
|
13
|
+
commands?: CommandFor<TData>[];
|
|
14
14
|
imageLoader?: (props: ImageLoaderProps) => string;
|
|
15
15
|
unoptimized?: boolean;
|
|
16
16
|
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Selection, TableColumnDef, TableFiltersResult, TableMetaInput } from "@tulip-systems/core/data-tables";
|
|
2
|
+
import { PropsWithChildren } from "react";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
import { TableConfigContextValue, useInfiniteStrategy } from "@tulip-systems/core/data-tables/client";
|
|
5
|
+
import { CommandFor } from "@tulip-systems/core/commands";
|
|
6
|
+
import { VisibilityState } from "@tanstack/react-table";
|
|
7
|
+
|
|
8
|
+
//#region src/lib/view-config.client.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* DriveViewConfig context
|
|
11
|
+
*/
|
|
12
|
+
type DriveViewCommands<TData, TMeta = object> = {
|
|
13
|
+
node?: CommandFor<TData, TMeta>[];
|
|
14
|
+
selectedNodes?: CommandFor<TData[], TMeta>[];
|
|
15
|
+
};
|
|
16
|
+
type DriveViewConfigContextValue<TData, TMeta = object> = {
|
|
17
|
+
commands?: DriveViewCommands<TData, TMeta>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Drive View configuration
|
|
21
|
+
*/
|
|
22
|
+
type DriveViewConfig<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>> = DriveViewConfigContextValue<TData, TMeta> & Omit<TableConfigContextValue<TData, TableFiltersResult, TMeta>, "commands">;
|
|
23
|
+
type CreateDriveViewConfigInput<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>> = {
|
|
24
|
+
queryData: TData[];
|
|
25
|
+
columns: TableColumnDef<TData>[];
|
|
26
|
+
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
27
|
+
commands?: DriveViewCommands<TData, TMeta>;
|
|
28
|
+
meta?: TMeta;
|
|
29
|
+
columnVisibility?: VisibilityState;
|
|
30
|
+
selection?: Selection;
|
|
31
|
+
getRowId?: (row: TData) => string;
|
|
32
|
+
};
|
|
33
|
+
declare function createDriveViewConfig<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>>({
|
|
34
|
+
queryData,
|
|
35
|
+
columns,
|
|
36
|
+
strategy,
|
|
37
|
+
commands,
|
|
38
|
+
meta,
|
|
39
|
+
columnVisibility,
|
|
40
|
+
selection,
|
|
41
|
+
getRowId
|
|
42
|
+
}: CreateDriveViewConfigInput<TData, TMeta>): DriveViewConfig<TData, TMeta>;
|
|
43
|
+
/**
|
|
44
|
+
* DriveViewConfigProvider component
|
|
45
|
+
* Wraps the children components with the DriveViewConfigContext provider
|
|
46
|
+
* and provides the configuration for the drive view
|
|
47
|
+
*/
|
|
48
|
+
type DriveViewConfigProviderProps<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>> = PropsWithChildren<{
|
|
49
|
+
config: ReturnType<typeof createDriveViewConfig<TData, TMeta>>;
|
|
50
|
+
}>;
|
|
51
|
+
declare function DriveViewConfigProvider<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>>({
|
|
52
|
+
config,
|
|
53
|
+
children
|
|
54
|
+
}: DriveViewConfigProviderProps<TData, TMeta>): react_jsx_runtime0.JSX.Element;
|
|
55
|
+
declare function useDriveViewConfig<TData, TMeta extends TableMetaInput<TData> = TableMetaInput<TData>>(): DriveViewConfig<TData, TMeta>;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { CreateDriveViewConfigInput, DriveViewCommands, DriveViewConfig, DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, use } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { TableConfigProvider, createTableConfig, useTableConfigContext } from "@tulip-systems/core/data-tables/client";
|
|
6
|
+
|
|
7
|
+
//#region src/lib/view-config.client.tsx
|
|
8
|
+
const DriveViewConfigContext = createContext({});
|
|
9
|
+
function createDriveViewConfig({ queryData, columns, strategy, commands, meta, columnVisibility, selection, getRowId = (row) => row.id }) {
|
|
10
|
+
const { commands: _commands, ...table } = createTableConfig({
|
|
11
|
+
queryData,
|
|
12
|
+
columns,
|
|
13
|
+
getRowId,
|
|
14
|
+
strategy,
|
|
15
|
+
meta,
|
|
16
|
+
columnVisibility,
|
|
17
|
+
selection
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
...table,
|
|
21
|
+
commands
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function DriveViewConfigProvider({ config, children }) {
|
|
25
|
+
return /* @__PURE__ */ jsx(DriveViewConfigContext, {
|
|
26
|
+
value: config,
|
|
27
|
+
children: /* @__PURE__ */ jsx(TableConfigProvider, {
|
|
28
|
+
config: {
|
|
29
|
+
...config,
|
|
30
|
+
commands: config.commands?.selectedNodes
|
|
31
|
+
},
|
|
32
|
+
children
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function useDriveViewConfig() {
|
|
37
|
+
const tableConfig = useTableConfigContext();
|
|
38
|
+
const viewConfig = use(DriveViewConfigContext);
|
|
39
|
+
return {
|
|
40
|
+
...tableConfig,
|
|
41
|
+
...viewConfig
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { DriveViewCommands } from "../../../lib/view-config.client.mjs";
|
|
1
2
|
import { GoogleDriveNode } from "../lib/validators.mjs";
|
|
2
3
|
import { TableColumnDef } from "@tulip-systems/core/data-tables";
|
|
3
4
|
import { ComponentProps } from "react";
|
|
4
5
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
6
|
import { useInfiniteStrategy } from "@tulip-systems/core/data-tables/client";
|
|
6
|
-
import { CommandDef } from "@tulip-systems/core/commands";
|
|
7
7
|
import { VisibilityState } from "@tanstack/react-table";
|
|
8
8
|
|
|
9
9
|
//#region src/providers/google/components/view.client.d.ts
|
|
@@ -14,7 +14,7 @@ type GoogleDriveViewProviderProps<TData extends GoogleDriveNode = GoogleDriveNod
|
|
|
14
14
|
queryData: TData[];
|
|
15
15
|
columns?: TableColumnDef<TData>[];
|
|
16
16
|
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
17
|
-
commands?:
|
|
17
|
+
commands?: DriveViewCommands<TData>;
|
|
18
18
|
columnVisibility?: VisibilityState;
|
|
19
19
|
};
|
|
20
20
|
declare function GoogleDriveViewProvider<TData extends GoogleDriveNode = GoogleDriveNode>({
|
|
@@ -4,27 +4,27 @@ import { useDriveSelectionContext } from "../../../components/selection.client.m
|
|
|
4
4
|
import { DriveGridCard, DriveGridCardSkeleton } from "../../../components/grid-card.client.mjs";
|
|
5
5
|
import { DriveGrid, DriveGridBottombar, DriveGridEmpty, DriveGridLoading } from "../../../components/grid.client.mjs";
|
|
6
6
|
import { useDriveViewContext } from "../../../components/view.client.mjs";
|
|
7
|
+
import { DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig } from "../../../lib/view-config.client.mjs";
|
|
7
8
|
import { googleDriveColumns } from "../config/columns-data.mjs";
|
|
8
9
|
import { useGoogleDriveContext } from "./provider.client.mjs";
|
|
9
10
|
import { TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
|
|
10
11
|
import { useMemo } from "react";
|
|
11
12
|
import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
|
|
12
13
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
-
import { DataTable
|
|
14
|
+
import { DataTable } from "@tulip-systems/core/data-tables/client";
|
|
14
15
|
|
|
15
16
|
//#region src/providers/google/components/view.client.tsx
|
|
16
17
|
function GoogleDriveViewProvider({ queryData, columns = googleDriveColumns, strategy, commands, columnVisibility, children, ...props }) {
|
|
17
18
|
const { meta } = useGoogleDriveContext();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
config: createTableConfig({
|
|
19
|
+
return /* @__PURE__ */ jsx(DriveViewConfigProvider, {
|
|
20
|
+
config: createDriveViewConfig({
|
|
21
21
|
queryData,
|
|
22
22
|
columns,
|
|
23
23
|
strategy,
|
|
24
24
|
commands,
|
|
25
25
|
meta,
|
|
26
26
|
columnVisibility,
|
|
27
|
-
selection
|
|
27
|
+
selection: useDriveSelectionContext()?.selection
|
|
28
28
|
}),
|
|
29
29
|
children: /* @__PURE__ */ jsx(TableLayout, {
|
|
30
30
|
...props,
|
|
@@ -45,7 +45,7 @@ function GoogleDriveView() {
|
|
|
45
45
|
* GoogleDriveGrid
|
|
46
46
|
*/
|
|
47
47
|
function GoogleDriveGrid(props) {
|
|
48
|
-
const { queryData, strategy, commands, selection, meta } =
|
|
48
|
+
const { queryData, strategy, commands, selection, meta } = useDriveViewConfig();
|
|
49
49
|
const { rowCount, paginationState } = strategy;
|
|
50
50
|
const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta;
|
|
51
51
|
const hasNextPage = rowCount == null ? false : queryData.length < rowCount;
|
|
@@ -55,7 +55,7 @@ function GoogleDriveGrid(props) {
|
|
|
55
55
|
children: [
|
|
56
56
|
queryData.length > 0 ? queryData.map((node) => /* @__PURE__ */ jsx(DriveGridCard, {
|
|
57
57
|
node,
|
|
58
|
-
commands,
|
|
58
|
+
commands: commands?.node,
|
|
59
59
|
unoptimized: true
|
|
60
60
|
}, node.id)) : /* @__PURE__ */ jsx(DriveGridEmpty, { title: "Geen resultaten gevonden" }),
|
|
61
61
|
isFetchingNextPage && Array.from({ length: paginationState?.pageSize ?? 0 }).map((_, index) => /* @__PURE__ */ jsx(DriveGridCardSkeleton, {}, index)),
|
|
@@ -65,9 +65,9 @@ function GoogleDriveGrid(props) {
|
|
|
65
65
|
isFetching,
|
|
66
66
|
isFetchingNextPage
|
|
67
67
|
}),
|
|
68
|
-
commands && commands.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
68
|
+
commands?.selectedNodes && commands.selectedNodes.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
69
69
|
data: selectedData,
|
|
70
|
-
commands,
|
|
70
|
+
commands: commands.selectedNodes,
|
|
71
71
|
meta,
|
|
72
72
|
state: selectedData.length > 0 ? "open" : "closed",
|
|
73
73
|
onSuccess: () => selection?.setRowSelection?.({})
|
|
@@ -6,8 +6,8 @@ import { TableColumnHeader } from "@tulip-systems/core/data-tables";
|
|
|
6
6
|
import { findStatus } from "@tulip-systems/core/components";
|
|
7
7
|
import { FolderIcon } from "lucide-react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/core/components/client";
|
|
10
9
|
import { TableTextCell, createTableSelectCell } from "@tulip-systems/core/data-tables/client";
|
|
10
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/core/components/client";
|
|
11
11
|
import Link from "next/link";
|
|
12
12
|
import { createSerializer, useQueryStates } from "nuqs";
|
|
13
13
|
|
|
@@ -315,7 +315,7 @@ declare function createGoogleDriveProcedures<TSchema extends TDatabaseSchema>(dr
|
|
|
315
315
|
trashedAt: Date | null;
|
|
316
316
|
googleParents: string[];
|
|
317
317
|
canEdit: boolean | null;
|
|
318
|
-
}, "
|
|
318
|
+
}, "name" | "parentId" | "id"> & {
|
|
319
319
|
depth: number;
|
|
320
320
|
})[], (Pick<{
|
|
321
321
|
id: string;
|
|
@@ -348,7 +348,7 @@ declare function createGoogleDriveProcedures<TSchema extends TDatabaseSchema>(dr
|
|
|
348
348
|
trashedAt: Date | null;
|
|
349
349
|
googleParents: string[];
|
|
350
350
|
canEdit: boolean | null;
|
|
351
|
-
}, "
|
|
351
|
+
}, "name" | "parentId" | "id"> & {
|
|
352
352
|
depth: number;
|
|
353
353
|
})[]>, Record<never, never>, Record<never, never>>;
|
|
354
354
|
createFolder: _orpc_server0.DecoratedProcedure<_orpc_server0.MergedInitialContext<_tulip_systems_core_router_server0.RPCContext<TSchema> & Record<never, never>, _tulip_systems_core_router_server0.RPCContext<TSchema> & Record<never, never>, _tulip_systems_core_router_server0.RPCContext<TSchema>>, _orpc_server0.MergedCurrentContext<_tulip_systems_core_router_server0.RPCContext<TSchema>, _tulip_systems_core_router_server0.ProtectedRPCContext<TSchema>>, z.ZodObject<{
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { DriveViewCommands } from "../../../lib/view-config.client.mjs";
|
|
1
2
|
import { LocalDriveNodeWithAsset } from "../lib/validators.mjs";
|
|
2
3
|
import { TableColumnDef } from "@tulip-systems/core/data-tables";
|
|
3
4
|
import { ComponentProps } from "react";
|
|
4
5
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
6
|
import { useInfiniteStrategy } from "@tulip-systems/core/data-tables/client";
|
|
6
|
-
import { CommandDef } from "@tulip-systems/core/commands";
|
|
7
7
|
import { VisibilityState } from "@tanstack/react-table";
|
|
8
8
|
|
|
9
9
|
//#region src/providers/local/components/view.client.d.ts
|
|
@@ -11,7 +11,7 @@ type LocalDriveViewProviderProps<TData extends LocalDriveNodeWithAsset = LocalDr
|
|
|
11
11
|
queryData: TData[];
|
|
12
12
|
columns?: TableColumnDef<TData>[];
|
|
13
13
|
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
14
|
-
commands?:
|
|
14
|
+
commands?: DriveViewCommands<TData>;
|
|
15
15
|
columnVisibility?: VisibilityState;
|
|
16
16
|
};
|
|
17
17
|
declare function LocalDriveViewProvider<TData extends LocalDriveNodeWithAsset = LocalDriveNodeWithAsset>({
|
|
@@ -4,6 +4,7 @@ import { useDriveSelectionContext } from "../../../components/selection.client.m
|
|
|
4
4
|
import { DriveGridCard, DriveGridCardSkeleton } from "../../../components/grid-card.client.mjs";
|
|
5
5
|
import { DriveGrid, DriveGridBottombar, DriveGridEmpty, DriveGridLoading } from "../../../components/grid.client.mjs";
|
|
6
6
|
import { useDriveViewContext } from "../../../components/view.client.mjs";
|
|
7
|
+
import { DriveViewConfigProvider, createDriveViewConfig, useDriveViewConfig } from "../../../lib/view-config.client.mjs";
|
|
7
8
|
import { localDriveColumns } from "../config/columns-data.mjs";
|
|
8
9
|
import { localDriveImageLoader } from "../lib/helpers.mjs";
|
|
9
10
|
import { useLocalDriveUploadZone } from "./upload-zone-context.client.mjs";
|
|
@@ -12,21 +13,20 @@ import { TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
|
|
|
12
13
|
import { useMemo } from "react";
|
|
13
14
|
import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
|
|
14
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
-
import { DataTable
|
|
16
|
+
import { DataTable } from "@tulip-systems/core/data-tables/client";
|
|
16
17
|
|
|
17
18
|
//#region src/providers/local/components/view.client.tsx
|
|
18
19
|
function LocalDriveViewProvider({ queryData, columns = localDriveColumns, strategy, commands, columnVisibility, children, ...props }) {
|
|
19
20
|
const { meta } = useLocalDriveContext();
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
config: createTableConfig({
|
|
21
|
+
return /* @__PURE__ */ jsx(DriveViewConfigProvider, {
|
|
22
|
+
config: createDriveViewConfig({
|
|
23
23
|
queryData,
|
|
24
24
|
columns,
|
|
25
25
|
strategy,
|
|
26
26
|
commands,
|
|
27
27
|
meta,
|
|
28
28
|
columnVisibility,
|
|
29
|
-
selection
|
|
29
|
+
selection: useDriveSelectionContext()?.selection
|
|
30
30
|
}),
|
|
31
31
|
children: /* @__PURE__ */ jsx(TableLayout, {
|
|
32
32
|
...props,
|
|
@@ -41,7 +41,7 @@ function LocalDriveView() {
|
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
43
|
function LocalDriveGrid(props) {
|
|
44
|
-
const { queryData, strategy, commands, selection, meta } =
|
|
44
|
+
const { queryData, strategy, commands, selection, meta } = useDriveViewConfig();
|
|
45
45
|
const { optimistic } = useLocalDriveUploadZone();
|
|
46
46
|
const { rowCount, paginationState } = strategy;
|
|
47
47
|
const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta;
|
|
@@ -52,7 +52,7 @@ function LocalDriveGrid(props) {
|
|
|
52
52
|
children: [
|
|
53
53
|
queryData.length > 0 ? queryData.filter((node) => !node.hidden).map((node) => /* @__PURE__ */ jsx(DriveGridCard, {
|
|
54
54
|
node,
|
|
55
|
-
commands,
|
|
55
|
+
commands: commands?.node,
|
|
56
56
|
imageLoader: localDriveImageLoader
|
|
57
57
|
}, node.id)) : /* @__PURE__ */ jsx(DriveGridEmpty, { title: "Geen resultaten gevonden" }),
|
|
58
58
|
isFetchingNextPage && Array.from({ length: paginationState?.pageSize ?? 0 }).map((_, index) => /* @__PURE__ */ jsx(DriveGridCardSkeleton, {}, index)),
|
|
@@ -62,9 +62,9 @@ function LocalDriveGrid(props) {
|
|
|
62
62
|
isFetching,
|
|
63
63
|
isFetchingNextPage
|
|
64
64
|
}),
|
|
65
|
-
commands && commands.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
65
|
+
commands?.selectedNodes && commands?.selectedNodes.length > 0 && /* @__PURE__ */ jsx(FloatingCommandMenu, {
|
|
66
66
|
data: selectedData,
|
|
67
|
-
commands,
|
|
67
|
+
commands: commands.selectedNodes,
|
|
68
68
|
meta,
|
|
69
69
|
state: selectedData.length > 0 ? "open" : "closed",
|
|
70
70
|
onSuccess: () => {
|
|
@@ -6,8 +6,8 @@ import { TableColumnHeader } from "@tulip-systems/core/data-tables";
|
|
|
6
6
|
import { findStatus } from "@tulip-systems/core/components";
|
|
7
7
|
import { FolderIcon } from "lucide-react";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/core/components/client";
|
|
10
9
|
import { TableTextCell, createTableSelectCell } from "@tulip-systems/core/data-tables/client";
|
|
10
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "@tulip-systems/core/components/client";
|
|
11
11
|
import Link from "next/link";
|
|
12
12
|
import { createSerializer, useQueryStates } from "nuqs";
|
|
13
13
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { nodes } from "../lib/schema.mjs";
|
|
2
|
+
import { asc, getTableColumns } from "drizzle-orm";
|
|
3
|
+
import { createTableQuerySortingParser } from "@tulip-systems/core/data-tables/server";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/local/config/sorting.ts
|
|
6
|
+
/**
|
|
7
|
+
* Local Drive specific sorting config
|
|
8
|
+
*/
|
|
9
|
+
const localDriveTableQuerySortingConfig = getTableColumns(nodes);
|
|
10
|
+
/**
|
|
11
|
+
* Local Drive specific sorting parser
|
|
12
|
+
*/
|
|
13
|
+
const parseLocalDriveTableQuerySorting = createTableQuerySortingParser(localDriveTableQuerySortingConfig, { fallback: asc(nodes.createdAt) });
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { parseLocalDriveTableQuerySorting };
|
|
@@ -13944,38 +13944,38 @@ declare function createLocalDriveProcedures(drive: LocalDrive<DriveSchema>): {
|
|
|
13944
13944
|
id: z.ZodNullable<z.ZodString>;
|
|
13945
13945
|
namespace: z.ZodString;
|
|
13946
13946
|
}, z.core.$strip>, _orpc_contract0.Schema<(Pick<{
|
|
13947
|
-
id: string;
|
|
13948
|
-
createdAt: Date;
|
|
13949
|
-
updatedAt: Date;
|
|
13950
13947
|
name: string;
|
|
13948
|
+
namespace: string;
|
|
13951
13949
|
type: "file" | "folder" | null;
|
|
13952
|
-
|
|
13950
|
+
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
13953
13951
|
size: number | null;
|
|
13954
13952
|
contentType: string | null;
|
|
13955
|
-
|
|
13956
|
-
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
13953
|
+
readonly: boolean | null;
|
|
13957
13954
|
hidden: boolean | null;
|
|
13958
13955
|
archivedAt: Date | null;
|
|
13959
13956
|
parentId: string | null;
|
|
13960
|
-
assetId: string | null;
|
|
13961
|
-
}, "id" | "name" | "parentId"> & {
|
|
13962
|
-
depth: number;
|
|
13963
|
-
})[], (Pick<{
|
|
13964
13957
|
id: string;
|
|
13965
13958
|
createdAt: Date;
|
|
13966
13959
|
updatedAt: Date;
|
|
13960
|
+
assetId: string | null;
|
|
13961
|
+
}, "name" | "parentId" | "id"> & {
|
|
13962
|
+
depth: number;
|
|
13963
|
+
})[], (Pick<{
|
|
13967
13964
|
name: string;
|
|
13965
|
+
namespace: string;
|
|
13968
13966
|
type: "file" | "folder" | null;
|
|
13969
|
-
|
|
13967
|
+
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
13970
13968
|
size: number | null;
|
|
13971
13969
|
contentType: string | null;
|
|
13972
|
-
|
|
13973
|
-
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
13970
|
+
readonly: boolean | null;
|
|
13974
13971
|
hidden: boolean | null;
|
|
13975
13972
|
archivedAt: Date | null;
|
|
13976
13973
|
parentId: string | null;
|
|
13974
|
+
id: string;
|
|
13975
|
+
createdAt: Date;
|
|
13976
|
+
updatedAt: Date;
|
|
13977
13977
|
assetId: string | null;
|
|
13978
|
-
}, "
|
|
13978
|
+
}, "name" | "parentId" | "id"> & {
|
|
13979
13979
|
depth: number;
|
|
13980
13980
|
})[]>, Record<never, never>, Record<never, never>>;
|
|
13981
13981
|
/**
|
|
@@ -19473,19 +19473,19 @@ declare function createLocalDriveProcedures(drive: LocalDrive<DriveSchema>): {
|
|
|
19473
19473
|
presignedUrl: string;
|
|
19474
19474
|
node: LocalDriveFileNode;
|
|
19475
19475
|
asset: {
|
|
19476
|
+
contentType: string | null;
|
|
19477
|
+
size: number | null;
|
|
19478
|
+
metadata: unknown;
|
|
19479
|
+
key: string;
|
|
19480
|
+
status: "error" | "pending" | "ready";
|
|
19476
19481
|
id: string;
|
|
19477
19482
|
createdAt: Date;
|
|
19478
19483
|
updatedAt: Date;
|
|
19479
19484
|
name: string | null;
|
|
19480
|
-
key: string;
|
|
19481
|
-
metadata: unknown;
|
|
19482
19485
|
provider: "s3";
|
|
19483
|
-
uploadId: string;
|
|
19484
|
-
visibility: "private" | "public";
|
|
19485
|
-
size: number | null;
|
|
19486
|
-
contentType: string | null;
|
|
19487
19486
|
bucket: string;
|
|
19488
|
-
|
|
19487
|
+
visibility: "private" | "public";
|
|
19488
|
+
uploadId: string;
|
|
19489
19489
|
etag: string | null;
|
|
19490
19490
|
uploadedAt: Date;
|
|
19491
19491
|
deletedAt: Date | null;
|
|
@@ -19495,19 +19495,19 @@ declare function createLocalDriveProcedures(drive: LocalDrive<DriveSchema>): {
|
|
|
19495
19495
|
presignedUrl: string;
|
|
19496
19496
|
node: LocalDriveFileNode;
|
|
19497
19497
|
asset: {
|
|
19498
|
+
contentType: string | null;
|
|
19499
|
+
size: number | null;
|
|
19500
|
+
metadata: unknown;
|
|
19501
|
+
key: string;
|
|
19502
|
+
status: "error" | "pending" | "ready";
|
|
19498
19503
|
id: string;
|
|
19499
19504
|
createdAt: Date;
|
|
19500
19505
|
updatedAt: Date;
|
|
19501
19506
|
name: string | null;
|
|
19502
|
-
key: string;
|
|
19503
|
-
metadata: unknown;
|
|
19504
19507
|
provider: "s3";
|
|
19505
|
-
uploadId: string;
|
|
19506
|
-
visibility: "private" | "public";
|
|
19507
|
-
size: number | null;
|
|
19508
|
-
contentType: string | null;
|
|
19509
19508
|
bucket: string;
|
|
19510
|
-
|
|
19509
|
+
visibility: "private" | "public";
|
|
19510
|
+
uploadId: string;
|
|
19511
19511
|
etag: string | null;
|
|
19512
19512
|
uploadedAt: Date;
|
|
19513
19513
|
deletedAt: Date | null;
|
|
@@ -104,21 +104,21 @@ declare class LocalDrive<TSchema extends TDatabaseSchema> implements DriveReader
|
|
|
104
104
|
id: string | null;
|
|
105
105
|
namespace: string;
|
|
106
106
|
}): Promise<(Pick<{
|
|
107
|
-
id: string;
|
|
108
|
-
createdAt: Date;
|
|
109
|
-
updatedAt: Date;
|
|
110
107
|
name: string;
|
|
108
|
+
namespace: string;
|
|
111
109
|
type: "file" | "folder" | null;
|
|
112
|
-
|
|
110
|
+
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
113
111
|
size: number | null;
|
|
114
112
|
contentType: string | null;
|
|
115
|
-
|
|
116
|
-
subtype: "image" | "document" | "spreadsheet" | "video" | "audio" | "archive" | "other";
|
|
113
|
+
readonly: boolean | null;
|
|
117
114
|
hidden: boolean | null;
|
|
118
115
|
archivedAt: Date | null;
|
|
119
116
|
parentId: string | null;
|
|
117
|
+
id: string;
|
|
118
|
+
createdAt: Date;
|
|
119
|
+
updatedAt: Date;
|
|
120
120
|
assetId: string | null;
|
|
121
|
-
}, "
|
|
121
|
+
}, "name" | "parentId" | "id"> & {
|
|
122
122
|
depth: number;
|
|
123
123
|
})[]>;
|
|
124
124
|
/**
|
|
@@ -247,19 +247,19 @@ declare class LocalDrive<TSchema extends TDatabaseSchema> implements DriveReader
|
|
|
247
247
|
presignedUrl: string;
|
|
248
248
|
node: LocalDriveFileNode;
|
|
249
249
|
asset: {
|
|
250
|
+
contentType: string | null;
|
|
251
|
+
size: number | null;
|
|
252
|
+
metadata: unknown;
|
|
253
|
+
key: string;
|
|
254
|
+
status: "error" | "pending" | "ready";
|
|
250
255
|
id: string;
|
|
251
256
|
createdAt: Date;
|
|
252
257
|
updatedAt: Date;
|
|
253
258
|
name: string | null;
|
|
254
|
-
key: string;
|
|
255
|
-
metadata: unknown;
|
|
256
259
|
provider: "s3";
|
|
257
|
-
uploadId: string;
|
|
258
|
-
visibility: "private" | "public";
|
|
259
|
-
size: number | null;
|
|
260
|
-
contentType: string | null;
|
|
261
260
|
bucket: string;
|
|
262
|
-
|
|
261
|
+
visibility: "private" | "public";
|
|
262
|
+
uploadId: string;
|
|
263
263
|
etag: string | null;
|
|
264
264
|
uploadedAt: Date;
|
|
265
265
|
deletedAt: Date | null;
|
|
@@ -2,12 +2,13 @@ import { deviceSizes } from "./constants.mjs";
|
|
|
2
2
|
import { inferLocalDriveNodeSubtype, isLocalDriveFile, isLocalDriveFolder, toLocalDriveNode } from "./helpers.mjs";
|
|
3
3
|
import { nodePresignedUrls, nodeVariants, nodes } from "./schema.mjs";
|
|
4
4
|
import { getLocalFileURLSchemaDefaults } from "./validators.mjs";
|
|
5
|
+
import { parseLocalDriveTableQuerySorting } from "../config/sorting.mjs";
|
|
5
6
|
import { storageAssets } from "@tulip-systems/core/storage";
|
|
6
|
-
import { and,
|
|
7
|
+
import { and, eq, getTableColumns, inArray, isNotNull, isNull, sql } from "drizzle-orm";
|
|
7
8
|
import { ServerError } from "@tulip-systems/core/router/server";
|
|
8
9
|
import { after } from "next/server";
|
|
9
10
|
import stream from "node:stream/consumers";
|
|
10
|
-
import {
|
|
11
|
+
import { convertSearchToQueryParams, createTableQueryResponse } from "@tulip-systems/core/data-tables/server";
|
|
11
12
|
import { addSeconds } from "date-fns";
|
|
12
13
|
|
|
13
14
|
//#region src/providers/local/lib/service.server.ts
|
|
@@ -105,11 +106,11 @@ var LocalDrive = class {
|
|
|
105
106
|
* @returns A promise resolving to the matching child nodes.
|
|
106
107
|
*/
|
|
107
108
|
async getNodesByParentId({ filters, ...query }) {
|
|
108
|
-
const orderBy =
|
|
109
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
109
110
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
110
111
|
const archivedFilter = filters.isArchived === true ? isNotNull(nodes.archivedAt) : filters.isArchived === false ? isNull(nodes.archivedAt) : void 0;
|
|
111
112
|
const parentFilter = filters.parentId ? eq(nodes.parentId, filters.parentId) : isNull(nodes.parentId);
|
|
112
|
-
return (await this.#db.select().from(nodes).where(and(filters.nodeIds != null ? inArray(nodes.id, filters.nodeIds) : void 0, filters.types != null ? inArray(nodes.type, filters.types) : void 0, archivedFilter, filters.hidden != null ? eq(nodes.hidden, filters.hidden) : void 0, parentFilter, eq(nodes.namespace, filters.namespace), search)).orderBy(orderBy)).map(toLocalDriveNode);
|
|
113
|
+
return (await this.#db.select().from(nodes).where(and(filters.nodeIds != null ? inArray(nodes.id, filters.nodeIds) : void 0, filters.types != null ? inArray(nodes.type, filters.types) : void 0, archivedFilter, filters.hidden != null ? eq(nodes.hidden, filters.hidden) : void 0, parentFilter, eq(nodes.namespace, filters.namespace), search)).orderBy(...orderBy)).map(toLocalDriveNode);
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
115
116
|
* Lists tree-scoped nodes with pagination, search, and richer local filters.
|
|
@@ -121,7 +122,7 @@ var LocalDrive = class {
|
|
|
121
122
|
* @returns A paginated table-query response.
|
|
122
123
|
*/
|
|
123
124
|
async listTree({ filters, ...query }) {
|
|
124
|
-
const orderBy =
|
|
125
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
125
126
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
126
127
|
const archivedFilter = filters.isArchived === true ? isNotNull(nodes.archivedAt) : filters.isArchived === false ? isNull(nodes.archivedAt) : void 0;
|
|
127
128
|
const parentFilter = filters.parentId ? eq(nodes.parentId, filters.parentId) : isNull(nodes.parentId);
|
|
@@ -132,7 +133,7 @@ var LocalDrive = class {
|
|
|
132
133
|
return [await tx.select({
|
|
133
134
|
...getTableColumns(nodes),
|
|
134
135
|
asset: storageAssets
|
|
135
|
-
}).from(nodes).where(where).leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id)).orderBy(orderBy).limit(limit).offset(offset), await tx.$count(nodes, where)];
|
|
136
|
+
}).from(nodes).where(where).leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id)).orderBy(...orderBy).limit(limit).offset(offset), await tx.$count(nodes, where)];
|
|
136
137
|
});
|
|
137
138
|
return createTableQueryResponse({
|
|
138
139
|
data: data.map(({ asset, ...node }) => ({
|
|
@@ -153,7 +154,7 @@ var LocalDrive = class {
|
|
|
153
154
|
* @returns A paginated table-query response.
|
|
154
155
|
*/
|
|
155
156
|
async listFlat({ filters, ...query }) {
|
|
156
|
-
const orderBy =
|
|
157
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
157
158
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
158
159
|
const archivedFilter = filters.isArchived === true ? isNotNull(nodes.archivedAt) : filters.isArchived === false ? isNull(nodes.archivedAt) : void 0;
|
|
159
160
|
const limit = query.limit;
|
|
@@ -163,7 +164,7 @@ var LocalDrive = class {
|
|
|
163
164
|
return [await tx.select({
|
|
164
165
|
...getTableColumns(nodes),
|
|
165
166
|
asset: storageAssets
|
|
166
|
-
}).from(nodes).where(where).leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id)).orderBy(orderBy).limit(limit).offset(offset), await tx.$count(nodes, where)];
|
|
167
|
+
}).from(nodes).where(where).leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id)).orderBy(...orderBy).limit(limit).offset(offset), await tx.$count(nodes, where)];
|
|
167
168
|
});
|
|
168
169
|
return createTableQueryResponse({
|
|
169
170
|
data: data.map(({ asset, ...node }) => ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tulip-systems/drive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"uuid": "^14.0.0",
|
|
66
66
|
"vaul": "^1.1.2",
|
|
67
67
|
"zod": "^4.4.3",
|
|
68
|
-
"@tulip-systems/core": "0.
|
|
68
|
+
"@tulip-systems/core": "0.10.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"@tailwindcss/typography": "^0.5.19",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useDraggable, useDroppable } from "@dnd-kit/react";
|
|
4
|
-
import type {
|
|
4
|
+
import type { CommandFor } from "@tulip-systems/core/commands";
|
|
5
5
|
import {
|
|
6
6
|
ContextCommandMenu,
|
|
7
7
|
ContextCommandMenuContent,
|
|
@@ -29,7 +29,7 @@ import { useDriveSelectionContext } from "./selection.client";
|
|
|
29
29
|
*/
|
|
30
30
|
type DriveGridCardProps<TData extends DriveNode> = ComponentProps<"div"> & {
|
|
31
31
|
node: TData;
|
|
32
|
-
commands?:
|
|
32
|
+
commands?: CommandFor<TData>[];
|
|
33
33
|
imageLoader?: (props: ImageLoaderProps) => string;
|
|
34
34
|
unoptimized?: boolean;
|
|
35
35
|
};
|
package/src/entry.client.ts
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { VisibilityState } from "@tanstack/react-table";
|
|
4
|
+
import type { CommandFor } from "@tulip-systems/core/commands";
|
|
5
|
+
import type {
|
|
6
|
+
Selection,
|
|
7
|
+
TableColumnDef,
|
|
8
|
+
TableFiltersResult,
|
|
9
|
+
TableMetaInput,
|
|
10
|
+
} from "@tulip-systems/core/data-tables";
|
|
11
|
+
import {
|
|
12
|
+
createTableConfig,
|
|
13
|
+
type TableConfigContextValue,
|
|
14
|
+
TableConfigProvider,
|
|
15
|
+
type useInfiniteStrategy,
|
|
16
|
+
useTableConfigContext,
|
|
17
|
+
} from "@tulip-systems/core/data-tables/client";
|
|
18
|
+
import { createContext, type PropsWithChildren, use } from "react";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* DriveViewConfig context
|
|
22
|
+
*/
|
|
23
|
+
export type DriveViewCommands<TData, TMeta = object> = {
|
|
24
|
+
node?: CommandFor<TData, TMeta>[];
|
|
25
|
+
selectedNodes?: CommandFor<TData[], TMeta>[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type DriveViewConfigContextValue<TData, TMeta = object> = {
|
|
29
|
+
commands?: DriveViewCommands<TData, TMeta>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DriveViewConfigContext = createContext({} as DriveViewConfigContextValue<any, any>);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Drive View configuration
|
|
36
|
+
*/
|
|
37
|
+
export type DriveViewConfig<
|
|
38
|
+
TData,
|
|
39
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
40
|
+
> = DriveViewConfigContextValue<TData, TMeta> &
|
|
41
|
+
Omit<TableConfigContextValue<TData, TableFiltersResult, TMeta>, "commands">;
|
|
42
|
+
|
|
43
|
+
export type CreateDriveViewConfigInput<
|
|
44
|
+
TData,
|
|
45
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
46
|
+
> = {
|
|
47
|
+
queryData: TData[];
|
|
48
|
+
columns: TableColumnDef<TData>[];
|
|
49
|
+
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
50
|
+
commands?: DriveViewCommands<TData, TMeta>;
|
|
51
|
+
meta?: TMeta;
|
|
52
|
+
columnVisibility?: VisibilityState;
|
|
53
|
+
selection?: Selection;
|
|
54
|
+
getRowId?: (row: TData) => string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export function createDriveViewConfig<
|
|
58
|
+
TData,
|
|
59
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
60
|
+
>({
|
|
61
|
+
queryData,
|
|
62
|
+
columns,
|
|
63
|
+
strategy,
|
|
64
|
+
commands,
|
|
65
|
+
meta,
|
|
66
|
+
columnVisibility,
|
|
67
|
+
selection,
|
|
68
|
+
getRowId = (row) => (row as { id: string }).id,
|
|
69
|
+
}: CreateDriveViewConfigInput<TData, TMeta>) {
|
|
70
|
+
const { commands: _commands, ...table } = createTableConfig<TData, TableFiltersResult, TMeta>({
|
|
71
|
+
queryData,
|
|
72
|
+
columns,
|
|
73
|
+
getRowId,
|
|
74
|
+
strategy,
|
|
75
|
+
meta,
|
|
76
|
+
columnVisibility,
|
|
77
|
+
selection,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return { ...table, commands } as DriveViewConfig<TData, TMeta>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* DriveViewConfigProvider component
|
|
85
|
+
* Wraps the children components with the DriveViewConfigContext provider
|
|
86
|
+
* and provides the configuration for the drive view
|
|
87
|
+
*/
|
|
88
|
+
type DriveViewConfigProviderProps<
|
|
89
|
+
TData,
|
|
90
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
91
|
+
> = PropsWithChildren<{
|
|
92
|
+
config: ReturnType<typeof createDriveViewConfig<TData, TMeta>>;
|
|
93
|
+
}>;
|
|
94
|
+
|
|
95
|
+
export function DriveViewConfigProvider<
|
|
96
|
+
TData,
|
|
97
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
98
|
+
>({ config, children }: DriveViewConfigProviderProps<TData, TMeta>) {
|
|
99
|
+
return (
|
|
100
|
+
<DriveViewConfigContext value={config}>
|
|
101
|
+
<TableConfigProvider config={{ ...config, commands: config.commands?.selectedNodes }}>
|
|
102
|
+
{children}
|
|
103
|
+
</TableConfigProvider>
|
|
104
|
+
</DriveViewConfigContext>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function useDriveViewConfig<
|
|
109
|
+
TData,
|
|
110
|
+
TMeta extends TableMetaInput<TData> = TableMetaInput<TData>,
|
|
111
|
+
>() {
|
|
112
|
+
const tableConfig = useTableConfigContext<TData, TableFiltersResult, TMeta>();
|
|
113
|
+
const viewConfig = use(DriveViewConfigContext) as DriveViewConfigContextValue<TData, TMeta>;
|
|
114
|
+
|
|
115
|
+
return { ...tableConfig, ...viewConfig } as DriveViewConfig<TData, TMeta>;
|
|
116
|
+
}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { VisibilityState } from "@tanstack/react-table";
|
|
4
|
-
import type { CommandDef } from "@tulip-systems/core/commands";
|
|
5
4
|
import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
|
|
6
5
|
import { type TableColumnDef, TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
|
|
7
6
|
import {
|
|
8
|
-
createTableConfig,
|
|
9
7
|
DataTable,
|
|
10
8
|
type InfiniteStrategyMeta,
|
|
11
|
-
TableConfigProvider,
|
|
12
9
|
type useInfiniteStrategy,
|
|
13
|
-
useTableConfigContext,
|
|
14
10
|
} from "@tulip-systems/core/data-tables/client";
|
|
15
11
|
import { type ComponentProps, useMemo } from "react";
|
|
16
12
|
import {
|
|
@@ -22,6 +18,12 @@ import {
|
|
|
22
18
|
import { DriveGridCard, DriveGridCardSkeleton } from "@/components/grid-card.client";
|
|
23
19
|
import { useDriveSelectionContext } from "@/components/selection.client";
|
|
24
20
|
import { useDriveViewContext } from "@/components/view.client";
|
|
21
|
+
import {
|
|
22
|
+
createDriveViewConfig,
|
|
23
|
+
type DriveViewCommands,
|
|
24
|
+
DriveViewConfigProvider,
|
|
25
|
+
useDriveViewConfig,
|
|
26
|
+
} from "@/lib/view-config.client";
|
|
25
27
|
import { googleDriveColumns } from "../config/columns-data";
|
|
26
28
|
import type { GoogleDriveNode } from "../lib/validators";
|
|
27
29
|
import { useGoogleDriveContext } from "./provider.client";
|
|
@@ -34,7 +36,7 @@ type GoogleDriveViewProviderProps<TData extends GoogleDriveNode = GoogleDriveNod
|
|
|
34
36
|
queryData: TData[];
|
|
35
37
|
columns?: TableColumnDef<TData>[];
|
|
36
38
|
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
37
|
-
commands?:
|
|
39
|
+
commands?: DriveViewCommands<TData>;
|
|
38
40
|
columnVisibility?: VisibilityState;
|
|
39
41
|
};
|
|
40
42
|
|
|
@@ -48,25 +50,21 @@ export function GoogleDriveViewProvider<TData extends GoogleDriveNode = GoogleDr
|
|
|
48
50
|
...props
|
|
49
51
|
}: GoogleDriveViewProviderProps<TData>) {
|
|
50
52
|
const { meta } = useGoogleDriveContext();
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Table
|
|
55
|
-
*/
|
|
56
|
-
const config = createTableConfig<TData>({
|
|
53
|
+
const selectionContext = useDriveSelectionContext();
|
|
54
|
+
const config = createDriveViewConfig<TData>({
|
|
57
55
|
queryData,
|
|
58
56
|
columns,
|
|
59
57
|
strategy,
|
|
60
58
|
commands,
|
|
61
59
|
meta,
|
|
62
60
|
columnVisibility,
|
|
63
|
-
selection,
|
|
61
|
+
selection: selectionContext?.selection,
|
|
64
62
|
});
|
|
65
63
|
|
|
66
64
|
return (
|
|
67
|
-
<
|
|
65
|
+
<DriveViewConfigProvider config={config}>
|
|
68
66
|
<TableLayout {...props}>{children}</TableLayout>
|
|
69
|
-
</
|
|
67
|
+
</DriveViewConfigProvider>
|
|
70
68
|
);
|
|
71
69
|
}
|
|
72
70
|
|
|
@@ -91,8 +89,7 @@ export function GoogleDriveView() {
|
|
|
91
89
|
* GoogleDriveGrid
|
|
92
90
|
*/
|
|
93
91
|
function GoogleDriveGrid(props: ComponentProps<"div">) {
|
|
94
|
-
const { queryData, strategy, commands, selection, meta } =
|
|
95
|
-
useTableConfigContext<GoogleDriveNode>();
|
|
92
|
+
const { queryData, strategy, commands, selection, meta } = useDriveViewConfig<GoogleDriveNode>();
|
|
96
93
|
const { rowCount, paginationState } = strategy;
|
|
97
94
|
const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta as InfiniteStrategyMeta;
|
|
98
95
|
|
|
@@ -107,7 +104,7 @@ function GoogleDriveGrid(props: ComponentProps<"div">) {
|
|
|
107
104
|
<DriveGrid {...props}>
|
|
108
105
|
{queryData.length > 0 ? (
|
|
109
106
|
queryData.map((node) => (
|
|
110
|
-
<DriveGridCard key={node.id} node={node} commands={commands} unoptimized />
|
|
107
|
+
<DriveGridCard key={node.id} node={node} commands={commands?.node} unoptimized />
|
|
111
108
|
))
|
|
112
109
|
) : (
|
|
113
110
|
<DriveGridEmpty title="Geen resultaten gevonden" />
|
|
@@ -125,10 +122,10 @@ function GoogleDriveGrid(props: ComponentProps<"div">) {
|
|
|
125
122
|
isFetchingNextPage={isFetchingNextPage}
|
|
126
123
|
/>
|
|
127
124
|
|
|
128
|
-
{commands && commands.length > 0 && (
|
|
125
|
+
{commands?.selectedNodes && commands.selectedNodes.length > 0 && (
|
|
129
126
|
<FloatingCommandMenu
|
|
130
|
-
data={selectedData
|
|
131
|
-
commands={commands
|
|
127
|
+
data={selectedData}
|
|
128
|
+
commands={commands.selectedNodes}
|
|
132
129
|
meta={meta}
|
|
133
130
|
state={selectedData.length > 0 ? "open" : "closed"}
|
|
134
131
|
onSuccess={() => selection?.setRowSelection?.({})}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { VisibilityState } from "@tanstack/react-table";
|
|
4
|
-
import type { CommandDef } from "@tulip-systems/core/commands";
|
|
5
4
|
import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
|
|
6
5
|
import { type TableColumnDef, TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
|
|
7
6
|
import {
|
|
8
|
-
createTableConfig,
|
|
9
7
|
DataTable,
|
|
10
8
|
type InfiniteStrategyMeta,
|
|
11
|
-
TableConfigProvider,
|
|
12
9
|
type useInfiniteStrategy,
|
|
13
|
-
useTableConfigContext,
|
|
14
10
|
} from "@tulip-systems/core/data-tables/client";
|
|
15
11
|
import { type ComponentProps, useMemo } from "react";
|
|
16
12
|
import {
|
|
@@ -22,6 +18,12 @@ import {
|
|
|
22
18
|
import { DriveGridCard, DriveGridCardSkeleton } from "@/components/grid-card.client";
|
|
23
19
|
import { useDriveSelectionContext } from "@/components/selection.client";
|
|
24
20
|
import { useDriveViewContext } from "@/components/view.client";
|
|
21
|
+
import {
|
|
22
|
+
createDriveViewConfig,
|
|
23
|
+
type DriveViewCommands,
|
|
24
|
+
DriveViewConfigProvider,
|
|
25
|
+
useDriveViewConfig,
|
|
26
|
+
} from "@/lib/view-config.client";
|
|
25
27
|
import { localDriveColumns } from "../config/columns-data";
|
|
26
28
|
import { localDriveImageLoader } from "../lib/helpers";
|
|
27
29
|
import type { LocalDriveNodeWithAsset } from "../lib/validators";
|
|
@@ -33,7 +35,7 @@ type LocalDriveViewProviderProps<TData extends LocalDriveNodeWithAsset = LocalDr
|
|
|
33
35
|
queryData: TData[];
|
|
34
36
|
columns?: TableColumnDef<TData>[];
|
|
35
37
|
strategy: ReturnType<typeof useInfiniteStrategy>;
|
|
36
|
-
commands?:
|
|
38
|
+
commands?: DriveViewCommands<TData>;
|
|
37
39
|
columnVisibility?: VisibilityState;
|
|
38
40
|
};
|
|
39
41
|
|
|
@@ -49,22 +51,21 @@ export function LocalDriveViewProvider<
|
|
|
49
51
|
...props
|
|
50
52
|
}: LocalDriveViewProviderProps<TData>) {
|
|
51
53
|
const { meta } = useLocalDriveContext();
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
const config = createTableConfig<TData>({
|
|
54
|
+
const selectionContext = useDriveSelectionContext();
|
|
55
|
+
const config = createDriveViewConfig<TData>({
|
|
55
56
|
queryData,
|
|
56
57
|
columns,
|
|
57
58
|
strategy,
|
|
58
59
|
commands,
|
|
59
60
|
meta,
|
|
60
61
|
columnVisibility,
|
|
61
|
-
selection,
|
|
62
|
+
selection: selectionContext?.selection,
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
return (
|
|
65
|
-
<
|
|
66
|
+
<DriveViewConfigProvider config={config}>
|
|
66
67
|
<TableLayout {...props}>{children}</TableLayout>
|
|
67
|
-
</
|
|
68
|
+
</DriveViewConfigProvider>
|
|
68
69
|
);
|
|
69
70
|
}
|
|
70
71
|
|
|
@@ -79,7 +80,7 @@ export function LocalDriveView() {
|
|
|
79
80
|
|
|
80
81
|
function LocalDriveGrid(props: ComponentProps<"div">) {
|
|
81
82
|
const { queryData, strategy, commands, selection, meta } =
|
|
82
|
-
|
|
83
|
+
useDriveViewConfig<LocalDriveNodeWithAsset>();
|
|
83
84
|
const { optimistic } = useLocalDriveUploadZone();
|
|
84
85
|
|
|
85
86
|
const { rowCount, paginationState } = strategy;
|
|
@@ -101,7 +102,7 @@ function LocalDriveGrid(props: ComponentProps<"div">) {
|
|
|
101
102
|
<DriveGridCard
|
|
102
103
|
key={node.id}
|
|
103
104
|
node={node}
|
|
104
|
-
commands={commands}
|
|
105
|
+
commands={commands?.node}
|
|
105
106
|
imageLoader={localDriveImageLoader}
|
|
106
107
|
/>
|
|
107
108
|
))
|
|
@@ -121,10 +122,10 @@ function LocalDriveGrid(props: ComponentProps<"div">) {
|
|
|
121
122
|
isFetchingNextPage={isFetchingNextPage}
|
|
122
123
|
/>
|
|
123
124
|
|
|
124
|
-
{commands && commands.length > 0 && (
|
|
125
|
+
{commands?.selectedNodes && commands?.selectedNodes.length > 0 && (
|
|
125
126
|
<FloatingCommandMenu
|
|
126
|
-
data={selectedData
|
|
127
|
-
commands={commands
|
|
127
|
+
data={selectedData}
|
|
128
|
+
commands={commands.selectedNodes}
|
|
128
129
|
meta={meta}
|
|
129
130
|
state={selectedData.length > 0 ? "open" : "closed"}
|
|
130
131
|
onSuccess={() => {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createTableQuerySortingParser } from "@tulip-systems/core/data-tables/server";
|
|
2
|
+
import { asc, getTableColumns } from "drizzle-orm";
|
|
3
|
+
import { nodes } from "../lib/schema";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Local Drive specific sorting config
|
|
7
|
+
*/
|
|
8
|
+
const localDriveTableQuerySortingConfig = getTableColumns(nodes);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Local Drive specific sorting parser
|
|
12
|
+
*/
|
|
13
|
+
export const parseLocalDriveTableQuerySorting = createTableQuerySortingParser(
|
|
14
|
+
localDriveTableQuerySortingConfig,
|
|
15
|
+
{ fallback: asc(nodes.createdAt) },
|
|
16
|
+
);
|
|
@@ -2,7 +2,6 @@ import stream from "node:stream/consumers";
|
|
|
2
2
|
import type { TDatabaseSchema } from "@tulip-systems/core/config";
|
|
3
3
|
import type { TableQueryResponse } from "@tulip-systems/core/data-tables/server";
|
|
4
4
|
import {
|
|
5
|
-
convertOrderByToQueryParams,
|
|
6
5
|
convertSearchToQueryParams,
|
|
7
6
|
createTableQueryResponse,
|
|
8
7
|
} from "@tulip-systems/core/data-tables/server";
|
|
@@ -11,18 +10,7 @@ import { ServerError } from "@tulip-systems/core/router/server";
|
|
|
11
10
|
import { type ObjectBodyInput, storageAssets } from "@tulip-systems/core/storage";
|
|
12
11
|
import type { Storage } from "@tulip-systems/core/storage/server";
|
|
13
12
|
import { addSeconds } from "date-fns";
|
|
14
|
-
import {
|
|
15
|
-
and,
|
|
16
|
-
asc,
|
|
17
|
-
desc,
|
|
18
|
-
eq,
|
|
19
|
-
getTableColumns,
|
|
20
|
-
inArray,
|
|
21
|
-
isNotNull,
|
|
22
|
-
isNull,
|
|
23
|
-
type SQL,
|
|
24
|
-
sql,
|
|
25
|
-
} from "drizzle-orm";
|
|
13
|
+
import { and, eq, getTableColumns, inArray, isNotNull, isNull, sql } from "drizzle-orm";
|
|
26
14
|
import { after } from "next/server";
|
|
27
15
|
import type { QueryResult } from "pg";
|
|
28
16
|
import type {
|
|
@@ -34,6 +22,7 @@ import type {
|
|
|
34
22
|
DriveReader,
|
|
35
23
|
DriveReadonly,
|
|
36
24
|
} from "../../../lib/contracts";
|
|
25
|
+
import { parseLocalDriveTableQuerySorting } from "../config/sorting";
|
|
37
26
|
import { deviceSizes } from "./constants";
|
|
38
27
|
import {
|
|
39
28
|
inferLocalDriveNodeSubtype,
|
|
@@ -221,7 +210,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
221
210
|
filters,
|
|
222
211
|
...query
|
|
223
212
|
}: GetLocalDriveNodesByParentIdInput): Promise<LocalDriveNode[]> {
|
|
224
|
-
const orderBy =
|
|
213
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
225
214
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
226
215
|
const archivedFilter =
|
|
227
216
|
filters.isArchived === true
|
|
@@ -247,7 +236,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
247
236
|
search,
|
|
248
237
|
),
|
|
249
238
|
)
|
|
250
|
-
.orderBy(orderBy
|
|
239
|
+
.orderBy(...orderBy);
|
|
251
240
|
|
|
252
241
|
return items.map(toLocalDriveNode);
|
|
253
242
|
}
|
|
@@ -265,7 +254,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
265
254
|
filters,
|
|
266
255
|
...query
|
|
267
256
|
}: ListLocalDriveTreeSchema): Promise<TableQueryResponse<LocalDriveNodeWithAsset>> {
|
|
268
|
-
const orderBy =
|
|
257
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
269
258
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
270
259
|
|
|
271
260
|
const archivedFilter =
|
|
@@ -303,7 +292,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
303
292
|
.from(nodes)
|
|
304
293
|
.where(where)
|
|
305
294
|
.leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id))
|
|
306
|
-
.orderBy(orderBy
|
|
295
|
+
.orderBy(...orderBy)
|
|
307
296
|
.limit(limit)
|
|
308
297
|
.offset(offset);
|
|
309
298
|
|
|
@@ -331,7 +320,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
331
320
|
filters,
|
|
332
321
|
...query
|
|
333
322
|
}: ListLocalDriveFlatSchema): Promise<TableQueryResponse<LocalDriveNodeWithAsset>> {
|
|
334
|
-
const orderBy =
|
|
323
|
+
const orderBy = parseLocalDriveTableQuerySorting.parse(query);
|
|
335
324
|
const search = convertSearchToQueryParams(query, [nodes.name]);
|
|
336
325
|
const archivedFilter =
|
|
337
326
|
filters.isArchived === true
|
|
@@ -363,7 +352,7 @@ export class LocalDrive<TSchema extends TDatabaseSchema>
|
|
|
363
352
|
.from(nodes)
|
|
364
353
|
.where(where)
|
|
365
354
|
.leftJoin(storageAssets, eq(nodes.assetId, storageAssets.id))
|
|
366
|
-
.orderBy(orderBy
|
|
355
|
+
.orderBy(...orderBy)
|
|
367
356
|
.limit(limit)
|
|
368
357
|
.offset(offset);
|
|
369
358
|
|