mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 19:35:06 +03:00
refactor(studio): merge the worker settings tab into overview
Move the Container, Resources, and Develop locally sections onto the overview tab and remove the Settings tab. The invocation snippets that lived in both tabs are now a single How to call section.
This commit is contained in:
1 parent
407d39fe32
commit
a4fa232d59
3 files changed
+219
-270
No files matched your search
@@ -35,21 +35,19 @@ import { WorkerSnippetTabs } from '../WorkerSnippetTabs'
|
||||
import { WorkerStatePill } from '../WorkerStatePill'
|
||||
import { WorkerLogsTab } from './WorkerLogsTab'
|
||||
import { WorkerOverviewTab } from './WorkerOverviewTab'
|
||||
import { WorkerSettingsTab } from './WorkerSettingsTab'
|
||||
import { AlertError } from '@/components/ui/AlertError'
|
||||
import type { WorkerLogStream } from '@/data/workers/worker-logs-query'
|
||||
import { workerQueryOptions } from '@/data/workers/worker-query'
|
||||
import { PRODUCT_NAME } from '@/lib/constants/workers'
|
||||
|
||||
type WorkerTab = 'overview' | 'invocations' | 'logs' | 'activity' | 'settings'
|
||||
const WORKER_TABS: WorkerTab[] = ['overview', 'invocations', 'logs', 'activity', 'settings']
|
||||
type WorkerTab = 'overview' | 'invocations' | 'logs' | 'activity'
|
||||
const WORKER_TABS: WorkerTab[] = ['overview', 'invocations', 'logs', 'activity']
|
||||
|
||||
const TAB_LABEL: Record<WorkerTab, string> = {
|
||||
overview: 'Overview',
|
||||
invocations: 'Invocations',
|
||||
logs: 'Logs',
|
||||
activity: 'Activity',
|
||||
settings: 'Settings',
|
||||
}
|
||||
|
||||
const TAB_STREAM: Partial<Record<WorkerTab, WorkerLogStream>> = {
|
||||
@@ -171,7 +169,6 @@ export const WorkerDetail = () => {
|
||||
<WorkerLogsTab workerName={worker.name} stream={stream} />
|
||||
</div>
|
||||
)}
|
||||
{tab === 'settings' && <WorkerSettingsTab worker={worker} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { Badge } from 'ui'
|
||||
import { Admonition } from 'ui-patterns/Admonition'
|
||||
import { InfoTooltip } from 'ui-patterns/info-tooltip'
|
||||
import { PageContainer } from 'ui-patterns/PageContainer'
|
||||
@@ -11,8 +12,12 @@ import {
|
||||
PageSectionTitle,
|
||||
} from 'ui-patterns/PageSection'
|
||||
|
||||
import { RuntimeBadge } from '../RuntimeBadge'
|
||||
import { WorkerCommandLine } from '../WorkerCommandLine'
|
||||
import { LISTENING_PORT, WORKERS_REGION_LABEL } from '../Workers.constants'
|
||||
import type { Worker } from '../Workers.types'
|
||||
import { formatSize, getRuntimeMeta } from '../Workers.utils'
|
||||
import { buildWorkerCliCommands } from '../workerSnippets'
|
||||
import { WorkerSnippetTabs } from '../WorkerSnippetTabs'
|
||||
import { CLI_NAME } from '@/lib/constants/workers'
|
||||
|
||||
@@ -40,100 +45,216 @@ const InstanceCount = ({
|
||||
</div>
|
||||
)
|
||||
|
||||
export const WorkerOverviewTab = ({ worker }: WorkerOverviewTabProps) => (
|
||||
<PageContainer size="small">
|
||||
{worker.buildState === 'failed' && (
|
||||
<PageSection>
|
||||
<PageSectionContent>
|
||||
<Admonition type="destructive" title="This worker failed to build">
|
||||
<div className="space-y-3">
|
||||
<p>{worker.stateReason ?? 'The build did not complete.'}</p>
|
||||
<WorkerCommandLine
|
||||
comment="Redeploy after fixing the build"
|
||||
command={`supabase ${CLI_NAME} push ${worker.name}`}
|
||||
/>
|
||||
</div>
|
||||
</Admonition>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
)}
|
||||
|
||||
{worker.instancesError !== undefined && (
|
||||
<PageSection>
|
||||
<PageSectionContent>
|
||||
<Admonition type="warning" title="Instances reported an error">
|
||||
{worker.instancesError}
|
||||
</Admonition>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
)}
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Instances</PageSectionTitle>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
{worker.instances === undefined ? (
|
||||
<p className="text-sm text-foreground-light">
|
||||
No instances are running for this worker yet.
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm text-foreground-light">
|
||||
<span className="tabular-nums text-foreground">{worker.instances.ready}</span> of{' '}
|
||||
<span className="tabular-nums text-foreground">{worker.instances.declared}</span>{' '}
|
||||
instances ready
|
||||
</p>
|
||||
<div className="grid grid-cols-2 divide-x divide-y rounded-md border border-default bg-surface-100 sm:grid-cols-4 sm:divide-y-0">
|
||||
<InstanceCount
|
||||
label="Instances"
|
||||
value={worker.instances.declared}
|
||||
tooltip="The number of instances you configured for this worker."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Live"
|
||||
value={worker.instances.live}
|
||||
tooltip="Instances currently running."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Ready"
|
||||
value={worker.instances.ready}
|
||||
tooltip="Instances passing health checks and serving requests."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Stale"
|
||||
value={worker.instances.stale}
|
||||
tooltip="Instances from a previous deployment, being replaced."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>How to call</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
Call the worker over its gateway URL. Pass your project API key as a bearer token.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<WorkerSnippetTabs
|
||||
input={{
|
||||
name: worker.name,
|
||||
runtime: worker.runtime,
|
||||
size: worker.size,
|
||||
access: worker.access,
|
||||
instances: worker.declaredInstances,
|
||||
}}
|
||||
tabs={['curl', 'js', 'python']}
|
||||
/>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
</PageContainer>
|
||||
const SettingsRow = ({
|
||||
label,
|
||||
children,
|
||||
isFirst,
|
||||
}: {
|
||||
label: string
|
||||
children: ReactNode
|
||||
isFirst?: boolean
|
||||
}) => (
|
||||
<div
|
||||
className={`flex items-center justify-between px-4 py-3 ${
|
||||
isFirst ? '' : 'border-t border-default'
|
||||
}`}
|
||||
>
|
||||
<span className="text-sm text-foreground-light">{label}</span>
|
||||
<span className="text-sm text-foreground">{children}</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const WorkerOverviewTab = ({ worker }: WorkerOverviewTabProps) => {
|
||||
const runtime = getRuntimeMeta(worker.runtime)
|
||||
const commands = buildWorkerCliCommands(worker.name)
|
||||
|
||||
return (
|
||||
<PageContainer size="small">
|
||||
{worker.buildState === 'failed' && (
|
||||
<PageSection>
|
||||
<PageSectionContent>
|
||||
<Admonition type="destructive" title="This worker failed to build">
|
||||
<div className="space-y-3">
|
||||
<p>{worker.stateReason ?? 'The build did not complete.'}</p>
|
||||
<WorkerCommandLine
|
||||
comment="Redeploy after fixing the build"
|
||||
command={`supabase ${CLI_NAME} push ${worker.name}`}
|
||||
/>
|
||||
</div>
|
||||
</Admonition>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
)}
|
||||
|
||||
{worker.instancesError !== undefined && (
|
||||
<PageSection>
|
||||
<PageSectionContent>
|
||||
<Admonition type="warning" title="Instances reported an error">
|
||||
{worker.instancesError}
|
||||
</Admonition>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
)}
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Instances</PageSectionTitle>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
{worker.instances === undefined ? (
|
||||
<p className="text-sm text-foreground-light">
|
||||
No instances are running for this worker yet.
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm text-foreground-light">
|
||||
<span className="tabular-nums text-foreground">{worker.instances.ready}</span> of{' '}
|
||||
<span className="tabular-nums text-foreground">{worker.instances.declared}</span>{' '}
|
||||
instances ready
|
||||
</p>
|
||||
<div className="grid grid-cols-2 divide-x divide-y rounded-md border border-default bg-surface-100 sm:grid-cols-4 sm:divide-y-0">
|
||||
<InstanceCount
|
||||
label="Instances"
|
||||
value={worker.instances.declared}
|
||||
tooltip="The number of instances you configured for this worker."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Live"
|
||||
value={worker.instances.live}
|
||||
tooltip="Instances currently running."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Ready"
|
||||
value={worker.instances.ready}
|
||||
tooltip="Instances passing health checks and serving requests."
|
||||
/>
|
||||
<InstanceCount
|
||||
label="Stale"
|
||||
value={worker.instances.stale}
|
||||
tooltip="Instances from a previous deployment, being replaced."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Container</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
The runtime image and entrypoint resolved for this worker.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="rounded-md border border-default bg-surface-100">
|
||||
<SettingsRow label="Runtime" isFirst>
|
||||
<RuntimeBadge runtime={worker.runtime} />
|
||||
</SettingsRow>
|
||||
{worker.imageVersion !== undefined && (
|
||||
<SettingsRow label="Image version">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
{worker.imageVersion}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
{runtime !== undefined && (
|
||||
<SettingsRow label="Base image">
|
||||
<span className="font-mono text-xs text-foreground-light">{runtime.baseImage}</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
{runtime !== undefined && (
|
||||
<SettingsRow label="Entrypoint">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
{runtime.entrypoint}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
<SettingsRow label="Listening port">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
$PORT → {LISTENING_PORT}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Resources</PageSectionTitle>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="rounded-md border border-default bg-surface-100">
|
||||
<SettingsRow label="Size" isFirst>
|
||||
{formatSize(worker.size)}
|
||||
</SettingsRow>
|
||||
<SettingsRow label="Instances">{worker.declaredInstances}</SettingsRow>
|
||||
<SettingsRow label="Access">
|
||||
{worker.access === 'public' ? (
|
||||
<Badge variant="success">Public</Badge>
|
||||
) : (
|
||||
<Badge>Private</Badge>
|
||||
)}
|
||||
</SettingsRow>
|
||||
<SettingsRow label="Region">
|
||||
<span className="text-foreground-light">
|
||||
{WORKERS_REGION_LABEL} <span className="text-foreground-lighter">(locked)</span>
|
||||
</span>
|
||||
</SettingsRow>
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>How to call</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
Call the worker over its gateway URL. Pass your project API key as a bearer token.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<WorkerSnippetTabs
|
||||
input={{
|
||||
name: worker.name,
|
||||
runtime: worker.runtime,
|
||||
size: worker.size,
|
||||
access: worker.access,
|
||||
instances: worker.declaredInstances,
|
||||
}}
|
||||
tabs={['curl', 'js', 'python']}
|
||||
/>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Develop locally</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
Manage this worker from the Supabase CLI.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="space-y-4 rounded-md border border-default bg-surface-100 p-4">
|
||||
{commands.map((command) => (
|
||||
<WorkerCommandLine
|
||||
key={command.command}
|
||||
comment={command.comment}
|
||||
command={command.command}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
</PageContainer>
|
||||
)
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { Badge } from 'ui'
|
||||
import { PageContainer } from 'ui-patterns/PageContainer'
|
||||
import {
|
||||
PageSection,
|
||||
PageSectionContent,
|
||||
PageSectionDescription,
|
||||
PageSectionMeta,
|
||||
PageSectionSummary,
|
||||
PageSectionTitle,
|
||||
} from 'ui-patterns/PageSection'
|
||||
|
||||
import { RuntimeBadge } from '../RuntimeBadge'
|
||||
import { WorkerCommandLine } from '../WorkerCommandLine'
|
||||
import { LISTENING_PORT, WORKERS_REGION_LABEL } from '../Workers.constants'
|
||||
import type { Worker } from '../Workers.types'
|
||||
import { formatSize, getRuntimeMeta } from '../Workers.utils'
|
||||
import { buildWorkerCliCommands } from '../workerSnippets'
|
||||
import { WorkerSnippetTabs } from '../WorkerSnippetTabs'
|
||||
|
||||
interface WorkerSettingsTabProps {
|
||||
worker: Worker
|
||||
}
|
||||
|
||||
const SettingsRow = ({
|
||||
label,
|
||||
children,
|
||||
isFirst,
|
||||
}: {
|
||||
label: string
|
||||
children: ReactNode
|
||||
isFirst?: boolean
|
||||
}) => (
|
||||
<div
|
||||
className={`flex items-center justify-between px-4 py-3 ${
|
||||
isFirst ? '' : 'border-t border-default'
|
||||
}`}
|
||||
>
|
||||
<span className="text-sm text-foreground-light">{label}</span>
|
||||
<span className="text-sm text-foreground">{children}</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const WorkerSettingsTab = ({ worker }: WorkerSettingsTabProps) => {
|
||||
const runtime = getRuntimeMeta(worker.runtime)
|
||||
const commands = buildWorkerCliCommands(worker.name)
|
||||
|
||||
const snippetInput = {
|
||||
name: worker.name,
|
||||
runtime: worker.runtime,
|
||||
size: worker.size,
|
||||
access: worker.access,
|
||||
instances: worker.declaredInstances,
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageContainer size="small">
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Container</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
The runtime image and entrypoint resolved for this worker.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="rounded-md border border-default bg-surface-100">
|
||||
<SettingsRow label="Runtime" isFirst>
|
||||
<RuntimeBadge runtime={worker.runtime} />
|
||||
</SettingsRow>
|
||||
{worker.imageVersion !== undefined && (
|
||||
<SettingsRow label="Image version">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
{worker.imageVersion}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
{runtime !== undefined && (
|
||||
<SettingsRow label="Base image">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
{runtime.baseImage}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
{runtime !== undefined && (
|
||||
<SettingsRow label="Entrypoint">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
{runtime.entrypoint}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
)}
|
||||
<SettingsRow label="Listening port">
|
||||
<span className="font-mono text-xs text-foreground-light">
|
||||
$PORT → {LISTENING_PORT}
|
||||
</span>
|
||||
</SettingsRow>
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Resources</PageSectionTitle>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="rounded-md border border-default bg-surface-100">
|
||||
<SettingsRow label="Size" isFirst>
|
||||
{formatSize(worker.size)}
|
||||
</SettingsRow>
|
||||
<SettingsRow label="Instances">{worker.declaredInstances}</SettingsRow>
|
||||
<SettingsRow label="Access">
|
||||
{worker.access === 'public' ? (
|
||||
<Badge variant="success">Public</Badge>
|
||||
) : (
|
||||
<Badge>Private</Badge>
|
||||
)}
|
||||
</SettingsRow>
|
||||
<SettingsRow label="Region">
|
||||
<span className="text-foreground-light">
|
||||
{WORKERS_REGION_LABEL} <span className="text-foreground-lighter">(locked)</span>
|
||||
</span>
|
||||
</SettingsRow>
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Invoke worker</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
Call the worker over its gateway URL. Pass your project API key as a bearer token.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<WorkerSnippetTabs input={snippetInput} tabs={['curl', 'js', 'python']} />
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<PageSectionMeta>
|
||||
<PageSectionSummary>
|
||||
<PageSectionTitle>Develop locally</PageSectionTitle>
|
||||
<PageSectionDescription>
|
||||
Manage this worker from the Supabase CLI.
|
||||
</PageSectionDescription>
|
||||
</PageSectionSummary>
|
||||
</PageSectionMeta>
|
||||
<PageSectionContent>
|
||||
<div className="space-y-4 rounded-md border border-default bg-surface-100 p-4">
|
||||
{commands.map((command) => (
|
||||
<WorkerCommandLine
|
||||
key={command.command}
|
||||
comment={command.comment}
|
||||
command={command.command}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
</PageContainer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user