create-chaaskit 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/templates/app/routes/chat.admin.promo-codes.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.waitlist.tsx +10 -0
- package/dist/templates/app/routes.ts +2 -0
- package/dist/templates/config/app.config.ts +24 -0
- package/dist/templates/server.js +40 -10
- package/package.json +19 -10
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -25
- package/dist/cli.js.map +0 -1
- package/dist/templates/app/components/AcceptInviteClient.tsx +0 -10
- package/dist/templates/app/components/AdminDashboardClient.tsx +0 -10
- package/dist/templates/app/components/AdminTeamClient.tsx +0 -10
- package/dist/templates/app/components/AdminTeamsClient.tsx +0 -10
- package/dist/templates/app/components/AdminUsersClient.tsx +0 -10
- package/dist/templates/app/components/ApiKeysClient.tsx +0 -10
- package/dist/templates/app/components/AutomationsClient.tsx +0 -10
- package/dist/templates/app/components/ChatClient.tsx +0 -13
- package/dist/templates/app/components/DocumentsClient.tsx +0 -10
- package/dist/templates/app/components/OAuthConsentClient.tsx +0 -10
- package/dist/templates/app/components/PricingClient.tsx +0 -10
- package/dist/templates/app/components/TeamSettingsClient.tsx +0 -10
- package/dist/templates/app/components/VerifyEmailClient.tsx +0 -10
- package/dist/templates/app/routes/admin._index.tsx +0 -57
- package/dist/templates/app/routes/admin.teams.$teamId.tsx +0 -57
- package/dist/templates/app/routes/admin.teams._index.tsx +0 -57
- package/dist/templates/app/routes/admin.users.tsx +0 -57
- package/dist/templates/app/routes/api-keys.tsx +0 -57
- package/dist/templates/app/routes/automations.tsx +0 -57
- package/dist/templates/app/routes/documents.tsx +0 -57
- package/dist/templates/app/routes/team.$teamId.settings.tsx +0 -57
- package/dist/templates/app/routes/thread.$threadId.tsx +0 -102
- package/dist/templates/docs/admin.md +0 -257
- package/dist/templates/docs/api-keys.md +0 -403
- package/dist/templates/docs/authentication.md +0 -247
- package/dist/templates/docs/configuration.md +0 -1212
- package/dist/templates/docs/custom-pages.md +0 -466
- package/dist/templates/docs/deployment.md +0 -362
- package/dist/templates/docs/development.md +0 -411
- package/dist/templates/docs/documents.md +0 -293
- package/dist/templates/docs/extensions.md +0 -639
- package/dist/templates/docs/index.md +0 -139
- package/dist/templates/docs/installation.md +0 -286
- package/dist/templates/docs/mcp.md +0 -952
- package/dist/templates/docs/native-tools.md +0 -688
- package/dist/templates/docs/queue.md +0 -514
- package/dist/templates/docs/scheduled-prompts.md +0 -279
- package/dist/templates/docs/settings.md +0 -415
- package/dist/templates/docs/slack.md +0 -318
- package/dist/templates/docs/styling.md +0 -288
- package/dist/templates/index.html +0 -16
- package/dist/templates/prisma/schema.prisma +0 -271
- package/dist/templates/src/main.tsx +0 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Matt Ferrante
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRoute } from '@chaaskit/client/ssr-utils';
|
|
2
|
+
|
|
3
|
+
const route = createRoute({
|
|
4
|
+
title: 'Admin Promo Codes',
|
|
5
|
+
load: () => import('@chaaskit/client/routes/AdminPromoCodesRoute'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const meta = route.meta;
|
|
9
|
+
export const links = route.links;
|
|
10
|
+
export default route.default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRoute } from '@chaaskit/client/ssr-utils';
|
|
2
|
+
|
|
3
|
+
const route = createRoute({
|
|
4
|
+
title: 'Admin Waitlist',
|
|
5
|
+
load: () => import('@chaaskit/client/routes/AdminWaitlistRoute'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const meta = route.meta;
|
|
9
|
+
export const links = route.links;
|
|
10
|
+
export default route.default;
|
|
@@ -41,6 +41,8 @@ export default [
|
|
|
41
41
|
// Admin pages
|
|
42
42
|
route(`${base}/admin`, 'routes/chat.admin._index.tsx'),
|
|
43
43
|
route(`${base}/admin/users`, 'routes/chat.admin.users.tsx'),
|
|
44
|
+
route(`${base}/admin/waitlist`, 'routes/chat.admin.waitlist.tsx'),
|
|
45
|
+
route(`${base}/admin/promo-codes`, 'routes/chat.admin.promo-codes.tsx'),
|
|
44
46
|
route(`${base}/admin/teams`, 'routes/chat.admin.teams._index.tsx'),
|
|
45
47
|
route(`${base}/admin/teams/:teamId`, 'routes/chat.admin.teams.$teamId.tsx'),
|
|
46
48
|
]),
|
|
@@ -29,6 +29,11 @@ export const config: AppConfig = {
|
|
|
29
29
|
enabled: true,
|
|
30
30
|
expiresInMinutes: 15,
|
|
31
31
|
},
|
|
32
|
+
gating: {
|
|
33
|
+
mode: 'open',
|
|
34
|
+
inviteExpiryDays: 7,
|
|
35
|
+
waitlistEnabled: true,
|
|
36
|
+
},
|
|
32
37
|
},
|
|
33
38
|
|
|
34
39
|
// Configure your AI agent(s) here
|
|
@@ -138,4 +143,23 @@ export const config: AppConfig = {
|
|
|
138
143
|
'application/json',
|
|
139
144
|
],
|
|
140
145
|
},
|
|
146
|
+
|
|
147
|
+
credits: {
|
|
148
|
+
enabled: true,
|
|
149
|
+
expiryEnabled: true,
|
|
150
|
+
defaultExpiryDays: 365,
|
|
151
|
+
tokensPerCredit: 1000,
|
|
152
|
+
referralRewardCredits: 10,
|
|
153
|
+
referralTriggers: {
|
|
154
|
+
signup: true,
|
|
155
|
+
firstMessage: true,
|
|
156
|
+
paying: true,
|
|
157
|
+
},
|
|
158
|
+
promoEnabled: true,
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
metering: {
|
|
162
|
+
enabled: true,
|
|
163
|
+
recordPromptCompletion: true,
|
|
164
|
+
},
|
|
141
165
|
};
|
package/dist/templates/server.js
CHANGED
|
@@ -4,21 +4,43 @@
|
|
|
4
4
|
* This is a single server that handles:
|
|
5
5
|
* - API routes at /api/*, /mcp/*, /v1/*
|
|
6
6
|
* - SSR for all other routes via React Router
|
|
7
|
+
*
|
|
8
|
+
* ARCHITECTURE: We create a wrapper Express app that handles React Router routes
|
|
9
|
+
* BEFORE body parsing, then delegates API routes to the chaaskit app (which has
|
|
10
|
+
* body parsing). This prevents the body stream from being consumed before React
|
|
11
|
+
* Router can read it with request.formData().
|
|
12
|
+
*
|
|
13
|
+
* SECRETS: Configure secret loading via environment variables:
|
|
14
|
+
* SECRETS_PROVIDER=env (default) - secrets already in env vars
|
|
15
|
+
* SECRETS_PROVIDER=aws-secrets-manager - load from AWS Secrets Manager
|
|
16
|
+
* AWS_SECRET_ARN - ARN of the secret to load
|
|
17
|
+
* AWS_REGION - Region (optional, defaults to 'us-west-2')
|
|
7
18
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
|
|
20
|
+
// Load secrets BEFORE importing anything that uses them (Prisma, etc.)
|
|
21
|
+
const { loadSecrets } = await import('@chaaskit/server');
|
|
22
|
+
await loadSecrets();
|
|
23
|
+
|
|
24
|
+
// Now safe to import modules that depend on DATABASE_URL, OPENAI_API_KEY, etc.
|
|
25
|
+
const { createApp } = await import('@chaaskit/server');
|
|
26
|
+
const { createRequestHandler } = await import('@react-router/express');
|
|
27
|
+
const express = (await import('express')).default;
|
|
28
|
+
const path = (await import('path')).default;
|
|
29
|
+
const { fileURLToPath } = await import('url');
|
|
13
30
|
|
|
14
31
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
32
|
|
|
16
33
|
async function startServer() {
|
|
17
|
-
// Create the chaaskit Express app with all API routes
|
|
18
|
-
|
|
19
|
-
const app = await createApp({ serveSpa: false });
|
|
34
|
+
// Create the chaaskit Express app with all API routes (has body parsing)
|
|
35
|
+
const chaaskitApp = await createApp({ serveSpa: false });
|
|
20
36
|
|
|
21
|
-
//
|
|
37
|
+
// Create wrapper Express app (NO body parsing here)
|
|
38
|
+
const app = express();
|
|
39
|
+
|
|
40
|
+
// Trust proxy headers when behind load balancer (ALB, nginx, CloudFlare, etc.)
|
|
41
|
+
app.set('trust proxy', true);
|
|
42
|
+
|
|
43
|
+
// Serve static assets FIRST (before any other processing)
|
|
22
44
|
app.use(
|
|
23
45
|
'/assets',
|
|
24
46
|
express.static(path.join(__dirname, 'build/client/assets'), {
|
|
@@ -28,8 +50,16 @@ async function startServer() {
|
|
|
28
50
|
);
|
|
29
51
|
app.use(express.static(path.join(__dirname, 'build/client'), { maxAge: '1h' }));
|
|
30
52
|
|
|
53
|
+
// Delegate API routes to chaaskit app (which has body parsing)
|
|
54
|
+
app.use((req, res, next) => {
|
|
55
|
+
if (req.path.startsWith('/api/') || req.path.startsWith('/v1/') || req.path.startsWith('/mcp/')) {
|
|
56
|
+
return chaaskitApp(req, res, next);
|
|
57
|
+
}
|
|
58
|
+
next();
|
|
59
|
+
});
|
|
60
|
+
|
|
31
61
|
// Handle all other routes with React Router SSR
|
|
32
|
-
//
|
|
62
|
+
// No body parsing has occurred, so request.formData() works
|
|
33
63
|
app.all(
|
|
34
64
|
'*',
|
|
35
65
|
createRequestHandler({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-chaaskit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "CLI to create and manage ChaasKit AI chat SaaS applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Matt Ferrante <@ferrants>",
|
|
@@ -13,7 +13,16 @@
|
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/ferrants/chaaskit/issues"
|
|
15
15
|
},
|
|
16
|
-
"keywords": [
|
|
16
|
+
"keywords": [
|
|
17
|
+
"chaaskit",
|
|
18
|
+
"ai",
|
|
19
|
+
"chat",
|
|
20
|
+
"saas",
|
|
21
|
+
"cli",
|
|
22
|
+
"create",
|
|
23
|
+
"scaffold",
|
|
24
|
+
"template"
|
|
25
|
+
],
|
|
17
26
|
"type": "module",
|
|
18
27
|
"main": "./dist/index.js",
|
|
19
28
|
"bin": {
|
|
@@ -23,13 +32,6 @@
|
|
|
23
32
|
"dist",
|
|
24
33
|
"templates"
|
|
25
34
|
],
|
|
26
|
-
"scripts": {
|
|
27
|
-
"build": "tsc && npm run copy-templates",
|
|
28
|
-
"copy-templates": "cp -r src/templates dist/",
|
|
29
|
-
"dev": "tsc --watch",
|
|
30
|
-
"typecheck": "tsc --noEmit",
|
|
31
|
-
"clean": "rm -rf dist"
|
|
32
|
-
},
|
|
33
35
|
"dependencies": {
|
|
34
36
|
"commander": "^12.0.0",
|
|
35
37
|
"fs-extra": "^11.2.0",
|
|
@@ -42,5 +44,12 @@
|
|
|
42
44
|
"@types/node": "^20.11.0",
|
|
43
45
|
"@types/prompts": "^2.4.9",
|
|
44
46
|
"typescript": "^5.3.3"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc && npm run copy-templates",
|
|
50
|
+
"copy-templates": "cp -r src/templates dist/",
|
|
51
|
+
"dev": "tsc --watch",
|
|
52
|
+
"typecheck": "tsc --noEmit",
|
|
53
|
+
"clean": "rm -rf dist"
|
|
45
54
|
}
|
|
46
|
-
}
|
|
55
|
+
}
|
package/dist/cli.d.ts
DELETED
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { Command } from 'commander';
|
|
3
|
-
import { dev } from './commands/dev.js';
|
|
4
|
-
import { build } from './commands/build.js';
|
|
5
|
-
const program = new Command();
|
|
6
|
-
program
|
|
7
|
-
.name('chat-saas')
|
|
8
|
-
.description('CLI for managing Chat SaaS applications')
|
|
9
|
-
.version('0.1.0');
|
|
10
|
-
program
|
|
11
|
-
.command('dev')
|
|
12
|
-
.description('Start development servers')
|
|
13
|
-
.option('-p, --port <port>', 'Server port', '3000')
|
|
14
|
-
.option('--client-port <port>', 'Client dev server port', '5173')
|
|
15
|
-
.action(async (options) => {
|
|
16
|
-
await dev(options);
|
|
17
|
-
});
|
|
18
|
-
program
|
|
19
|
-
.command('build')
|
|
20
|
-
.description('Build for production')
|
|
21
|
-
.action(async () => {
|
|
22
|
-
await build();
|
|
23
|
-
});
|
|
24
|
-
program.parse();
|
|
25
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,yCAAyC,CAAC;KACtD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,mBAAmB,EAAE,aAAa,EAAE,MAAM,CAAC;KAClD,MAAM,CAAC,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,CAAC;KAChE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Client-only component for Automations (Scheduled Prompts) page
|
|
2
|
-
import { ChatProviders, ScheduledPromptsPage } from '@chaaskit/client';
|
|
3
|
-
|
|
4
|
-
export default function AutomationsClient() {
|
|
5
|
-
return (
|
|
6
|
-
<ChatProviders>
|
|
7
|
-
<ScheduledPromptsPage />
|
|
8
|
-
</ChatProviders>
|
|
9
|
-
);
|
|
10
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// This file is only imported on the client side via dynamic import
|
|
2
|
-
// It uses @chaaskit/client components directly
|
|
3
|
-
import { ChatProviders, MainLayout, ChatPage } from '@chaaskit/client';
|
|
4
|
-
|
|
5
|
-
export default function ChatClient() {
|
|
6
|
-
return (
|
|
7
|
-
<ChatProviders>
|
|
8
|
-
<MainLayout>
|
|
9
|
-
<ChatPage />
|
|
10
|
-
</MainLayout>
|
|
11
|
-
</ChatProviders>
|
|
12
|
-
);
|
|
13
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { Route } from './+types/admin._index';
|
|
2
|
-
import { lazy, Suspense } from 'react';
|
|
3
|
-
import { ClientOnly } from '../components/ClientOnly';
|
|
4
|
-
|
|
5
|
-
const AdminDashboardClient = lazy(() => import('../components/AdminDashboardClient'));
|
|
6
|
-
|
|
7
|
-
export function meta({}: Route.MetaArgs) {
|
|
8
|
-
return [{ title: 'Admin Dashboard' }];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function links() {
|
|
12
|
-
return [{ rel: 'stylesheet', href: '/node_modules/@chaaskit/client/dist/lib/styles.css' }];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function AdminDashboard() {
|
|
16
|
-
return (
|
|
17
|
-
<ClientOnly fallback={<LoadingSkeleton />}>
|
|
18
|
-
{() => (
|
|
19
|
-
<Suspense fallback={<LoadingSkeleton />}>
|
|
20
|
-
<AdminDashboardClient />
|
|
21
|
-
</Suspense>
|
|
22
|
-
)}
|
|
23
|
-
</ClientOnly>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function LoadingSkeleton() {
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
style={{
|
|
31
|
-
display: 'flex',
|
|
32
|
-
height: '100vh',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
backgroundColor: 'rgb(var(--color-background))',
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
<div
|
|
39
|
-
style={{
|
|
40
|
-
width: '2rem',
|
|
41
|
-
height: '2rem',
|
|
42
|
-
border: '2px solid rgb(var(--color-primary))',
|
|
43
|
-
borderTopColor: 'transparent',
|
|
44
|
-
borderRadius: '50%',
|
|
45
|
-
animation: 'spin 1s linear infinite',
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<style>
|
|
49
|
-
{`
|
|
50
|
-
@keyframes spin {
|
|
51
|
-
to { transform: rotate(360deg); }
|
|
52
|
-
}
|
|
53
|
-
`}
|
|
54
|
-
</style>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { Route } from './+types/admin.teams.$teamId';
|
|
2
|
-
import { lazy, Suspense } from 'react';
|
|
3
|
-
import { ClientOnly } from '../components/ClientOnly';
|
|
4
|
-
|
|
5
|
-
const AdminTeamClient = lazy(() => import('../components/AdminTeamClient'));
|
|
6
|
-
|
|
7
|
-
export function meta({}: Route.MetaArgs) {
|
|
8
|
-
return [{ title: 'Admin - Team Details' }];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function links() {
|
|
12
|
-
return [{ rel: 'stylesheet', href: '/node_modules/@chaaskit/client/dist/lib/styles.css' }];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function AdminTeamDetails() {
|
|
16
|
-
return (
|
|
17
|
-
<ClientOnly fallback={<LoadingSkeleton />}>
|
|
18
|
-
{() => (
|
|
19
|
-
<Suspense fallback={<LoadingSkeleton />}>
|
|
20
|
-
<AdminTeamClient />
|
|
21
|
-
</Suspense>
|
|
22
|
-
)}
|
|
23
|
-
</ClientOnly>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function LoadingSkeleton() {
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
style={{
|
|
31
|
-
display: 'flex',
|
|
32
|
-
height: '100vh',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
backgroundColor: 'rgb(var(--color-background))',
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
<div
|
|
39
|
-
style={{
|
|
40
|
-
width: '2rem',
|
|
41
|
-
height: '2rem',
|
|
42
|
-
border: '2px solid rgb(var(--color-primary))',
|
|
43
|
-
borderTopColor: 'transparent',
|
|
44
|
-
borderRadius: '50%',
|
|
45
|
-
animation: 'spin 1s linear infinite',
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<style>
|
|
49
|
-
{`
|
|
50
|
-
@keyframes spin {
|
|
51
|
-
to { transform: rotate(360deg); }
|
|
52
|
-
}
|
|
53
|
-
`}
|
|
54
|
-
</style>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { Route } from './+types/admin.teams._index';
|
|
2
|
-
import { lazy, Suspense } from 'react';
|
|
3
|
-
import { ClientOnly } from '../components/ClientOnly';
|
|
4
|
-
|
|
5
|
-
const AdminTeamsClient = lazy(() => import('../components/AdminTeamsClient'));
|
|
6
|
-
|
|
7
|
-
export function meta({}: Route.MetaArgs) {
|
|
8
|
-
return [{ title: 'Admin - Teams' }];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function links() {
|
|
12
|
-
return [{ rel: 'stylesheet', href: '/node_modules/@chaaskit/client/dist/lib/styles.css' }];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function AdminTeams() {
|
|
16
|
-
return (
|
|
17
|
-
<ClientOnly fallback={<LoadingSkeleton />}>
|
|
18
|
-
{() => (
|
|
19
|
-
<Suspense fallback={<LoadingSkeleton />}>
|
|
20
|
-
<AdminTeamsClient />
|
|
21
|
-
</Suspense>
|
|
22
|
-
)}
|
|
23
|
-
</ClientOnly>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function LoadingSkeleton() {
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
style={{
|
|
31
|
-
display: 'flex',
|
|
32
|
-
height: '100vh',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
backgroundColor: 'rgb(var(--color-background))',
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
<div
|
|
39
|
-
style={{
|
|
40
|
-
width: '2rem',
|
|
41
|
-
height: '2rem',
|
|
42
|
-
border: '2px solid rgb(var(--color-primary))',
|
|
43
|
-
borderTopColor: 'transparent',
|
|
44
|
-
borderRadius: '50%',
|
|
45
|
-
animation: 'spin 1s linear infinite',
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<style>
|
|
49
|
-
{`
|
|
50
|
-
@keyframes spin {
|
|
51
|
-
to { transform: rotate(360deg); }
|
|
52
|
-
}
|
|
53
|
-
`}
|
|
54
|
-
</style>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { Route } from './+types/admin.users';
|
|
2
|
-
import { lazy, Suspense } from 'react';
|
|
3
|
-
import { ClientOnly } from '../components/ClientOnly';
|
|
4
|
-
|
|
5
|
-
const AdminUsersClient = lazy(() => import('../components/AdminUsersClient'));
|
|
6
|
-
|
|
7
|
-
export function meta({}: Route.MetaArgs) {
|
|
8
|
-
return [{ title: 'Admin - Users' }];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function links() {
|
|
12
|
-
return [{ rel: 'stylesheet', href: '/node_modules/@chaaskit/client/dist/lib/styles.css' }];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function AdminUsers() {
|
|
16
|
-
return (
|
|
17
|
-
<ClientOnly fallback={<LoadingSkeleton />}>
|
|
18
|
-
{() => (
|
|
19
|
-
<Suspense fallback={<LoadingSkeleton />}>
|
|
20
|
-
<AdminUsersClient />
|
|
21
|
-
</Suspense>
|
|
22
|
-
)}
|
|
23
|
-
</ClientOnly>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function LoadingSkeleton() {
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
style={{
|
|
31
|
-
display: 'flex',
|
|
32
|
-
height: '100vh',
|
|
33
|
-
alignItems: 'center',
|
|
34
|
-
justifyContent: 'center',
|
|
35
|
-
backgroundColor: 'rgb(var(--color-background))',
|
|
36
|
-
}}
|
|
37
|
-
>
|
|
38
|
-
<div
|
|
39
|
-
style={{
|
|
40
|
-
width: '2rem',
|
|
41
|
-
height: '2rem',
|
|
42
|
-
border: '2px solid rgb(var(--color-primary))',
|
|
43
|
-
borderTopColor: 'transparent',
|
|
44
|
-
borderRadius: '50%',
|
|
45
|
-
animation: 'spin 1s linear infinite',
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<style>
|
|
49
|
-
{`
|
|
50
|
-
@keyframes spin {
|
|
51
|
-
to { transform: rotate(360deg); }
|
|
52
|
-
}
|
|
53
|
-
`}
|
|
54
|
-
</style>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|