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
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export const Default: Story = {
},
execution: {
stageStatus: {
duration: 'SLA: None',
slaText: 'SLA: None',
},
},
onTaskAdd: () => {
Expand All @@ -212,7 +212,7 @@ export const Default: Story = {
},
execution: {
stageStatus: {
duration: 'SLA: None',
slaText: 'SLA: None',
},
},
onAddTaskFromToolbox: (taskItem: ListItem) => {
Expand Down Expand Up @@ -391,7 +391,7 @@ export const ExecutionStatus: Story = {
execution: {
stageStatus: {
status: 'Completed',
duration: 'SLA: 4h',
slaText: 'SLA: 4h',
},
taskStatus: {
'1': { status: 'Completed', label: 'KYC and AML Checks', duration: '2h 15m' },
Expand Down Expand Up @@ -427,7 +427,7 @@ export const ExecutionStatus: Story = {
execution: {
stageStatus: {
status: 'Completed',
duration: 'SLA: 6h 15m',
slaText: 'SLA: 6h 15m',
},
taskStatus: {
'1': {
Expand Down Expand Up @@ -480,7 +480,7 @@ export const ExecutionStatus: Story = {
stageStatus: {
status: 'InProgress',
label: 'In progress',
duration: 'SLA: 2h 15m',
slaText: 'SLA: 2h 15m',
},
taskStatus: {
'1': { status: 'Completed', label: 'Report Ordering', duration: '2h 15m' },
Expand Down Expand Up @@ -567,6 +567,110 @@ export const ExecutionStatus: Story = {
},
};

export const SLAStates: Story = {
name: 'SLA States',
parameters: {
nodes: [
{
id: '0',
type: 'stage',
position: { x: 48, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Stage 1',
isReadOnly: true,
tasks: [],
},
execution: {
stageStatus: {
slaText: 'SLA: None',
},
taskStatus: {},
},
},
},
{
id: '1',
type: 'stage',
position: { x: 400, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Closing',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
slaText: 'SLA: 10 days remaining',
},
taskStatus: {},
},
},
},
{
id: '2',
type: 'stage',
position: { x: 752, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Closing',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
slaText: 'SLA: 1 day remaining',
slaIcon: 'warning',
},
taskStatus: {},
},
},
},
{
id: '3',
type: 'stage',
position: { x: 1104, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Closing',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
slaText: 'SLA: 1 day overdue',
slaIcon: 'error',
},
taskStatus: {},
},
},
},
],
},
};

export const InteractiveTaskManagement: Story = {
name: 'Interactive Task Management',
parameters: {
Expand Down Expand Up @@ -695,6 +799,92 @@ export const InteractiveTaskManagement: Story = {
},
};

export const ExecutionModeWithSla: Story = {
name: 'Execution Mode - Runtime vs SLA',
parameters: {
nodes: [
{
id: 'exec-runtime-only',
type: 'stage',
position: { x: 48, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Runtime only',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
duration: 'Duration: 2h 15m',
},
taskStatus: {},
},
},
},
{
id: 'exec-sla-only',
type: 'stage',
position: { x: 400, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'SLA only',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
slaText: 'SLA: 1 day remaining',
slaIcon: 'warning',
},
taskStatus: {},
},
},
},
{
id: 'exec-runtime-and-sla',
type: 'stage',
position: { x: 752, y: 96 },
width: 304,
data: {
stageDetails: {
label: 'Runtime + SLA (both)',
isReadOnly: true,
tasks: [
[{ id: '1', label: 'Prepare closing docs', icon: <DocumentIcon /> }],
[{ id: '2', label: 'eSign envelope', icon: <DocumentIcon /> }],
[{ id: '3', label: 'Review closing docs', icon: <DocumentIcon /> }],
],
},
execution: {
stageStatus: {
status: 'InProgress',
label: 'In progress',
duration: 'Duration: 2h 15m',
slaText: 'SLA: 1 day remaining',
slaIcon: 'warning',
},
taskStatus: {},
},
},
},
],
},
};

export const LoanProcessingWorkflow: Story = {
name: 'Loan Processing Workflow',
parameters: {
Expand Down Expand Up @@ -1929,7 +2119,7 @@ export const AdhocTasks: Story = {
stageStatus: {
status: 'InProgress',
label: 'In progress',
duration: 'SLA: 3h 45m',
slaText: 'SLA: 3h 45m',
},
taskStatus: {
'1': {
Expand Down Expand Up @@ -2205,7 +2395,7 @@ export const TasksBySection: Story = {
stageStatus: {
status: 'InProgress',
label: 'In progress',
duration: 'SLA: 3h 45m',
slaText: 'SLA: 3h 45m',
},
taskStatus: {
'1': {
Expand Down Expand Up @@ -2444,7 +2634,7 @@ export const WithRulesTags: Story = {
],
},
execution: {
stageStatus: { status: 'Completed', label: 'Completed', duration: 'SLA: 4h' },
stageStatus: { status: 'Completed', label: 'Completed', slaText: 'SLA: 4h' },
},
},
},
Expand Down Expand Up @@ -2477,7 +2667,7 @@ export const WithRulesTags: Story = {
],
},
execution: {
stageStatus: { status: 'InProgress', label: 'In progress', duration: 'SLA: 2h' },
stageStatus: { status: 'InProgress', label: 'In progress', slaText: 'SLA: 2h' },
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const StageContainer = styled.div<{
export const StageHeader = styled.div<{ isException?: boolean }>`
position: relative;
display: flex;
justify-content: space-between;
flex-direction: column;
padding: ${Spacing.SpacingS} ${Spacing.SpacingBase};
border-bottom: solid 1px var(--canvas-border-de-emp);
background: ${(props) => (props.isException ? 'var(--color-background-secondary)' : 'var(--canvas-background)')};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,93 @@ describe('StageNode - ReadOnly Mode', () => {
});
});

describe('StageNode - SLA Indicator', () => {
beforeEach(() => {
vi.clearAllMocks();
});

const getSlaIndicator = () => screen.getByTestId('stage-sla-stage-1');

it('does not render the SLA indicator when slaText is undefined', () => {
renderStageNode({
execution: { stageStatus: {}, taskStatus: {} },
});

expect(screen.queryByTestId('stage-sla-stage-1')).not.toBeInTheDocument();
});

it('does not render the SLA indicator when only duration is provided', () => {
renderStageNode({
execution: {
stageStatus: { duration: 'Duration: 1h 30m' },
taskStatus: {},
},
});

expect(screen.queryByTestId('stage-sla-stage-1')).not.toBeInTheDocument();
});

it('renders slaText without an icon when slaIcon is omitted', () => {
renderStageNode({
execution: {
stageStatus: { slaText: 'SLA: 10 days remaining' },
taskStatus: {},
},
});

const indicator = getSlaIndicator();
expect(indicator).toHaveTextContent('SLA: 10 days remaining');
expect(indicator).not.toHaveAttribute('data-sla-icon');
expect(indicator.querySelector('svg')).toBeNull();
});

it('renders a warning icon and text when slaIcon is "warning"', () => {
renderStageNode({
execution: {
stageStatus: { slaText: 'SLA: 1 day remaining', slaIcon: 'warning' },
taskStatus: {},
},
});

const indicator = getSlaIndicator();
expect(indicator).toHaveTextContent('SLA: 1 day remaining');
expect(indicator).toHaveAttribute('data-sla-icon', 'warning');
expect(indicator.querySelector('svg')).not.toBeNull();
});

it('renders an error icon and text when slaIcon is "error"', () => {
renderStageNode({
execution: {
stageStatus: { slaText: 'SLA: 1 day overdue', slaIcon: 'error' },
taskStatus: {},
},
});

const indicator = getSlaIndicator();
expect(indicator).toHaveTextContent('SLA: 1 day overdue');
expect(indicator).toHaveAttribute('data-sla-icon', 'error');
expect(indicator.querySelector('svg')).not.toBeNull();
});

it('renders both duration and slaText as independent lines when both are provided', () => {
renderStageNode({
execution: {
stageStatus: {
duration: 'Duration: 1h 30m',
slaText: 'SLA: 1 day remaining',
slaIcon: 'warning',
},
taskStatus: {},
},
});

expect(screen.getByText('Duration: 1h 30m')).toBeInTheDocument();
const indicator = getSlaIndicator();
expect(indicator).toHaveTextContent('SLA: 1 day remaining');
expect(indicator).toHaveAttribute('data-sla-icon', 'warning');
});
});

describe('StageNode - Header Chips', () => {
beforeEach(() => {
vi.clearAllMocks();
Expand Down
Loading
Loading