Remove organization switcher from side bar (#9)
All checks were successful
Lint / lint (20.x) (push) Successful in 5m1s

Part of [Service provider auctions for web deployments](https://www.notion.so/Service-provider-auctions-for-web-deployments-104a6b22d47280dbad51d28aa3a91d75)
- Display DNS URLs in overview tab

Co-authored-by: Neeraj <neeraj.rtly@gmail.com>
Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #9
This commit is contained in:
nabarun 2024-10-22 10:16:35 +00:00
parent 5152952a45
commit 27ef859075
23 changed files with 203 additions and 158 deletions

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Repository URL # Repository URL
REPO_URL="https://github.com/snowball-tools/snowballtools-base" REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base"
# Get the latest commit hash from the repository # Get the latest commit hash from the repository
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}') LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')

View File

@ -14,5 +14,5 @@ record:
LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2 LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2
meta: meta:
note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024 note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024
repository: "https://github.com/snowball-tools/snowballtools-base" repository: "https://git.vdb.to/cerc-io/snowballtools-base"
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e

View File

@ -2,7 +2,7 @@ record:
type: ApplicationRecord type: ApplicationRecord
version: 0.0.2 version: 0.0.2
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
repository: ["https://github.com/snowball-tools/snowballtools-base"] repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
app_type: webapp app_type: webapp
name: snowballtools-base-frontend name: snowballtools-base-frontend
app_version: 0.1.8 app_version: 0.1.8

View File

@ -20,5 +20,5 @@ record:
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591 LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
meta: meta:
note: Added by Snowball @ Mon Jun 24 23:51:48 UTC 2024 note: Added by Snowball @ Mon Jun 24 23:51:48 UTC 2024
repository: "https://github.com/snowball-tools/snowballtools-base" repository: "https://git.vdb.to/cerc-io/snowballtools-base"
repository_ref: 61e3e88a6c9d57e95441059369ee5a46f5c07601 repository_ref: 61e3e88a6c9d57e95441059369ee5a46f5c07601

View File

@ -2,7 +2,7 @@ record:
type: ApplicationRecord type: ApplicationRecord
version: 0.0.1 version: 0.0.1
repository_ref: 61e3e88a6c9d57e95441059369ee5a46f5c07601 repository_ref: 61e3e88a6c9d57e95441059369ee5a46f5c07601
repository: ["https://github.com/snowball-tools/snowballtools-base"] repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
app_type: webapp app_type: webapp
name: staging-snowballtools-base-frontend name: staging-snowballtools-base-frontend
app_version: 0.0.0 app_version: 0.0.0

View File

@ -10,11 +10,16 @@ import {
LinkChainIcon, LinkChainIcon,
} from 'components/shared/CustomIcon'; } from 'components/shared/CustomIcon';
import { TagProps } from 'components/shared/Tag'; import { TagProps } from 'components/shared/Tag';
import {
ArrowRightCircleFilledIcon,
LoadingIcon,
} from 'components/shared/CustomIcon';
interface ChangeStateToProductionDialogProps extends ConfirmDialogProps { interface ChangeStateToProductionDialogProps extends ConfirmDialogProps {
deployment: Deployment; deployment: Deployment;
newDeployment?: Deployment; newDeployment?: Deployment;
domains: Domain[]; domains: Domain[];
isConfirmButtonLoading?: boolean;
} }
export const ChangeStateToProductionDialog = ({ export const ChangeStateToProductionDialog = ({
@ -24,6 +29,7 @@ export const ChangeStateToProductionDialog = ({
open, open,
handleCancel, handleCancel,
handleConfirm, handleConfirm,
isConfirmButtonLoading,
...props ...props
}: ChangeStateToProductionDialogProps) => { }: ChangeStateToProductionDialogProps) => {
const currentChip = { const currentChip = {
@ -41,6 +47,14 @@ export const ChangeStateToProductionDialog = ({
handleCancel={handleCancel} handleCancel={handleCancel}
open={open} open={open}
handleConfirm={handleConfirm} handleConfirm={handleConfirm}
confirmButtonProps={{
disabled: isConfirmButtonLoading,
rightIcon: isConfirmButtonLoading ? (
<LoadingIcon className="animate-spin" />
) : (
<ArrowRightCircleFilledIcon />
),
}}
> >
<div className="flex flex-col gap-7"> <div className="flex flex-col gap-7">
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">

View File

@ -25,7 +25,8 @@ type ConfigureDeploymentFormValues = {
maxPrice?: string; maxPrice?: string;
}; };
type ConfigureFormValues = ConfigureDeploymentFormValues & EnvironmentVariablesFormValues; type ConfigureFormValues = ConfigureDeploymentFormValues &
EnvironmentVariablesFormValues;
const Configure = () => { const Configure = () => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@ -55,7 +56,10 @@ const Configure = () => {
const isTabletView = useMediaQuery('(min-width: 720px)'); // md: const isTabletView = useMediaQuery('(min-width: 720px)'); // md:
const buttonSize = isTabletView ? { size: 'lg' as const } : {}; const buttonSize = isTabletView ? { size: 'lg' as const } : {};
const createProject = async (data: FieldValues, envVariables: AddEnvironmentVariableInput[]): Promise<string> => { const createProject = async (
data: FieldValues,
envVariables: AddEnvironmentVariableInput[],
): Promise<string> => {
setIsLoading(true); setIsLoading(true);
let projectId: string | null = null; let projectId: string | null = null;
@ -68,7 +72,7 @@ const Configure = () => {
} else if (data.option === 'Auction') { } else if (data.option === 'Auction') {
auctionParams = { auctionParams = {
numProviders: Number(data.numProviders!), numProviders: Number(data.numProviders!),
maxPrice: (data.maxPrice!).toString(), maxPrice: data.maxPrice!.toString(),
}; };
} }
@ -86,7 +90,7 @@ const Configure = () => {
projectData, projectData,
lrn, lrn,
auctionParams, auctionParams,
envVariables envVariables,
); );
projectId = addProjectFromTemplate.id; projectId = addProjectFromTemplate.id;
@ -94,14 +98,14 @@ const Configure = () => {
const { addProject } = await client.addProject( const { addProject } = await client.addProject(
orgSlug!, orgSlug!,
{ {
name: fullName!, name: `${owner}-${name}`,
prodBranch: defaultBranch!, prodBranch: defaultBranch!,
repository: fullName!, repository: fullName!,
template: 'webapp', template: 'webapp',
}, },
lrn, lrn,
auctionParams, auctionParams,
envVariables envVariables,
); );
projectId = addProject.id; projectId = addProject.id;
@ -127,39 +131,44 @@ const Configure = () => {
const handleFormSubmit = useCallback( const handleFormSubmit = useCallback(
async (createFormData: FieldValues) => { async (createFormData: FieldValues) => {
const environmentVariables = createFormData.variables.map((variable: any) => { const environmentVariables = createFormData.variables.map(
return { (variable: any) => {
key: variable.key, return {
value: variable.value, key: variable.key,
environments: Object.entries(createFormData.environment) value: variable.value,
.filter(([, value]) => value === true) environments: Object.entries(createFormData.environment)
.map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)), .filter(([, value]) => value === true)
}; .map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)),
}); };
},
);
const projectId = await createProject(createFormData, environmentVariables); const projectId = await createProject(
createFormData,
environmentVariables,
);
await client.getEnvironmentVariables(projectId); await client.getEnvironmentVariables(projectId);
if (templateId) { if (templateId) {
createFormData.option === 'Auction' createFormData.option === 'Auction'
? navigate( ? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true`, `/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
) )
: navigate( : navigate(
`/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}` `/${orgSlug}/projects/create/template/deploy?projectId=${projectId}&templateId=${templateId}`,
); );
} else { } else {
createFormData.option === 'Auction' createFormData.option === 'Auction'
? navigate( ? navigate(
`/${orgSlug}/projects/create/success/${projectId}?isAuction=true` `/${orgSlug}/projects/create/success/${projectId}?isAuction=true`,
) )
: navigate( : navigate(
`/${orgSlug}/projects/create/deploy?projectId=${projectId}` `/${orgSlug}/projects/create/deploy?projectId=${projectId}`,
); );
} }
}, },
[client, createProject, dismiss, toast] [client, createProject, dismiss, toast],
); );
return ( return (
@ -190,10 +199,15 @@ const Configure = () => {
value={ value={
{ {
value: value || 'LRN', value: value || 'LRN',
label: value === 'Auction' ? 'Create Auction' : 'Deployer LRN', label:
value === 'Auction'
? 'Create Auction'
: 'Deployer LRN',
} as SelectOption } as SelectOption
} }
onChange={(value) => onChange((value as SelectOption).value)} onChange={(value) =>
onChange((value as SelectOption).value)
}
options={[ options={[
{ value: 'LRN', label: 'Deployer LRN' }, { value: 'LRN', label: 'Deployer LRN' },
{ value: 'Auction', label: 'Create Auction' }, { value: 'Auction', label: 'Create Auction' },
@ -205,7 +219,10 @@ const Configure = () => {
{selectedOption === 'LRN' && ( {selectedOption === 'LRN' && (
<div className="flex flex-col justify-start gap-4 mb-6"> <div className="flex flex-col justify-start gap-4 mb-6">
<Heading as="h5" className="text-sm font-sans text-elements-low-em"> <Heading
as="h5"
className="text-sm font-sans text-elements-low-em"
>
The app will be deployed by the configured deployer The app will be deployed by the configured deployer
</Heading> </Heading>
<span className="text-sm text-elements-high-em"> <span className="text-sm text-elements-high-em">
@ -225,8 +242,12 @@ const Configure = () => {
{selectedOption === 'Auction' && ( {selectedOption === 'Auction' && (
<> <>
<div className="flex flex-col justify-start gap-4 mb-6"> <div className="flex flex-col justify-start gap-4 mb-6">
<Heading as="h5" className="text-sm font-sans text-elements-low-em"> <Heading
Set the number of deployers and maximum price for each deployment as="h5"
className="text-sm font-sans text-elements-low-em"
>
Set the number of deployers and maximum price for each
deployment
</Heading> </Heading>
<span className="text-sm text-elements-high-em"> <span className="text-sm text-elements-high-em">
Number of Deployers Number of Deployers

View File

@ -39,7 +39,7 @@ export const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({
} }
navigate( navigate(
`configure?owner=${repository.owner?.login}&name=${repository.name}&defaultBranch=${repository.default_branch}&fullName=${repository.full_name}&orgSlug=${orgSlug}` `configure?owner=${repository.owner?.login}&name=${repository.name}&defaultBranch=${repository.default_branch}&fullName=${repository.full_name}&orgSlug=${orgSlug}`,
); );
}, [client, repository, orgSlug, setIsLoading, navigate, toast]); }, [client, repository, orgSlug, setIsLoading, navigate, toast]);

View File

@ -34,13 +34,13 @@ import { formatAddress } from '../../../../utils/format';
import { DeploymentMenu } from './DeploymentMenu'; import { DeploymentMenu } from './DeploymentMenu';
const DEPLOYMENT_LOGS_STYLE = { const DEPLOYMENT_LOGS_STYLE = {
backgroundColor: "rgba(0,0,0, .9)", backgroundColor: 'rgba(0,0,0, .9)',
padding: "2em", padding: '2em',
borderRadius: "0.5em", borderRadius: '0.5em',
marginLeft: "0.5em", marginLeft: '0.5em',
marginRight: "0.5em", marginRight: '0.5em',
color: "gray", color: 'gray',
fontSize: "small", fontSize: 'small',
}; };
interface DeployDetailsCardProps { interface DeployDetailsCardProps {
@ -95,7 +95,11 @@ const DeploymentDetailsCard = ({
const logs = await res.text(); const logs = await res.text();
setDeploymentLogs(logs); setDeploymentLogs(logs);
handleOpenDialog(); handleOpenDialog();
}, [deployment.deployer.deployerApiUrl, deployment.applicationDeploymentRequestId, handleOpenDialog]); }, [
deployment.deployer.deployerApiUrl,
deployment.applicationDeploymentRequestId,
handleOpenDialog,
]);
const renderDeploymentStatus = useCallback( const renderDeploymentStatus = useCallback(
(className?: string) => { (className?: string) => {
@ -201,10 +205,15 @@ const DeploymentDetailsCard = ({
prodBranchDomains={prodBranchDomains} prodBranchDomains={prodBranchDomains}
/> />
</div> </div>
<Dialog open={openDialog} onClose={handleCloseDialog} fullWidth maxWidth="md"> <Dialog
open={openDialog}
onClose={handleCloseDialog}
fullWidth
maxWidth="md"
>
<DialogTitle>Deployment logs</DialogTitle> <DialogTitle>Deployment logs</DialogTitle>
<DialogContent style={DEPLOYMENT_LOGS_STYLE} > <DialogContent style={DEPLOYMENT_LOGS_STYLE}>
{deploymentLogs && <pre >{deploymentLogs}</pre>} {deploymentLogs && <pre>{deploymentLogs}</pre>}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={handleCloseDialog}>Close</Button> <Button onClick={handleCloseDialog}>Close</Button>

View File

@ -48,6 +48,8 @@ export const DeploymentMenu = ({
const [redeployToProduction, setRedeployToProduction] = useState(false); const [redeployToProduction, setRedeployToProduction] = useState(false);
const [rollbackDeployment, setRollbackDeployment] = useState(false); const [rollbackDeployment, setRollbackDeployment] = useState(false);
const [assignDomainDialog, setAssignDomainDialog] = useState(false); const [assignDomainDialog, setAssignDomainDialog] = useState(false);
const [isConfirmButtonLoading, setConfirmButtonLoadingLoading] =
useState(false);
const updateDeployment = async () => { const updateDeployment = async () => {
const isUpdated = await client.updateDeploymentToProd(deployment.id); const isUpdated = await client.updateDeploymentToProd(deployment.id);
@ -71,6 +73,7 @@ export const DeploymentMenu = ({
const redeployToProd = async () => { const redeployToProd = async () => {
const isRedeployed = await client.redeployToProd(deployment.id); const isRedeployed = await client.redeployToProd(deployment.id);
setConfirmButtonLoadingLoading(false);
if (isRedeployed) { if (isRedeployed) {
await onUpdate(); await onUpdate();
toast({ toast({
@ -113,12 +116,19 @@ export const DeploymentMenu = ({
}; };
const deleteDeployment = async () => { const deleteDeployment = async () => {
toast({
id: 'deleting_deployment',
title: 'Deleting deployment....',
variant: 'success',
onDismiss: dismiss,
});
const isDeleted = await client.deleteDeployment(deployment.id); const isDeleted = await client.deleteDeployment(deployment.id);
if (isDeleted) { if (isDeleted) {
await onUpdate(); await onUpdate();
toast({ toast({
id: 'deployment_deleted', id: 'deployment_removal_requested',
title: 'Deployment deleted', title: 'Deployment removal requested',
variant: 'success', variant: 'success',
onDismiss: dismiss, onDismiss: dismiss,
}); });
@ -228,11 +238,13 @@ export const DeploymentMenu = ({
open={redeployToProduction} open={redeployToProduction}
confirmButtonTitle="Redeploy" confirmButtonTitle="Redeploy"
handleConfirm={async () => { handleConfirm={async () => {
setConfirmButtonLoadingLoading(true);
await redeployToProd(); await redeployToProd();
setRedeployToProduction((preVal) => !preVal); setRedeployToProduction((preVal) => !preVal);
}} }}
deployment={deployment} deployment={deployment}
domains={deployment.domain ? [deployment.domain] : []} domains={deployment.domain ? [deployment.domain] : []}
isConfirmButtonLoading={isConfirmButtonLoading}
/> />
{Boolean(currentDeployment) && ( {Boolean(currentDeployment) && (
<ChangeStateToProductionDialog <ChangeStateToProductionDialog

View File

@ -8,7 +8,10 @@ import {
DialogActions, DialogActions,
} from '@mui/material'; } from '@mui/material';
import { CheckRoundFilledIcon, LoadingIcon } from 'components/shared/CustomIcon'; import {
CheckRoundFilledIcon,
LoadingIcon,
} from 'components/shared/CustomIcon';
import { useGQLClient } from 'context/GQLClientContext'; import { useGQLClient } from 'context/GQLClientContext';
import { Button, Heading, Tag } from 'components/shared'; import { Button, Heading, Tag } from 'components/shared';
@ -23,7 +26,11 @@ export const AuctionCard = ({ project }: { project: Project }) => {
const client = useGQLClient(); const client = useGQLClient();
const getIconByAuctionStatus = (status: string) => const getIconByAuctionStatus = (status: string) =>
status === 'completed' ? <CheckRoundFilledIcon /> : <LoadingIcon className="animate-spin" />; status === 'completed' ? (
<CheckRoundFilledIcon />
) : (
<LoadingIcon className="animate-spin" />
);
const checkAuctionStatus = useCallback(async () => { const checkAuctionStatus = useCallback(async () => {
const result = await client.getAuctionData(project.auctionId); const result = await client.getAuctionData(project.auctionId);
@ -61,7 +68,7 @@ export const AuctionCard = ({ project }: { project: Project }) => {
{auctionStatus.toUpperCase()} {auctionStatus.toUpperCase()}
</Tag> </Tag>
), ),
[auctionStatus] [auctionStatus],
); );
const handleOpenDialog = () => setOpenDialog(true); const handleOpenDialog = () => setOpenDialog(true);
@ -71,19 +78,25 @@ export const AuctionCard = ({ project }: { project: Project }) => {
<> <>
<div className="p-3 gap-2 rounded-xl border border-gray-200 transition-colors hover:bg-base-bg-alternate flex flex-col mt-8"> <div className="p-3 gap-2 rounded-xl border border-gray-200 transition-colors hover:bg-base-bg-alternate flex flex-col mt-8">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<Heading className="text-lg leading-6 font-medium">Auction details</Heading> <Heading className="text-lg leading-6 font-medium">
Auction details
</Heading>
<Button onClick={handleOpenDialog} variant="tertiary" size="sm"> <Button onClick={handleOpenDialog} variant="tertiary" size="sm">
View details View details
</Button> </Button>
</div> </div>
<div className="flex justify-between items-center mt-1"> <div className="flex justify-between items-center mt-1">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Auction Status</span> <span className="text-elements-high-em text-sm font-medium tracking-tight">
Auction Status
</span>
<div className="ml-2">{renderAuctionStatus()}</div> <div className="ml-2">{renderAuctionStatus()}</div>
</div> </div>
<div className="flex justify-between items-center mt-2"> <div className="flex justify-between items-center mt-2">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Auction Id</span> <span className="text-elements-high-em text-sm font-medium tracking-tight">
Auction Id
</span>
<span className="text-elements-mid-em text-sm text-right"> <span className="text-elements-mid-em text-sm text-right">
{project.auctionId} {project.auctionId}
</span> </span>
@ -91,7 +104,9 @@ export const AuctionCard = ({ project }: { project: Project }) => {
{deployerLrns?.length > 0 && ( {deployerLrns?.length > 0 && (
<div className="mt-3"> <div className="mt-3">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Deployer LRNs</span> <span className="text-elements-high-em text-sm font-medium tracking-tight">
Deployer LRNs
</span>
{deployerLrns.map((lrn, index) => ( {deployerLrns.map((lrn, index) => (
<p key={index} className="text-elements-mid-em text-sm"> <p key={index} className="text-elements-mid-em text-sm">
{'\u2022'} {lrn} {'\u2022'} {lrn}
@ -101,22 +116,28 @@ export const AuctionCard = ({ project }: { project: Project }) => {
)} )}
<div className="flex justify-between items-center mt-1"> <div className="flex justify-between items-center mt-1">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Deployer Funds Status</span> <span className="text-elements-high-em text-sm font-medium tracking-tight">
Deployer Funds Status
</span>
<div className="ml-2"> <div className="ml-2">
<Tag <Tag size="xs" type={fundsStatus ? 'positive' : 'emphasized'}>
size="xs"
type={fundsStatus ? 'positive' : 'emphasized'}
>
{fundsStatus ? 'RELEASED' : 'LOCKED'} {fundsStatus ? 'RELEASED' : 'LOCKED'}
</Tag> </Tag>
</div> </div>
</div> </div>
</div> </div>
<Dialog open={openDialog} onClose={handleCloseDialog} fullWidth maxWidth="md"> <Dialog
open={openDialog}
onClose={handleCloseDialog}
fullWidth
maxWidth="md"
>
<DialogTitle>Auction Details</DialogTitle> <DialogTitle>Auction Details</DialogTitle>
<DialogContent> <DialogContent>
{auctionDetails && <pre>{JSON.stringify(auctionDetails, null, 2)}</pre>} {auctionDetails && (
<pre>{JSON.stringify(auctionDetails, null, 2)}</pre>
)}
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={handleCloseDialog}>Close</Button> <Button onClick={handleCloseDialog}>Close</Button>

View File

@ -60,8 +60,10 @@ const DeleteProjectDialog = ({
<Modal.Body> <Modal.Body>
<Input <Input
label={ label={
"Deleting your project is irreversible. Enter your project's name " + '"' + "Deleting your project is irreversible. Enter your project's name " +
project.name + '"' + '"' +
project.name +
'"' +
' below to confirm you want to permanently delete it:' ' below to confirm you want to permanently delete it:'
} }
id="input" id="input"

View File

@ -1,6 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { NavLink, useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { Organization, User } from 'gql-client'; import { User } from 'gql-client';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useDisconnect } from 'wagmi'; import { useDisconnect } from 'wagmi';
@ -19,8 +19,6 @@ import { getInitials } from 'utils/geInitials';
import { Button } from 'components/shared/Button'; import { Button } from 'components/shared/Button';
import { cn } from 'utils/classnames'; import { cn } from 'utils/classnames';
import { useMediaQuery } from 'usehooks-ts'; import { useMediaQuery } from 'usehooks-ts';
import { SIDEBAR_MENU } from './constants';
import { UserSelect } from 'components/shared/UserSelect';
import { BASE_URL } from 'utils/constants'; import { BASE_URL } from 'utils/constants';
interface SidebarProps { interface SidebarProps {
@ -45,46 +43,6 @@ export const Sidebar = ({ mobileOpen }: SidebarProps) => {
fetchUser(); fetchUser();
}, []); }, []);
const [selectedOrgSlug, setSelectedOrgSlug] = useState(orgSlug);
const [organizations, setOrganizations] = useState<Organization[]>([]);
const fetchUserOrganizations = useCallback(async () => {
const { organizations } = await client.getOrganizations();
setOrganizations(organizations);
}, [orgSlug]);
useEffect(() => {
fetchUserOrganizations();
setSelectedOrgSlug(orgSlug);
}, [orgSlug]);
const formattedSelected = useMemo(() => {
const selected = organizations.find((org) => org.slug === selectedOrgSlug);
return {
value: selected?.slug ?? '',
label: selected?.name ?? '',
imgSrc: '/logo.svg',
};
}, [organizations, selectedOrgSlug, orgSlug]);
const formattedSelectOptions = useMemo(() => {
return organizations.map((org) => ({
value: org.slug,
label: org.name,
imgSrc: '/logo.svg',
}));
}, [organizations, selectedOrgSlug, orgSlug]);
const renderMenu = useMemo(() => {
return SIDEBAR_MENU(orgSlug).map(({ title, icon, url }, index) => (
<NavLink to={url} key={index}>
<Tabs.Trigger icon={icon} value={title}>
{title}
</Tabs.Trigger>
</NavLink>
));
}, [orgSlug]);
const handleLogOut = useCallback(async () => { const handleLogOut = useCallback(async () => {
await fetch(`${BASE_URL}/auth/logout`, { await fetch(`${BASE_URL}/auth/logout`, {
method: 'POST', method: 'POST',
@ -117,16 +75,8 @@ export const Sidebar = ({ mobileOpen }: SidebarProps) => {
<div className="hidden lg:flex"> <div className="hidden lg:flex">
<Logo orgSlug={orgSlug} /> <Logo orgSlug={orgSlug} />
</div> </div>
{/* Switch organization */} {/* This element ensures the space between logo and navigation */}
<div className="flex flex-1 flex-col gap-4"> <div className="flex-1"></div>
<UserSelect
value={formattedSelected}
options={formattedSelectOptions}
/>
<Tabs defaultValue="Projects" orientation="vertical">
<Tabs.List>{renderMenu}</Tabs.List>
</Tabs>
</div>
{/* Bottom navigation */} {/* Bottom navigation */}
<div className="flex flex-col gap-5 justify-end"> <div className="flex flex-col gap-5 justify-end">
<Tabs defaultValue="Projects" orientation="vertical"> <Tabs defaultValue="Projects" orientation="vertical">

View File

@ -55,7 +55,7 @@ const siweConfig = createSIWEConfig({
statement: 'Sign in With Ethereum.', statement: 'Sign in With Ethereum.',
}).prepareMessage(), }).prepareMessage(),
getNonce: async () => { getNonce: async () => {
return generateNonce() return generateNonce();
}, },
getSession: async () => { getSession: async () => {
try { try {

View File

@ -17,7 +17,6 @@ import { LogErrorBoundary } from 'utils/log-error';
import { BASE_URL } from 'utils/constants'; import { BASE_URL } from 'utils/constants';
import Web3ModalProvider from './context/Web3Provider'; import Web3ModalProvider from './context/Web3Provider';
console.log(`v-0.0.9`); console.log(`v-0.0.9`);
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
@ -33,11 +32,11 @@ root.render(
<LogErrorBoundary> <LogErrorBoundary>
<React.StrictMode> <React.StrictMode>
<ThemeProvider> <ThemeProvider>
<Web3ModalProvider> <Web3ModalProvider>
<GQLClientProvider client={gqlClient}> <GQLClientProvider client={gqlClient}>
<App /> <App />
<Toaster /> <Toaster />
</GQLClientProvider> </GQLClientProvider>
</Web3ModalProvider> </Web3ModalProvider>
</ThemeProvider> </ThemeProvider>
</React.StrictMode> </React.StrictMode>

View File

@ -12,7 +12,7 @@ export const Login = () => {
<div className="self-stretch p-4 xs:p-6 flex-col justify-center items-center gap-8 flex"> <div className="self-stretch p-4 xs:p-6 flex-col justify-center items-center gap-8 flex">
<div className="self-stretch flex-col justify-center items-center gap-3 flex"> <div className="self-stretch flex-col justify-center items-center gap-3 flex">
<w3m-button /> <w3m-button />
</div> </div>
</div> </div>
</div> </div>

View File

@ -39,7 +39,7 @@ const deployment: Deployment = {
deployer: { deployer: {
deployerApiUrl: 'https://webapp-deployer-api.example.com', deployerApiUrl: 'https://webapp-deployer-api.example.com',
deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu', deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu',
deployerLrn:'lrn://example/deployers/webapp-deployer-api.example.com' deployerLrn: 'lrn://example/deployers/webapp-deployer-api.example.com',
}, },
status: DeploymentStatus.Ready, status: DeploymentStatus.Ready,
createdBy: { createdBy: {
@ -53,7 +53,8 @@ const deployment: Deployment = {
}, },
createdAt: '1677676800', // 2023-03-01T12:00:00Z createdAt: '1677676800', // 2023-03-01T12:00:00Z
updatedAt: '1677680400', // 2023-03-01T13:00:00Z updatedAt: '1677680400', // 2023-03-01T13:00:00Z
applicationDeploymentRequestId: 'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize', applicationDeploymentRequestId:
'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize',
}; };
const domains: Domain[] = [ const domains: Domain[] = [

View File

@ -1,4 +1,4 @@
import { Link, useParams, useSearchParams } from 'react-router-dom'; import { Link, useParams, useSearchParams } from 'react-router-dom';
import Lottie from 'lottie-react'; import Lottie from 'lottie-react';
import { Badge } from 'components/shared/Badge'; import { Badge } from 'components/shared/Badge';
@ -48,7 +48,9 @@ const Id = () => {
{/* Heading */} {/* Heading */}
<div className="flex flex-col items-center gap-1.5"> <div className="flex flex-col items-center gap-1.5">
<Heading as="h3" className="font-medium text-xl"> <Heading as="h3" className="font-medium text-xl">
{isAuction? 'Auction created successfully.' : 'Project deployment created successfully.'} {isAuction
? 'Auction created successfully.'
: 'Project deployment created successfully.'}
</Heading> </Heading>
</div> </div>

View File

@ -54,7 +54,7 @@ const CreateRepo = () => {
setIsLoading(true); setIsLoading(true);
navigate( navigate(
`configure?templateId=${template.id}&templateOwner=${owner}&templateRepo=${repo}&owner=${data.account}&name=${data.repoName}&isPrivate=false&orgSlug=${orgSlug}` `configure?templateId=${template.id}&templateOwner=${owner}&templateRepo=${repo}&owner=${data.account}&name=${data.repoName}&isPrivate=false&orgSlug=${orgSlug}`,
); );
} catch (err) { } catch (err) {
setIsLoading(false); setIsLoading(false);
@ -173,7 +173,7 @@ const CreateRepo = () => {
<Controller <Controller
name="isPrivate" name="isPrivate"
control={control} control={control}
render={({ }) => ( render={({}) => (
<Checkbox label="Make this repo private" disabled={true} /> <Checkbox label="Make this repo private" disabled={true} />
)} )}
/> />

View File

@ -129,15 +129,19 @@ const OverviewTabPanel = () => {
<Heading className="text-lg leading-6 font-medium truncate"> <Heading className="text-lg leading-6 font-medium truncate">
{project.name} {project.name}
</Heading> </Heading>
{project.baseDomains && project.baseDomains.length > 0 && project.baseDomains.map((baseDomain, index) => ( {project.baseDomains &&
<a project.baseDomains.length > 0 &&
key={index} project.baseDomains.map((baseDomain, index) => (
href={`https://${project.name}.${baseDomain}`} <p>
className="text-sm text-elements-low-em tracking-tight truncate" <a
> key={index}
{baseDomain} href={`https://${project.name.toLowerCase()}.${baseDomain}`}
</a> className="text-sm text-elements-low-em tracking-tight truncate"
))} >
{baseDomain}
</a>
</p>
))}
</div> </div>
</div> </div>
<OverviewInfo label="Domain" icon={<GlobeIcon />}> <OverviewInfo label="Domain" icon={<GlobeIcon />}>
@ -209,7 +213,7 @@ const OverviewTabPanel = () => {
No current deployment found. No current deployment found.
</p> </p>
)} )}
{project.auctionId && <AuctionCard project={project}/>} {project.auctionId && <AuctionCard project={project} />}
</div> </div>
<Activity activities={activities} isLoading={fetchingActivities} /> <Activity activities={activities} isLoading={fetchingActivities} />
</div> </div>

View File

@ -64,15 +64,17 @@ export const EnvironmentVariablesTabPanel = () => {
const createEnvironmentVariablesHandler = useCallback( const createEnvironmentVariablesHandler = useCallback(
async (createFormData: FieldValues) => { async (createFormData: FieldValues) => {
const environmentVariables = createFormData.variables.map((variable: any) => { const environmentVariables = createFormData.variables.map(
return { (variable: any) => {
key: variable.key, return {
value: variable.value, key: variable.key,
environments: Object.entries(createFormData.environment) value: variable.value,
.filter(([, value]) => value === true) environments: Object.entries(createFormData.environment)
.map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)), .filter(([, value]) => value === true)
}; .map(([key]) => key.charAt(0).toUpperCase() + key.slice(1)),
}); };
},
);
const { addEnvironmentVariables: isEnvironmentVariablesAdded } = const { addEnvironmentVariables: isEnvironmentVariablesAdded } =
await client.addEnvironmentVariables(id!, environmentVariables); await client.addEnvironmentVariables(id!, environmentVariables);
@ -124,7 +126,11 @@ export const EnvironmentVariablesTabPanel = () => {
</Heading> </Heading>
<Collapse open={createNewVariable}> <Collapse open={createNewVariable}>
<FormProvider {...methods}> <FormProvider {...methods}>
<form onSubmit={methods.handleSubmit((data) => createEnvironmentVariablesHandler(data))}> <form
onSubmit={methods.handleSubmit((data) =>
createEnvironmentVariablesHandler(data),
)}
>
<div className="p-4 bg-slate-100"> <div className="p-4 bg-slate-100">
<EnvironmentVariablesForm /> <EnvironmentVariablesForm />
</div> </div>

View File

@ -67,7 +67,10 @@ const EnvironmentVariablesForm = () => {
<div className="flex gap-2 p-2"> <div className="flex gap-2 p-2">
<Checkbox label="Production" {...register('environment.production')} /> <Checkbox label="Production" {...register('environment.production')} />
<Checkbox label="Preview" {...register('environment.preview')} /> <Checkbox label="Preview" {...register('environment.preview')} />
<Checkbox label="Development" {...register('environment.development')} /> <Checkbox
label="Development"
{...register('environment.development')}
/>
</div> </div>
</> </>
); );

View File

@ -102,12 +102,13 @@ export const deployment0: Deployment = {
domain: domain0, domain: domain0,
commitMessage: 'Commit Message', commitMessage: 'Commit Message',
createdBy: user, createdBy: user,
deployer: { deployer: {
deployerApiUrl: 'https://webapp-deployer-api.example.com', deployerApiUrl: 'https://webapp-deployer-api.example.com',
deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu', deployerId: 'bafyreicrtgmkir4evvvysxdqxddf2ftdq2wrzuodgvwnxr4rmubi4obdfu',
deployerLrn:'lrn://deployer.apps.snowballtools.com ' deployerLrn: 'lrn://deployer.apps.snowballtools.com ',
}, },
applicationDeploymentRequestId: 'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize', applicationDeploymentRequestId:
'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize',
}; };
export const project: Project = { export const project: Project = {