Skip to content

Commit cc38872

Browse files
chore: Allow App to start extract/transform per selected tenant (#364)
* add tenant select to extract/transform start * update tenants prop provision
1 parent f7b592a commit cc38872

File tree

5 files changed

+91
-8
lines changed

5 files changed

+91
-8
lines changed

apps/app/src/app/page.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { MainNav } from "~/components/ui/main-nav";
33
import { GenerateToken } from "~/components/generate-token";
44
import { ExtractStartForm } from "~/components/extract-start-form";
55
import { TransformStartForm } from "~/components/transform-start-form";
6+
import { getEnvTenants } from "~/components/tenant.env";
67

78
export default function Page() {
9+
const tenants = getEnvTenants(); // getServerSideProps is deprecated. createServerContext documentation lackluster
810
return (
911
<>
1012
<div className="flex-col">
@@ -19,8 +21,8 @@ export default function Page() {
1921
</div>
2022
</div>
2123
<GenerateToken />
22-
<ExtractStartForm/>
23-
<TransformStartForm/>
24+
<ExtractStartForm TENANTS={tenants}/>
25+
<TransformStartForm TENANTS={tenants}/>
2426
</>
2527
);
26-
}
28+
}

apps/app/src/components/extract-start-form.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ import { useAuth } from '@clerk/nextjs';
33
import { useState } from 'react';
44
import type { ChangeEvent, Dispatch, SetStateAction } from 'react';
55
import { Input } from './ui/input';
6+
import { TenantPicker } from './tenant-picker';
7+
import type { Tenant } from './tenant.env';
68

7-
8-
export function ExtractStartForm() {
9+
type ExtractStartFormProps = {
10+
TENANTS: Tenant[] | undefined
11+
}
12+
export function ExtractStartForm({ TENANTS }: ExtractStartFormProps) {
913
const { getToken } = useAuth();
1014
const currentDate = new Date();
1115
currentDate.setMonth(currentDate.getMonth() - 6);
@@ -18,20 +22,22 @@ export function ExtractStartForm() {
1822
const [to, setTo] = useState(new Date().toISOString().slice(0, 10));
1923
const [status, setStatus] = useState('---');
2024
const [body, setBody] = useState('');
25+
const [tenantId, setTenantId] = useState((TENANTS || [])[0]?.id || -1);
2126

2227
const handleInputChange = (stateSetter: Dispatch<SetStateAction<any>>) => (ev: ChangeEvent<HTMLInputElement>) => stateSetter(ev.target.value);
2328

2429
const handleSelectChange = (ev: ChangeEvent<HTMLSelectElement>) => setSourceControl(ev.target.value);
2530

2631
const handleSubmit = async () => {
2732
if (!process.env.NEXT_PUBLIC_EXTRACT_API_URL) return console.error('Missing ENV variable: NEXT_PUBLIC_EXTRACT_API_URL');
33+
if (tenantId === -1) return console.error(`Invalid ENV variable: TENANTS`);
2834
setStatus('...');
2935
setBody('');
3036

3137
const token = await getToken({ template: 'dashboard' });
3238
if (!token) return;
3339

34-
const requestBody = JSON.stringify({ repositoryId, repositoryName, namespaceName, sourceControl, from: new Date(from), to: new Date(to) });
40+
const requestBody = JSON.stringify({ repositoryId, repositoryName, namespaceName, sourceControl, from: new Date(from), to: new Date(to), tenantId });
3541

3642
const res = await fetch(process.env.NEXT_PUBLIC_EXTRACT_API_URL, {
3743
method: 'post',
@@ -81,6 +87,12 @@ export function ExtractStartForm() {
8187
<td><input type='date' value={from} onChange={handleInputChange(setFrom)} className='flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50' /></td>
8288
<td><input type='date' value={to} onChange={handleInputChange(setTo)} className='flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50' /></td>
8389
</tr>
90+
<tr>
91+
<td>tenant:</td>
92+
<td>
93+
<TenantPicker tenants={TENANTS} setTenantId={setTenantId} />
94+
</td>
95+
</tr>
8496
</tbody>
8597
</table>
8698
<button onClick={() => void handleSubmit()}>Submit</button>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use client"
2+
import type { ChangeEvent } from "react";
3+
import type { Tenant } from "./tenant.env";
4+
5+
type TenantPickerProps = {
6+
tenants: Tenant[] | undefined
7+
setTenantId: (tenantId: number) => void;
8+
}
9+
export function TenantPicker({ tenants, setTenantId }: TenantPickerProps) {
10+
11+
if (tenants === undefined) return (<span style={{color: 'red'}}>Invalid environment varibale: TENANTS</span>);
12+
13+
if (tenants.length === 0) return (<span style={{color: 'blue'}}>Empty tenancy config</span>);
14+
15+
const handleSelectChange = (ev: ChangeEvent<HTMLSelectElement>) => setTenantId(Number(ev.target.value));
16+
17+
return (
18+
<select defaultValue={tenants[0]?.id} onChange={handleSelectChange} className='flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50'>
19+
{tenants.map(t=>(
20+
<option key={t.id} value={t.id}>{t.tenant}</option>
21+
))}
22+
</select>
23+
);
24+
25+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { z } from "zod";
2+
3+
const ENVSchema = z.object({
4+
TENANTS: z.string(),
5+
})
6+
const TenantSchema = z.object({
7+
id: z.number(),
8+
tenant: z.string(),
9+
dbUrl: z.string(),
10+
});
11+
const TenantArraySchema = z.array(TenantSchema);
12+
13+
const processEnv = () => {
14+
const validEnv = ENVSchema.safeParse(process.env);
15+
if (!validEnv.success) {
16+
console.error(`Missing required environment variable 'TENANT'`);
17+
return undefined;
18+
}
19+
20+
const validTenantArray = TenantArraySchema.safeParse(JSON.parse(validEnv.data.TENANTS));
21+
if (!validTenantArray.success) {
22+
console.error("Invalid environment variable 'TENANTS' value:", ...validTenantArray.error.issues);
23+
return undefined;
24+
}
25+
26+
return validTenantArray.data;
27+
}
28+
29+
const TENANTS = processEnv();
30+
31+
32+
export const getEnvTenants = () => TENANTS;
33+
34+
export type Tenant = z.infer<typeof TenantSchema>;

apps/app/src/components/transform-start-form.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
"use client"
22
import { useAuth } from '@clerk/nextjs';
33
import { useState } from 'react';
4+
import type { Tenant } from './tenant.env';
5+
import { TenantPicker } from './tenant-picker';
46

5-
6-
export function TransformStartForm() {
7+
type TransformStartFormProps = {
8+
TENANTS: Tenant[] | undefined
9+
}
10+
export function TransformStartForm({ TENANTS }: TransformStartFormProps) {
711
const { getToken } = useAuth();
12+
const [tenantId, setTenantId] = useState((TENANTS || [])[0]?.id || -1);
813
const [status, setStatus] = useState('---');
914
const [body, setBody] = useState('');
1015

1116
const handleClick = async () => {
1217
if (!process.env.NEXT_PUBLIC_TRANSFORM_API_URL) return console.error('Missing ENV variable: NEXT_PUBLIC_TRANSFORM_API_URL');
18+
if (tenantId === -1) return console.error(`Invalid ENV variable: TENANTS`);
19+
const requestBody = JSON.stringify({ tenantId });
20+
1321
setStatus('...');
1422
setBody('');
1523

@@ -18,6 +26,7 @@ export function TransformStartForm() {
1826

1927
const res = await fetch(process.env.NEXT_PUBLIC_TRANSFORM_API_URL, {
2028
method: 'post',
29+
body: requestBody,
2130
headers: {
2231
'Authorization': 'Bearer ' + token
2332
}
@@ -36,6 +45,7 @@ export function TransformStartForm() {
3645
<button onClick={() => { handleClick().catch(console.log) }}>
3746
Transform
3847
</button>
48+
<div>tenant: <span className="inline-block"><TenantPicker tenants={TENANTS} setTenantId={setTenantId} /></span></div>
3949
</div>
4050
<div><b>{status}</b></div>
4151
<pre>{body}</pre>

0 commit comments

Comments
 (0)