Skip to content

Commit d00ed80

Browse files
BboyAkersdawsontoth
authored andcommitted
feat: import/create package improvement, temp disabled url validation
1 parent 7872701 commit d00ed80

File tree

4 files changed

+60
-69
lines changed

4 files changed

+60
-69
lines changed

src/features/instance/applications/components/TextEditorView/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useParams } from '@tanstack/react-router';
88
import { ImportIcon, PlusIcon, Save } from 'lucide-react';
99
import { useEffect, useState } from 'react';
1010
import { useEditorView } from '@/features/instance/applications/hooks/useEditorView';
11-
import { NewProjectModal } from '@/features/instance/applications/modals/NewProjectModal';
11+
import { NewApplicationModal } from '@/features/instance/applications/modals/NewApplicationModal';
1212

1313
function parseFileExtension(filename: string) {
1414
const parts = (filename || '')?.split('.');
@@ -40,7 +40,7 @@ export function TextEditorView() {
4040
const { instanceId }: { instanceId: string } = useParams({ strict: false });
4141
const targetNoun = instanceId || isLocalStudio ? 'Instance' : 'Cluster';
4242
const instanceParams = useInstanceClientParams();
43-
const [isNewProjectModalOpen, setIsNewProjectModalOpen] = useState(false);
43+
const [isNewApplicationModalOpen, setIsNewApplicationModalOpen] = useState(false);
4444
const [appType, setAppType] = useState<'create' | 'import'>('create');
4545

4646
const crumbPath = selectedFolderFile.filePath.split('/').slice(1).join('/').replace(/\//g, ' > ');
@@ -89,7 +89,7 @@ export function TextEditorView() {
8989
operation="restart_service"
9090
/>
9191

92-
<Button variant="defaultOutline" className="w-38 rounded-full" onClick={() => setIsNewProjectModalOpen(true)}>
92+
<Button variant="defaultOutline" className="w-38 rounded-full" onClick={() => setIsNewApplicationModalOpen(true)}>
9393
<PlusIcon /> New Application
9494
</Button>
9595
</div>
@@ -100,13 +100,13 @@ export function TextEditorView() {
100100
<span className="text-white">No file selected</span>
101101
<div className="flex flex-col space-y-4 md:flex-row md:space-y-0 md:space-x-4">
102102
<Button variant="positiveOutline" className="ms-4" size="lg" onClick={() => {
103-
setIsNewProjectModalOpen(true);
103+
setIsNewApplicationModalOpen(true);
104104
setAppType('create');
105105
}}>
106106
<PlusIcon /> Create New Application
107107
</Button>
108108
<Button variant="defaultOutline" className="ms-4" size="lg" onClick={() => {
109-
setIsNewProjectModalOpen(true);
109+
setIsNewApplicationModalOpen(true);
110110
setAppType('import');
111111
}}>
112112
<ImportIcon /> Import Application
@@ -129,7 +129,7 @@ export function TextEditorView() {
129129
}}
130130
/>
131131
)}
132-
<NewProjectModal isModalOpen={isNewProjectModalOpen} setIsModalOpen={setIsNewProjectModalOpen} appType={appType} setAppType={setAppType} />
132+
<NewApplicationModal isModalOpen={isNewApplicationModalOpen} setIsModalOpen={setIsNewApplicationModalOpen} appType={appType} setAppType={setAppType} />
133133
</div>
134134
);
135135
}

src/features/instance/applications/modals/NewProjectModal.tsx renamed to src/features/instance/applications/modals/NewApplicationModal.tsx

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
2-
import { Button } from '@/components/ui/button';
3-
import { FolderPlus, Import } from 'lucide-react';
4-
import { useCallback} from 'react';
2+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
53
import { useInstanceClientIdParams, useInstanceClientParams } from '@/config/useInstanceClient';
4+
import { CreateNewApplicationForm } from '@/features/instance/applications/new/CreateNewApplicationForm';
5+
import { ImportApplicationForm } from '@/features/instance/applications/new/ImportApplicationForm';
66
import { useRestartInstanceClick } from '@/hooks/useRestartInstanceClick';
7-
import { CreateNewProjectForm } from '@/features/instance/applications/new/CreateNewProjectForm';
8-
import { ImportProjectForm } from '@/features/instance/applications/new/ImportProjectForm';
97
import { useQueryClient } from '@tanstack/react-query';
8+
import { useCallback } from 'react';
109

11-
export function NewProjectModal({
10+
export function NewApplicationModal({
1211
isModalOpen = false,
1312
setIsModalOpen,
1413
appType,
@@ -40,25 +39,19 @@ export function NewProjectModal({
4039
<DialogTitle>Create/Import An Application</DialogTitle>
4140
<DialogDescription>Create a new application or import an existing one.</DialogDescription>
4241
</DialogHeader>
43-
<div className="flex justify-center my-4">
44-
<Button className="py-4" variant="positiveOutline" onClick={() => setAppType('create')}>
45-
<FolderPlus />
46-
Create
47-
</Button>
48-
49-
<Button className="py-4 ml-4" variant="positiveOutline" onClick={() => setAppType('import')}>
50-
<Import />
51-
Import
52-
</Button>
53-
</div>
5442
<div>
55-
{appType === 'create' ? (
56-
<CreateNewProjectForm triggerRestart={onRestartClick} isRestartPending={isRestartPending} />
57-
) : appType === 'import' ? (
58-
<ImportProjectForm onRestartedSuccessfully={onRestartedSuccessfully} />
59-
) : (
60-
<p className="text-center">Please select an option to continue.</p>
61-
)}
43+
<Tabs defaultValue={appType} className="w-full" onValueChange={(value) => setAppType(value as 'create' | 'import')}>
44+
<TabsList>
45+
<TabsTrigger value="create">Create</TabsTrigger>
46+
<TabsTrigger value="import">Import</TabsTrigger>
47+
</TabsList>
48+
<TabsContent value="create" className='mt-4'>
49+
<CreateNewApplicationForm triggerRestart={onRestartClick} isRestartPending={isRestartPending} />
50+
</TabsContent>
51+
<TabsContent value="import" className='mt-4'>
52+
<ImportApplicationForm onRestartedSuccessfully={onRestartedSuccessfully} />
53+
</TabsContent>
54+
</Tabs>
6255
</div>
6356
</DialogContent>
6457
</Dialog>

src/features/instance/applications/new/CreateNewProjectForm.tsx renamed to src/features/instance/applications/new/CreateNewApplicationForm.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ import { useForm } from 'react-hook-form';
1717
import { toast } from 'sonner';
1818
import { z } from 'zod';
1919

20-
const NewProjectSchema = z.object({
20+
const NewApplicationSchema = z.object({
2121
applicationName: z
2222
.string()
23-
.nonempty({ error: 'Project name is required.' })
24-
.max(75, { error: 'Project name cannot be longer than 75 characters.' })
23+
.nonempty({ error: 'Application name is required.' })
24+
.max(75, { error: 'Application name cannot be longer than 75 characters.' })
2525
.regex(/^[a-zA-Z0-9-_]*$/, { error: 'Can only contain letters, numbers, dashes and underscores.' }),
2626
replicated: z.boolean(),
2727
});
2828

29-
export function CreateNewProjectForm({
29+
export function CreateNewApplicationForm({
3030
triggerRestart,
3131
isRestartPending,
3232
}: {
@@ -35,41 +35,41 @@ export function CreateNewProjectForm({
3535
}) {
3636
const instanceParams = useInstanceClientParams();
3737
const form = useForm({
38-
resolver: zodResolver(NewProjectSchema),
38+
resolver: zodResolver(NewApplicationSchema),
3939
defaultValues: {
4040
applicationName: '',
4141
replicated: instanceParams.entityType === 'cluster',
4242
},
4343
});
4444

45-
const { mutate: createNewProject } = useCreateComponentMutation();
45+
const { mutate: createNewApplication } = useCreateComponentMutation();
4646
const submitForm = (formData: CreateComponentFormData) => {
47-
createNewProject({ ...formData, ...instanceParams }, {
47+
createNewApplication({ ...formData, ...instanceParams }, {
4848
onSuccess: () => {
49-
toast.success(`Project ${formData.applicationName} created successfully`);
49+
toast.success(`Application ${formData.applicationName} created successfully`);
5050
triggerRestart();
5151
},
5252
});
5353
};
5454
return (
5555
<div className="mx-auto max-w-96">
5656
<Form {...form}>
57-
<form onSubmit={form.handleSubmit(submitForm)} className="text-white">
57+
<form onSubmit={form.handleSubmit(submitForm)} className="text-white w-full flex flex-col gap-4">
5858
<FormField
5959
control={form.control}
6060
name="applicationName"
6161
render={({ field }) => (
6262
<FormItem>
63-
<FormLabel className="pb-1 text-center">New Project Name</FormLabel>
63+
<FormLabel className="pb-1">New Application Name</FormLabel>
6464
<FormControl>
65-
<Input type="text" placeholder="e-commerce-store" className="text-center" {...field} />
65+
<Input type="text" placeholder="e-commerce-store" {...field} />
6666
</FormControl>
6767
<FormMessage />
6868
</FormItem>
6969
)}
7070
/>
7171
<Button
72-
className="w-full mt-4"
72+
className="w-full"
7373
variant="submit"
7474
type="submit"
7575
disabled={!form.formState.isDirty || isRestartPending}

src/features/instance/applications/new/ImportProjectForm.tsx renamed to src/features/instance/applications/new/ImportApplicationForm.tsx

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import { FormLabel } from '@/components/ui/form/FormLabel';
77
import { FormMessage } from '@/components/ui/form/FormMessage';
88
import { Input } from '@/components/ui/input';
99
import { useInstanceClientParams } from '@/config/useInstanceClient';
10-
import { getGitHubRepo } from '@/features/instance/applications/new/functions/getGitHubRepo';
11-
import { isValidTarballUrl } from '@/features/instance/applications/new/functions/isValidTarballUrl';
1210
import {
1311
DeployComponentFormData,
1412
useDeployComponentMutation,
@@ -20,26 +18,26 @@ import { useForm } from 'react-hook-form';
2018
import { toast } from 'sonner';
2119
import { z } from 'zod';
2220

23-
const ImportProjectSchema = z.object({
21+
const ImportApplicationSchema = z.object({
2422
applicationName: z
2523
.string()
26-
.nonempty({ error: 'Project name is required.' })
27-
.max(75, { error: 'Project name cannot be longer than 75 characters.' })
24+
.nonempty({ error: 'Application name is required.' })
25+
.max(75, { error: 'Application name cannot be longer than 75 characters.' })
2826
.regex(/^[a-zA-Z0-9-_]*$/, { error: 'Can only contain letters, numbers, dashes and underscores.' }),
2927
applicationUrl: z
3028
.string()
3129
.nonempty({ error: 'Please enter a Application URL.' }),
3230
replicated: z.boolean(),
3331
});
3432

35-
export function ImportProjectForm({
33+
export function ImportApplicationForm({
3634
onRestartedSuccessfully
3735
}: {
3836
onRestartedSuccessfully: () => void;
3937
}) {
4038
const instanceParams = useInstanceClientParams();
4139
const form = useForm({
42-
resolver: zodResolver(ImportProjectSchema),
40+
resolver: zodResolver(ImportApplicationSchema),
4341
defaultValues: {
4442
applicationName: '',
4543
applicationUrl: '',
@@ -67,21 +65,23 @@ export function ImportProjectForm({
6765
}
6866
});
6967
};
70-
const handleFetchApplication = async (url: string) => {
71-
if (url.includes('github.com')) {
72-
const response = await getGitHubRepo(new URL(url));
73-
if (response) {
74-
form.setValue('applicationName', response);
75-
toast.success(`Application "${response}" found successfully`);
76-
} else {
77-
toast.error('Invalid GitHub repository URL');
78-
}
79-
} else {
80-
if (url && isValidTarballUrl(url)) {
81-
form.setValue('applicationName', url);
82-
}
83-
}
84-
};
68+
69+
//NOTE - disabled for now until we build out OAuth to improve the experience from private repos/packages
70+
// const handleFetchApplication = async (url: string) => {
71+
// if (url.includes('github.com')) {
72+
// const response = await getGitHubRepo(new URL(url));
73+
// if (response) {
74+
// form.setValue('applicationName', response);
75+
// toast.success(`Application "${response}" found successfully`);
76+
// } else {
77+
// toast.error('Invalid GitHub repository URL');
78+
// }
79+
// } else {
80+
// if (url && isValidTarballUrl(url)) {
81+
// form.setValue('applicationName', url);
82+
// }
83+
// }
84+
// };
8585

8686
return (
8787
<div className="mx-auto max-w-96">
@@ -92,7 +92,7 @@ export function ImportProjectForm({
9292
name="applicationName"
9393
render={({ field }) => (
9494
<FormItem>
95-
<FormLabel className="pb-1">New Project Name</FormLabel>
95+
<FormLabel className="pb-1">New Application Name</FormLabel>
9696
<FormControl>
9797
<Input type="text" placeholder="e-commerce-store" {...field} />
9898
</FormControl>
@@ -105,16 +105,14 @@ export function ImportProjectForm({
105105
name="applicationUrl"
106106
render={({ field }) => (
107107
<FormItem>
108-
<FormLabel className="pb-1">Project URL</FormLabel>
108+
<FormLabel className="pb-1">Package Reference</FormLabel>
109109
<FormControl>
110110
<Input
111111
type="url"
112112
placeholder="https://github.com/HarperDB/nextjs-example"
113113
{...field}
114114
onChange={(e: FormEvent<HTMLInputElement>) => {
115-
// field.onChange(handleFetchApplication(e.currentTarget.value));
116115
field.onChange(e.currentTarget.value);
117-
handleFetchApplication(e.currentTarget.value);
118116
}}
119117
/>
120118
</FormControl>
@@ -123,7 +121,7 @@ export function ImportProjectForm({
123121
)}
124122
/>
125123
<Button
126-
className="w-full mt-4"
124+
className="w-full"
127125
variant="submit"
128126
type="submit"
129127
disabled={!form.formState.isDirty || isDeployComponentPending}

0 commit comments

Comments
 (0)