Display project URLs in Overview tab #20

Merged
nabarun merged 5 commits from nv-display-base-domain into main 2024-10-29 14:10:02 +00:00
10 changed files with 143 additions and 121 deletions

View File

@ -140,6 +140,7 @@ export class Database {
)
.leftJoinAndSelect('deployments.createdBy', 'user')
.leftJoinAndSelect('deployments.domain', 'domain')
.leftJoinAndSelect('deployments.deployer', 'deployer')
.leftJoinAndSelect('project.owner', 'owner')
.leftJoinAndSelect('project.deployers', 'deployers')
.leftJoinAndSelect('project.organization', 'organization')

View File

@ -143,6 +143,7 @@ type Deployer {
paymentAddress: String
createdAt: String!
updatedAt: String!
baseDomain: String
}
type AuthResult {

View File

@ -70,6 +70,7 @@ const Configure = () => {
maxPrice: DEFAULT_MAX_PRICE,
lrn: '',
numProviders: 1,
variables: [],
},
});
@ -173,100 +174,110 @@ const Configure = () => {
const handleFormSubmit = useCallback(
async (createFormData: FieldValues) => {
const deployerLrn = createFormData.lrn;
const deployer = deployers.find(
(deployer) => deployer.deployerLrn === deployerLrn,
);
let amount: string;
let senderAddress: string;
let txHash: string;
if (createFormData.option === 'LRN' && !deployer?.minimumPayment) {
toast({
id: 'no-payment-required',
title: 'No payment required. Deploying app...',
variant: 'info',
onDismiss: dismiss,
});
txHash = '';
senderAddress = '';
} else {
if (!selectedAccount) return;
senderAddress = selectedAccount.split(':')[2];
if (createFormData.option === 'LRN') {
amount = deployer?.minimumPayment!;
} else {
amount = (
createFormData.numProviders * createFormData.maxPrice
).toString();
}
const amountToBePaid = amount.replace(/\D/g, '').toString();
const txHashResponse = await cosmosSendTokensHandler(
selectedAccount,
amountToBePaid,
try {
const deployerLrn = createFormData.lrn;
const deployer = deployers.find(
(deployer) => deployer.deployerLrn === deployerLrn,
);
if (!txHashResponse) {
console.error('Tx not successful');
return;
let amount: string;
let senderAddress: string;
let txHash: string;
if (createFormData.option === 'LRN' && !deployer?.minimumPayment) {
toast({
id: 'no-payment-required',
title: 'No payment required. Deploying app...',
variant: 'info',
onDismiss: dismiss,
});
txHash = '';
senderAddress = '';
} else {
if (!selectedAccount) return;
senderAddress = selectedAccount.split(':')[2];
if (createFormData.option === 'LRN') {
amount = deployer?.minimumPayment!;
} else {
amount = (
createFormData.numProviders * createFormData.maxPrice
).toString();
}
const amountToBePaid = amount.replace(/\D/g, '').toString();
const txHashResponse = await cosmosSendTokensHandler(
selectedAccount,
amountToBePaid,
);
if (!txHashResponse) {
console.error('Tx not successful');
return;
}
txHash = txHashResponse;
const isTxHashValid = await verifyTx(
senderAddress,
txHash,
amountToBePaid.toString(),
);
if (isTxHashValid === false) {
console.error('Invalid Tx hash', txHash);
return;
}
}
txHash = txHashResponse;
const environmentVariables = createFormData.variables.map(
(variable: any) => {
return {
key: variable.key,
value: variable.value,
environments: Object.entries(createFormData.environment)
.filter(([, value]) => value === true)
.map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)),
};
},
);
const isTxHashValid = await verifyTx(
const projectId = await createProject(
createFormData,
environmentVariables,
senderAddress,
txHash,
amountToBePaid.toString(),
);
if (isTxHashValid === false) {
console.error('Invalid Tx hash', txHash);
return;
await client.getEnvironmentVariables(projectId);
if (templateId) {
createFormData.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
)
: navigate(
`/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}`,
);
} else {
createFormData.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
)
: navigate(
`/${orgSlug}/projects/create/deploy?projectId=${projectId}`,
);
}
}
const environmentVariables = createFormData.variables.map(
(variable: any) => {
return {
key: variable.key,
value: variable.value,
environments: Object.entries(createFormData.environment)
.filter(([, value]) => value === true)
.map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)),
};
},
);
const projectId = await createProject(
createFormData,
environmentVariables,
senderAddress,
txHash,
);
await client.getEnvironmentVariables(projectId);
if (templateId) {
createFormData.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
)
: navigate(
`/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}`,
);
} else {
createFormData.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
)
: navigate(
`/${orgSlug}/projects/create/deploy?projectId=${projectId}`,
);
} catch (error) {
console.error(error);
toast({
id: 'error-deploying-app',
title: 'Error deploying app',
variant: 'error',
onDismiss: dismiss,
});
}
},
[client, createProject, dismiss, toast],
@ -281,10 +292,13 @@ const Configure = () => {
setSelectedAccount(account);
}, []);
const onDeployerChange = useCallback((selectedLrn: string) => {
const deployer = deployers.find((d) => d.deployerLrn === selectedLrn);
setSelectedDeployer(deployer);
}, [deployers]);
const onDeployerChange = useCallback(
(selectedLrn: string) => {
const deployer = deployers.find((d) => d.deployerLrn === selectedLrn);
setSelectedDeployer(deployer);
},
[deployers],
);
const cosmosSendTokensHandler = useCallback(
async (selectedAccount: string, amount: string) => {
@ -496,8 +510,7 @@ const Configure = () => {
<EnvironmentVariablesForm />
</div>
{selectedOption === 'LRN' &&
!selectedDeployer?.minimumPayment ? (
{selectedOption === 'LRN' && !selectedDeployer?.minimumPayment ? (
<div>
<Button
{...buttonSize}

View File

@ -42,31 +42,31 @@ export const AuctionCard = ({ project }: { project: Project }) => {
<LoadingIcon className="animate-spin" />
);
const checkAuctionStatus = useCallback(async () => {
const result = await client.getAuctionData(project.auctionId);
setAuctionStatus(result.status);
setAuctionDetails(result);
setDeployers(project.deployers);
setFundsStatus(project.fundsReleased);
}, []);
const checkAuctionStatus = useCallback(async () => {
const result = await client.getAuctionData(project.auctionId);
setAuctionStatus(result.status);
setAuctionDetails(result);
}, [project.auctionId, project.deployers, project.fundsReleased]);
useEffect(() => {
if (auctionStatus !== 'completed') {
checkAuctionStatus();
const intervalId = setInterval(checkAuctionStatus, WAIT_DURATION);
return () => clearInterval(intervalId);
}
const fetchUpdatedProject = useCallback(async () => {
const updatedProject = await client.getProject(project.id);
setDeployers(updatedProject.project!.deployers!);
setFundsStatus(updatedProject.project!.fundsReleased!);
}, [project.id]);
if (auctionStatus === 'completed') {
const fetchUpdatedProject = async () => {
// Wait for 5 secs since the project is not immediately updated with deployer LRNs
await new Promise((resolve) => setTimeout(resolve, WAIT_DURATION));
const updatedProject = await client.getProject(project.id);
setDeployers(updatedProject.project?.deployers || []);
};
fetchUpdatedProject();
}
}, [auctionStatus, client]);
const fetchData = useCallback(async () => {
await Promise.all([checkAuctionStatus(), fetchUpdatedProject()]);
}, [checkAuctionStatus, fetchUpdatedProject]);
useEffect(() => {
fetchData();
const timerId = setInterval(() => {
fetchData();
}, WAIT_DURATION);
return () => clearInterval(timerId);
}, [fetchData]);
const renderAuctionStatus = useCallback(
() => (
@ -134,7 +134,7 @@ export const AuctionCard = ({ project }: { project: Project }) => {
size="xs"
type={fundsStatus ? 'positive' : 'emphasized'}
>
{fundsStatus ? 'RELEASED' : 'LOCKED'}
{fundsStatus ? 'RELEASED' : 'WAITING'}
</Tag>
</div>
</div>

View File

@ -31,8 +31,8 @@ const axiosInstance = axios.create({
withCredentials: true,
});
const metadata = {
name: 'Web3Modal',
description: 'Snowball Web3Modal',
name: 'Deploy App Auth',
description: '',
url: window.location.origin,
icons: ['https://avatars.githubusercontent.com/u/37784886'],
};

View File

@ -41,6 +41,7 @@ const deployment: Deployment = {
deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu',
deployerLrn: 'lrn://example/deployers/webapp-deployer-api.example.com',
minimumPayment: '1000alnt',
baseDomain: 'pwa.example.com',
},
status: DeploymentStatus.Ready,
createdBy: {

View File

@ -129,16 +129,16 @@ const OverviewTabPanel = () => {
<Heading className="text-lg leading-6 font-medium truncate">
{project.name}
</Heading>
{project.baseDomains &&
project.baseDomains.length > 0 &&
project.baseDomains.map((baseDomain, index) => (
{project.deployments &&
project.deployments.length > 0 &&
project.deployments.map((deployment, index) => (
<p>
<a
key={index}
href={`https://${project.name.toLowerCase()}.${baseDomain}`}
href={`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}
className="text-sm text-elements-low-em tracking-tight truncate"
>
{baseDomain}
{deployment.deployer.baseDomain}
</a>
</p>
))}

View File

@ -107,6 +107,7 @@ export const deployment0: Deployment = {
deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu',
deployerLrn: 'lrn://deployer.apps.snowballtools.com ',
minimumPayment: '1000alnt',
baseDomain: 'pwa.example.com',
},
applicationDeploymentRequestId:
'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize',
@ -134,6 +135,7 @@ export const project: Project = {
deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu',
deployerLrn: 'lrn://deployer.apps.snowballtools.com ',
minimumPayment: '1000alnt',
baseDomain: 'pwa.example.com',
},
],
paymentAddress: '0x657868687686rb4787987br8497298r79284797487',

View File

@ -57,6 +57,9 @@ query ($projectId: String!) {
commitHash
createdAt
environment
deployer {
baseDomain
}
domain {
status
branch

View File

@ -119,6 +119,7 @@ export type Deployer = {
deployerLrn: string;
deployerId: string;
deployerApiUrl: string;
baseDomain: string;
minimumPayment: string | null;
}