@izumisy-tailor/tailor-data-viewer 0.1.6 → 0.1.7
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/package.json
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
defineModule,
|
|
3
|
+
defineResource,
|
|
4
|
+
useNavigate,
|
|
5
|
+
useSearchParams,
|
|
6
|
+
Link,
|
|
7
|
+
} from "@tailor-platform/app-shell";
|
|
8
|
+
import {
|
|
9
|
+
Database,
|
|
10
|
+
Trash2,
|
|
11
|
+
Calendar,
|
|
12
|
+
Filter,
|
|
13
|
+
Columns,
|
|
14
|
+
LayoutGrid,
|
|
15
|
+
} from "lucide-react";
|
|
3
16
|
import type { DataViewModuleConfig } from "./types";
|
|
4
17
|
import { isStoreFactory } from "./types";
|
|
5
18
|
import { DataViewer } from "../component/data-viewer";
|
|
6
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
SavedViewProvider,
|
|
21
|
+
useSavedViews,
|
|
22
|
+
} from "../component/saved-view-context";
|
|
23
|
+
import { Card, CardContent, CardHeader, CardTitle } from "../component/ui/card";
|
|
24
|
+
import { Button } from "../component/ui/button";
|
|
25
|
+
import { Badge } from "../component/ui/badge";
|
|
7
26
|
|
|
8
27
|
/**
|
|
9
28
|
* Create a DataView module for use with AppShell
|
|
@@ -42,22 +61,130 @@ export function createDataViewModule(config: DataViewModuleConfig) {
|
|
|
42
61
|
|
|
43
62
|
// Create the explorer resource page component
|
|
44
63
|
const ExplorerPage = () => {
|
|
64
|
+
const [searchParams] = useSearchParams();
|
|
65
|
+
const viewId = searchParams.get("viewId") ?? undefined;
|
|
66
|
+
|
|
45
67
|
return (
|
|
46
68
|
<SavedViewProvider store={store}>
|
|
47
|
-
<DataViewer
|
|
69
|
+
<DataViewer
|
|
70
|
+
tableMetadata={tableMetadata}
|
|
71
|
+
appUri={appUri}
|
|
72
|
+
initialViewId={viewId}
|
|
73
|
+
/>
|
|
48
74
|
</SavedViewProvider>
|
|
49
75
|
);
|
|
50
76
|
};
|
|
51
77
|
|
|
78
|
+
// Saved views list component (used inside ModulePage)
|
|
79
|
+
const SavedViewsList = ({
|
|
80
|
+
explorerFullPath,
|
|
81
|
+
}: {
|
|
82
|
+
explorerFullPath: string;
|
|
83
|
+
}) => {
|
|
84
|
+
const { views, deleteView } = useSavedViews();
|
|
85
|
+
const navigate = useNavigate();
|
|
86
|
+
|
|
87
|
+
const handleOpenView = (viewId: string) => {
|
|
88
|
+
navigate(`${explorerFullPath}?viewId=${viewId}`);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<Card>
|
|
93
|
+
<CardHeader>
|
|
94
|
+
<CardTitle className="flex items-center gap-2">
|
|
95
|
+
<LayoutGrid className="size-5" />
|
|
96
|
+
保存済みビュー
|
|
97
|
+
</CardTitle>
|
|
98
|
+
</CardHeader>
|
|
99
|
+
<CardContent>
|
|
100
|
+
{views.length === 0 ? (
|
|
101
|
+
<div className="py-8 text-center">
|
|
102
|
+
<div className="text-muted-foreground mb-4">
|
|
103
|
+
保存されたビューはありません
|
|
104
|
+
</div>
|
|
105
|
+
<Link to={explorerFullPath}>
|
|
106
|
+
<Button variant="outline">
|
|
107
|
+
<Database className="mr-2 size-4" />
|
|
108
|
+
Data View Explorer を開く
|
|
109
|
+
</Button>
|
|
110
|
+
</Link>
|
|
111
|
+
</div>
|
|
112
|
+
) : (
|
|
113
|
+
<div className="space-y-3">
|
|
114
|
+
{views.map((savedView) => (
|
|
115
|
+
<div
|
|
116
|
+
key={savedView.id}
|
|
117
|
+
className="hover:bg-muted flex cursor-pointer items-center justify-between rounded-lg border p-4 transition-colors"
|
|
118
|
+
onClick={() => handleOpenView(savedView.id)}
|
|
119
|
+
>
|
|
120
|
+
<div className="flex-1">
|
|
121
|
+
<div className="flex items-center gap-2">
|
|
122
|
+
<span className="font-medium">{savedView.name}</span>
|
|
123
|
+
<Badge variant="secondary">{savedView.tableName}</Badge>
|
|
124
|
+
</div>
|
|
125
|
+
<div className="text-muted-foreground mt-1 flex items-center gap-4 text-sm">
|
|
126
|
+
<span className="flex items-center gap-1">
|
|
127
|
+
<Filter className="size-3" />
|
|
128
|
+
{savedView.filters.length} フィルター
|
|
129
|
+
</span>
|
|
130
|
+
<span className="flex items-center gap-1">
|
|
131
|
+
<Columns className="size-3" />
|
|
132
|
+
{savedView.selectedFields.length} カラム
|
|
133
|
+
</span>
|
|
134
|
+
<span className="flex items-center gap-1">
|
|
135
|
+
<Calendar className="size-3" />
|
|
136
|
+
{savedView.createdAt.toLocaleString()}
|
|
137
|
+
</span>
|
|
138
|
+
</div>
|
|
139
|
+
{savedView.filters.length > 0 && (
|
|
140
|
+
<div className="mt-2 flex flex-wrap gap-1">
|
|
141
|
+
{savedView.filters.map((filter) => (
|
|
142
|
+
<Badge
|
|
143
|
+
key={filter.field}
|
|
144
|
+
variant="outline"
|
|
145
|
+
className="text-xs"
|
|
146
|
+
>
|
|
147
|
+
{filter.field}=
|
|
148
|
+
{typeof filter.value === "boolean"
|
|
149
|
+
? filter.value
|
|
150
|
+
? "true"
|
|
151
|
+
: "false"
|
|
152
|
+
: filter.value}
|
|
153
|
+
</Badge>
|
|
154
|
+
))}
|
|
155
|
+
</div>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
<Button
|
|
159
|
+
variant="ghost"
|
|
160
|
+
size="sm"
|
|
161
|
+
className="text-destructive hover:text-destructive"
|
|
162
|
+
onClick={(e) => {
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
deleteView(savedView.id);
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
<Trash2 className="size-4" />
|
|
168
|
+
</Button>
|
|
169
|
+
</div>
|
|
170
|
+
))}
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
173
|
+
</CardContent>
|
|
174
|
+
</Card>
|
|
175
|
+
);
|
|
176
|
+
};
|
|
177
|
+
|
|
52
178
|
// Create the module page component
|
|
179
|
+
const explorerFullPath = `/${basePath}/${explorerPath}`;
|
|
180
|
+
|
|
53
181
|
const ModulePage = () => {
|
|
54
182
|
return (
|
|
55
|
-
<
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
</div>
|
|
183
|
+
<SavedViewProvider store={store}>
|
|
184
|
+
<div className="space-y-6">
|
|
185
|
+
<SavedViewsList explorerFullPath={explorerFullPath} />
|
|
186
|
+
</div>
|
|
187
|
+
</SavedViewProvider>
|
|
61
188
|
);
|
|
62
189
|
};
|
|
63
190
|
|