Integrate SP auctions for app deployment #2
@ -222,13 +222,13 @@ type Mutation {
|
||||
addProjectFromTemplate(
|
||||
organizationSlug: String!
|
||||
data: AddProjectFromTemplateInput
|
||||
lrn: [String]
|
||||
lrn: String
|
||||
auctionData: AuctionData
|
||||
): Project!
|
||||
addProject(
|
||||
organizationSlug: String!
|
||||
data: AddProjectInput
|
||||
lrn: [String]
|
||||
lrn: String
|
||||
auctionData: AuctionData
|
||||
): Project!
|
||||
updateProject(projectId: String!, data: UpdateProjectInput): Boolean!
|
||||
|
@ -644,6 +644,14 @@ export class Service {
|
||||
applicationDeploymentRequestData,
|
||||
});
|
||||
|
||||
// Save deployer lrn only if present
|
||||
let updateData: Partial<Project> = {};
|
||||
if (lrn) {
|
||||
updateData.deployerLrn = [lrn];
|
||||
}
|
||||
|
||||
await this.db.updateProjectById(data.project.id!, updateData);
|
||||
|
||||
return newDeployment;
|
||||
}
|
||||
|
||||
|
165
packages/frontend/src/components/projects/create/Configure.tsx
Normal file
165
packages/frontend/src/components/projects/create/Configure.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useForm, Controller, SubmitHandler } from 'react-hook-form';
|
||||
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { Heading } from '../../shared/Heading';
|
||||
import { Button } from '../../shared/Button';
|
||||
import { Select, SelectOption } from 'components/shared/Select';
|
||||
import { Input } from 'components/shared/Input';
|
||||
import { useToast } from 'components/shared/Toast';
|
||||
import { useGQLClient } from '../../../context/GQLClientContext';
|
||||
|
||||
type ConfigureFormValues = {
|
||||
option: string;
|
||||
lrn?: string;
|
||||
numProviders?: number;
|
||||
maxPrice?: number;
|
||||
};
|
||||
|
||||
const Configure = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const templateId = searchParams.get('templateId');
|
||||
const location = useLocation();
|
||||
const { templateOwner, templateRepo, owner, name, isPrivate, orgSlug } = location.state || {};
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { toast, dismiss } = useToast();
|
||||
const client = useGQLClient();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { handleSubmit, control, watch } = useForm<ConfigureFormValues>({
|
||||
defaultValues: { option: 'LRN' },
|
||||
});
|
||||
|
||||
const selectedOption = watch('option');
|
||||
|
||||
const onSubmit: SubmitHandler<ConfigureFormValues> = useCallback(
|
||||
async (data) => {
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const projectData: any = {
|
||||
templateOwner,
|
||||
templateRepo,
|
||||
owner,
|
||||
name,
|
||||
isPrivate
|
||||
};
|
||||
|
||||
let configData: any;
|
||||
if (data.option === 'LRN') {
|
||||
configData = data.lrn;
|
||||
} else if (data.option === 'Auction') {
|
||||
configData = {
|
||||
numProviders: data.numProviders,
|
||||
maxPrice: data.maxPrice
|
||||
}
|
||||
}
|
||||
|
||||
const { addProjectFromTemplate } = await client.addProjectFromTemplate(
|
||||
orgSlug,
|
||||
projectData,
|
||||
configData
|
||||
);
|
||||
|
||||
navigate(`/${orgSlug}/projects/create/template/deploy?projectId=${addProjectFromTemplate.id}&templateId=${templateId}`);
|
||||
} catch (error) {
|
||||
console.error('Error creating project:', error);
|
||||
toast({
|
||||
id: 'error-creating-project',
|
||||
title: 'Error creating project',
|
||||
variant: 'error',
|
||||
onDismiss: dismiss,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[client, isPrivate, templateId, navigate, dismiss, toast]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-7">
|
||||
<div className="flex justify-between">
|
||||
<div className="space-y-1.5">
|
||||
<Heading as="h4" className="md:text-lg font-medium">
|
||||
Configure deployment
|
||||
</Heading>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="flex flex-col gap-4 lg:gap-7 w-full">
|
||||
<div className="flex flex-col justify-start gap-3">
|
||||
<span className="text-sm text-elements-high-em">Choose an option</span>
|
||||
<Controller
|
||||
name="option"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<Select
|
||||
value={{ value } as SelectOption}
|
||||
onChange={(value) =>
|
||||
onChange((value as SelectOption).value)
|
||||
}
|
||||
options={[
|
||||
{ value: 'LRN', label: 'Set LRN' },
|
||||
{ value: 'Auction', label: 'Create Auction' },
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{selectedOption === 'LRN' && (
|
||||
<div className="flex flex-col justify-start gap-3">
|
||||
<span className="text-sm text-elements-high-em">Enter LRN</span>
|
||||
<Controller
|
||||
name="lrn"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<Input value={value} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectedOption === 'Auction' && (
|
||||
<>
|
||||
<div className="flex flex-col justify-start gap-3">
|
||||
<span className="text-sm text-elements-high-em">Num Providers</span>
|
||||
<Controller
|
||||
name="numProviders"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<Input type="number" value={value} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col justify-start gap-3">
|
||||
<span className="text-sm text-elements-high-em">Max Price</span>
|
||||
<Controller
|
||||
name="maxPrice"
|
||||
control={control}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<Input type="number" value={value} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
>
|
||||
{isLoading? 'Deploying' : 'Deploy' }
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Configure;
|
@ -31,6 +31,11 @@ const CreateWithTemplate = () => {
|
||||
},
|
||||
{
|
||||
step: 2,
|
||||
route: `/${orgSlug}/projects/create/template/configure`,
|
||||
label: 'Configure',
|
||||
},
|
||||
{
|
||||
step: 3,
|
||||
route: `/${orgSlug}/projects/create/template/deploy`,
|
||||
label: 'Deploy',
|
||||
},
|
||||
|
@ -0,0 +1,7 @@
|
||||
import ConfigureComponent from '../../../../../components/projects/create/Configure';
|
||||
|
||||
const Configure = () => {
|
||||
return <ConfigureComponent />;
|
||||
};
|
||||
|
||||
export default Configure;
|
@ -6,7 +6,6 @@ import { useMediaQuery } from 'usehooks-ts';
|
||||
import { RequestError } from 'octokit';
|
||||
|
||||
import { useOctokit } from '../../../../../context/OctokitContext';
|
||||
import { useGQLClient } from '../../../../../context/GQLClientContext';
|
||||
import { Template } from '../../../../../types/types';
|
||||
import { Heading } from 'components/shared/Heading';
|
||||
import { Input } from 'components/shared/Input';
|
||||
@ -31,7 +30,6 @@ type SubmitRepoValues = {
|
||||
const CreateRepo = () => {
|
||||
const { octokit, isAuth } = useOctokit();
|
||||
const { template } = useOutletContext<{ template: Template }>();
|
||||
const client = useGQLClient();
|
||||
|
||||
const { orgSlug } = useParams();
|
||||
const { toast, dismiss } = useToast();
|
||||
@ -55,19 +53,18 @@ const CreateRepo = () => {
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
const { addProjectFromTemplate } = await client.addProjectFromTemplate(
|
||||
orgSlug!,
|
||||
navigate(
|
||||
`configure?templateId=${template.id}`,
|
||||
{
|
||||
state: {
|
||||
templateOwner: owner,
|
||||
templateRepo: repo,
|
||||
owner: data.account,
|
||||
name: data.repoName,
|
||||
isPrivate: false,
|
||||
orgSlug
|
||||
},
|
||||
);
|
||||
|
||||
navigate(
|
||||
`deploy?projectId=${addProjectFromTemplate.id}&templateId=${template.id}`,
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
setIsLoading(false);
|
||||
@ -203,7 +200,7 @@ const CreateRepo = () => {
|
||||
)
|
||||
}
|
||||
>
|
||||
Deploy
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import CreateRepo from './index';
|
||||
import Configure from './Configure';
|
||||
import Deploy from './Deploy';
|
||||
|
||||
export const templateRoutes = [
|
||||
@ -6,6 +7,10 @@ export const templateRoutes = [
|
||||
index: true,
|
||||
element: <CreateRepo />,
|
||||
},
|
||||
{
|
||||
path: 'configure',
|
||||
element: <Configure />,
|
||||
},
|
||||
{
|
||||
path: 'deploy',
|
||||
element: <Deploy />,
|
||||
|
4
packages/gql-client/dist/index.js
vendored
4
packages/gql-client/dist/index.js
vendored
@ -314,14 +314,14 @@ var updateDeploymentToProd = import_client2.gql`
|
||||
}
|
||||
`;
|
||||
var addProjectFromTemplate = import_client2.gql`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
var addProject = import_client2.gql`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProject(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
|
2
packages/gql-client/dist/index.js.map
vendored
2
packages/gql-client/dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
4
packages/gql-client/dist/index.mjs
vendored
4
packages/gql-client/dist/index.mjs
vendored
@ -287,14 +287,14 @@ var updateDeploymentToProd = gql2`
|
||||
}
|
||||
`;
|
||||
var addProjectFromTemplate = gql2`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
var addProject = gql2`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProject(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
|
2
packages/gql-client/dist/index.mjs.map
vendored
2
packages/gql-client/dist/index.mjs.map
vendored
File diff suppressed because one or more lines are too long
@ -49,7 +49,7 @@ export const updateDeploymentToProd = gql`
|
||||
`;
|
||||
|
||||
export const addProjectFromTemplate = gql`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
@ -57,7 +57,7 @@ export const addProjectFromTemplate = gql`
|
||||
`;
|
||||
|
||||
export const addProject = gql`
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: string, $auctionData: Auctiondata) {
|
||||
mutation ($organizationSlug: String!, $data: AddProjectInput, $lrn: String, $auctionData: AuctionData) {
|
||||
addProject(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionData: $auctionData) {
|
||||
id
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user