Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion docs/schema/yaml/1.0.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,35 @@ environment:
state: ''
# @param environment.webhooks.type (required)
type: ''
# @param environment.webhooks.pipelineId (required)
# @param environment.webhooks.pipelineId
pipelineId: ''
# @param environment.webhooks.trigger (required)
trigger: ''
# @param environment.webhooks.env (required)
env:

# @param environment.webhooks.docker
docker:
# @param environment.webhooks.docker.image (required)
image: ''
# @param environment.webhooks.docker.command
command:
# @param environment.webhooks.docker.command[]
- ''
# @param environment.webhooks.docker.args
args:
# @param environment.webhooks.docker.args[]
- ''
# @param environment.webhooks.docker.timeout
timeout: 0
# @param environment.webhooks.command
command:
# @param environment.webhooks.command.image (required)
image: ''
# @param environment.webhooks.command.script (required)
script: ''
# @param environment.webhooks.command.timeout
timeout: 0
# @section services
services:
# @param services[]
Expand Down
169 changes: 101 additions & 68 deletions src/components/logs/PageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,56 +28,75 @@ interface PageLayoutProps {

export function PageLayout({ backLink, title, serviceName, environmentId, deploymentType, children }: PageLayoutProps) {
return (
<div style={{
height: '100vh',
overflow: 'hidden',
backgroundColor: '#f5f5f5',
fontFamily: "'Inter', 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif",
}}>
<div style={{
padding: '32px',
maxWidth: '100%',
margin: '0',
height: '100%',
display: 'flex',
flexDirection: 'column',
boxSizing: 'border-box'
}}>
<div
style={{
height: '100vh',
overflow: 'hidden',
backgroundColor: '#f5f5f5',
fontFamily: "'Inter', 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif",
}}
>
<div
style={{
padding: '32px',
maxWidth: '100%',
margin: '0',
height: '100%',
display: 'flex',
flexDirection: 'column',
boxSizing: 'border-box',
}}
>
<div style={{ marginBottom: '24px', flexShrink: 0 }}>
<Link
<Link
href={backLink}
style={{
display: 'inline-flex',
alignItems: 'center',
color: '#666',
style={{
display: 'inline-flex',
alignItems: 'center',
color: '#666',
textDecoration: 'none',
fontSize: '14px',
marginBottom: '16px'
marginBottom: '16px',
}}
>
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24" style={{ marginRight: '6px' }}>
<svg
width="16"
height="16"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
style={{ marginRight: '6px' }}
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Back to Environment
</Link>
<h1 style={{
fontSize: '28px',
fontWeight: 700,
color: '#333',
margin: 0,
letterSpacing: '-0.02em'
}}>
<h1
style={{
fontSize: '28px',
fontWeight: 700,
color: '#333',
margin: 0,
letterSpacing: '-0.02em',
}}
>
{title}
</h1>
{serviceName && environmentId && (
<div style={{ marginTop: '8px', color: '#666', fontSize: '14px' }}>
<span style={{ fontWeight: 500 }}>Service:</span> {serviceName} &nbsp;&nbsp;•&nbsp;&nbsp;
<span style={{ fontWeight: 500 }}>Environment:</span> <code style={{ fontSize: '13px', color: '#555' }}>{environmentId}</code>
{deploymentType && (
<>
&nbsp;&nbsp;•&nbsp;&nbsp;
<span style={{ fontWeight: 500 }}>Type:</span>{' '}
<span style={{
<div style={{ marginTop: '8px', color: '#666', fontSize: '14px' }}>
<span style={{ fontWeight: 500 }}>Environment:</span>{' '}
<code style={{ fontSize: '13px', color: '#555' }}>{environmentId}</code>
{serviceName && (
<>
<span style={{ fontWeight: 500 }}> &nbsp;&nbsp;•&nbsp;&nbsp; Service:</span>{' '}
<code style={{ fontSize: '13px', color: '#555' }}>{serviceName}</code>
</>
)}
{deploymentType && (
<>
&nbsp;&nbsp;•&nbsp;&nbsp;
<span style={{ fontWeight: 500 }}>Type:</span>{' '}
<span
style={{
display: 'inline-flex',
alignItems: 'center',
padding: '2px 8px',
Expand All @@ -86,16 +105,16 @@ export function PageLayout({ backLink, title, serviceName, environmentId, deploy
fontWeight: 500,
backgroundColor: deploymentType === 'helm' ? '#dbeafe' : '#e0e7ff',
color: deploymentType === 'helm' ? '#1e40af' : '#4338ca',
textTransform: 'uppercase'
}}>
{deploymentType}
</span>
</>
)}
</div>
)}
textTransform: 'uppercase',
}}
>
{deploymentType}
</span>
</>
)}
</div>
</div>

{children}

<style>{`
Expand All @@ -119,18 +138,24 @@ interface ErrorAlertProps {

export function ErrorAlert({ error }: ErrorAlertProps) {
return (
<div style={{
backgroundColor: '#fee',
border: '1px solid #fcc',
borderRadius: '8px',
padding: '16px',
marginBottom: '24px',
display: 'flex',
alignItems: 'flex-start',
flexShrink: 0
}}>
<div
style={{
backgroundColor: '#fee',
border: '1px solid #fcc',
borderRadius: '8px',
padding: '16px',
marginBottom: '24px',
display: 'flex',
alignItems: 'flex-start',
flexShrink: 0,
}}
>
<svg width="20" height="20" fill="#dc2626" viewBox="0 0 20 20" style={{ marginRight: '12px', flexShrink: 0 }}>
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clipRule="evenodd"
/>
</svg>
<div>
<div style={{ fontWeight: 600, color: '#dc2626', marginBottom: '4px' }}>Error</div>
Expand All @@ -147,21 +172,29 @@ interface EmptyStateProps {

export function EmptyState({ title, description }: EmptyStateProps) {
return (
<div style={{
backgroundColor: 'white',
borderRadius: '12px',
padding: '48px',
textAlign: 'center',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
flex: 1
}}>
<div
style={{
backgroundColor: 'white',
borderRadius: '12px',
padding: '48px',
textAlign: 'center',
boxShadow: '0 1px 3px rgba(0,0,0,0.1)',
flex: 1,
}}
>
<svg width="32" height="32" fill="none" stroke="#ccc" viewBox="0 0 24 24" style={{ margin: '0 auto' }}>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={1.5}
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
<h3 style={{ fontSize: '18px', fontWeight: 600, color: '#333', marginTop: '16px', marginBottom: '8px' }}>
{title}
</h3>
<p style={{ color: '#666', fontSize: '14px' }}>{description}</p>
</div>
);
}
}

54 changes: 29 additions & 25 deletions src/components/logs/TerminalContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface TerminalContainerProps {
showTimestamps: boolean;
onTimestampsToggle: () => void;
showDetailsTab?: boolean;
showEventsTab?: boolean;
}

export function TerminalContainer({
Expand All @@ -47,7 +48,8 @@ export function TerminalContainer({
children,
showTimestamps,
onTimestampsToggle,
showDetailsTab = false
showDetailsTab = false,
showEventsTab = true
}: TerminalContainerProps) {
return (
<>
Expand Down Expand Up @@ -136,26 +138,28 @@ export function TerminalContainer({
Details
</button>
)}
<button
onClick={() => onTabChange('events')}
style={{
padding: '10px 16px',
backgroundColor: activeContainer === 'events' ? '#1a1a1a' : 'transparent',
color: activeContainer === 'events' ? '#fff' : '#999',
border: 'none',
borderBottom: activeContainer === 'events' ? '2px solid #3b82f6' : '2px solid transparent',
fontSize: '13px',
fontWeight: 500,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '8px',
transition: 'all 0.15s',
marginLeft: showDetailsTab ? undefined : 'auto'
}}
>
Job Events
</button>
{showEventsTab && (
<button
onClick={() => onTabChange('events')}
style={{
padding: '10px 16px',
backgroundColor: activeContainer === 'events' ? '#1a1a1a' : 'transparent',
color: activeContainer === 'events' ? '#fff' : '#999',
border: 'none',
borderBottom: activeContainer === 'events' ? '2px solid #3b82f6' : '2px solid transparent',
fontSize: '13px',
fontWeight: 500,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '8px',
transition: 'all 0.15s',
marginLeft: showDetailsTab ? undefined : 'auto'
}}
>
Job Events
</button>
)}
</div>

<div style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
Expand All @@ -165,7 +169,7 @@ export function TerminalContainer({
);
}

export function EmptyTerminalState({ type }: { type: 'build' | 'deployment' }) {
export function EmptyTerminalState({ type }: { type: 'build' | 'deployment' | 'webhook' }) {
return (
<div style={{
display: 'flex',
Expand All @@ -178,13 +182,13 @@ export function EmptyTerminalState({ type }: { type: 'build' | 'deployment' }) {
textAlign: 'center'
}}>
<svg width="32" height="32" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 002 2v12a2 2 0 002 2z" />
</svg>
<h3 style={{ marginTop: '16px', fontSize: '16px', fontWeight: 600, color: '#fff' }}>
Select a {type === 'build' ? 'build job' : 'deployment'}
Select a {type === 'build' ? 'build job' : type === 'deployment' ? 'deployment' : 'webhook'}
</h3>
<p style={{ marginTop: '8px', fontSize: '14px' }}>
Choose a {type} from the table to view its logs
Choose a {type} from the table to view its {type === 'webhook' ? 'details' : 'logs'}
</p>
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/components/logs/hooks/useJobPolling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface UseJobPollingProps<T extends JobInfo> {
fetchJobInfo: (job: T) => Promise<void>;
// eslint-disable-next-line no-unused-vars
onJobSelect: (job: T) => Promise<void>;
pollingInterval?: number; // in milliseconds, default 3000
}

export function useJobPolling<T extends JobInfo>({
Expand All @@ -45,6 +46,7 @@ export function useJobPolling<T extends JobInfo>({
fetchJobs,
fetchJobInfo,
onJobSelect,
pollingInterval = 3000,
}: UseJobPollingProps<T>) {
const pollingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

Expand All @@ -62,15 +64,15 @@ export function useJobPolling<T extends JobInfo>({

pollingIntervalRef.current = setInterval(() => {
fetchJobs(true);
}, 3000);
}, pollingInterval);

return () => {
if (pollingIntervalRef.current) {
clearInterval(pollingIntervalRef.current);
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [uuid, name]);
}, [uuid, name, pollingInterval]);

const handleJobUpdate = (jobs: T[]) => {
if (selectedJob) {
Expand Down
Loading