UI fixes in Snowball frontend app (#93)
* Fix alignment of deployment status chip * Use template name from env * Use env for git template link * Add loading spinner for create project * Display user name * Format the displayed user name --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
e816c596ca
commit
6b17dce2ae
6
packages/backend/test/fixtures/users.json
vendored
6
packages/backend/test/fixtures/users.json
vendored
@ -1,19 +1,19 @@
|
||||
[
|
||||
{
|
||||
"id": "59f4355d-9549-4aac-9b54-eeefceeabef0",
|
||||
"name": "Snowball",
|
||||
"name": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||
"email": "snowball@snowballtools.xyz",
|
||||
"isVerified": true
|
||||
},
|
||||
{
|
||||
"id": "e505b212-8da6-48b2-9614-098225dab34b",
|
||||
"name": "Alice Anderson",
|
||||
"name": "0xbe0eb53f46cd790cd13851d5eff43d12404d33e8",
|
||||
"email": "alice@snowballtools.xyz",
|
||||
"isVerified": true
|
||||
},
|
||||
{
|
||||
"id": "cd892fad-9138-4aa2-a62c-414a32776ea7",
|
||||
"name": "Bob Banner",
|
||||
"name": "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a",
|
||||
"email": "bob@snowballtools.xyz",
|
||||
"isVerified": true
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import { Chip, IconButton } from '@material-tailwind/react';
|
||||
import { Chip, IconButton, Spinner } from '@material-tailwind/react';
|
||||
|
||||
import { relativeTimeISO } from '../../../utils/time';
|
||||
import { GitRepositoryDetails } from '../../../types';
|
||||
@ -14,6 +15,7 @@ interface ProjectRepoCardProps {
|
||||
const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
const client = useGQLClient();
|
||||
const navigate = useNavigate();
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
|
||||
const { orgSlug } = useParams();
|
||||
|
||||
@ -22,6 +24,7 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
const { addProject } = await client.addProject(orgSlug!, {
|
||||
name: `${repository.owner!.login}-${repository.name}`,
|
||||
prodBranch: repository.default_branch!,
|
||||
@ -30,7 +33,13 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
template: 'webapp',
|
||||
});
|
||||
|
||||
if (Boolean(addProject)) {
|
||||
setIsLoading(false);
|
||||
navigate(`import?projectId=${addProject.id}`);
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
toast.error('Failed to create project');
|
||||
}
|
||||
}, [client, repository]);
|
||||
|
||||
return (
|
||||
@ -53,9 +62,13 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
</div>
|
||||
<p>{repository.updated_at && relativeTimeISO(repository.updated_at)}</p>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
<Spinner className="h-4 w-4" />
|
||||
) : (
|
||||
<div className="hidden group-hover:block">
|
||||
<IconButton size="sm">{'>'}</IconButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -87,18 +87,12 @@ const DeploymentDetailsCard = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 gap-2 border-b border-gray-300 p-3 my-2">
|
||||
<div className="col-span-2">
|
||||
<div className="grid grid-cols-8 gap-2 border-b border-gray-300 p-3 my-2">
|
||||
<div className="col-span-3">
|
||||
<div className="flex">
|
||||
{deployment.url && (
|
||||
<Typography className=" basis-3/4">{deployment.url}</Typography>
|
||||
)}
|
||||
<Chip
|
||||
value={deployment.status}
|
||||
color={STATUS_COLORS[deployment.status] ?? 'gray'}
|
||||
variant="ghost"
|
||||
icon={<i>^</i>}
|
||||
/>
|
||||
</div>
|
||||
<Typography color="gray">
|
||||
{deployment.environment === Environment.Production
|
||||
@ -107,13 +101,21 @@ const DeploymentDetailsCard = ({
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<Chip
|
||||
value={deployment.status}
|
||||
color={STATUS_COLORS[deployment.status] ?? 'gray'}
|
||||
variant="ghost"
|
||||
icon={<i>^</i>}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<Typography color="gray">^ {deployment.branch}</Typography>
|
||||
<Typography color="gray">
|
||||
^ {deployment.commitHash.substring(0, SHORT_COMMIT_HASH_LENGTH)}{' '}
|
||||
{deployment.commitMessage}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="col-span-1 flex items-center">
|
||||
<div className="col-span-2 flex items-center">
|
||||
<Typography color="gray" className="grow">
|
||||
^ {relativeTimeMs(deployment.createdAt)} ^ {deployment.createdBy.name}
|
||||
</Typography>
|
||||
|
@ -44,18 +44,18 @@ const FilterForm = ({ value, onChange }: FilterFormProps) => {
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 gap-2 text-sm text-gray-600">
|
||||
<div className="col-span-2">
|
||||
<div className="grid grid-cols-8 gap-2 text-sm text-gray-600">
|
||||
<div className="col-span-4">
|
||||
<SearchBar
|
||||
placeholder="Search branches"
|
||||
value={searchedBranch}
|
||||
onChange={(event) => setSearchedBranch(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<div className="col-span-2">
|
||||
<DatePicker mode="range" selected={dateRange} onSelect={setDateRange} />
|
||||
</div>
|
||||
<div className="col-span-1 relative">
|
||||
<div className="col-span-2 relative">
|
||||
<Select
|
||||
value={selectedStatus}
|
||||
onChange={(value) => setSelectedStatus(value as StatusOptions)}
|
||||
|
@ -1,4 +1,3 @@
|
||||
export const GIT_TEMPLATE_LINK =
|
||||
'https://git.vdb.to/cerc-io/test-progressive-web-app';
|
||||
export const GIT_TEMPLATE_LINK = `https://github.com/${process.env.REACT_APP_GITHUB_TEMPLATE_REPO}`;
|
||||
|
||||
export const SHORT_COMMIT_HASH_LENGTH = 8;
|
||||
|
@ -1,13 +1,40 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Outlet, useNavigate } from 'react-router-dom';
|
||||
import { User } from 'gql-client';
|
||||
|
||||
import { IconButton, Typography } from '@material-tailwind/react';
|
||||
import { IconButton, Tooltip, Typography } from '@material-tailwind/react';
|
||||
|
||||
import HorizontalLine from '../components/HorizontalLine';
|
||||
import ProjectSearchBar from '../components/projects/ProjectSearchBar';
|
||||
import { useGQLClient } from '../context/GQLClientContext';
|
||||
|
||||
const ProjectSearch = () => {
|
||||
const navigate = useNavigate();
|
||||
const client = useGQLClient();
|
||||
const [user, setUser] = useState<User>();
|
||||
|
||||
const fetchUser = useCallback(async () => {
|
||||
const { user } = await client.getUser();
|
||||
setUser(user);
|
||||
}, []);
|
||||
|
||||
const formattedAddress = useMemo(() => {
|
||||
const address = user?.name || '';
|
||||
|
||||
if (address.length <= 8) {
|
||||
return address;
|
||||
}
|
||||
|
||||
if (address.startsWith('0x')) {
|
||||
return address.slice(0, 4) + '..' + address.slice(-4);
|
||||
}
|
||||
|
||||
return address;
|
||||
}, [user?.name]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUser();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -28,8 +55,10 @@ const ProjectSearch = () => {
|
||||
<div className="mr-2 flex items-center">
|
||||
<Typography>^</Typography>
|
||||
</div>
|
||||
<div className="px-2 py-1 bg-blue-gray-50 rounded-lg">
|
||||
<Typography variant="lead">SY</Typography>
|
||||
<div className="px-2 py-1 bg-blue-gray-50 rounded-lg flex items-center">
|
||||
{user?.name && (
|
||||
<Tooltip content={user.name}>{formattedAddress}</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<HorizontalLine />
|
||||
|
@ -50,7 +50,7 @@ const CreateWithTemplate = () => {
|
||||
<div className="grow px-2">{template?.name}</div>
|
||||
<div>
|
||||
<a href={GIT_TEMPLATE_LINK} target="_blank" rel="noreferrer">
|
||||
^ cerc-io/test-progressive-web-app
|
||||
^ {process.env.REACT_APP_GITHUB_TEMPLATE_REPO}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,7 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import assert from 'assert';
|
||||
|
||||
import { Option, Typography } from '@material-tailwind/react';
|
||||
import { Button, Option, Typography } from '@material-tailwind/react';
|
||||
|
||||
import { useOctokit } from '../../../../../context/OctokitContext';
|
||||
import { useGQLClient } from '../../../../../context/GQLClientContext';
|
||||
@ -27,10 +27,12 @@ const CreateRepo = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [gitAccounts, setGitAccounts] = useState<string[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const submitRepoHandler: SubmitHandler<SubmitRepoValues> = useCallback(
|
||||
async (data) => {
|
||||
assert(data.account);
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
assert(
|
||||
@ -62,11 +64,17 @@ const CreateRepo = () => {
|
||||
template: 'webapp',
|
||||
});
|
||||
|
||||
if (Boolean(addProject)) {
|
||||
setIsLoading(true);
|
||||
navigate(
|
||||
`/${orgSlug}/projects/create/template/deploy?projectId=${addProject.id}`,
|
||||
);
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setIsLoading(false);
|
||||
toast.error('Error deploying project');
|
||||
}
|
||||
},
|
||||
@ -174,9 +182,14 @@ const CreateRepo = () => {
|
||||
</label>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<button className="bg-blue-500 rounded-xl p-2" type="submit">
|
||||
<Button
|
||||
className="bg-blue-500 rounded-xl p-2"
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
loading={isLoading}
|
||||
>
|
||||
Deploy ^
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user