Skip to content

Commit 1d7670c

Browse files
authored
Merge pull request #28 from oasisprotocol/mz/tweaks
UI improvements
2 parents 8d03607 + 3001761 commit 1d7670c

File tree

25 files changed

+653
-196
lines changed

25 files changed

+653
-196
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Oasis ROFL App (name to be decided)
1+
# ROFL App
22

33
A web-based dashboard application for creating, exploring, monitoring and
44
interacting with Oasis ROFL (Runtime Offchain Logic) Apps.

src/components/EmptyState/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export function EmptyState({ title, description, children }: EmptyStateProps) {
2020
<CardHeader className="text-xl font-semibold text-white text-center">
2121
{isConnected ? title : 'Wallet is not connected'}
2222
</CardHeader>
23-
<CardContent className="max-w-[60%] mx-auto text-gray-400 text-sm text-balance text-center leading-relaxed">
23+
<CardContent className="md:max-w-[60%] mx-auto text-gray-400 text-sm text-balance text-center leading-relaxed">
2424
{isConnected
2525
? description
2626
: 'Please connect your wallet to to gain access to the view.'}

src/components/Layout/Header.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const Header: FC = () => {
3434
return (
3535
<div className="w-full flex justify-between items-center">
3636
<Link to={isConnected ? '/dashboard' : '/'}>
37-
<img src={Logotype} alt="Oasis ROFL" />
37+
<img src={Logotype} alt="ROFL App" className="h-[36px]" />
3838
</Link>
3939

4040
<div className="hidden md:flex">
@@ -68,7 +68,7 @@ export const Header: FC = () => {
6868
<SheetTitle className="sr-only">Navigation Menu</SheetTitle>
6969
<div className="flex items-start px-3 py-2.5">
7070
<NavLink to="/" onClick={() => setIsOpen(false)}>
71-
<img src={Logotype} alt="Oasis ROFL" />
71+
<img src={Logotype} alt="ROFL App" />
7272
</NavLink>
7373
</div>
7474
</SheetHeader>

src/components/Layout/MainLayout.tsx

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,51 +24,79 @@ import {
2424
BreadcrumbSeparator,
2525
} from '@oasisprotocol/ui-library/src/components/ui/breadcrumb';
2626

27-
const locationListMap: Record<string, string[]> = {
28-
'/explore': ['Explore'],
29-
'/dashboard/machines': ['Dashboard', 'Machines'],
30-
'/dashboard/apps': ['Dashboard', 'My Apps'],
31-
'/': ['Dashboard'],
27+
const navItems = {
28+
dashboard: { label: 'Dashboard', path: '/dashboard' },
29+
myApps: { label: 'My Apps', path: '/dashboard/apps' },
30+
machines: { label: 'Machines', path: '/dashboard/machines' },
31+
explore: { label: 'Explore', path: '/explore' },
3232
};
3333

34+
const breadcrumbConfigs = [
35+
{
36+
pattern: navItems.explore.path,
37+
breadcrumbs: [navItems.explore],
38+
matchType: 'startsWith',
39+
},
40+
{
41+
pattern: navItems.machines.path,
42+
breadcrumbs: [navItems.dashboard, navItems.machines],
43+
matchType: 'startsWith',
44+
},
45+
{
46+
pattern: navItems.myApps.path,
47+
breadcrumbs: [navItems.dashboard, navItems.myApps],
48+
matchType: 'startsWith',
49+
},
50+
{
51+
pattern: navItems.dashboard.path,
52+
breadcrumbs: [navItems.dashboard],
53+
matchType: 'exact',
54+
},
55+
];
56+
3457
export const MainLayout: FC = () => {
3558
const navigate = useNavigate();
3659
const location = useLocation();
37-
const locationList = Object.entries(locationListMap).find(([path]) =>
38-
location.pathname.toLowerCase().startsWith(path)
39-
)?.[1];
4060

41-
const getBreadcrumbPath = (index: number) => {
42-
if (!locationList) return '/';
43-
if (index === 0 && locationList[0] === 'Dashboard') {
44-
return '/dashboard';
45-
}
46-
return location.pathname;
61+
const getBreadcrumbConfig = () => {
62+
const pathname = location.pathname.toLowerCase();
63+
64+
return breadcrumbConfigs.find((config) => {
65+
if (config.matchType === 'exact') {
66+
return pathname === config.pattern;
67+
} else {
68+
return pathname.startsWith(config.pattern);
69+
}
70+
});
4771
};
72+
73+
const breadcrumbConfig = getBreadcrumbConfig();
74+
const breadcrumbs = breadcrumbConfig?.breadcrumbs || [];
75+
4876
return (
4977
<Layout
5078
headerContent={<Header />}
5179
headerBreadcrumbsContent={
52-
!!locationList?.length && (
80+
!!breadcrumbs.length && (
5381
<Breadcrumb className="flex px-2">
5482
<BreadcrumbList>
55-
{locationList.flatMap((loc, i) => {
83+
{breadcrumbs.flatMap((breadcrumb, i) => {
5684
const elements = [
57-
<BreadcrumbItem key={loc + i}>
85+
<BreadcrumbItem key={breadcrumb.label + i}>
5886
<BreadcrumbLink asChild>
5987
<NavLink
60-
to={getBreadcrumbPath(i)}
88+
to={breadcrumb.path}
6189
className="text-foreground text-sm font-normal"
6290
>
63-
{loc}
91+
{breadcrumb.label}
6492
</NavLink>
6593
</BreadcrumbLink>
6694
</BreadcrumbItem>,
6795
];
6896

69-
if (i + 1 < locationList.length) {
97+
if (i + 1 < breadcrumbs.length) {
7098
elements.push(
71-
<BreadcrumbSeparator key={`sep-${loc}-${i}`} />
99+
<BreadcrumbSeparator key={`sep-${breadcrumb.label}-${i}`} />
72100
);
73101
}
74102

src/components/Layout/logo.svg

Lines changed: 1 addition & 19 deletions
Loading
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { type FC } from 'react';
2+
3+
export const ResourcesCpu: FC<{
4+
value: unknown;
5+
}> = ({ value }) => {
6+
if (!value) return 'N/A';
7+
8+
const cpuCount = Number(value);
9+
return `${cpuCount} CPU${cpuCount === 1 ? '' : 's'}`;
10+
};
11+
12+
export const ResourcesMemory: FC<{
13+
value: unknown;
14+
}> = ({ value }) => {
15+
if (!value) return 'N/A';
16+
17+
const valueInMB = Number(value);
18+
const valueInGB = valueInMB / 1024;
19+
20+
const formatter = new Intl.NumberFormat('en-US', {
21+
minimumFractionDigits: 0,
22+
maximumFractionDigits: 1,
23+
});
24+
25+
return `${formatter.format(valueInGB)} GB`;
26+
};
27+
28+
export const ResourcesStorage: FC<{
29+
value: unknown;
30+
}> = ({ value }) => {
31+
if (!value) return 'N/A';
32+
33+
const storageInMB = Number(value);
34+
const storageInGB = Math.round(storageInMB / 1024);
35+
36+
const formatter = new Intl.NumberFormat('en-US', {
37+
minimumFractionDigits: 0,
38+
maximumFractionDigits: 0,
39+
});
40+
41+
return `${formatter.format(storageInGB)} GB Storage`;
42+
};
43+
44+
export const MachineResources: FC<{
45+
cpus?: unknown;
46+
memory?: unknown;
47+
storage?: unknown;
48+
}> = ({ cpus, memory, storage }) => {
49+
return (
50+
<div className="flex flex-col gap-2">
51+
<ResourcesCpu value={cpus} />
52+
{', '}
53+
<ResourcesMemory value={memory} />
54+
{', '}
55+
<ResourcesStorage value={storage} />
56+
</div>
57+
);
58+
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { type FC } from 'react';
2+
import { type Control } from 'react-hook-form';
3+
import { InputFormField } from '../../pages/CreateApp/InputFormField';
4+
import { type MetadataFormData } from '../../pages/CreateApp/types';
5+
6+
type MetadataFormFieldsProps = {
7+
control: Control<MetadataFormData>;
8+
};
9+
10+
export const MetadataFormFields: FC<MetadataFormFieldsProps> = ({
11+
control,
12+
}) => {
13+
return (
14+
<div className="space-y-6">
15+
<InputFormField
16+
control={control}
17+
name="name"
18+
label="Name"
19+
placeholder="ROFL App name"
20+
/>
21+
22+
<InputFormField
23+
control={control}
24+
name="author"
25+
label="Author"
26+
placeholder="Rofl App Creator"
27+
/>
28+
29+
<InputFormField
30+
control={control}
31+
name="description"
32+
label="Description"
33+
placeholder="Tell us something about it"
34+
type="textarea"
35+
/>
36+
37+
<InputFormField
38+
control={control}
39+
name="version"
40+
label="Version"
41+
placeholder="Rofl App version"
42+
/>
43+
44+
<InputFormField
45+
control={control}
46+
name="license"
47+
label="license"
48+
placeholder="MIT, Apache-2.0, etc."
49+
/>
50+
51+
<InputFormField
52+
control={control}
53+
name="homepage"
54+
label="Homepage"
55+
placeholder="Website, Twitter, Discord"
56+
/>
57+
</div>
58+
);
59+
};

src/pages/CreateApp/InputFormField.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type InputFormFieldProps<T extends FieldValues> = {
1515
label: string;
1616
placeholder?: string;
1717
type?: 'input' | 'password' | 'textarea';
18+
disabled?: boolean;
1819
};
1920

2021
export const InputFormField = <T extends FieldValues>({
@@ -23,6 +24,7 @@ export const InputFormField = <T extends FieldValues>({
2324
label,
2425
placeholder,
2526
type = 'input',
27+
disabled = false,
2628
}: InputFormFieldProps<T>): ReactNode => {
2729
return (
2830
<div className="grid gap-2">
@@ -42,6 +44,7 @@ export const InputFormField = <T extends FieldValues>({
4244
type={type === 'password' ? 'password' : 'text'}
4345
autoComplete={type === 'password' ? 'new-password' : 'off'}
4446
spellCheck={type === 'password' ? 'false' : 'true'}
47+
disabled={disabled}
4548
/>
4649
) : (
4750
<Textarea

src/pages/CreateApp/MetadataStep.tsx

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { CreateFormHeader } from './CreateFormHeader';
44
import { CreateFormNavigation } from './CreateFormNavigation';
55
import { zodResolver } from '@hookform/resolvers/zod';
66
import { useForm } from 'react-hook-form';
7-
import { InputFormField } from './InputFormField';
7+
import { MetadataFormFields } from '../../components/MetadataFormFields';
88
import { metadataFormSchema, type MetadataFormData } from './types';
99

1010
type MetadataStepProps = {
@@ -64,41 +64,7 @@ export const MetadataStep: FC<MetadataStepProps> = ({
6464
onSubmit={form.handleSubmit(onSubmit)}
6565
className="space-y-6 mb-6 w-full"
6666
>
67-
<InputFormField
68-
control={form.control}
69-
name="name"
70-
label="Name"
71-
placeholder="ROFL App name"
72-
/>
73-
74-
<InputFormField
75-
control={form.control}
76-
name="author"
77-
label="Author"
78-
placeholder="Rofl App Creator"
79-
/>
80-
81-
<InputFormField
82-
control={form.control}
83-
name="description"
84-
label="Description"
85-
placeholder="Tell us something about it"
86-
type="textarea"
87-
/>
88-
89-
<InputFormField
90-
control={form.control}
91-
name="version"
92-
label="Version"
93-
placeholder="Rofl App version"
94-
/>
95-
96-
<InputFormField
97-
control={form.control}
98-
name="homepage"
99-
label="Homepage"
100-
placeholder="Website, Twitter, Discord"
101-
/>
67+
<MetadataFormFields control={form.control} />
10268

10369
<CreateFormNavigation
10470
handleNext={handleFormSubmit}

src/pages/CreateApp/templates.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ export const templates = [
1616
id: 'tgbot',
1717
initialValues: {
1818
metadata: {
19-
name: parsedTemplate.name,
20-
author: parsedTemplate.author,
21-
description: parsedTemplate.description,
22-
version: parsedTemplate.version,
23-
homepage: parsedTemplate.homepage,
19+
name: parsedTemplate.name || '',
20+
author: parsedTemplate.author || '',
21+
description: parsedTemplate.description || '',
22+
version: parsedTemplate.version || '',
23+
homepage: parsedTemplate.homepage || '',
24+
license: parsedTemplate.license || '',
2425
},
2526
build: {
2627
provider: 'OPF',
@@ -43,6 +44,7 @@ export const templates = [
4344
author: metadata.author,
4445
version: metadata.version,
4546
homepage: metadata.homepage,
47+
license: metadata.license,
4648
deployments: {
4749
default: {
4850
...parsedDefaultDeployments.deployments.default,

0 commit comments

Comments
 (0)