fix: use generic error component, tab padding fixes (#6563)

* fix: use generic error component, tab padding fixes

* fix: script error padding

* rename errorMessage to error banner, move to ui folder

* fix: replace errorAlert with errorBanner component

* show orange dot always
This commit is contained in:
sanish chirayath
2025-12-30 18:48:53 +05:30
committed by GitHub
parent d7cef7aa4e
commit 36b0a90de3
12 changed files with 90 additions and 94 deletions

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
import { useDispatch } from 'react-redux';
import ErrorBanner from 'ui/ErrorBanner';
import Button from 'ui/Button';
const ExampleNotFound = ({ exampleUid }) => {
@@ -23,14 +24,16 @@ const ExampleNotFound = ({ exampleUid }) => {
return null;
}
const errors = [
{
title: 'Response example no longer exists',
message: 'This can occur when the example definition in your local file has been deleted or updated.'
}
];
return (
<div className="mt-6 px-6">
<div className="p-4 bg-orange-100 border-l-4 border-yellow-500 text-yellow-700">
<div>Response example no longer exists.</div>
<div className="mt-2">
This can occur when the example definition in your local file has been deleted or updated.
</div>
</div>
<ErrorBanner errors={errors} className="mb-4" />
<Button size="md" color="secondary" variant="ghost" onClick={closeTab}>
Close Tab
</Button>

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState, useCallback } from 'react';
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
import { useDispatch } from 'react-redux';
import ErrorBanner from 'ui/ErrorBanner';
import Button from 'ui/Button';
const FolderNotFound = ({ folderUid }) => {
@@ -25,14 +26,16 @@ const FolderNotFound = ({ folderUid }) => {
return null;
}
const errors = [
{
title: 'Folder no longer exists',
message: 'This can happen when the folder was renamed or deleted on your filesystem.'
}
];
return (
<div className="mt-6 px-6">
<div className="p-4 bg-orange-100 border-l-4 border-yellow-500 text-yellow-700">
<div>Folder no longer exists.</div>
<div className="mt-2">
This can happen when the folder was renamed or deleted on your filesystem.
</div>
</div>
<ErrorBanner errors={errors} className="mb-4" />
<Button size="md" color="secondary" variant="ghost" onClick={closeTab}>
Close Tab
</Button>

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
import { useDispatch } from 'react-redux';
import ErrorBanner from 'ui/ErrorBanner';
import Button from 'ui/Button';
const RequestNotFound = ({ itemUid }) => {
@@ -29,14 +30,16 @@ const RequestNotFound = ({ itemUid }) => {
return null;
}
const errors = [
{
title: 'Request no longer exists',
message: 'This can happen when the .bru file associated with this request was deleted on your filesystem.'
}
];
return (
<div className="mt-6 px-6">
<div className="p-4 bg-orange-100 border-l-4 border-yellow-500 text-yellow-700">
<div>Request no longer exists.</div>
<div className="mt-2">
This can happen when the .bru file associated with this request was deleted on your filesystem.
</div>
</div>
<ErrorBanner errors={errors} className="mb-4" />
<Button size="md" color="secondary" variant="ghost" onClick={closeTab}>
Close Tab
</Button>

View File

@@ -58,7 +58,7 @@ const ExampleTab = ({ tab, collection }) => {
if (!item || !example) {
return (
<StyledWrapper
className="flex items-center justify-between tab-container px-3"
className="flex items-center justify-between tab-container"
onMouseUp={(e) => {
if (e.button === 1) {
e.preventDefault();

View File

@@ -20,7 +20,7 @@ const RequestTabNotFound = ({ handleCloseClick }) => {
return (
<>
<div className="flex items-center tab-label pl-2">
<div className="flex items-center tab-label px-3">
{showErrorMessage ? (
<>
<IconAlertTriangle size={18} strokeWidth={1.5} className="text-yellow-600" />

View File

@@ -320,7 +320,7 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
if (!item) {
return (
<StyledWrapper
className="flex items-center justify-between tab-container px-1"
className="flex items-center justify-between tab-container"
onMouseUp={(e) => {
if (e.button === 1) {
e.preventDefault();

View File

@@ -1,6 +1,6 @@
import React from 'react';
import ReactJson from 'react-json-view';
import ErrorAlert from 'ui/ErrorAlert/index';
import ErrorBanner from 'ui/ErrorBanner';
const JsonPreview = ({ data, displayedTheme }) => {
// Helper function to validate and parse JSON data
@@ -29,16 +29,16 @@ const JsonPreview = ({ data, displayedTheme }) => {
// Show error if parsing failed
if (jsonData.error) {
return <ErrorAlert title="Cannot preview as JSON" message={jsonData.error} />;
return <ErrorBanner errors={[{ title: 'Cannot preview as JSON', message: jsonData.error }]} />;
}
// Validate that data can be rendered as JSON tree
if (jsonData.data === null || jsonData.data === undefined) {
return <ErrorAlert title="Cannot preview as JSON" message="Data is null or undefined. Expected a valid JSON object or array." />;
return <ErrorBanner errors={[{ title: 'Cannot preview as JSON', message: 'Data is null or undefined. Expected a valid JSON object or array.' }]} />;
}
if (typeof jsonData.data !== 'object') {
return <ErrorAlert title="Cannot preview as JSON" message="Data cannot be rendered as a JSON tree. Expected a JSON object or array." />;
return <ErrorBanner errors={[{ title: 'Cannot preview as JSON', message: 'Data cannot be rendered as a JSON tree. Expected a JSON object or array.' }]} />;
}
return (

View File

@@ -1,4 +1,4 @@
import ErrorAlert from 'ui/ErrorAlert/index';
import ErrorBanner from 'ui/ErrorBanner';
import React, { useState, useMemo } from 'react';
import StyledWrapper from './StyledWrapper';
@@ -21,7 +21,7 @@ export default function XmlPreview({ data, defaultExpanded = true }) {
if (parsedData && typeof parsedData === 'object' && parsedData.error) {
return (
<div className="px-2">
<ErrorAlert title="Cannot preview as XML" message={parsedData.error} />
<ErrorBanner errors={[{ title: 'Cannot preview as XML', message: parsedData.error }]} />
</div>
);
}
@@ -37,7 +37,7 @@ export default function XmlPreview({ data, defaultExpanded = true }) {
if (!isValidTreeData(parsedData)) {
return (
<div className="px-2">
<ErrorAlert title="Cannot preview as XML" message="Data cannot be rendered as a tree. Expected a valid XML string." />
<ErrorBanner errors={[{ title: 'Cannot preview as XML', message: 'Data cannot be rendered as a tree. Expected a valid XML string.' }]} />
</div>
);
}
@@ -55,7 +55,7 @@ export default function XmlPreview({ data, defaultExpanded = true }) {
// Empty object with no children
return (
<div className="px-2">
<ErrorAlert title="Cannot preview as XML" message="Cannot render XML tree. Root object is empty." />
<ErrorBanner errors={[{ title: 'Cannot preview as XML', message: 'Cannot render XML tree. Root object is empty.' }]} />
</div>
);
}

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { IconX } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
import ErrorBanner from 'ui/ErrorBanner';
const ScriptError = ({ item, onClose }) => {
const preRequestError = item?.preRequestScriptErrorMessage;
@@ -32,31 +31,7 @@ const ScriptError = ({ item, onClose }) => {
});
}
return (
<StyledWrapper className="mt-4 mb-2">
<div className="flex items-start gap-3 px-4 py-3">
<div className="flex-1 min-w-0">
{errors.map((error, index) => (
<div key={index}>
{index > 0 && <div className="separator my-2"></div>}
<div className="error-title">
{error.title}
</div>
<div className="error-message">
{error.message}
</div>
</div>
))}
</div>
<div
className="close-button flex-shrink-0 cursor-pointer"
onClick={onClose}
>
<IconX size={16} strokeWidth={1.5} />
</div>
</div>
</StyledWrapper>
);
return <ErrorBanner errors={errors} onClose={onClose} className="mt-4 mb-2" />;
};
export default ScriptError;

View File

@@ -1,25 +0,0 @@
import React from 'react';
import { IconX } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
const ErrorAlert = ({ title, message, onClose }) => {
if (!message) return null;
return (
<StyledWrapper className="mt-4 mb-2">
<div className="flex items-start gap-3 px-4 py-3">
<div className="flex-1 min-w-0">
{title && <div className="error-title">{title}</div>}
<div className="error-message">{typeof message === 'string' ? message : JSON.stringify(message, null, 2)}</div>
</div>
{onClose && (
<div className="close-button flex-shrink-0 cursor-pointer" onClick={onClose}>
<IconX size={16} strokeWidth={1.5} />
</div>
)}
</div>
</StyledWrapper>
);
};
export default ErrorAlert;

View File

@@ -1,36 +1,33 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
border-left: 4px solid ${(props) => props.theme.colors.text.danger};
border-top: 1px solid transparent;
border-right: 1px solid transparent;
border-bottom: 1px solid transparent;
border-radius: ${(props) => props.theme.border.radius.base};
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
max-height: 200px;
min-height: 70px;
overflow-y: auto;
background-color: ${(props) => (props.theme.bg === '#1e1e1e' ? 'rgba(40, 40, 40, 0.5)' : 'rgba(250, 250, 250, 0.9)')};
background-color: ${(props) => props.theme.background.base};
border: solid 1px ${(props) => props.theme.border.border2};
border-left: 4px solid ${(props) => props.theme.colors.text.danger};
border-radius: ${(props) => props.theme.border.radius.base};
.close-button {
opacity: 0.7;
transition: opacity 0.2s;
&:hover {
opacity: 1;
}
svg {
color: ${(props) => props.theme.text};
}
}
.error-title {
font-weight: 500;
margin-bottom: 0.375rem;
color: ${(props) => props.theme.colors.text.danger};
}
.error-message {
font-family: monospace;
font-size: ${(props) => props.theme.font.size.xs};
@@ -39,6 +36,9 @@ const StyledWrapper = styled.div`
word-break: break-all;
color: ${(props) => props.theme.text};
}
`;
.separator {
border-top: 1px solid ${(props) => props.theme.border.border1};
}
`;
export default StyledWrapper;

View File

@@ -0,0 +1,37 @@
import React from 'react';
import { IconX } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
const ErrorBanner = ({ errors, onClose, className = '' }) => {
if (!errors || errors.length === 0) return null;
return (
<StyledWrapper className={className}>
<div className="flex items-start gap-3 px-4 py-3">
<div className="flex-1 min-w-0">
{errors.map((error, index) => (
<div key={index}>
{index > 0 && <div className="separator my-2"></div>}
<div className="error-title">
{error.title}
</div>
<div className="error-message">
{error.message}
</div>
</div>
))}
</div>
{onClose && (
<div
className="close-button flex-shrink-0 cursor-pointer"
onClick={onClose}
>
<IconX size={16} strokeWidth={1.5} />
</div>
)}
</div>
</StyledWrapper>
);
};
export default ErrorBanner;