Skip to main content

React UI components for visualizing Neuroline pipelines with MUI.

English | Русский

neuroline-ui

Demo GitHub

React components for visualizing Neuroline pipelines with Material-UI.

Installation

yarn add neuroline-ui @mui/material @emotion/react @emotion/styled @mui/icons-material

Note: This package has peer dependencies on React, MUI, and Emotion.

UI language: English-only labels (e.g. Error, Artefact).

Features

  • PipelineViewer - visual representation of pipeline execution flow
  • JobNode - individual job status display with optional compact / one-line layouts (jobDisplay)
  • JobDetailsPanel - detailed job information with tabs for artefact, input, options, error
  • StageColumn - stage grouping with parallel job visualization
  • StatusBadge - color-coded status indicators
  • ArtifactView - job artifact display
  • InputView - job input data display with edit button
  • OptionsView - job options display with edit button
  • ErrorView - job error details display
  • TypeScript Support - full type safety
  • Storybook - interactive component documentation

Quick Start

'use client';

import { PipelineViewer, JobDetailsPanel } from 'neuroline-ui';
import type { PipelineDisplayData, JobDisplayInfo } from 'neuroline-ui';
import { useEffect, useState, useCallback } from 'react';

export function PipelineDemo() {
const [pipeline, setPipeline] = useState<PipelineDisplayData | null>(null);
const [selectedJob, setSelectedJob] = useState<JobDisplayInfo | null>(null);

useEffect(() => {
// Fetch pipeline status
fetch('/api/pipeline/status')
.then(res => res.json())
.then(setPipeline);
}, []);

const handleJobClick = useCallback((job: JobDisplayInfo) => {
setSelectedJob(job);
}, []);

return (
<div>
{pipeline && (
<PipelineViewer
pipeline={pipeline}
onJobClick={handleJobClick}
selectedJobName={selectedJob?.name}
/>
)}
{selectedJob && (
<JobDetailsPanel
job={selectedJob}
onInputEditClick={(job) => console.log('Edit input:', job)}
onOptionsEditClick={(job) => console.log('Edit options:', job)}
/>
)}
</div>
);
}

Components

PipelineViewer

Main component for visualizing pipeline execution.

import { PipelineViewer } from 'neuroline-ui';

<PipelineViewer
pipeline={{
pipelineId: 'pl_123',
pipelineType: 'data-processing',
status: 'processing',
stages: [
{
index: 0,
jobs: [
{
name: 'fetch-data',
status: 'done',
startedAt: new Date('2024-01-01T00:00:00Z'),
finishedAt: new Date('2024-01-01T00:00:02Z'),
artifact: { size: 2048 },
},
],
},
{
index: 1,
jobs: [
{
name: 'process-data',
status: 'processing',
startedAt: new Date('2024-01-01T00:00:02Z'),
input: { records: 150 },
options: { batchSize: 50 },
},
],
},
],
}}
onJobClick={(job) => console.log('Job clicked:', job)}
selectedJobName="fetch-data"
/>

Props:

PropTypeDefaultDescription
pipelinePipelineDisplayDataRequiredPipeline data with stages
onJobClick(job: JobDisplayInfo) => void-Click handler for job nodes
onJobRetry(job: JobDisplayInfo) => void-Retry callback for failed jobs
onJobRunManual(job: JobDisplayInfo) => void-Run callback for manual jobs
selectedJobNamestring-Name of currently selected job
jobDisplayJobNodeDisplayMode'details'How each job card is rendered (passed to every JobNode)

Job display modes (jobDisplay)

Type: JobNodeDisplayMode'details' | 'compact' | 'one-line'.

ValueTitleDurationLayout
detailsFull job.nameShown when startedAt is setDefault multi-line card
compactAbbreviation from name (see below)HiddenNarrower card; full name in tooltip
one-lineAbbreviationShown when availableTitle, status, chips in one row; full name in tooltip

Set jobDisplay on PipelineViewer, StageColumn, or JobNode. The viewer forwards the same mode to all nodes.

Abbreviation: export jobNameToAbbreviation from neuroline-ui. It splits on -, _, ., /, spaces, and camelCase boundaries, then takes the first letter or digit of each segment (uppercase). Example: very-long-job-name-that-might-need-wrappingVLJNTMNW. For a single segment, only the first alphanumeric character is used.

JobDetailsPanel

Panel for displaying detailed job information with tabs.

import { JobDetailsPanel } from 'neuroline-ui';

<JobDetailsPanel
job={{
name: 'process-data',
status: 'done',
startedAt: new Date(),
finishedAt: new Date(),
artifact: { processed: true, count: 150 },
input: { records: 150, format: 'json' },
options: { batchSize: 50, parallel: true },
}}
onInputEditClick={(job) => console.log('Edit input:', job)}
onOptionsEditClick={(job) => console.log('Edit options:', job)}
/>

Props:

PropTypeDefaultDescription
jobJobDisplayInfoRequiredJob to display
onInputEditClick(job: JobDisplayInfo) => void-Edit input callback
onOptionsEditClick(job: JobDisplayInfo) => void-Edit options callback

JobNode

Individual job display component.

import { JobNode } from 'neuroline-ui';

<JobNode
job={{
name: 'fetch-data',
status: 'done',
startedAt: new Date(),
finishedAt: new Date(),
artifact: { size: 2048 },
}}
isSelected={true}
onClick={(job) => console.log('Clicked:', job)}
/>

Props:

PropTypeDefaultDescription
jobJobDisplayInfoRequiredJob data
isSelectedbooleanfalseHighlight as selected
onClick(job: JobDisplayInfo) => void-Click handler
onRetry(job: JobDisplayInfo) => void-Retry callback (shown for failed/done jobs)
onRunManual(job: JobDisplayInfo) => void-Run callback (shown for awaiting_manual jobs)
jobDisplayJobNodeDisplayMode'details'Card layout: details, compact, or one-line (see Job display modes)

StageColumn

Stage grouping component for parallel jobs.

import { StageColumn } from 'neuroline-ui';

<StageColumn
stage={{
index: 1,
jobs: [
{ name: 'job1', status: 'done' },
{ name: 'job2', status: 'done' },
],
}}
selectedJobName="job1"
onJobClick={(job) => console.log(job)}
jobDisplay="compact"
/>

Optional prop jobDisplay — same as on JobNode / PipelineViewer (Job display modes).

StatusBadge

Status indicator with color coding.

import { StatusBadge } from 'neuroline-ui';

<StatusBadge status="processing" size="small" />

Status colors:

  • pending - Gray
  • awaiting_manual - Orange
  • processing - Cyan (animated)
  • done - Green
  • error - Red

ArtifactView

Display job artifact data.

import { ArtifactView } from 'neuroline-ui';

<ArtifactView artifact={{ processed: true, count: 150 }} />

InputView

Display job input data with optional edit button.

import { InputView } from 'neuroline-ui';

<InputView
input={{ records: 150, format: 'json' }}
onEditClick={() => console.log('Edit input')}
/>

OptionsView

Display job options with optional edit button.

import { OptionsView } from 'neuroline-ui';

<OptionsView
options={{ batchSize: 50, parallel: true }}
onEditClick={() => console.log('Edit options')}
/>

ErrorView

Display job error details (supports error history with retries).

import { ErrorView } from 'neuroline-ui';

<ErrorView errors={[{ message: 'Database connection timeout', stack: 'Error: ...', attempt: 0 }]} />

Types

import type {
PipelineDisplayData,
StageDisplayInfo,
JobDisplayInfo,
JobError,
JobStatus,
PipelineStatus,
SerializableValue,
} from 'neuroline-ui';

JobDisplayInfo

interface JobDisplayInfo {
name: string;
status: 'pending' | 'awaiting_manual' | 'processing' | 'done' | 'error';
manual?: boolean;
startedAt?: Date;
finishedAt?: Date;
errors: JobError[];
artifact?: SerializableValue;
input?: SerializableValue;
options?: SerializableValue;
}

StageDisplayInfo

interface StageDisplayInfo {
index: number;
jobs: JobDisplayInfo[];
}

PipelineDisplayData

interface PipelineDisplayData {
pipelineId: string;
pipelineType: string;
status: 'processing' | 'awaiting_manual' | 'done' | 'error';
stages: StageDisplayInfo[];
input?: SerializableValue;
error?: { message: string; jobName?: string };
}

SerializableValue

type SerializableValue = Record<string, unknown> | string | number | boolean | null;

Styling

All components use MUI's sx prop and support theme customization.

Custom Theme

import { ThemeProvider, createTheme } from '@mui/material';
import { PipelineViewer } from 'neuroline-ui';

const theme = createTheme({
palette: {
primary: { main: '#7c4dff' },
success: { main: '#00e676' },
error: { main: '#ff1744' },
info: { main: '#00e5ff' },
},
});

<ThemeProvider theme={theme}>
<PipelineViewer pipeline={pipeline} />
</ThemeProvider>

Storybook

Run Storybook for interactive component documentation:

yarn workspace neuroline-ui storybook

This will start Storybook on http://localhost:6006 with live examples of all components.

Integration Examples

With Next.js App Router

'use client';

import { PipelineViewer, JobDetailsPanel } from 'neuroline-ui';
import type { PipelineDisplayData, JobDisplayInfo } from 'neuroline-ui';
import { Container, Typography } from '@mui/material';
import { useState, useEffect, useCallback } from 'react';

export default function PipelinePage({ params }: { params: { id: string } }) {
const [pipeline, setPipeline] = useState<PipelineDisplayData | null>(null);
const [selectedJob, setSelectedJob] = useState<JobDisplayInfo | null>(null);

useEffect(() => {
const pollStatus = async () => {
const res = await fetch(`/api/pipeline/${params.id}/status`);
const data = await res.json();
setPipeline(data);

if (data.status === 'processing') {
setTimeout(pollStatus, 1000);
}
};

pollStatus();
}, [params.id]);

const handleJobClick = useCallback((job: JobDisplayInfo) => {
setSelectedJob(job);
}, []);

return (
<Container>
<Typography variant="h4" gutterBottom>
Pipeline: {params.id}
</Typography>
{pipeline && (
<PipelineViewer
pipeline={pipeline}
onJobClick={handleJobClick}
selectedJobName={selectedJob?.name}
/>
)}
{selectedJob && <JobDetailsPanel job={selectedJob} />}
</Container>
);
}

Development

Build the package:

yarn workspace neuroline-ui build

Watch mode:

yarn workspace neuroline-ui dev

License

UNLICENSED


neuroline-ui

Demo GitHub

React компоненты для визуализации Neuroline пайплайнов с Material-UI.

Установка

yarn add neuroline-ui @mui/material @emotion/react @emotion/styled @mui/icons-material

Примечание: Этот пакет имеет peer-зависимости от React, MUI и Emotion.

Язык интерфейса: только английский (например, Error, Artefact).

Возможности

  • PipelineViewer - визуальное представление процесса выполнения pipeline
  • JobNode - отображение статуса отдельной job; опционально компактный или однострочный вид (jobDisplay)
  • JobDetailsPanel - детальная информация о job с табами для artefact, input, options, error
  • StageColumn - группировка stage с визуализацией параллельных jobs
  • StatusBadge - цветные индикаторы статуса
  • ArtifactView - отображение артефакта job
  • InputView - отображение входных данных job с кнопкой редактирования
  • OptionsView - отображение опций job с кнопкой редактирования
  • ErrorView - отображение деталей ошибки job
  • TypeScript поддержка - полная типобезопасность
  • Storybook - интерактивная документация компонентов

Быстрый старт

'use client';

import { PipelineViewer, JobDetailsPanel } from 'neuroline-ui';
import type { PipelineDisplayData, JobDisplayInfo } from 'neuroline-ui';
import { useEffect, useState, useCallback } from 'react';

export function PipelineDemo() {
const [pipeline, setPipeline] = useState<PipelineDisplayData | null>(null);
const [selectedJob, setSelectedJob] = useState<JobDisplayInfo | null>(null);

useEffect(() => {
// Получение статуса pipeline
fetch('/api/pipeline/status')
.then(res => res.json())
.then(setPipeline);
}, []);

const handleJobClick = useCallback((job: JobDisplayInfo) => {
setSelectedJob(job);
}, []);

return (
<div>
{pipeline && (
<PipelineViewer
pipeline={pipeline}
onJobClick={handleJobClick}
selectedJobName={selectedJob?.name}
/>
)}
{selectedJob && (
<JobDetailsPanel
job={selectedJob}
onInputEditClick={(job) => console.log('Редактировать input:', job)}
onOptionsEditClick={(job) => console.log('Редактировать options:', job)}
/>
)}
</div>
);
}

Компоненты

PipelineViewer

Основной компонент для визуализации выполнения pipeline.

import { PipelineViewer } from 'neuroline-ui';

<PipelineViewer
pipeline={{
pipelineId: 'pl_123',
pipelineType: 'data-processing',
status: 'processing',
stages: [
{
index: 0,
jobs: [
{
name: 'fetch-data',
status: 'done',
startedAt: new Date('2024-01-01T00:00:00Z'),
finishedAt: new Date('2024-01-01T00:00:02Z'),
artifact: { size: 2048 },
},
],
},
{
index: 1,
jobs: [
{
name: 'process-data',
status: 'processing',
startedAt: new Date('2024-01-01T00:00:02Z'),
input: { records: 150 },
options: { batchSize: 50 },
},
],
},
],
}}
onJobClick={(job) => console.log('Job clicked:', job)}
selectedJobName="fetch-data"
/>

Пропсы:

ПропТипПо умолчаниюОписание
pipelinePipelineDisplayDataОбязательноДанные pipeline со stages
onJobClick(job: JobDisplayInfo) => void-Обработчик клика по job
onJobRetry(job: JobDisplayInfo) => void-Callback retry для упавших jobs
onJobRunManual(job: JobDisplayInfo) => void-Callback запуска для manual jobs
selectedJobNamestring-Имя выбранной job
jobDisplayJobNodeDisplayMode'details'Как рисуется каждая карточка job (пробрасывается во все JobNode)

Режимы отображения job (jobDisplay)

Тип: JobNodeDisplayMode'details' | 'compact' | 'one-line'.

ЗначениеЗаголовокДлительностьВёрстка
detailsПолное job.nameПоказывается, если задан startedAtКарточка по умолчанию, несколько строк
compactАббревиатура имени (см. ниже)СкрытаУже карточка; полное имя в tooltip
one-lineАббревиатураПоказывается при наличииИмя, статус и кнопки в одну строку; полное имя в tooltip

Задаётся на PipelineViewer, StageColumn или JobNode. Viewer передаёт один и тот же режим всем нодам.

Аббревиатура: из пакета экспортируется jobNameToAbbreviation. Имя делится по -, _, ., /, пробелам и границам camelCase; из каждого сегмента берётся первая буква или цифра (в верхнем регистре). Пример: very-long-job-name-that-might-need-wrappingVLJNTMNW. Если сегмент один — используется первая буква/цифра слова.

JobDetailsPanel

Панель для отображения детальной информации о job с табами.

import { JobDetailsPanel } from 'neuroline-ui';

<JobDetailsPanel
job={{
name: 'process-data',
status: 'done',
startedAt: new Date(),
finishedAt: new Date(),
artifact: { processed: true, count: 150 },
input: { records: 150, format: 'json' },
options: { batchSize: 50, parallel: true },
}}
onInputEditClick={(job) => console.log('Редактировать input:', job)}
onOptionsEditClick={(job) => console.log('Редактировать options:', job)}
/>

Пропсы:

ПропТипПо умолчаниюОписание
jobJobDisplayInfoОбязательноJob для отображения
onInputEditClick(job: JobDisplayInfo) => void-Callback редактирования input
onOptionsEditClick(job: JobDisplayInfo) => void-Callback редактирования options

JobNode

Компонент отображения отдельной job.

import { JobNode } from 'neuroline-ui';

<JobNode
job={{
name: 'fetch-data',
status: 'done',
startedAt: new Date(),
finishedAt: new Date(),
artifact: { size: 2048 },
}}
isSelected={true}
onClick={(job) => console.log('Clicked:', job)}
/>

Пропсы:

ПропТипПо умолчаниюОписание
jobJobDisplayInfoОбязательноДанные job
isSelectedbooleanfalseПодсветить как выбранную
onClick(job: JobDisplayInfo) => void-Обработчик клика
onRetry(job: JobDisplayInfo) => void-Callback retry (для упавших/завершённых jobs)
onRunManual(job: JobDisplayInfo) => void-Callback запуска (для awaiting_manual jobs)
jobDisplayJobNodeDisplayMode'details'Вид карточки: details, compact или one-line (см. Режимы отображения job)

StageColumn

Компонент группировки stage для параллельных jobs.

import { StageColumn } from 'neuroline-ui';

<StageColumn
stage={{
index: 1,
jobs: [
{ name: 'job1', status: 'done' },
{ name: 'job2', status: 'done' },
],
}}
selectedJobName="job1"
onJobClick={(job) => console.log(job)}
jobDisplay="compact"
/>

Опциональный проп jobDisplay — как у JobNode / PipelineViewer (Режимы отображения job).

StatusBadge

Индикатор статуса с цветовым кодированием.

import { StatusBadge } from 'neuroline-ui';

<StatusBadge status="processing" size="small" />

Цвета статусов:

  • pending - Серый
  • awaiting_manual - Оранжевый
  • processing - Бирюзовый (анимированный)
  • done - Зелёный
  • error - Красный

ArtifactView

Отображение артефакта job.

import { ArtifactView } from 'neuroline-ui';

<ArtifactView artifact={{ processed: true, count: 150 }} />

InputView

Отображение входных данных job с опциональной кнопкой редактирования.

import { InputView } from 'neuroline-ui';

<InputView
input={{ records: 150, format: 'json' }}
onEditClick={() => console.log('Редактировать input')}
/>

OptionsView

Отображение опций job с опциональной кнопкой редактирования.

import { OptionsView } from 'neuroline-ui';

<OptionsView
options={{ batchSize: 50, parallel: true }}
onEditClick={() => console.log('Редактировать options')}
/>

ErrorView

Отображение деталей ошибок job (включая историю ретраев).

import { ErrorView } from 'neuroline-ui';

<ErrorView errors={[{ message: 'Database connection timeout', stack: 'Error: ...', attempt: 0 }]} />

Типы

import type {
PipelineDisplayData,
StageDisplayInfo,
JobDisplayInfo,
JobError,
JobStatus,
PipelineStatus,
SerializableValue,
} from 'neuroline-ui';

JobDisplayInfo

interface JobDisplayInfo {
name: string;
status: 'pending' | 'awaiting_manual' | 'processing' | 'done' | 'error';
manual?: boolean;
startedAt?: Date;
finishedAt?: Date;
errors: JobError[];
artifact?: SerializableValue;
input?: SerializableValue;
options?: SerializableValue;
}

StageDisplayInfo

interface StageDisplayInfo {
index: number;
jobs: JobDisplayInfo[];
}

PipelineDisplayData

interface PipelineDisplayData {
pipelineId: string;
pipelineType: string;
status: 'processing' | 'awaiting_manual' | 'done' | 'error';
stages: StageDisplayInfo[];
input?: SerializableValue;
error?: { message: string; jobName?: string };
}

SerializableValue

type SerializableValue = Record<string, unknown> | string | number | boolean | null;

Стилизация

Все компоненты используют sx проп MUI и поддерживают кастомизацию темы.

Кастомная тема

import { ThemeProvider, createTheme } from '@mui/material';
import { PipelineViewer } from 'neuroline-ui';

const theme = createTheme({
palette: {
primary: { main: '#7c4dff' },
success: { main: '#00e676' },
error: { main: '#ff1744' },
info: { main: '#00e5ff' },
},
});

<ThemeProvider theme={theme}>
<PipelineViewer pipeline={pipeline} />
</ThemeProvider>

Storybook

Запустите Storybook для интерактивной документации:

yarn workspace neuroline-ui storybook

Это запустит Storybook на http://localhost:6006 с живыми примерами всех компонентов.

Примеры интеграции

С Next.js App Router

'use client';

import { PipelineViewer, JobDetailsPanel } from 'neuroline-ui';
import type { PipelineDisplayData, JobDisplayInfo } from 'neuroline-ui';
import { Container, Typography } from '@mui/material';
import { useState, useEffect, useCallback } from 'react';

export default function PipelinePage({ params }: { params: { id: string } }) {
const [pipeline, setPipeline] = useState<PipelineDisplayData | null>(null);
const [selectedJob, setSelectedJob] = useState<JobDisplayInfo | null>(null);

useEffect(() => {
const pollStatus = async () => {
const res = await fetch(`/api/pipeline/${params.id}/status`);
const data = await res.json();
setPipeline(data);

if (data.status === 'processing') {
setTimeout(pollStatus, 1000);
}
};

pollStatus();
}, [params.id]);

const handleJobClick = useCallback((job: JobDisplayInfo) => {
setSelectedJob(job);
}, []);

return (
<Container>
<Typography variant="h4" gutterBottom>
Pipeline: {params.id}
</Typography>
{pipeline && (
<PipelineViewer
pipeline={pipeline}
onJobClick={handleJobClick}
selectedJobName={selectedJob?.name}
/>
)}
{selectedJob && <JobDetailsPanel job={selectedJob} />}
</Container>
);
}

Разработка

Сборка пакета:

yarn workspace neuroline-ui build

Режим watch:

yarn workspace neuroline-ui dev

License

UNLICENSED