mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-27 22:54:07 +00:00
feat: include pinned data in filtering for more accurate results in env variables search (#7513)
This commit is contained in:
@@ -99,24 +99,6 @@ const Wrapper = styled.div`
|
||||
.name-cell-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.name-highlight-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: ${(props) => props.theme.text};
|
||||
}
|
||||
}
|
||||
|
||||
.search-highlight {
|
||||
background: ${(props) => props.theme.colors.accent}55;
|
||||
color: inherit;
|
||||
border-radius: 2px;
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
|
||||
@@ -31,15 +31,6 @@ const TableRow = React.memo(
|
||||
}
|
||||
);
|
||||
|
||||
const highlightText = (text, query) => {
|
||||
if (!query?.trim() || !text) return text;
|
||||
const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
||||
const parts = text.split(regex);
|
||||
return parts.map((part, i) =>
|
||||
regex.test(part) ? <mark key={i} className="search-highlight">{part}</mark> : part
|
||||
);
|
||||
};
|
||||
|
||||
const EnvironmentVariablesTable = ({
|
||||
environment,
|
||||
collection,
|
||||
@@ -51,8 +42,7 @@ const EnvironmentVariablesTable = ({
|
||||
renderExtraValueContent,
|
||||
searchQuery = ''
|
||||
}) => {
|
||||
const { storedTheme, theme } = useTheme();
|
||||
const valueMatchBg = theme?.colors?.accent ? `${theme.colors.accent}1a` : undefined;
|
||||
const { storedTheme } = useTheme();
|
||||
const { globalEnvironments, activeGlobalEnvironmentUid } = useSelector((state) => state.globalEnvironments);
|
||||
|
||||
const hasDraftForThisEnv = draft?.environmentUid === environment.uid;
|
||||
@@ -60,7 +50,7 @@ const EnvironmentVariablesTable = ({
|
||||
const [tableHeight, setTableHeight] = useState(MIN_H);
|
||||
const [columnWidths, setColumnWidths] = useState({ name: '30%', value: 'auto' });
|
||||
const [resizing, setResizing] = useState(null);
|
||||
const [focusedNameIndex, setFocusedNameIndex] = useState(null);
|
||||
const [pinnedData, setPinnedData] = useState({ query: '', uids: new Set() });
|
||||
|
||||
const handleResizeStart = useCallback((e, columnKey) => {
|
||||
e.preventDefault();
|
||||
@@ -103,6 +93,13 @@ const EnvironmentVariablesTable = ({
|
||||
setTableHeight(h);
|
||||
}, []);
|
||||
|
||||
const handleRowFocus = useCallback((uid) => {
|
||||
setPinnedData((prev) => ({
|
||||
query: searchQuery,
|
||||
uids: prev.query === searchQuery ? new Set([...prev.uids, uid]) : new Set([uid])
|
||||
}));
|
||||
}, [searchQuery]);
|
||||
|
||||
const prevEnvUidRef = useRef(null);
|
||||
const prevEnvVariablesRef = useRef(environment.variables);
|
||||
const mountedRef = useRef(false);
|
||||
@@ -205,6 +202,10 @@ const EnvironmentVariablesTable = ({
|
||||
return JSON.stringify((environment.variables || []).map(stripEnvVarUid));
|
||||
}, [environment.variables]);
|
||||
|
||||
useEffect(() => {
|
||||
setPinnedData({ query: '', uids: new Set() });
|
||||
}, [savedValuesJson]);
|
||||
|
||||
// Sync modified state
|
||||
useEffect(() => {
|
||||
const currentValues = formik.values.filter((variable) => variable.name && variable.name.trim() !== '');
|
||||
@@ -419,12 +420,20 @@ const EnvironmentVariablesTable = ({
|
||||
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
|
||||
const effectivePins = pinnedData.query === searchQuery ? pinnedData.uids : new Set();
|
||||
return allVariables.filter(({ variable }) => {
|
||||
if (effectivePins.has(variable.uid)) return true;
|
||||
const nameMatch = variable.name ? variable.name.toLowerCase().includes(query) : false;
|
||||
const valueMatch = typeof variable.value === 'string' ? variable.value.toLowerCase().includes(query) : false;
|
||||
const valueText
|
||||
= typeof variable.value === 'string'
|
||||
? variable.value
|
||||
: typeof variable.value === 'number' || typeof variable.value === 'boolean'
|
||||
? String(variable.value)
|
||||
: '';
|
||||
const valueMatch = valueText.toLowerCase().includes(query);
|
||||
return !!(nameMatch || valueMatch);
|
||||
});
|
||||
}, [formik.values, searchQuery]);
|
||||
}, [formik.values, searchQuery, pinnedData]);
|
||||
|
||||
const isSearchActive = !!searchQuery?.trim();
|
||||
|
||||
@@ -461,11 +470,6 @@ const EnvironmentVariablesTable = ({
|
||||
const isLastRow = actualIndex === formik.values.length - 1;
|
||||
const isEmptyRow = !variable.name || variable.name.trim() === '';
|
||||
const isLastEmptyRow = isLastRow && isEmptyRow;
|
||||
const activeQuery = searchQuery?.trim().toLowerCase();
|
||||
const valueMatchesOnly = activeQuery
|
||||
&& !(variable.name?.toLowerCase().includes(activeQuery))
|
||||
&& typeof variable.value === 'string'
|
||||
&& variable.value.toLowerCase().includes(activeQuery);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -476,8 +480,7 @@ const EnvironmentVariablesTable = ({
|
||||
className="mousetrap"
|
||||
name={`${actualIndex}.enabled`}
|
||||
checked={variable.enabled}
|
||||
onChange={isSearchActive ? undefined : formik.handleChange}
|
||||
disabled={isSearchActive}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
@@ -495,29 +498,25 @@ const EnvironmentVariablesTable = ({
|
||||
name={`${actualIndex}.name`}
|
||||
value={variable.name}
|
||||
placeholder={!variable.value || (typeof variable.value === 'string' && variable.value.trim() === '') ? 'Name' : ''}
|
||||
readOnly={isSearchActive}
|
||||
onChange={isSearchActive ? undefined : (e) => handleNameChange(actualIndex, e)}
|
||||
onFocus={() => !isSearchActive && setFocusedNameIndex(actualIndex)}
|
||||
onChange={(e) => handleNameChange(actualIndex, e)}
|
||||
onFocus={() => handleRowFocus(variable.uid)}
|
||||
onBlur={() => {
|
||||
setFocusedNameIndex(null); if (!isSearchActive) handleNameBlur(actualIndex);
|
||||
handleNameBlur(actualIndex);
|
||||
}}
|
||||
onKeyDown={isSearchActive ? undefined : (e) => handleNameKeyDown(actualIndex, e)}
|
||||
style={searchQuery?.trim() && focusedNameIndex !== actualIndex ? { color: 'transparent' } : undefined}
|
||||
onKeyDown={(e) => handleNameKeyDown(actualIndex, e)}
|
||||
/>
|
||||
{searchQuery?.trim() && focusedNameIndex !== actualIndex && (
|
||||
<div className="name-highlight-overlay">
|
||||
{highlightText(variable.name || '', searchQuery)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ErrorMessage name={`${actualIndex}.name`} index={actualIndex} />
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="flex flex-row flex-nowrap items-center"
|
||||
style={{ width: columnWidths.value, ...(valueMatchesOnly && valueMatchBg ? { background: valueMatchBg } : {}) }}
|
||||
style={{ width: columnWidths.value }}
|
||||
>
|
||||
<div className="overflow-hidden grow w-full relative">
|
||||
<div
|
||||
className="overflow-hidden grow w-full relative"
|
||||
onFocus={() => handleRowFocus(variable.uid)}
|
||||
>
|
||||
<MultiLineEditor
|
||||
theme={storedTheme}
|
||||
collection={_collection}
|
||||
@@ -525,7 +524,7 @@ const EnvironmentVariablesTable = ({
|
||||
value={variable.value}
|
||||
placeholder={isLastEmptyRow ? 'Value' : ''}
|
||||
isSecret={variable.secret}
|
||||
readOnly={isSearchActive || typeof variable.value !== 'string'}
|
||||
readOnly={typeof variable.value !== 'string'}
|
||||
onChange={(newValue) => {
|
||||
formik.setFieldValue(`${actualIndex}.value`, newValue, true);
|
||||
// Clear ephemeral metadata when user manually edits the value
|
||||
@@ -556,14 +555,13 @@ const EnvironmentVariablesTable = ({
|
||||
className="mousetrap"
|
||||
name={`${actualIndex}.secret`}
|
||||
checked={variable.secret}
|
||||
onChange={isSearchActive ? undefined : formik.handleChange}
|
||||
disabled={isSearchActive}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{!isLastEmptyRow && (
|
||||
<button onClick={isSearchActive ? undefined : () => handleRemoveVar(variable.uid)} disabled={isSearchActive}>
|
||||
<button onClick={() => handleRemoveVar(variable.uid)}>
|
||||
<IconTrash strokeWidth={1.5} size={18} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user