mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
feat: enhance OpenAPI Sync tab with sync status indicators and improved styling (#7371)
- Added sync status logic to determine if the collection is in sync with the spec, displaying appropriate indicators in the UI. - Updated OpenAPISyncHeader to include linked collection information and sync status icons. - Refined styling in StyledWrapper for better layout and visual feedback on sync status. - Removed unused styles and components to streamline the codebase.
This commit is contained in:
@@ -9,6 +9,7 @@ const Wrapper = styled.div`
|
||||
border: 1px solid ${(props) => props.theme.app.collection.toolbar.environmentSelector.border};
|
||||
line-height: 1rem;
|
||||
transition: all 0.15s ease;
|
||||
height: 24px;
|
||||
|
||||
&:hover {
|
||||
border-color: ${(props) => props.theme.app.collection.toolbar.environmentSelector.hoverBorder};
|
||||
@@ -73,7 +74,7 @@ const Wrapper = styled.div`
|
||||
border-top: 0.0625rem solid ${(props) => props.theme.dropdown.separator};
|
||||
z-index: 10;
|
||||
margin: 0;
|
||||
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props) => props.theme.dropdown.bg + ' !important'};
|
||||
}
|
||||
@@ -119,7 +120,7 @@ const Wrapper = styled.div`
|
||||
.environment-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
max-height: calc(75vh - 8rem);
|
||||
max-height: calc(75vh - 8rem);
|
||||
padding-bottom: 2.625rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,10 @@ import React from 'react';
|
||||
|
||||
const OpenAPISyncIcon = ({ size = 16, color = 'currentColor', ...props }) => {
|
||||
return (
|
||||
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path d="M20.5152 2.03784C19.7741 2.20613 19.198 2.71101 18.9585 3.41007C18.8776 3.63986 18.8711 3.71106 18.8744 4.04117C18.8776 4.24507 18.8841 4.45867 18.8905 4.51692C18.897 4.6302 18.842 4.68522 15.4179 7.90221C14.6962 8.58185 13.8515 9.37801 13.5408 9.67576L12.9744 10.2162L12.6993 10.1321C12.4566 10.0609 12.3659 10.0512 11.9226 10.0479C11.2203 10.0447 10.8384 10.1547 10.3043 10.5075C9.64412 10.9444 9.21368 11.5852 9.05833 12.3555C8.98389 12.718 9.00655 13.375 9.10364 13.7019C9.25252 14.2067 9.59558 14.744 9.98071 15.0773C10.573 15.5854 11.2397 15.8152 12.0358 15.7796C13.2042 15.7311 14.1783 15.0353 14.6152 13.9413C14.8612 13.3297 14.8644 12.5367 14.625 11.8765L14.544 11.6629L15.1363 11.0707C18.9391 7.25493 20.2175 5.9992 20.2822 6.00244C20.321 6.00567 20.4311 6.02509 20.5282 6.04451C21.2272 6.19015 22.0396 5.90211 22.4927 5.34221C23.2144 4.45867 23.072 3.12203 22.182 2.43915C21.7192 2.08315 21.0428 1.92132 20.5152 2.03784Z" fill={color} />
|
||||
<path d="M10.822 3.18312C7.54673 3.55854 4.74076 5.46155 3.12903 8.40992C2.32964 9.86954 1.90243 11.8308 2.01894 13.5202C2.17105 15.8116 2.99634 17.7793 4.52392 19.5043C6.00296 21.1775 8.1843 22.3653 10.3559 22.6792C11.3398 22.8249 12.0971 22.8378 13.0875 22.7278C15.2041 22.4915 17.2171 21.5336 18.7803 20.0157C19.994 18.8344 20.8451 17.4751 21.35 15.9022C22.2433 13.1189 21.8128 10.0411 20.1817 7.57492C20.0846 7.42928 19.9972 7.30954 19.9842 7.30954C19.9713 7.30954 19.8645 7.40987 19.7415 7.53285L19.5214 7.75292L19.6703 7.98271C20.392 9.11222 20.8451 10.3129 21.0652 11.6949C21.1364 12.1415 21.1655 13.3131 21.117 13.8018C20.8225 16.6951 19.2334 19.226 16.7284 20.7827C15.6086 21.4785 14.2364 21.9543 12.9095 22.1064C12.4596 22.1582 11.3689 22.1549 10.9029 22.1032C9.17788 21.909 7.56615 21.2455 6.16802 20.1484C4.44301 18.7988 3.20023 16.7566 2.8151 14.6432C2.70506 14.0445 2.66622 13.6011 2.66622 12.9279C2.66622 11.4262 2.9931 10.1026 3.70187 8.74003C4.59512 7.0215 6.05474 5.60395 7.8283 4.73659C9.11639 4.10549 10.2362 3.82716 11.6634 3.79156C12.8836 3.7592 13.848 3.90807 14.984 4.30291C15.4403 4.4615 16.2753 4.85958 16.7252 5.13144L17.0488 5.32886L17.2851 5.11525C17.4145 4.9955 17.5213 4.89194 17.5213 4.88223C17.5213 4.83692 16.7737 4.40001 16.2753 4.15404C15.3206 3.68476 14.3723 3.38701 13.3302 3.22843C12.7347 3.13781 11.4207 3.11515 10.822 3.18312Z" fill={color} />
|
||||
<path d="M10.7153 4.75567C9.63757 4.91749 8.63105 5.27349 7.64718 5.83986C7.23939 6.07612 7.24263 6.04052 7.58245 6.48714C7.74427 6.70075 8.13264 7.2121 8.44981 7.6296C8.76697 8.04709 9.04854 8.39986 9.07443 8.41928C9.11003 8.4387 9.178 8.41604 9.3204 8.3319C9.76055 8.07622 10.5114 7.82055 11.081 7.73316C11.2137 7.71051 11.3723 7.68785 11.4305 7.67814L11.5341 7.66196V6.225C11.5341 5.43531 11.5244 4.76861 11.5147 4.73948C11.4888 4.67152 11.2493 4.67476 10.7153 4.75567Z" fill={color} />
|
||||
<path d="M12.2848 4.75339C12.2362 4.8343 12.2265 7.61761 12.2783 7.64997C12.2945 7.65968 12.4433 7.68881 12.6084 7.7147C13.0162 7.77619 13.466 7.89594 13.8026 8.02863L14.0842 8.13867L14.2557 7.97685C14.4337 7.81179 15.3788 6.91531 16.0002 6.32305C16.1879 6.14504 16.3432 5.9897 16.3497 5.97999C16.3626 5.9541 15.9969 5.73726 15.615 5.54954C14.7606 5.1191 13.9256 4.86666 12.9482 4.73721C12.4336 4.67248 12.3365 4.67248 12.2848 4.75339Z" fill={color} />
|
||||
<path d="M6.26832 6.85656C5.49159 7.54915 4.89932 8.33236 4.39444 9.34859C4.12906 9.87936 4.09993 9.96998 4.16142 10.0185C4.21968 10.0671 6.83146 10.9668 6.91561 10.9668C6.93826 10.9668 7.02241 10.8438 7.09684 10.6885C7.37518 10.1286 7.88329 9.45216 8.29432 9.09615C8.40112 9.0023 8.49174 8.9052 8.49174 8.88255C8.49174 8.84371 6.95768 6.81125 6.7991 6.63648C6.76349 6.59765 6.702 6.56528 6.66317 6.56528C6.62433 6.56528 6.46251 6.68179 6.26832 6.85656Z" fill={color} />
|
||||
<path d="M17.7577 9.48521L16.6509 10.5953L16.748 10.7798C16.8548 10.9869 16.8807 10.9966 17.104 10.9157C17.1816 10.8866 17.7771 10.6827 18.4277 10.4626C19.0782 10.2393 19.6284 10.0386 19.651 10.016C19.7222 9.94478 19.4342 9.31045 19.0329 8.64375C18.9455 8.49811 18.8711 8.37836 18.8678 8.37836C18.8646 8.37836 18.3662 8.87677 17.7577 9.48521Z" fill={color} />
|
||||
<path d="M3.83459 10.8592C3.49477 12.1312 3.47211 13.4192 3.76986 14.8141C3.81841 15.0439 3.85401 15.1442 3.89284 15.154C3.92197 15.1637 4.56278 14.963 5.3201 14.7073C6.48844 14.3125 6.69557 14.2316 6.69234 14.183C6.6891 14.1474 6.66321 13.9565 6.63408 13.7558C6.55964 13.2445 6.56612 12.6037 6.65026 12.0891C6.68586 11.8593 6.71176 11.6651 6.70528 11.6586C6.67615 11.6295 3.9867 10.7395 3.92844 10.7395C3.88313 10.7395 3.85724 10.7751 3.83459 10.8592Z" fill={color} />
|
||||
<path d="M18.4275 11.2088C17.476 11.5357 17.0876 11.6813 17.0908 11.7137C17.0941 11.7396 17.12 11.8884 17.1491 12.0503C17.2365 12.5454 17.2462 13.1215 17.1815 13.6199C17.0876 14.3125 17.052 14.2284 17.5051 14.3805C17.7187 14.4517 18.3433 14.6621 18.8903 14.8465C19.7479 15.1378 19.8936 15.1766 19.9292 15.1378C19.981 15.086 20.0845 14.6523 20.159 14.1701C20.2431 13.6458 20.2593 12.5357 20.1946 11.9985C20.1331 11.5227 19.9939 10.8431 19.9421 10.7784C19.9227 10.7589 19.8774 10.7428 19.8386 10.7428C19.803 10.746 19.1654 10.9531 18.4275 11.2088Z" fill={color} />
|
||||
<path d="M6.79279 14.9643C6.33645 15.1132 4.18424 15.8511 4.15511 15.8705C4.1001 15.9028 4.11628 15.9643 4.27486 16.3139C4.75385 17.3786 5.49175 18.3852 6.32027 19.1134C6.4918 19.2622 6.61802 19.3496 6.66657 19.3496C6.72159 19.3496 6.8025 19.2719 6.99344 19.0227C7.13261 18.8447 7.44007 18.4467 7.67633 18.1424C7.90935 17.835 8.16826 17.5049 8.2427 17.4078C8.32037 17.3107 8.40775 17.1909 8.44012 17.1391L8.49837 17.0518L8.26212 16.8317C7.81226 16.4174 7.32679 15.7378 7.06465 15.1488C7.00639 15.0193 6.95137 14.9157 6.94166 14.919C6.93195 14.9222 6.86399 14.9416 6.79279 14.9643Z" fill={color} />
|
||||
<path d="M16.6963 15.2446C16.4018 15.8465 15.939 16.4712 15.4923 16.8725C15.3985 16.9566 15.3208 17.0375 15.3208 17.0537C15.3208 17.1055 17.0361 19.3322 17.1008 19.3613C17.1526 19.3839 17.1979 19.3613 17.3338 19.2448C17.5895 19.0247 18.1721 18.4292 18.4051 18.1444C18.8388 17.6201 19.3339 16.7948 19.5767 16.2025C19.6802 15.9501 19.6835 15.9307 19.6317 15.8789C19.6026 15.8498 18.9877 15.6297 18.2659 15.3902C17.5442 15.1475 16.9325 14.9436 16.9066 14.9339C16.8678 14.9177 16.816 14.9954 16.6963 15.2446Z" fill={color} />
|
||||
<path d="M8.80246 17.8237C8.65682 18.0114 8.38173 18.3707 8.19402 18.6199C8.00307 18.8691 7.73445 19.2251 7.58881 19.4128C7.44641 19.6005 7.32666 19.7817 7.32666 19.8206C7.32666 19.9338 8.14871 20.3934 8.88014 20.6847C9.63746 20.9889 10.5598 21.196 11.178 21.2025L11.5178 21.209V19.7364V18.2639L11.3074 18.2412C10.7055 18.1732 10.0808 17.9855 9.48534 17.6845L9.07108 17.4774L8.80246 17.8237Z" fill={color} />
|
||||
<path d="M14.4566 17.6207C13.9258 17.9087 13.1167 18.1741 12.5697 18.2324C12.4532 18.2421 12.3335 18.2615 12.3043 18.268C12.2493 18.2841 12.2461 18.3812 12.2461 19.7049C12.2461 21.006 12.2493 21.1289 12.3043 21.1904C12.3594 21.2584 12.3594 21.2584 12.7963 21.2099C14.0196 21.0675 15.078 20.7114 16.1557 20.0868C16.4146 19.9347 16.4858 19.8797 16.4858 19.8247C16.4858 19.7858 16.3434 19.569 16.1686 19.3457C15.9971 19.1224 15.6087 18.6143 15.3077 18.2194C15.0068 17.8246 14.7511 17.4977 14.7414 17.488C14.7284 17.4815 14.6022 17.5398 14.4566 17.6207Z" fill={color} />
|
||||
<svg width={size} height={size} viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path d="M39.1499 0.0455742C36.8449 0.458965 35.0171 2.12048 34.4267 4.37029C34.2407 5.06987 34.2245 6.31799 34.3944 7.02553C34.4591 7.30377 34.4914 7.56612 34.4672 7.61382C34.4348 7.66152 34.4429 7.67742 34.4914 7.65357C34.5319 7.62972 34.6208 7.76486 34.6936 7.94771L34.823 8.28955L32.9305 10.1498C31.8872 11.1753 30.9976 12.0021 30.9491 11.9862C30.9006 11.9783 30.8844 12.0021 30.9087 12.0419C30.9329 12.0816 29.6227 13.4172 27.9971 15.0072C26.3716 16.5892 24.6085 18.3222 24.0828 18.8469L23.1284 19.793L22.3278 19.4193C21.1794 18.8787 20.4515 18.7118 19.2707 18.7118C17.726 18.7038 16.715 18.99 15.4776 19.793C14.2079 20.6118 13.3506 21.5499 12.7198 22.8059C12.1779 23.8792 12.0081 24.6503 12 25.962C12 27.0671 12.0809 27.5202 12.4448 28.506C13.205 30.5411 15.138 32.1788 17.5319 32.8068C18.5509 33.0771 20.1765 33.0612 21.2683 32.775C25.5224 31.6621 27.803 27.393 26.2583 23.426C26.1208 23.0683 26.0157 22.7582 26.0319 22.7423C26.048 22.7264 27.0994 21.6771 28.3692 20.421C29.6389 19.1649 31.1108 17.6863 31.6446 17.1377C34.2488 14.4666 37.8397 10.8573 37.8882 10.8573C37.9044 10.8573 38.058 10.9289 38.2198 11.0084C39.1984 11.5013 40.8402 11.5887 41.9967 11.223C42.8782 10.9448 43.5737 10.5235 44.245 9.87157C45.4581 8.67909 45.9919 7.44687 46 5.80126C46 4.37824 45.539 3.16191 44.5442 1.96148C44.2774 1.63554 44.059 1.39705 44.059 1.42885C44.059 1.46065 43.9134 1.36525 43.7274 1.2142C43.2664 0.824657 42.4253 0.403316 41.7136 0.212521C41.01 0.0217247 39.7645 -0.0577736 39.1499 0.0455742Z" fill={color} />
|
||||
<circle cx="20" cy="26" r="18.5" stroke={color} strokeWidth="3" />
|
||||
<path d="M26 15.4988C22 13.4999 17.793 13.752 15.2009 14.6172C12.6088 15.4823 10.3896 17.2063 8.91029 19.504C7.431 21.8016 6.78025 24.5354 7.06564 27.2531C7.35103 29.9709 8.55548 32.5098 10.4798 34.4501C12.4041 36.3904 14.933 37.6157 17.6483 37.9235C20.3636 38.2314 23.1027 37.6032 25.4125 36.1429C27.7223 34.6826 29.6135 32.5849 30.5 30C31.3865 27.4151 31.5 25 31 20L28 22.5C28.5 24.5 28.0118 26.9632 27.359 28.8667C26.7061 30.7702 25.4231 32.3939 23.7222 33.4693C22.0212 34.5446 20.0042 35.0072 18.0046 34.7805C16.0051 34.5539 14.1427 33.6515 12.7257 32.2227C11.3086 30.7939 10.4216 28.9242 10.2115 26.9228C10.0013 24.9214 10.4805 22.9083 11.5699 21.2163C12.6592 19.5242 14.2935 18.2547 16.2023 17.6176C18.1112 16.9805 20 16.9999 23.5 17.9999L26 15.4988Z" fill={color} />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,16 +3,19 @@ import {
|
||||
IconDotsVertical,
|
||||
IconUnlink,
|
||||
IconSettings,
|
||||
IconRefresh
|
||||
IconRefresh,
|
||||
IconCircleCheck,
|
||||
IconAlertTriangle
|
||||
} from '@tabler/icons';
|
||||
import toast from 'react-hot-toast';
|
||||
import Button from 'ui/Button';
|
||||
import StatusBadge from 'ui/StatusBadge';
|
||||
import ActionIcon from 'ui/ActionIcon/index';
|
||||
import MenuDropdown from 'ui/MenuDropdown';
|
||||
import Help from 'components/Help';
|
||||
|
||||
const OpenAPISyncHeader = ({
|
||||
collection, spec, sourceUrl, onViewSpec,
|
||||
collection, spec, sourceUrl, syncStatus, onViewSpec,
|
||||
onOpenSettings, onOpenDisconnect,
|
||||
onCheck, isLoading
|
||||
}) => {
|
||||
@@ -100,7 +103,7 @@ const OpenAPISyncHeader = ({
|
||||
</div>
|
||||
</div>
|
||||
<div className="spec-url-row">
|
||||
<span className="spec-url-label">{sourceIsLocal ? 'Source File' : 'Source URL'}</span>
|
||||
<span className="spec-url-label">{sourceIsLocal ? 'Source File:' : 'Source URL:'}</span>
|
||||
{sourceIsLocal ? (
|
||||
<button
|
||||
className="spec-url-value spec-file-reveal"
|
||||
@@ -125,6 +128,28 @@ const OpenAPISyncHeader = ({
|
||||
<IconCopy size={12} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="linked-collection-row mt-1">
|
||||
<span className="spec-url-label">Linked Collection:</span>
|
||||
<span className="linked-collection-name">{collection.name}</span>
|
||||
{syncStatus === 'in-sync' && (
|
||||
<Help
|
||||
placement="bottom"
|
||||
width={240}
|
||||
iconComponent={() => <IconCircleCheck size={14} className="sync-status-icon in-sync" />}
|
||||
>
|
||||
Collection is up to date with the spec
|
||||
</Help>
|
||||
)}
|
||||
{syncStatus === 'not-in-sync' && (
|
||||
<Help
|
||||
placement="bottom"
|
||||
width={260}
|
||||
iconComponent={() => <IconAlertTriangle size={14} className="sync-status-icon not-in-sync" />}
|
||||
>
|
||||
Collection is not up to date with the spec
|
||||
</Help>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
|
||||
.setup-form {
|
||||
/* background: ${(props) => props.theme.background.surface0}; */
|
||||
border: 1px solid ${(props) => props.theme.border.border1};
|
||||
border-radius: ${(props) => props.theme.border.radius.md};
|
||||
padding: 1rem;
|
||||
@@ -40,6 +39,7 @@ const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.url-input {
|
||||
@@ -87,40 +87,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.url-label {
|
||||
display: block;
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
margin-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.url-row {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.url-input {
|
||||
flex: 1;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: ${(props) => props.theme.font.size.sm};
|
||||
font-family: monospace;
|
||||
color: ${(props) => props.theme.text};
|
||||
background: ${(props) => props.theme.input.bg};
|
||||
border: 1px solid ${(props) => props.theme.input.border};
|
||||
border-radius: ${(props) => props.theme.border.radius.md};
|
||||
outline: none;
|
||||
|
||||
&:focus {
|
||||
border-color: ${(props) => props.theme.input.focusBorder};
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
}
|
||||
}
|
||||
|
||||
/* Spec Info Card — borderless header */
|
||||
.spec-info-card {
|
||||
margin-bottom: 14px;
|
||||
@@ -161,20 +127,19 @@ const StyledWrapper = styled.div`
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.spec-url-label {
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.spec-url-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
|
||||
.spec-url-label {
|
||||
font-size: 11px;
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
flex-shrink: 0;
|
||||
}
|
||||
font-size: 11px;
|
||||
|
||||
.spec-url-value {
|
||||
font-family: monospace;
|
||||
font-size: 11px;
|
||||
color: ${(props) => props.theme.colors.text.subtext0};
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -203,6 +168,27 @@ const StyledWrapper = styled.div`
|
||||
|
||||
}
|
||||
|
||||
.linked-collection-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
|
||||
.linked-collection-name {
|
||||
color: ${(props) => props.theme.colors.text.subtext0};
|
||||
}
|
||||
|
||||
.sync-status-icon {
|
||||
&.in-sync {
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
&.not-in-sync {
|
||||
color: ${(props) => props.theme.colors.text.warning};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copy-btn {
|
||||
flex-shrink: 0;
|
||||
padding: 0 4px;
|
||||
@@ -279,59 +265,8 @@ const StyledWrapper = styled.div`
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.35;
|
||||
animation: radiate 1.6s ease-out infinite;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: relative;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.success {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.green}; }
|
||||
&::before { animation: none; }
|
||||
}
|
||||
&.warning {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.warning}; }
|
||||
}
|
||||
&.muted {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.muted}; }
|
||||
}
|
||||
&.danger {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.danger}; }
|
||||
}
|
||||
&.info {
|
||||
&::before, &::after { background: ${(props) => props.theme.status.info.text}; }
|
||||
}
|
||||
}
|
||||
|
||||
.status-check-icon {
|
||||
flex-shrink: 0;
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
.status-dot.success::before {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.banner-subtitle {
|
||||
@@ -456,58 +391,7 @@ const StyledWrapper = styled.div`
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.35;
|
||||
animation: radiate 1.6s ease-out infinite;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: relative;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.success {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.green}; }
|
||||
}
|
||||
&.info {
|
||||
&::before, &::after { background: ${(props) => props.theme.status.info.text}; }
|
||||
}
|
||||
&.warning {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.warning}; }
|
||||
}
|
||||
&.danger {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.danger}; }
|
||||
}
|
||||
&.muted {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.muted}; }
|
||||
}
|
||||
}
|
||||
|
||||
.status-check-icon {
|
||||
flex-shrink: 0;
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.text};
|
||||
|
||||
.version-code {
|
||||
@@ -548,6 +432,60 @@ const StyledWrapper = styled.div`
|
||||
100% { transform: scale(2.8); opacity: 0; }
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
opacity: 0.35;
|
||||
animation: radiate 1.6s ease-out infinite;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: relative;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.success {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.green}; }
|
||||
}
|
||||
&.warning {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.warning}; }
|
||||
}
|
||||
&.muted {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.muted}; }
|
||||
}
|
||||
&.danger {
|
||||
&::before, &::after { background: ${(props) => props.theme.colors.text.danger}; }
|
||||
}
|
||||
&.info {
|
||||
&::before, &::after { background: ${(props) => props.theme.status.info.text}; }
|
||||
}
|
||||
}
|
||||
|
||||
.status-check-icon {
|
||||
flex-shrink: 0;
|
||||
color: ${(props) => props.theme.colors.text.green};
|
||||
}
|
||||
|
||||
.banner-title {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Summary Cards */
|
||||
|
||||
.sync-summary-title-row {
|
||||
@@ -803,8 +741,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* State Messages */
|
||||
.state-message {
|
||||
display: flex;
|
||||
@@ -859,54 +795,7 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.collection-status-section {
|
||||
margin-top: 20px;
|
||||
|
||||
.change-section {
|
||||
margin-top: 0.75rem;
|
||||
|
||||
.section-body.expandable-mode {
|
||||
border-radius: 0 0 8px 8px;
|
||||
max-height: none; /* Override default max-height so all items remain visible */
|
||||
}
|
||||
}
|
||||
|
||||
/* Local Changes tab: override hover background */
|
||||
.endpoint-review-row .review-row-header:hover {
|
||||
background: ${(props) => props.theme.sidebar.collection.item.hoverBg};
|
||||
}
|
||||
|
||||
.sync-review-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
|
||||
.empty-state-icon {
|
||||
color: var(--color-text-muted, #9ca3af);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: ${(props) => props.theme.font.size.base};
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.text};
|
||||
margin: 0 0 0.375rem 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
line-height: 1.5;
|
||||
max-width: 400px;
|
||||
margin: 0;
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sync-tab-content .sync-review-empty-state {
|
||||
.sync-review-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -935,6 +824,20 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.collection-status-section {
|
||||
margin-top: 20px;
|
||||
|
||||
.change-section {
|
||||
margin-top: 0.75rem;
|
||||
|
||||
.section-body.expandable-mode {
|
||||
border-radius: 0 0 8px 8px;
|
||||
max-height: none; /* Override default max-height so all items remain visible */
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Expandable endpoint rows — shared base styles */
|
||||
.endpoint-review-row {
|
||||
border-bottom: 1px solid ${(props) => props.theme.border.border1};
|
||||
@@ -1183,10 +1086,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Endpoint Details */
|
||||
.endpoint-details {
|
||||
padding: 0.75rem;
|
||||
@@ -1332,10 +1231,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Disconnect Modal */
|
||||
.disconnect-modal {
|
||||
.disconnect-message {
|
||||
@@ -1470,8 +1365,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Sync Review Modal */
|
||||
.sync-review-page {
|
||||
position: relative;
|
||||
@@ -1823,36 +1716,6 @@ const StyledWrapper = styled.div`
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.sync-review-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
color: var(--color-text-muted, #6b7280);
|
||||
|
||||
.empty-state-icon {
|
||||
color: var(--color-text-muted, #9ca3af);
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: ${(props) => props.theme.font.size.base};
|
||||
font-weight: 500;
|
||||
color: ${(props) => props.theme.text};
|
||||
margin: 0 0 0.375rem 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: ${(props) => props.theme.font.size.xs};
|
||||
line-height: 1.5;
|
||||
max-width: 400px;
|
||||
margin: 0;
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
}
|
||||
}
|
||||
|
||||
.endpoints-review-sections {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1890,7 +1753,6 @@ const StyledWrapper = styled.div`
|
||||
max-height: none;
|
||||
|
||||
&.expandable-mode {
|
||||
/* border: 1px solid ${(props) => props.theme.border.border1}; */
|
||||
border-top: none;
|
||||
border-radius: 0 0 ${(props) => props.theme.border.radius.sm} ${(props) => props.theme.border.radius.sm};
|
||||
}
|
||||
@@ -1974,10 +1836,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
.review-row-diff {
|
||||
background: ${(props) => props.theme.background.mantle};
|
||||
}
|
||||
|
||||
.endpoint-diff-view {
|
||||
.diff-section {
|
||||
margin-bottom: 0.5rem;
|
||||
@@ -2108,12 +1966,10 @@ const StyledWrapper = styled.div`
|
||||
bottom: 0rem;
|
||||
background: ${(props) => props.theme.background.base};
|
||||
margin-top: 1rem;
|
||||
/* box-shadow: 0 -4px 12px -4px rgba(0, 0, 0, 0.3); */
|
||||
z-index: 10;
|
||||
padding-top: 0.75rem;
|
||||
padding-bottom: 0.75rem;
|
||||
|
||||
|
||||
.bar-stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -2218,12 +2074,6 @@ const StyledWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
|
||||
.chevron {
|
||||
color: ${(props) => props.theme.colors.text.muted};
|
||||
transition: transform 0.15s ease;
|
||||
flex-shrink: 0;
|
||||
&.expanded { transform: rotate(90deg); }
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-group-label {
|
||||
|
||||
@@ -61,6 +61,14 @@ const OpenAPISyncTab = ({ collection }) => {
|
||||
? (specDrift?.added?.length || 0) + (specDrift?.modified?.length || 0) + (specDrift?.removed?.length || 0)
|
||||
: (remoteDrift?.modified?.length || 0) + (remoteDrift?.missing?.length || 0);
|
||||
|
||||
const syncStatus = (() => {
|
||||
if (isLoading) return 'loading';
|
||||
if (error) return 'not-in-sync';
|
||||
if (!hasDriftData) return null;
|
||||
if (collectionChangesCount > 0 || specUpdatesCount > 0) return 'not-in-sync';
|
||||
return 'in-sync';
|
||||
})();
|
||||
|
||||
const syncTabs = useMemo(() => [
|
||||
{ key: 'overview', label: 'Overview' },
|
||||
{
|
||||
@@ -96,6 +104,7 @@ const OpenAPISyncTab = ({ collection }) => {
|
||||
collection={collection}
|
||||
spec={storedSpec || specDrift?.newSpec}
|
||||
sourceUrl={sourceUrl}
|
||||
syncStatus={syncStatus}
|
||||
onViewSpec={handleViewSpec}
|
||||
onOpenSettings={() => setShowSettingsModal(true)}
|
||||
onOpenDisconnect={() => setShowDisconnectModal(true)}
|
||||
|
||||
@@ -22,6 +22,7 @@ import { addTab, focusTab } from 'providers/ReduxStore/slices/tabs';
|
||||
import { uuid } from 'utils/common';
|
||||
import toast from 'react-hot-toast';
|
||||
import Dropdown from 'components/Dropdown';
|
||||
import MenuDropdown from 'ui/MenuDropdown';
|
||||
import CloseWorkspace from 'components/Sidebar/CloseWorkspace';
|
||||
import EnvironmentSelector from 'components/Environments/EnvironmentSelector';
|
||||
import ToolHint from 'components/ToolHint';
|
||||
@@ -197,6 +198,15 @@ const CollectionHeader = ({ collection, isScratchCollection }) => {
|
||||
}));
|
||||
};
|
||||
|
||||
// Build overflow menu items for the "..." dropdown
|
||||
const overflowMenuItems = [
|
||||
{ id: 'variables', label: 'Variables', leftSection: IconEye, onClick: viewVariables },
|
||||
{ id: 'collection-settings', label: 'Collection Settings', leftSection: IconSettings, onClick: viewCollectionSettings },
|
||||
...(!hasOpenApiSyncConfigured
|
||||
? [{ id: 'openapi-sync', label: 'OpenAPI Sync', leftSection: () => <OpenAPISyncIcon size={16} />, onClick: viewOpenApiSync }]
|
||||
: [])
|
||||
];
|
||||
|
||||
// Workspace action handlers (only used when isScratchCollection is true)
|
||||
const handleRenameWorkspaceClick = () => {
|
||||
workspaceActionsRef.current?.hide();
|
||||
@@ -450,36 +460,38 @@ const CollectionHeader = ({ collection, isScratchCollection }) => {
|
||||
|
||||
{/* Right side: Actions (only for regular collections) */}
|
||||
{!isScratchCollection && (
|
||||
<div className="flex flex-grow gap-1 items-center justify-end">
|
||||
<ToolHint
|
||||
text={hasOpenApiError ? 'OpenAPI Error' : hasOpenApiUpdates ? 'OpenAPI Updates Available' : 'OpenAPI'}
|
||||
toolhintId="OpenApiSyncToolhintId"
|
||||
place="bottom"
|
||||
>
|
||||
<ActionIcon onClick={viewOpenApiSync} aria-label="OpenAPI" size="sm" className="relative">
|
||||
<OpenAPISyncIcon size={16} />
|
||||
{(hasOpenApiUpdates || hasOpenApiError) && (
|
||||
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full" style={{ backgroundColor: hasOpenApiError ? theme.status.danger.text : theme.status.warning.text }} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
</ToolHint>
|
||||
<div className="flex flex-grow gap-1.5 items-center justify-end">
|
||||
{/* OpenAPI Sync - standalone only when configured */}
|
||||
{hasOpenApiSyncConfigured && (
|
||||
<ToolHint
|
||||
text={hasOpenApiError ? 'OpenAPI Error' : hasOpenApiUpdates ? 'OpenAPI Updates Available' : 'OpenAPI'}
|
||||
toolhintId="OpenApiSyncToolhintId"
|
||||
place="bottom"
|
||||
>
|
||||
<ActionIcon onClick={viewOpenApiSync} aria-label="OpenAPI" size="sm" className="relative">
|
||||
<OpenAPISyncIcon size={15} />
|
||||
{(hasOpenApiUpdates || hasOpenApiError) && (
|
||||
<span className="absolute top-0 right-0 w-1.5 h-1.5 rounded-full" style={{ backgroundColor: hasOpenApiError ? theme.status.danger.text : theme.status.warning.text }} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
</ToolHint>
|
||||
)}
|
||||
{/* Runner - always visible */}
|
||||
<ToolHint text="Runner" toolhintId="RunnerToolhintId" place="bottom">
|
||||
<ActionIcon onClick={handleRun} aria-label="Runner" size="sm">
|
||||
<IconRun size={16} strokeWidth={1.5} />
|
||||
</ActionIcon>
|
||||
</ToolHint>
|
||||
<ToolHint text="Variables" toolhintId="VariablesToolhintId">
|
||||
<ActionIcon onClick={viewVariables} aria-label="Variables" size="sm">
|
||||
<IconEye size={16} strokeWidth={1.5} />
|
||||
</ActionIcon>
|
||||
</ToolHint>
|
||||
<ToolHint text="Collection Settings" toolhintId="CollectionSettingsToolhintId">
|
||||
<ActionIcon onClick={viewCollectionSettings} aria-label="Collection Settings" size="sm">
|
||||
<IconSettings size={16} strokeWidth={1.5} />
|
||||
</ActionIcon>
|
||||
</ToolHint>
|
||||
{/* JS Sandbox Mode - always visible */}
|
||||
<JsSandboxMode collection={collection} />
|
||||
<span className="ml-2">
|
||||
{/* Overflow menu */}
|
||||
<MenuDropdown items={overflowMenuItems} placement="bottom-end">
|
||||
<ActionIcon label="More actions" size="sm" style={{ border: `1px solid ${theme.border.border1}`, borderRadius: theme.border.radius.base, width: 24, marginRight: 4, marginLeft: 4 }}>
|
||||
<IconDots size={16} strokeWidth={1.5} />
|
||||
</ActionIcon>
|
||||
</MenuDropdown>
|
||||
{/* Environment Selector - always visible */}
|
||||
<span>
|
||||
<EnvironmentSelector collection={collection} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user