realtimex-crm 0.5.0 → 0.5.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/assets/{DealList-B7Q5fWfD.js → DealList-C_0DbLKA.js} +2 -2
- package/dist/assets/{DealList-B7Q5fWfD.js.map → DealList-C_0DbLKA.js.map} +1 -1
- package/dist/assets/{index-7x4zGeo4.js → index-CdC59W53.js} +45 -48
- package/dist/assets/{index-7x4zGeo4.js.map → index-CdC59W53.js.map} +1 -1
- package/dist/index.html +1 -1
- package/dist/stats.html +1 -1
- package/package.json +1 -3
- package/src/components/atomic-crm/login/StartPage.tsx +5 -37
- package/src/components/atomic-crm/root/DatabaseHealthCheck.tsx +4 -2
- package/src/components/atomic-crm/setup/DatabaseSetupGuide.tsx +51 -98
- package/src/lib/database-health-check.ts +18 -27
- package/dist/setup.sql +0 -976
- package/public/setup.sql +0 -976
- package/supabase/migrations/README.md +0 -98
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "realtimex-crm",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "RealTimeX CRM - A full-featured CRM built with React, shadcn-admin-kit, and Supabase. Fork of Atomic CRM with RealTimeX App SDK integration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -65,8 +65,6 @@
|
|
|
65
65
|
"prettier": "prettier --config ./.prettierrc.json --check \"**/*.{js,json,ts,tsx,css,md,html}\"",
|
|
66
66
|
"registry:build": "npx shadcn build",
|
|
67
67
|
"registry:gen": "node ./scripts/generate-registry.mjs",
|
|
68
|
-
"setup:gen": "cat supabase/migrations/*.sql > public/setup.sql && echo 'Generated public/setup.sql from migrations'",
|
|
69
|
-
"db:migrate": "node ./scripts/auto-migrate.mjs",
|
|
70
68
|
"ghpages:deploy": "node ./scripts/ghpages-deploy.mjs",
|
|
71
69
|
"supabase:remote:init": "node ./scripts/supabase-remote-init.mjs",
|
|
72
70
|
"prepare": "husky"
|
|
@@ -2,58 +2,26 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
2
2
|
import { useDataProvider } from "ra-core";
|
|
3
3
|
import { Navigate } from "react-router-dom";
|
|
4
4
|
import { LoginPage } from "@/components/admin/login-page";
|
|
5
|
-
import { checkDatabaseHealth } from "@/lib/database-health-check";
|
|
6
|
-
import { getSupabaseConfig } from "@/lib/supabase-config";
|
|
7
|
-
import { DatabaseSetupGuide } from "../setup/DatabaseSetupGuide";
|
|
8
5
|
|
|
9
6
|
import type { CrmDataProvider } from "../providers/types";
|
|
10
7
|
import { LoginSkeleton } from "./LoginSkeleton";
|
|
11
8
|
|
|
12
9
|
export const StartPage = () => {
|
|
13
10
|
const dataProvider = useDataProvider<CrmDataProvider>();
|
|
14
|
-
|
|
15
|
-
// First check database health
|
|
16
|
-
const {
|
|
17
|
-
data: healthStatus,
|
|
18
|
-
error: healthError,
|
|
19
|
-
isPending: isCheckingHealth,
|
|
20
|
-
} = useQuery({
|
|
21
|
-
queryKey: ["database-health"],
|
|
22
|
-
queryFn: checkDatabaseHealth,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// Then check if initialized (only if database is healthy)
|
|
26
11
|
const {
|
|
27
12
|
data: isInitialized,
|
|
28
|
-
error
|
|
29
|
-
isPending
|
|
13
|
+
error,
|
|
14
|
+
isPending,
|
|
30
15
|
} = useQuery({
|
|
31
16
|
queryKey: ["init"],
|
|
32
17
|
queryFn: async () => {
|
|
33
18
|
return dataProvider.isInitialized();
|
|
34
19
|
},
|
|
35
|
-
enabled: healthStatus?.isHealthy === true,
|
|
36
20
|
});
|
|
37
21
|
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
// Show database setup guide if schema is missing
|
|
42
|
-
if (healthStatus && !healthStatus.isHealthy) {
|
|
43
|
-
const config = getSupabaseConfig();
|
|
44
|
-
if (config) {
|
|
45
|
-
return (
|
|
46
|
-
<DatabaseSetupGuide
|
|
47
|
-
missingTables={healthStatus.missingTables}
|
|
48
|
-
supabaseUrl={config.url}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Show login page if there's an error or already initialized
|
|
55
|
-
if (healthError || initError || isInitialized) return <LoginPage />;
|
|
22
|
+
if (isPending) return <LoginSkeleton />;
|
|
23
|
+
if (error) return <LoginPage />;
|
|
24
|
+
if (isInitialized) return <LoginPage />;
|
|
56
25
|
|
|
57
|
-
// Not initialized yet, go to signup
|
|
58
26
|
return <Navigate to="/sign-up" />;
|
|
59
27
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
|
+
import { useDataProvider } from "ra-core";
|
|
2
3
|
import { checkDatabaseHealth, DatabaseHealthStatus } from "@/lib/database-health-check";
|
|
3
4
|
import { getSupabaseConfig } from "@/lib/supabase-config";
|
|
4
5
|
import { DatabaseSetupGuide } from "../setup/DatabaseSetupGuide";
|
|
@@ -8,6 +9,7 @@ interface DatabaseHealthCheckProps {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
export function DatabaseHealthCheck({ children }: DatabaseHealthCheckProps) {
|
|
12
|
+
const dataProvider = useDataProvider();
|
|
11
13
|
const [healthStatus, setHealthStatus] = useState<DatabaseHealthStatus | null>(null);
|
|
12
14
|
const [isChecking, setIsChecking] = useState(true);
|
|
13
15
|
|
|
@@ -16,7 +18,7 @@ export function DatabaseHealthCheck({ children }: DatabaseHealthCheckProps) {
|
|
|
16
18
|
|
|
17
19
|
async function checkHealth() {
|
|
18
20
|
try {
|
|
19
|
-
const status = await checkDatabaseHealth();
|
|
21
|
+
const status = await checkDatabaseHealth(dataProvider);
|
|
20
22
|
if (!cancelled) {
|
|
21
23
|
setHealthStatus(status);
|
|
22
24
|
setIsChecking(false);
|
|
@@ -34,7 +36,7 @@ export function DatabaseHealthCheck({ children }: DatabaseHealthCheckProps) {
|
|
|
34
36
|
return () => {
|
|
35
37
|
cancelled = true;
|
|
36
38
|
};
|
|
37
|
-
}, []);
|
|
39
|
+
}, [dataProvider]);
|
|
38
40
|
|
|
39
41
|
// Show loading state
|
|
40
42
|
if (isChecking) {
|
|
@@ -61,50 +61,56 @@ export function DatabaseSetupGuide({
|
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
63
63
|
|
|
64
|
-
{/* Option 1:
|
|
64
|
+
{/* Option 1: Supabase CLI */}
|
|
65
65
|
<div className="space-y-3">
|
|
66
66
|
<div className="flex items-center gap-2">
|
|
67
67
|
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-primary-foreground text-sm font-bold">
|
|
68
68
|
1
|
|
69
69
|
</div>
|
|
70
|
-
<h3 className="font-semibold">
|
|
70
|
+
<h3 className="font-semibold">Using Supabase CLI (Recommended)</h3>
|
|
71
71
|
</div>
|
|
72
72
|
<div className="ml-8 space-y-3">
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
<div>
|
|
74
|
+
<p className="text-sm text-muted-foreground mb-2">
|
|
75
|
+
Install Supabase CLI:
|
|
76
|
+
</p>
|
|
77
|
+
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
78
|
+
npm install -g supabase
|
|
79
|
+
</pre>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div>
|
|
83
|
+
<p className="text-sm text-muted-foreground mb-2">
|
|
84
|
+
Clone the RealTimeX CRM repository to get migrations:
|
|
85
|
+
</p>
|
|
86
|
+
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
87
|
+
git clone https://github.com/therealtimex/realtimex-crm.git
|
|
88
|
+
{"\n"}cd realtimex-crm
|
|
89
|
+
</pre>
|
|
90
|
+
</div>
|
|
76
91
|
|
|
77
|
-
<div
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</div>
|
|
92
|
+
<div>
|
|
93
|
+
<p className="text-sm text-muted-foreground mb-2">
|
|
94
|
+
Link to your Supabase project:
|
|
95
|
+
</p>
|
|
96
|
+
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
97
|
+
supabase link --project-ref {projectRef || "YOUR_PROJECT_REF"}
|
|
98
|
+
</pre>
|
|
99
|
+
</div>
|
|
86
100
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
npm run db:migrate
|
|
96
|
-
</pre>
|
|
97
|
-
</div>
|
|
101
|
+
<div>
|
|
102
|
+
<p className="text-sm text-muted-foreground mb-2">
|
|
103
|
+
Push the migrations:
|
|
104
|
+
</p>
|
|
105
|
+
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
106
|
+
supabase db push
|
|
107
|
+
</pre>
|
|
108
|
+
</div>
|
|
98
109
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<li>Link your project using Project ID and Database Password</li>
|
|
104
|
-
<li>Apply all migrations automatically</li>
|
|
105
|
-
<li>Take about 5-10 seconds to complete</li>
|
|
106
|
-
</ul>
|
|
107
|
-
</div>
|
|
110
|
+
<div>
|
|
111
|
+
<p className="text-sm text-muted-foreground mb-2">
|
|
112
|
+
Reload this page after migrations are complete.
|
|
113
|
+
</p>
|
|
108
114
|
</div>
|
|
109
115
|
</div>
|
|
110
116
|
</div>
|
|
@@ -115,24 +121,23 @@ export function DatabaseSetupGuide({
|
|
|
115
121
|
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-primary-foreground text-sm font-bold">
|
|
116
122
|
2
|
|
117
123
|
</div>
|
|
118
|
-
<h3 className="font-semibold">
|
|
124
|
+
<h3 className="font-semibold">Using Supabase SQL Editor</h3>
|
|
119
125
|
</div>
|
|
120
126
|
<div className="ml-8 space-y-3">
|
|
121
127
|
<p className="text-sm text-muted-foreground">
|
|
122
|
-
|
|
128
|
+
Manually run the SQL migrations in your Supabase SQL Editor:
|
|
123
129
|
</p>
|
|
124
130
|
|
|
125
131
|
<ol className="list-decimal list-inside space-y-2 text-sm text-muted-foreground">
|
|
126
132
|
<li>
|
|
127
|
-
Download{" "}
|
|
133
|
+
Download migrations from{" "}
|
|
128
134
|
<a
|
|
129
|
-
href="https://
|
|
135
|
+
href="https://github.com/therealtimex/realtimex-crm/tree/main/supabase/migrations"
|
|
130
136
|
target="_blank"
|
|
131
137
|
rel="noopener noreferrer"
|
|
132
138
|
className="text-primary hover:underline inline-flex items-center gap-1"
|
|
133
|
-
download="setup.sql"
|
|
134
139
|
>
|
|
135
|
-
|
|
140
|
+
GitHub
|
|
136
141
|
<ExternalLink className="h-3 w-3" />
|
|
137
142
|
</a>
|
|
138
143
|
</li>
|
|
@@ -148,9 +153,12 @@ export function DatabaseSetupGuide({
|
|
|
148
153
|
<ExternalLink className="h-3 w-3" />
|
|
149
154
|
</a>
|
|
150
155
|
</li>
|
|
151
|
-
<li>
|
|
152
|
-
|
|
153
|
-
|
|
156
|
+
<li>
|
|
157
|
+
Run each migration file in order (by date in filename)
|
|
158
|
+
</li>
|
|
159
|
+
<li>
|
|
160
|
+
Reload this page after all migrations are complete
|
|
161
|
+
</li>
|
|
154
162
|
</ol>
|
|
155
163
|
|
|
156
164
|
{projectRef && (
|
|
@@ -168,61 +176,6 @@ export function DatabaseSetupGuide({
|
|
|
168
176
|
</div>
|
|
169
177
|
</div>
|
|
170
178
|
|
|
171
|
-
{/* Option 3: Supabase CLI Manual */}
|
|
172
|
-
<div className="space-y-3">
|
|
173
|
-
<div className="flex items-center gap-2">
|
|
174
|
-
<div className="flex items-center justify-center w-6 h-6 rounded-full bg-primary text-primary-foreground text-sm font-bold">
|
|
175
|
-
3
|
|
176
|
-
</div>
|
|
177
|
-
<h3 className="font-semibold">Advanced: Manual CLI Setup</h3>
|
|
178
|
-
</div>
|
|
179
|
-
<div className="ml-8 space-y-3">
|
|
180
|
-
<div>
|
|
181
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
182
|
-
Install Supabase CLI:
|
|
183
|
-
</p>
|
|
184
|
-
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
185
|
-
npm install -g supabase
|
|
186
|
-
</pre>
|
|
187
|
-
</div>
|
|
188
|
-
|
|
189
|
-
<div>
|
|
190
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
191
|
-
Clone the RealTimeX CRM repository to get migrations:
|
|
192
|
-
</p>
|
|
193
|
-
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
194
|
-
git clone https://github.com/therealtimex/realtimex-crm.git
|
|
195
|
-
{"\n"}cd realtimex-crm
|
|
196
|
-
</pre>
|
|
197
|
-
</div>
|
|
198
|
-
|
|
199
|
-
<div>
|
|
200
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
201
|
-
Link to your Supabase project:
|
|
202
|
-
</p>
|
|
203
|
-
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
204
|
-
supabase link --project-ref {projectRef || "YOUR_PROJECT_REF"}
|
|
205
|
-
</pre>
|
|
206
|
-
</div>
|
|
207
|
-
|
|
208
|
-
<div>
|
|
209
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
210
|
-
Push the migrations:
|
|
211
|
-
</p>
|
|
212
|
-
<pre className="bg-muted p-3 rounded text-sm overflow-x-auto">
|
|
213
|
-
supabase db push
|
|
214
|
-
</pre>
|
|
215
|
-
</div>
|
|
216
|
-
|
|
217
|
-
<div>
|
|
218
|
-
<p className="text-sm text-muted-foreground mb-2">
|
|
219
|
-
Reload this page after migrations are complete.
|
|
220
|
-
</p>
|
|
221
|
-
</div>
|
|
222
|
-
</div>
|
|
223
|
-
</div>
|
|
224
|
-
|
|
225
|
-
|
|
226
179
|
{/* Verification */}
|
|
227
180
|
<div className="space-y-3 pt-4 border-t">
|
|
228
181
|
<h3 className="font-semibold">After Setup</h3>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DataProvider } from "ra-core";
|
|
2
2
|
|
|
3
3
|
export interface DatabaseHealthStatus {
|
|
4
4
|
isHealthy: boolean;
|
|
@@ -8,11 +8,10 @@ export interface DatabaseHealthStatus {
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Check if the database has the required schema
|
|
11
|
-
* This function directly queries the Supabase client to avoid data provider
|
|
12
|
-
* transformations (e.g., contacts -> contacts_summary) that would fail
|
|
13
|
-
* if the database schema doesn't exist yet.
|
|
14
11
|
*/
|
|
15
|
-
export async function checkDatabaseHealth(
|
|
12
|
+
export async function checkDatabaseHealth(
|
|
13
|
+
dataProvider: DataProvider,
|
|
14
|
+
): Promise<DatabaseHealthStatus> {
|
|
16
15
|
const requiredTables = [
|
|
17
16
|
"contacts",
|
|
18
17
|
"companies",
|
|
@@ -27,31 +26,23 @@ export async function checkDatabaseHealth(): Promise<DatabaseHealthStatus> {
|
|
|
27
26
|
const missingTables: string[] = [];
|
|
28
27
|
|
|
29
28
|
try {
|
|
30
|
-
// Try to query each table
|
|
29
|
+
// Try to query each table
|
|
31
30
|
for (const table of requiredTables) {
|
|
32
31
|
try {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (error) {
|
|
39
|
-
// Check if it's a "table not found" error
|
|
40
|
-
if (
|
|
41
|
-
error.message?.includes("Could not find the table") ||
|
|
42
|
-
error.message?.includes("relation") ||
|
|
43
|
-
error.message?.includes("does not exist") ||
|
|
44
|
-
error.code === "PGRST200" // PostgREST error code for missing table
|
|
45
|
-
) {
|
|
46
|
-
missingTables.push(table);
|
|
47
|
-
} else {
|
|
48
|
-
// Some other error - log it but don't fail health check
|
|
49
|
-
console.warn(`Unexpected error querying ${table}:`, error);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
32
|
+
await dataProvider.getList(table, {
|
|
33
|
+
pagination: { page: 1, perPage: 1 },
|
|
34
|
+
sort: { field: "id", order: "ASC" },
|
|
35
|
+
filter: {},
|
|
36
|
+
});
|
|
52
37
|
} catch (error: any) {
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
// Check if it's a "table not found" error
|
|
39
|
+
if (
|
|
40
|
+
error?.message?.includes("Could not find the table") ||
|
|
41
|
+
error?.message?.includes("relation") ||
|
|
42
|
+
error?.message?.includes("does not exist")
|
|
43
|
+
) {
|
|
44
|
+
missingTables.push(table);
|
|
45
|
+
}
|
|
55
46
|
}
|
|
56
47
|
}
|
|
57
48
|
|