Skip to content

Commit 4fa4529

Browse files
committed
services refactor
1 parent 9275125 commit 4fa4529

File tree

7 files changed

+56
-23
lines changed

7 files changed

+56
-23
lines changed

frontend/src/components/entity-forms/dependency-form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createComponent, Shade } from '@furystack/shades'
2-
import { Button, Form, Icon, icons, Input } from '@furystack/shades-common-components'
2+
import { Button, Form, Icon, icons, Input, MarkdownInput } from '@furystack/shades-common-components'
33
import type { Dependency } from 'common'
44

55
type DependencyFormPayload = {
@@ -55,11 +55,11 @@ export const DependencyForm = Shade<DependencyFormProps>({
5555
value={props.initial?.checkCommand ?? ''}
5656
getHelperText={() => 'Command that returns exit code 0 if installed (e.g., node --version)'}
5757
/>
58-
<Input
58+
<MarkdownInput
5959
name="installationHelp"
6060
labelTitle="Installation Help"
61-
variant="outlined"
6261
value={props.initial?.installationHelp ?? ''}
62+
rows={4}
6363
getHelperText={() => 'Instructions for installing this dependency'}
6464
/>
6565
<div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>

frontend/src/components/entity-forms/github-repo-form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createComponent, NestedRouteLink, Shade } from '@furystack/shades'
2-
import { Button, Form, Icon, icons, Input } from '@furystack/shades-common-components'
2+
import { Button, Form, Icon, icons, Input, MarkdownInput } from '@furystack/shades-common-components'
33
import type { GitHubRepository } from 'common'
44

55
type GitHubRepoFormPayload = {
@@ -55,11 +55,11 @@ export const GitHubRepoForm = Shade<GitHubRepoFormProps>({
5555
required
5656
value={props.initial?.displayName ?? ''}
5757
/>
58-
<Input
58+
<MarkdownInput
5959
name="description"
6060
labelTitle="Description"
61-
variant="outlined"
6261
value={props.initial?.description ?? ''}
62+
rows={4}
6363
/>
6464
<div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
6565
{props.cancelHref ? (

frontend/src/components/entity-forms/service-form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createComponent, NestedRouteLink, Shade } from '@furystack/shades'
2-
import { Button, Checkbox, Form, Icon, icons, Input, Select } from '@furystack/shades-common-components'
2+
import { Button, Checkbox, Form, Icon, icons, Input, MarkdownInput, Select } from '@furystack/shades-common-components'
33
import type { GitHubRepository, ServiceView } from 'common'
44

55
type ServiceFormPayload = {
@@ -64,11 +64,11 @@ export const ServiceForm = Shade<ServiceFormProps>({
6464
required
6565
value={props.initial?.displayName ?? ''}
6666
/>
67-
<Input
67+
<MarkdownInput
6868
name="description"
6969
labelTitle="Description"
70-
variant="outlined"
7170
value={props.initial?.description ?? ''}
71+
rows={4}
7272
/>
7373
{props.repositories && props.repositories.length > 0 ? (
7474
<Select

frontend/src/components/entity-forms/stack-form.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createComponent, NestedRouteLink, Shade } from '@furystack/shades'
2-
import { Button, Form, Icon, icons, Input } from '@furystack/shades-common-components'
2+
import { Button, Form, Icon, icons, Input, MarkdownInput } from '@furystack/shades-common-components'
33
import type { StackView } from 'common'
44

55
type StackFormPayload = {
@@ -58,11 +58,11 @@ export const StackForm = Shade<StackFormProps>({
5858
required
5959
value={props.initial?.displayName ?? ''}
6060
/>
61-
<Input
61+
<MarkdownInput
6262
name="description"
6363
labelTitle="Description"
64-
variant="outlined"
6564
value={props.initial?.description ?? ''}
65+
rows={4}
6666
/>
6767

6868
<h4 style={{ margin: '0', opacity: '0.7' }}>Configuration</h4>

frontend/src/pages/dashboard/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Icon,
88
icons,
99
Loader,
10+
MarkdownDisplay,
1011
PageContainer,
1112
PageHeader,
1213
Paper,
@@ -138,7 +139,6 @@ export const Dashboard = Shade<DashboardProps>({
138139
<PageHeader
139140
icon={<Icon icon={icons.layers} />}
140141
title={currentStack?.displayName ?? props.stackName}
141-
description={currentStack?.description}
142142
actions={
143143
<div style={{ display: 'flex', gap: '8px' }}>
144144
<NestedRouteLink href="/stacks/:stackName/export" params={{ stackName: props.stackName }}>
@@ -154,6 +154,11 @@ export const Dashboard = Shade<DashboardProps>({
154154
</div>
155155
}
156156
/>
157+
{currentStack?.description ? (
158+
<Paper>
159+
<MarkdownDisplay content={currentStack.description} />
160+
</Paper>
161+
) : null}
157162

158163
<Paper>
159164
<div

frontend/src/pages/services/service-detail.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Icon,
1010
icons,
1111
Loader,
12+
MarkdownDisplay,
1213
NotyService,
1314
PageContainer,
1415
PageHeader,
@@ -23,6 +24,7 @@ import {
2324
ServiceDefinition,
2425
ServiceStateHistory,
2526
ServiceStatus,
27+
StackConfig,
2628
StackDefinition,
2729
} from 'common'
2830

@@ -149,17 +151,19 @@ export const ServiceDetail = Shade<ServiceDetailProps>({
149151
}
150152

151153
const stackState = useEntitySync(options, StackDefinition, service.stackName)
154+
const stackConfigState = useEntitySync(options, StackConfig, service.stackName)
152155
const reposState = useCollectionSync(options, GitHubRepository, {
153156
filter: { stackName: { $eq: service.stackName } },
154157
})
155158
const repos = reposState.status === 'synced' || reposState.status === 'cached' ? reposState.data.entries : []
156159
const linkedRepo = service.repositoryId ? repos.find((r) => r.id === service.repositoryId) : undefined
157-
const stackData = stackState.status === 'synced' ? stackState.data : undefined
158-
const stack = stackData
160+
const stackDef = stackState.status === 'synced' ? stackState.data : undefined
161+
const stackConfig = stackConfigState.status === 'synced' ? stackConfigState.data : undefined
162+
const stack = stackDef
159163
? ({
160-
...stackData,
161-
stackName: (stackData as Partial<StackView>).stackName ?? stackData.name,
162-
mainDirectory: (stackData as Partial<StackView>).mainDirectory ?? '',
164+
...stackDef,
165+
stackName: stackDef.name,
166+
mainDirectory: stackConfig?.mainDirectory ?? '',
163167
} as StackView)
164168
: undefined
165169
const fullCwd = stack ? getServiceCwd(stack, service, linkedRepo ?? null) : null
@@ -271,7 +275,6 @@ export const ServiceDetail = Shade<ServiceDetailProps>({
271275
<PageContainer>
272276
<PageHeader
273277
title={service.displayName}
274-
description={service.description}
275278
actions={
276279
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' }}>
277280
<ServiceStatusIndicator service={service} />
@@ -300,6 +303,11 @@ export const ServiceDetail = Shade<ServiceDetailProps>({
300303
</div>
301304
}
302305
/>
306+
{service.description ? (
307+
<Paper>
308+
<MarkdownDisplay content={service.description} />
309+
</Paper>
310+
) : null}
303311
<Paper>
304312
<div
305313
style={{
@@ -331,7 +339,22 @@ export const ServiceDetail = Shade<ServiceDetailProps>({
331339
) : null}
332340
<strong>Working Directory</strong>
333341
<span style={{ fontFamily: 'monospace' }}>{fullCwd ?? '(loading…)'}</span>
334-
<span />
342+
{fullCwd ? (
343+
<span style={{ display: 'flex', gap: '4px' }}>
344+
<a href={`cursor://file/${fullCwd}`} style={{ color: 'inherit' }}>
345+
<Button variant="outlined" size="small" title="Open in Cursor">
346+
Cursor
347+
</Button>
348+
</a>
349+
<a href={`vscode://file/${fullCwd}`} style={{ color: 'inherit' }}>
350+
<Button variant="outlined" size="small" title="Open in VS Code">
351+
VS Code
352+
</Button>
353+
</a>
354+
</span>
355+
) : (
356+
<span />
357+
)}
335358
{service.repositoryId ? (
336359
<div style={{ display: 'contents' }}>
337360
<strong>Clone</strong>

frontend/src/pages/stacks/edit-stack.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
Paper,
1414
} from '@furystack/shades-common-components'
1515
import type { StackView } from 'common'
16-
import { StackDefinition } from 'common'
16+
import { StackConfig, StackDefinition } from 'common'
1717

1818
import { ConfirmDialog } from '../../components/confirm-dialog.js'
1919
import { StackForm } from '../../components/entity-forms/stack-form.js'
@@ -30,8 +30,9 @@ export const EditStack = Shade<EditStackProps>({
3030
const [isConfirmingDelete, setIsConfirmingDelete] = useState('isConfirmingDelete', false)
3131

3232
const stackState = useEntitySync(options, StackDefinition, props.stackName)
33+
const configState = useEntitySync(options, StackConfig, props.stackName)
3334

34-
if (stackState.status === 'connecting') {
35+
if (stackState.status === 'connecting' || configState.status === 'connecting') {
3536
return (
3637
<PageContainer>
3738
<div style={{ display: 'flex', justifyContent: 'center', padding: '48px' }}>
@@ -59,7 +60,11 @@ export const EditStack = Shade<EditStackProps>({
5960
)
6061
}
6162

62-
const stack = stackState.data
63+
const stackDef = stackState.data
64+
const stackConfig = configState.status === 'synced' ? configState.data : undefined
65+
const stack = stackDef
66+
? ({ ...stackDef, stackName: stackDef.name, mainDirectory: stackConfig?.mainDirectory ?? '' }) as StackView
67+
: undefined
6368
if (!stack) {
6469
return (
6570
<PageContainer>

0 commit comments

Comments
 (0)