mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
Lots more dropdown fixes
This commit is contained in:
parent
26d7423fa2
commit
27fcd29531
@ -36,7 +36,7 @@ class Dropdown extends PureComponent {
|
||||
}
|
||||
|
||||
_checkSizeAndPosition () {
|
||||
if (!this.state.open) {
|
||||
if (!this.state.open || !this._dropdownList) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,15 +58,19 @@ class Dropdown extends PureComponent {
|
||||
const {right, wide} = this.props;
|
||||
if (right || wide) {
|
||||
const {right} = dropdownRect;
|
||||
this._dropdownList.style.right = `${bodyRect.width - right}px`;
|
||||
this._dropdownList.style.maxWidth = `${right}px`;
|
||||
const {beside} = this.props;
|
||||
const offset = beside ? dropdownRect.width - dropdownRect.height : 0;
|
||||
this._dropdownList.style.right = `${bodyRect.width - right + offset}px`;
|
||||
this._dropdownList.style.maxWidth = `${right + offset}px`;
|
||||
this._dropdownList.style.minWidth = `${Math.min(right, 200)}px`;
|
||||
}
|
||||
|
||||
if (!right || wide) {
|
||||
const {left} = dropdownRect;
|
||||
this._dropdownList.style.left = `${left}px`;
|
||||
this._dropdownList.style.maxWidth = `${bodyRect.width - left - 5}px`;
|
||||
const {beside} = this.props;
|
||||
const offset = beside ? dropdownRect.width - dropdownRect.height : 0;
|
||||
this._dropdownList.style.left = `${left + offset}px`;
|
||||
this._dropdownList.style.maxWidth = `${bodyRect.width - left - 5 - offset}px`;
|
||||
this._dropdownList.style.minWidth = `${Math.min(bodyRect.width - left, 200)}px`;
|
||||
}
|
||||
|
||||
@ -93,6 +97,10 @@ class Dropdown extends PureComponent {
|
||||
|
||||
_addDropdownListRef (n) {
|
||||
this._dropdownList = n;
|
||||
}
|
||||
|
||||
_addDropdownMenuRef (n) {
|
||||
this._dropdownMenu = n;
|
||||
|
||||
// Move the element to the body so we can position absolutely
|
||||
if (n) {
|
||||
@ -103,7 +111,7 @@ class Dropdown extends PureComponent {
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
container.appendChild(ReactDOM.findDOMNode(n));
|
||||
container.appendChild(ReactDOM.findDOMNode(this._dropdownMenu));
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +171,7 @@ class Dropdown extends PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const {right, outline, wide, className, style, children, rightOffset} = this.props;
|
||||
const {right, outline, wide, className, style, children} = this.props;
|
||||
const {dropUp, open} = this.state;
|
||||
|
||||
const classes = classnames('dropdown', className, {
|
||||
@ -202,16 +210,14 @@ class Dropdown extends PureComponent {
|
||||
{allChildren}
|
||||
);
|
||||
} else {
|
||||
const styles = {};
|
||||
if (typeof rightOffset === 'number') {
|
||||
styles.marginRight = `-${rightOffset}px`;
|
||||
}
|
||||
|
||||
finalChildren = [
|
||||
dropdownButtons[0],
|
||||
<ul key="items" className={menuClasses} style={styles} ref={this._addDropdownListRef}>
|
||||
{dropdownItems}
|
||||
</ul>
|
||||
<div key="item" className={menuClasses} ref={this._addDropdownMenuRef}>
|
||||
<div className="dropdown__backdrop"></div>
|
||||
<ul ref={this._addDropdownListRef}>
|
||||
{dropdownItems}
|
||||
</ul>
|
||||
</div>
|
||||
];
|
||||
}
|
||||
|
||||
@ -222,7 +228,6 @@ class Dropdown extends PureComponent {
|
||||
onClick={this._handleClick}
|
||||
onMouseDown={this._handleMouseDown}>
|
||||
{finalChildren}
|
||||
<div className="dropdown__backdrop"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -240,7 +245,7 @@ Dropdown.propTypes = {
|
||||
onHide: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
style: PropTypes.string,
|
||||
rightOffset: PropTypes.number
|
||||
beside: PropTypes.bool
|
||||
};
|
||||
|
||||
export default Dropdown;
|
||||
|
@ -19,6 +19,7 @@ const TYPE_CONSTANT = 'constant';
|
||||
const MAX_CONSTANTS = -1;
|
||||
const MAX_VARIABLES = -1;
|
||||
const MAX_TAGS = -1;
|
||||
const MIN_CHAR_MATCH = 1;
|
||||
|
||||
const ICONS = {
|
||||
[TYPE_CONSTANT]: {char: '𝒄', title: 'Constant'},
|
||||
@ -308,6 +309,11 @@ function matchSegments (listOfThings, segment, type, limit = -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Throw away short matches
|
||||
if (matchSegment.length < MIN_CHAR_MATCH) {
|
||||
continue;
|
||||
}
|
||||
|
||||
matches.push({
|
||||
// Custom Insomnia keys
|
||||
type,
|
||||
|
@ -56,7 +56,7 @@ class AuthDropdown extends PureComponent {
|
||||
render () {
|
||||
const {children, className} = this.props;
|
||||
return (
|
||||
<Dropdown debug="true">
|
||||
<Dropdown beside debug="true">
|
||||
<DropdownDivider>Auth Types</DropdownDivider>
|
||||
<DropdownButton className={className}>
|
||||
{children}
|
||||
|
@ -22,11 +22,12 @@ class PreviewModeDropdown extends PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const {download, fullDownload} = this.props;
|
||||
const {download, fullDownload, previewMode} = this.props;
|
||||
return (
|
||||
<Dropdown>
|
||||
<Dropdown beside>
|
||||
<DropdownButton className="tall">
|
||||
<i className="fa fa-caret-down"/>
|
||||
{getPreviewModeName(previewMode)}
|
||||
<i className="fa fa-caret-down space-left"/>
|
||||
</DropdownButton>
|
||||
<DropdownDivider>Preview Mode</DropdownDivider>
|
||||
{PREVIEW_MODES.map(this.renderPreviewMode)}
|
||||
@ -36,7 +37,7 @@ class PreviewModeDropdown extends PureComponent {
|
||||
Save Response Body
|
||||
</DropdownItem>
|
||||
<DropdownItem onClick={fullDownload}>
|
||||
<i className="fa fa-save" />
|
||||
<i className="fa fa-save"/>
|
||||
Save Full Response
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
|
@ -91,7 +91,7 @@ class WorkspaceDropdown extends PureComponent {
|
||||
|
||||
const classes = classnames(className, 'wide', 'workspace-dropdown');
|
||||
return (
|
||||
<Dropdown right className={classes} rightOffset={150} onOpen={this._handleDropdownOpen} {...other}>
|
||||
<Dropdown beside className={classes} onOpen={this._handleDropdownOpen} {...other}>
|
||||
<DropdownButton className="btn wide">
|
||||
<h1 className="no-pad text-left">
|
||||
<div className="pull-right">
|
||||
|
@ -39,6 +39,10 @@ class MarkdownEditor extends PureComponent {
|
||||
this._editor && this._editor.focusEnd();
|
||||
}
|
||||
|
||||
focus () {
|
||||
this._editor && this._editor.focus();
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
fontSize,
|
||||
@ -88,7 +92,7 @@ class MarkdownEditor extends PureComponent {
|
||||
dynamicHeight={!tall}
|
||||
manualPrettify
|
||||
noStyleActiveLine
|
||||
mode={mode || 'text/plain'}
|
||||
mode={mode || 'text/x-markdown'}
|
||||
placeholder={placeholder}
|
||||
debounceMillis={300}
|
||||
keyMap={keyMap}
|
||||
|
@ -16,19 +16,25 @@ class MarkdownPreview extends PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
async _compileMarkdown (markdown) {
|
||||
try {
|
||||
const rendered = await this.props.handleRender(markdown);
|
||||
this.setState({
|
||||
compiled: markdownToHTML(rendered),
|
||||
renderError: ''
|
||||
});
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
renderError: err.message,
|
||||
compiled: ''
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Debounce and compile the markdown (won't debounce first render)
|
||||
*/
|
||||
_compileMarkdown (markdown) {
|
||||
clearTimeout(this._compileTimeout);
|
||||
this._compileTimeout = setTimeout(async () => {
|
||||
try {
|
||||
const rendered = await this.props.handleRender(markdown);
|
||||
this.setState({
|
||||
compiled: markdownToHTML(rendered),
|
||||
renderError: ''
|
||||
});
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
renderError: err.message,
|
||||
compiled: ''
|
||||
});
|
||||
}
|
||||
}, this.state.compiled ? this.props.debounceMillis : 0);
|
||||
}
|
||||
|
||||
_setPreviewRef (n) {
|
||||
@ -61,14 +67,14 @@ class MarkdownPreview extends PureComponent {
|
||||
this._compileMarkdown(this.props.markdown);
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this._highlightCodeBlocks();
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
this._compileMarkdown(nextProps.markdown);
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
this._highlightCodeBlocks();
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._highlightCodeBlocks();
|
||||
}
|
||||
@ -99,7 +105,8 @@ MarkdownPreview.propTypes = {
|
||||
handleRender: PropTypes.func.isRequired,
|
||||
|
||||
// Optional
|
||||
className: PropTypes.string
|
||||
className: PropTypes.string,
|
||||
debounceMillis: PropTypes.number
|
||||
};
|
||||
|
||||
export default MarkdownPreview;
|
||||
|
@ -62,7 +62,7 @@ class RequestSettingsModal extends PureComponent {
|
||||
|
||||
if (forceEditMode) {
|
||||
setTimeout(() => {
|
||||
this._editor.focusEnd();
|
||||
this._editor.focus();
|
||||
}, 400);
|
||||
}
|
||||
}
|
||||
|
@ -235,26 +235,22 @@ class RequestPane extends PureComponent {
|
||||
<Tabs className="pane__body" forceRenderTabPanel>
|
||||
<TabList>
|
||||
<Tab onClick={this._trackTabBody}>
|
||||
<button>
|
||||
{getContentTypeName(request.body.mimeType) || 'Body'}
|
||||
{' '}
|
||||
{numBodyParams ? <span className="bubble">{numBodyParams}</span> : null}
|
||||
</button>
|
||||
<ContentTypeDropdown onChange={updateRequestMimeType}
|
||||
contentType={request.body.mimeType}
|
||||
request={request}
|
||||
className="tall">
|
||||
<i className="fa fa-caret-down"/>
|
||||
{getContentTypeName(request.body.mimeType) || 'Body'}
|
||||
{' '}
|
||||
{numBodyParams ? <span className="bubble">{numBodyParams}</span> : null}
|
||||
<i className="fa fa-caret-down space-left"/>
|
||||
</ContentTypeDropdown>
|
||||
</Tab>
|
||||
<Tab onClick={this._trackTabAuthentication}>
|
||||
<button>
|
||||
{getAuthTypeName(request.authentication.type) || 'Auth'}
|
||||
</button>
|
||||
<AuthDropdown onChange={updateRequestAuthentication}
|
||||
authentication={request.authentication}
|
||||
className="tall">
|
||||
<i className="fa fa-caret-down"/>
|
||||
{getAuthTypeName(request.authentication.type) || 'Auth'}
|
||||
<i className="fa fa-caret-down space-left"/>
|
||||
</AuthDropdown>
|
||||
</Tab>
|
||||
<Tab onClick={this._trackTabQuery}>
|
||||
@ -372,6 +368,7 @@ class RequestPane extends PureComponent {
|
||||
</div>
|
||||
<MarkdownPreview
|
||||
className="pad"
|
||||
debounceMillis={1000}
|
||||
markdown={request.description}
|
||||
handleRender={handleRender}
|
||||
/>
|
||||
|
@ -16,7 +16,7 @@ import ResponseTimelineViewer from './viewers/response-timeline-viewer';
|
||||
import ResponseHeadersViewer from './viewers/response-headers-viewer';
|
||||
import ResponseCookiesViewer from './viewers/response-cookies-viewer';
|
||||
import * as models from '../../models';
|
||||
import {getPreviewModeName, PREVIEW_MODE_SOURCE} from '../../common/constants';
|
||||
import {PREVIEW_MODE_SOURCE} from '../../common/constants';
|
||||
import {getSetCookieHeaders, nullFn} from '../../common/misc';
|
||||
import {cancelCurrentRequest} from '../../network/network';
|
||||
import {trackEvent} from '../../analytics';
|
||||
@ -240,9 +240,6 @@ class ResponsePane extends PureComponent {
|
||||
<Tabs className="pane__body" forceRenderTabPanel>
|
||||
<TabList>
|
||||
<Tab>
|
||||
<Button onClick={this._trackTab} value="Response">
|
||||
{getPreviewModeName(previewMode)}
|
||||
</Button>
|
||||
<PreviewModeDropdown
|
||||
download={this._handleDownloadResponseBody}
|
||||
fullDownload={this._handleDownloadFullResponseBody}
|
||||
|
@ -12,123 +12,127 @@
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dropdown__backdrop {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
display: none;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
&.dropdown--open .dropdown__backdrop {
|
||||
display: block;
|
||||
}
|
||||
.dropdown__backdrop {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
display: none;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
content: ' ';
|
||||
//background: rgba(255, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.dropdown__menu {
|
||||
z-index: 1000;
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 1px solid @hl-sm;
|
||||
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
background: var(--color-bg);
|
||||
|
||||
// Separate it from the button a bit
|
||||
margin-top: @padding-xxs;
|
||||
margin-bottom: @padding-xxs;
|
||||
|
||||
padding-top: @radius-md;
|
||||
padding-bottom: @radius-md;
|
||||
|
||||
border-radius: @radius-md;
|
||||
overflow: auto;
|
||||
|
||||
&.dropdown__menu--open {
|
||||
&.dropdown__menu--open .dropdown__backdrop {
|
||||
display: block;
|
||||
animation: fadeIn 200ms ease-out;
|
||||
}
|
||||
|
||||
.dropdown__inner {
|
||||
width: 100%;
|
||||
}
|
||||
ul {
|
||||
z-index: 9999;
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 1px solid @hl-sm;
|
||||
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
background: var(--color-bg);
|
||||
|
||||
.dropdown__text {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
// Separate it from the button a bit
|
||||
margin-top: @padding-xxs;
|
||||
margin-bottom: @padding-xxs;
|
||||
|
||||
& > *:not(:first-child) {
|
||||
margin-left: 0.3em;
|
||||
padding-top: @radius-md;
|
||||
padding-bottom: @radius-md;
|
||||
|
||||
border-radius: @radius-md;
|
||||
overflow: auto;
|
||||
|
||||
.dropdown__inner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown__hint,
|
||||
.dropdown__right {
|
||||
color: @hl-xl;
|
||||
margin-left: auto;
|
||||
padding-left: @padding-lg;
|
||||
}
|
||||
}
|
||||
.dropdown__text {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
li > button {
|
||||
font-size: @font-size-md;
|
||||
text-align: left;
|
||||
padding-right: @padding-md;
|
||||
padding-left: @padding-sm;
|
||||
height: @line-height-xs;
|
||||
width: 100%;
|
||||
display: block;
|
||||
color: var(--color-font) !important;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
& > *:not(:first-child) {
|
||||
margin-left: 0.3em;
|
||||
}
|
||||
|
||||
&:hover:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
background: @hl-sm;
|
||||
.dropdown__hint,
|
||||
.dropdown__right {
|
||||
color: @hl-xl;
|
||||
margin-left: auto;
|
||||
padding-left: @padding-lg;
|
||||
}
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
background: @hl-md;
|
||||
li > button {
|
||||
font-size: @font-size-md;
|
||||
text-align: left;
|
||||
padding-right: @padding-md;
|
||||
padding-left: @padding-sm;
|
||||
height: @line-height-xs;
|
||||
width: 100%;
|
||||
display: block;
|
||||
color: var(--color-font) !important;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
|
||||
&:hover:not(:disabled),
|
||||
&:focus:not(:disabled) {
|
||||
background: @hl-sm;
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
background: @hl-md;
|
||||
}
|
||||
|
||||
i.fa:first-child {
|
||||
display: inline-block;
|
||||
width: 2.2em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
i.fa:first-child {
|
||||
display: inline-block;
|
||||
width: 2.2em;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
li.dropdown__divider {
|
||||
border-bottom: 1px solid @hl-lg;
|
||||
overflow: visible !important;
|
||||
height: 0;
|
||||
margin: @padding-md @padding-md @padding-md @padding-md;
|
||||
min-width: @dropdown-min-width - @padding-md * 2;
|
||||
|
||||
.dropdown__divider__label {
|
||||
position: relative;
|
||||
left: -@padding-sm / 2;
|
||||
top: -0.7rem;
|
||||
color: @hl;
|
||||
padding-right: 1em;
|
||||
background: var(--color-bg);
|
||||
font-size: @font-size-xs;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&.dropdown__divider--no-name {
|
||||
margin: @padding-xs 0;
|
||||
li.dropdown__divider {
|
||||
border-bottom: 1px solid @hl-lg;
|
||||
overflow: visible !important;
|
||||
height: 0;
|
||||
margin: @padding-md @padding-md @padding-md @padding-md;
|
||||
min-width: @dropdown-min-width - @padding-md * 2;
|
||||
|
||||
.dropdown__divider__label {
|
||||
display: none;
|
||||
position: relative;
|
||||
left: -@padding-sm / 2;
|
||||
top: -0.7rem;
|
||||
color: @hl;
|
||||
padding-right: 1em;
|
||||
background: var(--color-bg);
|
||||
font-size: @font-size-xs;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
&.dropdown__divider--no-name {
|
||||
margin: @padding-xs 0;
|
||||
|
||||
.dropdown__divider__label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.dropdown__menu--open ul {
|
||||
display: block;
|
||||
animation: fadeIn 200ms ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
box-sizing: border-box;
|
||||
background-color: var(--color-bg);
|
||||
overflow: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
@ -38,7 +39,16 @@
|
||||
border-top: 0 !important;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
position: static;
|
||||
position: relative;
|
||||
|
||||
&:not(.ReactTabs__Tab--selected)::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
position: relative;
|
||||
|
Loading…
Reference in New Issue
Block a user