Skip to content

Commit d4c06ce

Browse files
authored
Merge pull request #13 from oasisprotocol/mz/appsDetailsMock
Apps details view with mock data
2 parents 0a49d07 + 060d040 commit d4c06ce

File tree

7 files changed

+300
-12
lines changed

7 files changed

+300
-12
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
},
1616
"dependencies": {
1717
"@metamask/jazzicon": "^2.0.0",
18+
"@monaco-editor/react": "^4.7.0",
1819
"@oasisprotocol/client": "^1.2.0",
1920
"@oasisprotocol/ui-library": "file:./ui-library",
2021
"@rainbow-me/rainbowkit": "^2.2.6",
2122
"@tanstack/react-query": "^5.80.6",
2223
"axios": "^1.9.0",
2324
"lucide-react": "^0.514.0",
25+
"monaco-editor": "^0.52.2",
2426
"react": "^19.1.0",
2527
"react-dom": "^19.1.0",
2628
"react-intersection-observer": "^9.16.0",
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { type FC, lazy, Suspense } from 'react';
2+
3+
const TextAreaFallback = ({ value }: { value?: string }) => (
4+
<textarea
5+
readOnly
6+
value={value}
7+
className="w-full h-full bg-background text-foreground overflow-hidden"
8+
/>
9+
);
10+
11+
const MonacoEditor = lazy(async () => {
12+
try {
13+
const monaco = await import('monaco-editor');
14+
const monacoReact = await import('@monaco-editor/react');
15+
window.MonacoEnvironment = {
16+
getWorker() {
17+
return new Worker(
18+
new URL(
19+
'../../../node_modules/monaco-editor/esm/vs/editor/editor.worker.js',
20+
import.meta.url
21+
),
22+
{ type: 'module' }
23+
);
24+
},
25+
};
26+
monacoReact.loader.config({ monaco });
27+
28+
return monacoReact;
29+
} catch {
30+
console.error(
31+
'monaco-editor wrapper failed to load. Using <textarea> instead'
32+
);
33+
return {
34+
default: ((props) => (
35+
<TextAreaFallback value={props.value || props.defaultValue} />
36+
)) as typeof import('@monaco-editor/react').default,
37+
};
38+
}
39+
});
40+
41+
type CodeDisplayProps = {
42+
data: string;
43+
};
44+
45+
const CodeDisplay: FC<CodeDisplayProps> = ({ data }) => {
46+
if (!data) {
47+
return null;
48+
}
49+
50+
return (
51+
<div className="flex-1 relative">
52+
<div className="h-[550px] overflow-auto resize-y">
53+
<Suspense fallback={<TextAreaFallback value={data} />}>
54+
<MonacoEditor
55+
loading={<TextAreaFallback value={data} />}
56+
language="yaml"
57+
value={data}
58+
theme="vs-dark"
59+
options={{
60+
readOnly: true,
61+
fontSize: 14,
62+
wordWrap: 'on',
63+
}}
64+
/>
65+
</Suspense>
66+
</div>
67+
</div>
68+
);
69+
};
70+
71+
type YamlCodeProps = {
72+
data: string | undefined;
73+
};
74+
75+
export const YamlCode: FC<YamlCodeProps> = ({ data }) => {
76+
if (!data) return null;
77+
78+
return <CodeDisplay data={data} />;
79+
};

src/pages/Dashboard/MachinesDetails/MachineDetailsRow.tsx renamed to src/components/DetailsSectionRow/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import type { FC } from 'react';
22
import { cn } from '@oasisprotocol/ui-library/src/lib/utils';
33

4-
type MachineDetailsRowProps = {
4+
type DetailsSectionRowProps = {
55
className?: string;
66
label: string;
77
children: React.ReactNode;
88
};
99

10-
export const MachineDetailsRow: FC<MachineDetailsRowProps> = ({
10+
export const DetailsSectionRow: FC<DetailsSectionRowProps> = ({
1111
className,
1212
label,
1313
children,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { type FC } from 'react';
2+
import { Link } from 'react-router-dom';
3+
import { Button } from '@oasisprotocol/ui-library/src/components/ui/button';
4+
import { DetailsSectionRow } from '../../../components/DetailsSectionRow';
5+
import { SquarePen } from 'lucide-react';
6+
7+
export const AppMetadata: FC = () => {
8+
return (
9+
<div className="space-y-4">
10+
<DetailsSectionRow label="Machine(s)">
11+
<Link to="/dashboard/machines" className="text-primary">
12+
OPF-1
13+
</Link>
14+
</DetailsSectionRow>
15+
<DetailsSectionRow label="Minimum resources" className=" pb-6 border-b">
16+
1CPU, 2GB RAM, 10GB Storage
17+
</DetailsSectionRow>
18+
<DetailsSectionRow label="Explorer Link" className="pb-6 border-b">
19+
<a
20+
href="https://explorer.oasis.io/mainnet/sapphire/rofl/app/rofl1qpdzzm4h73gtes04xjn4whan84s3k33l5gx787l2"
21+
target="_blank"
22+
rel="noopener noreferrer"
23+
className="text-primary"
24+
>
25+
rofl1qpdzzm4h73gtes04xjn4whan84s3k33l5gx787l2
26+
</a>
27+
</DetailsSectionRow>
28+
<Button
29+
disabled
30+
variant="outline"
31+
className="w-full md:w-auto md:ml-8 float-right"
32+
>
33+
<SquarePen />
34+
Edit
35+
</Button>
36+
<DetailsSectionRow label="Author">
37+
<a
38+
href="https://explorer.oasis.io/mainnet/sapphire/address/0x1441b57bD02E92473c89733D00881e859Eff6508"
39+
target="_blank"
40+
rel="noopener noreferrer"
41+
className="text-primary"
42+
>
43+
0x1441b57bD02E92473c89733D00881e859Eff6508
44+
</a>
45+
</DetailsSectionRow>
46+
<DetailsSectionRow label="Description">
47+
Ac vel nullam elit facilisis justo dictum non metus a. Dictum quisque
48+
condimentum duis sit amet ac. Pharetra amet sed ornare id nunc vivamus
49+
habitant enim in. Sed lorem scelerisque sed purus eleifend diam.
50+
</DetailsSectionRow>
51+
<DetailsSectionRow label="Homepage">
52+
<a
53+
href="https://www.wt3.ai"
54+
target="_blank"
55+
rel="noopener noreferrer"
56+
className="text-primary"
57+
>
58+
www.wt3.ai
59+
</a>
60+
</DetailsSectionRow>
61+
<DetailsSectionRow label="Repository">
62+
<a
63+
href="https://github.com/oasisprotocol"
64+
target="_blank"
65+
rel="noopener noreferrer"
66+
className="text-primary"
67+
>
68+
https://github.com/oasisprotocol
69+
</a>
70+
</DetailsSectionRow>
71+
<DetailsSectionRow label="License" className=" pb-6 border-b">
72+
Apache-2.0
73+
</DetailsSectionRow>
74+
<div className="text-xl font-bold">Policy</div>
75+
<DetailsSectionRow label="Who can run this app">Anyone</DetailsSectionRow>
76+
<DetailsSectionRow label="Latest Update" className=" pb-6 border-b">
77+
May 14, 2025
78+
</DetailsSectionRow>
79+
</div>
80+
);
81+
};
Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,107 @@
1-
import type { FC } from 'react';
1+
import { type FC } from 'react';
2+
import { Button } from '@oasisprotocol/ui-library/src/components/ui/button';
3+
import {
4+
Tabs,
5+
TabsContent,
6+
TabsList,
7+
TabsTrigger,
8+
} from '@oasisprotocol/ui-library/src/components/ui/tabs';
9+
import { AppStatusIcon } from '../../../components/AppStatusIcon';
10+
import { YamlCode } from '../../../components/CodeDisplay';
11+
import { AppMetadata } from './AppMetadata';
212

313
export const AppDetails: FC = () => {
4-
return <>AppDetails</>;
14+
return (
15+
<>
16+
<>
17+
<div>
18+
<Tabs defaultValue="details">
19+
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 border-b py-5 mb-5">
20+
<div className="flex items-center gap-2 mb-">
21+
<h1 className="text-2xl font-bold">OPF-1</h1>
22+
<AppStatusIcon hasActiveInstances removed={false} />
23+
</div>
24+
<div className="flex flex-wrap gap-3">
25+
<Button
26+
disabled
27+
variant="destructive"
28+
className="w-full md:w-auto md:ml-8"
29+
>
30+
Discard
31+
</Button>
32+
<Button disabled className="w-full md:w-auto md:mr-8">
33+
Apply
34+
</Button>
35+
<TabsList className="w-full md:w-auto">
36+
<TabsTrigger value="details">Details</TabsTrigger>
37+
<TabsTrigger value="secrets">Secrets</TabsTrigger>
38+
<TabsTrigger value="compose">Compose</TabsTrigger>
39+
</TabsList>
40+
</div>
41+
</div>
42+
<TabsContent value="details">
43+
<AppMetadata />
44+
</TabsContent>
45+
<TabsContent value="secrets">secrets</TabsContent>
46+
<TabsContent value="compose">
47+
<YamlCode
48+
data={`
49+
services:
50+
ollama:
51+
image: "docker.io/ollama/ollama"
52+
ports:
53+
- "11434:11434"
54+
volumes:
55+
- ~/ollama-storage:/root/.ollama
56+
entrypoint: ["/usr/bin/bash", "-c", "/bin/ollama serve & sleep 5; ollama pull deepseek-r1:1.5b; wait"]
57+
58+
sapphire-localnet:
59+
image: "ghcr.io/oasisprotocol/sapphire-localnet"
60+
platform: "linux/x86_64"
61+
ports:
62+
- "8544-8548:8544-8548"
63+
healthcheck:
64+
test: ["CMD", "test", "-f", "/CONTAINER_READY"]
65+
interval: 30s
66+
timeout: 10s
67+
retries: 20
68+
69+
contracts:
70+
image: "ghcr.io/foundry-rs/foundry:latest"
71+
volumes:
72+
- ./contracts:/contracts
73+
entrypoint: /bin/sh -c 'cd contracts && forge create --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://sapphire-localnet:8545 --broadcast ChatBot --constructor-args localhost 00d795c033fb4b94873d81b6327f5371768ffc6fcf 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
74+
depends_on:
75+
sapphire-localnet:
76+
condition: service_healthy
77+
78+
oracle:
79+
environment:
80+
CONTRACT_ADDRESS: 0x5FbDB2315678afecb367f032d93F642f64180aa3
81+
build:
82+
dockerfile: Dockerfile.oracle
83+
# entrypoint: /bin/sh -c 'python main.py --network http://sapphire-localnet:8545 --ollama-address http://ollama:11434 --secret 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 $$CONTRACT_ADDRESS'
84+
entrypoint: /bin/sh -c 'sleep 100; python main.py --network http://sapphire-localnet:8545 --ollama-address http://ollama:11434 --secret 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 0x5FbDB2315678afecb367f032d93F642f64180aa3'
85+
restart: on-failure
86+
depends_on:
87+
contracts:
88+
condition: service_completed_successfully
89+
90+
frontend:
91+
build:
92+
dockerfile: Dockerfile.frontend
93+
ports:
94+
- "5173:5173"
95+
depends_on:
96+
contracts:
97+
condition: service_completed_successfully
98+
99+
`}
100+
/>
101+
</TabsContent>
102+
</Tabs>
103+
</div>
104+
</>
105+
</>
106+
);
5107
};

src/pages/Dashboard/MachinesDetails/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from '@oasisprotocol/ui-library/src/components/ui/tabs';
1010
import { Clock, CircleArrowUp } from 'lucide-react';
1111
import { MachineStatusIcon } from '../../../components/MachineStatusIcon';
12-
import { MachineDetailsRow } from './MachineDetailsRow';
12+
import { DetailsSectionRow } from '../../../components/DetailsSectionRow';
1313
import { MachineStop } from './MachineStop';
1414
import { MachineRestart } from './MachineRestart';
1515

@@ -43,16 +43,16 @@ export const MachinesDetails: FC = () => {
4343
</div>
4444
<TabsContent value="details">
4545
<div className="space-y-4">
46-
<MachineDetailsRow label="App Running" className=" py-6 border-b">
46+
<DetailsSectionRow label="App Running" className=" py-6 border-b">
4747
<Link to="/dashboard/apps" className="text-primary">
4848
WT3
4949
</Link>
50-
</MachineDetailsRow>
51-
<MachineDetailsRow label="Provider">OPF</MachineDetailsRow>
52-
<MachineDetailsRow label="Machine Size">
50+
</DetailsSectionRow>
51+
<DetailsSectionRow label="Provider">OPF</DetailsSectionRow>
52+
<DetailsSectionRow label="Machine Size">
5353
Small (1CPU, 2GB RAM, 10GB Storage)
54-
</MachineDetailsRow>
55-
<MachineDetailsRow label="Node ID" className="pb-6 border-b">
54+
</DetailsSectionRow>
55+
<DetailsSectionRow label="Node ID" className="pb-6 border-b">
5656
<a
5757
href="https://explorer.oasis.io/sapphire/rofl/node/0x4d3f5b2d3rP7lUVU2BSfSm53opnGui"
5858
target="_blank"
@@ -61,7 +61,7 @@ export const MachinesDetails: FC = () => {
6161
>
6262
oasis13Gmsfb2D3rP7lUVU2BSfSm53opnGui
6363
</a>
64-
</MachineDetailsRow>
64+
</DetailsSectionRow>
6565
</div>
6666
</TabsContent>
6767
<TabsContent value="logs">

yarn.lock

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,20 @@
748748
semver "^7.5.4"
749749
uuid "^9.0.1"
750750

751+
"@monaco-editor/loader@^1.5.0":
752+
version "1.5.0"
753+
resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.5.0.tgz#dcdbc7fe7e905690fb449bed1c251769f325c55d"
754+
integrity sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==
755+
dependencies:
756+
state-local "^1.0.6"
757+
758+
"@monaco-editor/react@^4.7.0":
759+
version "4.7.0"
760+
resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.7.0.tgz#35a1ec01bfe729f38bfc025df7b7bac145602a60"
761+
integrity sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==
762+
dependencies:
763+
"@monaco-editor/loader" "^1.5.0"
764+
751765
"@napi-rs/wasm-runtime@^0.2.10":
752766
version "0.2.11"
753767
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e"
@@ -4828,6 +4842,11 @@ modern-ahocorasick@^1.0.0:
48284842
resolved "https://registry.yarnpkg.com/modern-ahocorasick/-/modern-ahocorasick-1.1.0.tgz#9b1fa15d4f654be20a2ad7ecc44ec9d7645bb420"
48294843
integrity sha512-sEKPVl2rM+MNVkGQt3ChdmD8YsigmXdn5NifZn6jiwn9LRJpWm8F3guhaqrJT/JOat6pwpbXEk6kv+b9DMIjsQ==
48304844

4845+
monaco-editor@^0.52.2:
4846+
version "0.52.2"
4847+
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.52.2.tgz#53c75a6fcc6802684e99fd1b2700299857002205"
4848+
integrity sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==
4849+
48314850
ms@^2.1.3:
48324851
version "2.1.3"
48334852
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
@@ -5650,6 +5669,11 @@ split2@^4.0.0:
56505669
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
56515670
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
56525671

5672+
state-local@^1.0.6:
5673+
version "1.0.7"
5674+
resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5"
5675+
integrity sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==
5676+
56535677
stream-shift@^1.0.2:
56545678
version "1.0.3"
56555679
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b"

0 commit comments

Comments
 (0)