mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 22:45:25 +00:00
collection runner tag updates
This commit is contained in:
@@ -19,7 +19,7 @@ import StyledWrapper from './StyledWrapper';
|
||||
import Documentation from 'components/Documentation/index';
|
||||
import GraphQLSchemaActions from '../GraphQLSchemaActions/index';
|
||||
import HeightBoundContainer from 'ui/HeightBoundContainer';
|
||||
import Tags from 'components/RequestPane/Tags/index';
|
||||
import Settings from 'components/RequestPane/Settings';
|
||||
|
||||
const GraphQLRequestPane = ({ item, collection, onSchemaLoad, toggleDocs, handleGqlClickReference }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -102,8 +102,8 @@ const GraphQLRequestPane = ({ item, collection, onSchemaLoad, toggleDocs, handle
|
||||
case 'docs': {
|
||||
return <Documentation item={item} collection={collection} />;
|
||||
}
|
||||
case 'tags': {
|
||||
return <Tags item={item} collection={collection} />;
|
||||
case 'settings': {
|
||||
return <Settings item={item} collection={collection} />;
|
||||
}
|
||||
default: {
|
||||
return <div className="mt-4">404 | Not found</div>;
|
||||
@@ -156,8 +156,8 @@ const GraphQLRequestPane = ({ item, collection, onSchemaLoad, toggleDocs, handle
|
||||
<div className={getTabClassname('docs')} role="tab" onClick={() => selectTab('docs')}>
|
||||
Docs
|
||||
</div>
|
||||
<div className={getTabClassname('tags')} role="tab" onClick={() => selectTab('tags')}>
|
||||
Tags
|
||||
<div className={getTabClassname('settings')} role="tab" onClick={() => selectTab('settings')}>
|
||||
Settings
|
||||
</div>
|
||||
<GraphQLSchemaActions item={item} collection={collection} onSchemaLoad={setSchema} toggleDocs={toggleDocs} />
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,6 @@ import HeightBoundContainer from 'ui/HeightBoundContainer';
|
||||
import { useEffect } from 'react';
|
||||
import StatusDot from 'components/StatusDot';
|
||||
import Settings from 'components/RequestPane/Settings';
|
||||
import Tags from 'components/RequestPane/Tags/index';
|
||||
|
||||
const HttpRequestPane = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -66,9 +65,6 @@ const HttpRequestPane = ({ item, collection }) => {
|
||||
case 'settings': {
|
||||
return <Settings item={item} collection={collection} />;
|
||||
}
|
||||
case 'tags': {
|
||||
return <Tags item={item} collection={collection} />;
|
||||
}
|
||||
default: {
|
||||
return <div className="mt-4">404 | Not found</div>;
|
||||
}
|
||||
@@ -105,6 +101,7 @@ const HttpRequestPane = ({ item, collection }) => {
|
||||
const requestVars = getPropertyFromDraftOrRequest('request.vars.req');
|
||||
const responseVars = getPropertyFromDraftOrRequest('request.vars.res');
|
||||
const auth = getPropertyFromDraftOrRequest('request.auth');
|
||||
const tags = getPropertyFromDraftOrRequest('tags');
|
||||
|
||||
const activeParamsLength = params.filter((param) => param.enabled).length;
|
||||
const activeHeadersLength = headers.filter((header) => header.enabled).length;
|
||||
@@ -168,9 +165,7 @@ const HttpRequestPane = ({ item, collection }) => {
|
||||
</div>
|
||||
<div className={getTabClassname('settings')} role="tab" onClick={() => selectTab('settings')}>
|
||||
Settings
|
||||
</div>
|
||||
<div className={getTabClassname('tags')} role="tab" onClick={() => selectTab('tags')}>
|
||||
Tags
|
||||
{tags && tags.length > 0 && <StatusDot />}
|
||||
</div>
|
||||
{focusedTab.requestPaneTab === 'body' ? (
|
||||
<div className="flex flex-grow justify-end items-center">
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { addRequestTag, deleteRequestTag, updateCollectionTagsList } from 'providers/ReduxStore/slices/collections';
|
||||
import TagList from 'components/TagList/index';
|
||||
import { saveRequest } from 'providers/ReduxStore/slices/collections/actions';
|
||||
|
||||
const Tags = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
// all tags in the collection
|
||||
const collectionTags = collection.allTags || [];
|
||||
|
||||
// tags for the current request
|
||||
const tags = item.draft ? get(item, 'draft.tags', []) : get(item, 'tags', []);
|
||||
|
||||
// Filter out tags that are already associated with the current request
|
||||
const collectionTagsWithoutCurrentRequestTags = collectionTags?.filter(tag => !tags.includes(tag)) || [];
|
||||
|
||||
const handleAdd = useCallback((tag) => {
|
||||
const trimmedTag = tag.trim();
|
||||
if (trimmedTag && !tags.includes(trimmedTag)) {
|
||||
dispatch(
|
||||
addRequestTag({
|
||||
tag: trimmedTag,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [dispatch, tags, item.uid, collection.uid]);
|
||||
|
||||
const handleRemove = useCallback((tag) => {
|
||||
dispatch(
|
||||
deleteRequestTag({
|
||||
tag,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
}, [dispatch, item.uid, collection.uid]);
|
||||
|
||||
const handleRequestSave = () => {
|
||||
dispatch(saveRequest(item.uid, collection.uid));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(updateCollectionTagsList({ collectionUid: collection.uid }));
|
||||
}, [collection.uid, dispatch]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<TagList
|
||||
tagsHintList={collectionTagsWithoutCurrentRequestTags}
|
||||
handleAddTag={handleAdd}
|
||||
handleRemoveTag={handleRemove}
|
||||
tags={tags}
|
||||
onSave={handleRequestSave}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tags;
|
||||
@@ -1,8 +1,10 @@
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import get from 'lodash/get';
|
||||
import { IconTag } from '@tabler/icons';
|
||||
import ToggleSelector from 'components/RequestPane/Settings/ToggleSelector';
|
||||
import { updateItemSettings } from 'providers/ReduxStore/slices/collections';
|
||||
import Tags from './Tags/index';
|
||||
|
||||
const Settings = ({ item, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
@@ -22,7 +24,16 @@ const Settings = ({ item, collection }) => {
|
||||
}, [encodeUrl, dispatch, collection.uid, item.uid]);
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col gap-2">
|
||||
<div className="w-full h-full flex flex-col gap-10">
|
||||
<div className='flex flex-col gap-2 max-w-[400px]'>
|
||||
<h3 className="text-xs font-medium text-gray-900 dark:text-gray-100 flex items-center gap-1">
|
||||
<IconTag size={16} />
|
||||
Tags
|
||||
</h3>
|
||||
<div label="Tags">
|
||||
<Tags item={item} collection={collection} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex flex-col gap-4'>
|
||||
<ToggleSelector
|
||||
checked={encodeUrl}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
input[type='text'] {
|
||||
border: solid 1px transparent;
|
||||
outline: none !important;
|
||||
background-color: inherit;
|
||||
|
||||
&:focus {
|
||||
outline: none !important;
|
||||
border: solid 1px transparent;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid ${(props) => props.theme.text};
|
||||
border-radius: 5px;
|
||||
padding-inline: 5px;
|
||||
background: ${(props) => props.theme.sidebar.bg};
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
@@ -1,69 +0,0 @@
|
||||
import { IconX } from '@tabler/icons';
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
const TagList = ({ tags, onTagRemove, onTagAdd }) => {
|
||||
const tagNameRegex = /^[\w-]+$/;
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [text, setText] = useState('');
|
||||
|
||||
const handleChange = (e) => {
|
||||
setText(e.target.value);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e) => {
|
||||
if (e.code == 'Escape') {
|
||||
setText('');
|
||||
setIsEditing(false);
|
||||
return;
|
||||
}
|
||||
if (e.code !== 'Enter' && e.code !== 'Space') {
|
||||
return;
|
||||
}
|
||||
if (!tagNameRegex.test(text)) {
|
||||
toast.error('Tags must only contain alpha-numeric characters, "-", "_"');
|
||||
return;
|
||||
}
|
||||
if (tags.includes(text)) {
|
||||
toast.error(`Tag "${text}" already exists`);
|
||||
return;
|
||||
}
|
||||
onTagAdd(text);
|
||||
setText('');
|
||||
setIsEditing(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper className="flex flex-wrap gap-2 mt-1">
|
||||
<ul className="flex flex-wrap gap-1">
|
||||
{tags && tags.length
|
||||
? tags.map((_tag) => (
|
||||
<li key={_tag}>
|
||||
<span>{_tag}</span>
|
||||
<button tabIndex={-1} onClick={() => onTagRemove(_tag)}>
|
||||
<IconX strokeWidth={1.5} size={20} />
|
||||
</button>
|
||||
</li>
|
||||
))
|
||||
: null}
|
||||
</ul>
|
||||
{isEditing ? (
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Space or Enter to add tag"
|
||||
value={text}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
<button className="text-link select-none" onClick={() => setIsEditing(true)}>
|
||||
+ Add
|
||||
</button>
|
||||
)}
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagList;
|
||||
@@ -1,43 +0,0 @@
|
||||
import 'github-markdown-css/github-markdown.css';
|
||||
import get from 'lodash/get';
|
||||
import { addRequestTag, deleteRequestTag } from 'providers/ReduxStore/slices/collections';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import TagList from './TagList/TagList';
|
||||
|
||||
const Tags = ({ item, collection }) => {
|
||||
const tags = item.draft ? get(item, 'draft.request.tags') : get(item, 'request.tags');
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleAdd = (_tag) => {
|
||||
dispatch(
|
||||
addRequestTag({
|
||||
tag: _tag,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const handleRemove = (_tag) => {
|
||||
dispatch(
|
||||
deleteRequestTag({
|
||||
tag: _tag,
|
||||
itemUid: item.uid,
|
||||
collectionUid: collection.uid
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TagList tags={tags} onTagRemove={handleRemove} onTagAdd={handleAdd} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tags;
|
||||
Reference in New Issue
Block a user