diff --git a/packages/insomnia-app/app/ui/components/base/button.tsx b/packages/insomnia-app/app/ui/components/base/button.tsx index 4dafe81aa..359aea5bc 100644 --- a/packages/insomnia-app/app/ui/components/base/button.tsx +++ b/packages/insomnia-app/app/ui/components/base/button.tsx @@ -2,12 +2,12 @@ import React, { ButtonHTMLAttributes, PureComponent, ReactNode } from 'react'; import { autoBindMethodsForReact } from 'class-autobind-decorator'; import { AUTOBIND_CFG } from '../../../common/constants'; -interface Props { +export interface ButtonProps { children: ReactNode, - value?: any, + value?: T, className?: string, - onDisabledClick?: Function, - onClick?: React.MouseEventHandler | ((value: any, e: React.MouseEvent) => void), + onDisabledClick?: React.MouseEventHandler | ((value: T | undefined, e: React.MouseEvent) => void), + onClick?: React.MouseEventHandler | ((value: T | undefined, e: React.MouseEvent) => void), disabled?: boolean, tabIndex?: number, type?: ButtonHTMLAttributes['type'], @@ -17,15 +17,17 @@ interface Props { } @autoBindMethodsForReact(AUTOBIND_CFG) -class Button extends PureComponent { +class Button extends PureComponent> { _handleClick(e: React.MouseEvent) { - const { onClick, onDisabledClick, disabled } = this.props; + const { onClick, onDisabledClick, disabled, value } = this.props; const fn = disabled ? onDisabledClick : onClick; if (this.props.hasOwnProperty('value')) { - fn && fn(this.props.value, e); + // @ts-expect-error -- TSCONVERSION we really need to make the `value` argument come second + fn?.(value, e); } else { - fn && fn(e); + // @ts-expect-error -- TSCONVERSION we really need to make the `value` argument come second + fn?.(e); } } diff --git a/packages/insomnia-app/app/ui/components/modals/workspace-environments-edit-modal.tsx b/packages/insomnia-app/app/ui/components/modals/workspace-environments-edit-modal.tsx index 1642f72a7..8e08804df 100644 --- a/packages/insomnia-app/app/ui/components/modals/workspace-environments-edit-modal.tsx +++ b/packages/insomnia-app/app/ui/components/modals/workspace-environments-edit-modal.tsx @@ -2,10 +2,10 @@ import React, { FormEvent, Fragment, PureComponent } from 'react'; import { autoBindMethodsForReact } from 'class-autobind-decorator'; import { AUTOBIND_CFG, DEBOUNCE_MILLIS } from '../../../common/constants'; import classnames from 'classnames'; -import { SortableContainer, SortableElement, arrayMove } from 'react-sortable-hoc/dist/es6'; +import { SortableContainer, SortableElement, arrayMove, SortEndHandler } from 'react-sortable-hoc'; import { Dropdown, DropdownButton, DropdownItem } from '../base/dropdown'; import PromptButton from '../base/prompt-button'; -import Button from '../base/button'; +import Button, { ButtonProps } from '../base/button'; import Link from '../base/link'; import EnvironmentEditor from '../editors/environment-editor'; import Editable from '../base/editable'; @@ -44,11 +44,25 @@ interface State { selectedEnvironmentId: string | null; } -const SidebarListItem = SortableElement( - ({ environment, activeEnvironment, showEnvironment, changeEnvironmentName }) => { +interface SidebarListItemProps extends Pick { + changeEnvironmentName: (environment: Environment, name?: string) => void; + environment: Environment; + handleActivateEnvironment: ButtonProps['onClick']; + selectedEnvironment: Environment | null; + showEnvironment: ButtonProps['onClick']; +} + +const SidebarListItem = SortableElement(({ + activeEnvironmentId, + changeEnvironmentName, + environment, + handleActivateEnvironment, + selectedEnvironment, + showEnvironment, +}) => { const classes = classnames({ 'env-modal__sidebar-item': true, - 'env-modal__sidebar-item--active': activeEnvironment === environment, + 'env-modal__sidebar-item--active': selectedEnvironment === environment, // Specify theme because dragging will pull it out to 'theme--dialog': true, }); @@ -79,22 +93,44 @@ const SidebarListItem = SortableElement( value={environment.name} /> +
+ {environment._id === activeEnvironmentId ? ( + + ) : ( + + )} +
); }, ); -const SidebarList = SortableContainer( - ({ environments, activeEnvironment, showEnvironment, changeEnvironmentName }) => ( +interface SidebarListProps extends Omit { + environments: Environment[]; +} + +const SidebarList = SortableContainer( + ({ + activeEnvironmentId, + changeEnvironmentName, + environments, + handleActivateEnvironment, + selectedEnvironment, + showEnvironment, + }) => (
    - {environments.map((e, i) => ( + {environments.map((environment, index) => ( ))}
@@ -194,18 +230,18 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { await this._load(workspace, environment); } - async _handleShowEnvironment(environment: Environment) { + _handleShowEnvironment(environment: Environment) { // Don't allow switching if the current one has errors if (this.environmentEditorRef && !this.environmentEditorRef.isValid()) { return; } - if (environment === this._getActiveEnvironment()) { + if (environment === this._getSelectedEnvironment()) { return; } const { workspace } = this.state; - await this._load(workspace, environment); + this._load(workspace, environment); } async _handleDuplicateEnvironment(environment: Environment) { @@ -225,7 +261,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { // Unset active environment if it's being deleted if (activeEnvironmentId === environment._id) { - await handleChangeEnvironment(null); + handleChangeEnvironment(null); } // Delete the current one @@ -285,7 +321,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { } } - _getActiveEnvironment(): Environment | null { + _getSelectedEnvironment(): Environment | null { const { selectedEnvironmentId, subEnvironments, rootEnvironment } = this.state; if (rootEnvironment && rootEnvironment._id === selectedEnvironmentId) { @@ -315,11 +351,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { }); } - async _handleSortEnd(results: { - oldIndex: number; - newIndex: number; - collection: Environment[]; - }) { + _handleSortEnd: SortEndHandler = (results) => { const { oldIndex, newIndex } = results; if (newIndex === oldIndex) { @@ -334,25 +366,20 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { // Do this last so we don't block the sorting db.bufferChanges(); - for (let i = 0; i < newSubEnvironments.length; i++) { - const environment = newSubEnvironments[i]; - await this._updateEnvironment( - environment, - { - metaSortKey: i, - }, - false, - ); - } - - db.flushChanges(); + Promise.all(newSubEnvironments.map(environment => this._updateEnvironment( + environment, + { metaSortKey: 1 }, + false, + ))).then(() => { + db.flushChanges(); + }); } async _handleClickColorChange(environment: Environment) { const color = environment.color || '#7d69cb'; if (!environment.color) { - await this._handleChangeEnvironmentColor(environment, color); + this._handleChangeEnvironmentColor(environment, color); } this.environmentColorInputRef?.click(); @@ -360,7 +387,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { _handleInputColorChange(event: FormEvent) { this._handleChangeEnvironmentColor( - this._getActiveEnvironment(), + this._getSelectedEnvironment(), // @ts-expect-error -- TSCONVERSION what? apparently value doesn't exist on the target event.target && event.target.value, ); @@ -385,37 +412,50 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { return; } - const activeEnvironment = this._getActiveEnvironment(); + const selectedEnvironment = this._getSelectedEnvironment(); - if (activeEnvironment) { + if (selectedEnvironment) { if (this.saveTimeout !== null) { clearTimeout(this.saveTimeout); } this.saveTimeout = setTimeout(async () => { - await this._updateEnvironment(activeEnvironment, patch); + await this._updateEnvironment(selectedEnvironment, patch); }, DEBOUNCE_MILLIS * 4); } } + _handleActivateEnvironment: ButtonProps['onClick'] = (environment: Environment) => { + const { handleChangeEnvironment, activeEnvironmentId } = this.props; + + if (environment._id === activeEnvironmentId) { + return; + } + + handleChangeEnvironment(environment._id); + this._handleShowEnvironment(environment); + } + render() { const { + activeEnvironmentId, editorFontSize, editorIndentSize, editorKeyMap, - lineWrapping, - render, getRenderContext, - nunjucksPowerUserMode, isVariableUncovered, + lineWrapping, + nunjucksPowerUserMode, + render, } = this.props; const { subEnvironments, rootEnvironment, isValid } = this.state; - const activeEnvironment = this._getActiveEnvironment(); + const selectedEnvironment = this._getSelectedEnvironment(); const environmentInfo = { - object: activeEnvironment ? activeEnvironment.data : {}, - propertyOrder: activeEnvironment && activeEnvironment.dataPropertyOrder, + object: selectedEnvironment ? selectedEnvironment.data : {}, + propertyOrder: selectedEnvironment && selectedEnvironment.dataPropertyOrder, }; + return ( Manage Environments @@ -423,7 +463,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent {
  • {

    - {rootEnvironment === activeEnvironment ? ( + {rootEnvironment === selectedEnvironment ? ( ROOT_ENVIRONMENT_NAME ) : ( - activeEnvironment && + selectedEnvironment && // @ts-expect-error -- TSCONVERSION only set name if defined - this._handleChangeEnvironmentName(activeEnvironment, name) + this._handleChangeEnvironmentName(selectedEnvironment, name) } - value={activeEnvironment ? activeEnvironment.name : ''} + value={selectedEnvironment ? selectedEnvironment.name : ''} /> )}

    - {activeEnvironment && rootEnvironment !== activeEnvironment ? ( + {selectedEnvironment && rootEnvironment !== selectedEnvironment ? ( - {activeEnvironment.color && ( + {selectedEnvironment.color && ( )} Color - + - {activeEnvironment.color ? 'Change Color' : 'Assign Color'} + {selectedEnvironment.color ? 'Change Color' : 'Assign Color'} + disabled={!selectedEnvironment.color}> Unset Color @@ -547,7 +589,7 @@ class WorkspaceEnvironmentsEditModal extends PureComponent { editorKeyMap={editorKeyMap} lineWrapping={lineWrapping} ref={this._setEditorRef} - key={`${this.editorKey}::${activeEnvironment ? activeEnvironment._id : 'n/a'}`} + key={`${this.editorKey}::${selectedEnvironment ? selectedEnvironment._id : 'n/a'}`} environmentInfo={environmentInfo} didChange={this._didChange} render={render} diff --git a/packages/insomnia-app/app/ui/css/components/environment-modal.less b/packages/insomnia-app/app/ui/css/components/environment-modal.less index 1dbf4026f..6067c1464 100644 --- a/packages/insomnia-app/app/ui/css/components/environment-modal.less +++ b/packages/insomnia-app/app/ui/css/components/environment-modal.less @@ -109,20 +109,39 @@ } } - &.env-modal__sidebar-item--dragging > button, - &.env-modal__sidebar-item--active > button { + .env-status { + padding: 0 var(--padding-sm) 0 var(--padding-sm); + align-self: center; + + .active { + color: var(--hl-xl); + } + + .inactive { + color: var(--hl-xl); + opacity: 0; + } + } + + &.env-modal__sidebar-item--dragging , + &.env-modal__sidebar-item--active { color: var(--color-font); background-color: var(--hl-xs); } - &:hover > button { + &:hover { background-color: var(--hl-xs); } &.env-modal__sidebar-item--dragging .drag-handle, - &:hover .drag-handle { + &:hover .drag-handle, + &:hover .inactive { opacity: 1; } + + &:hover .inactive:hover { + color: var(--color-font); + } } .env-modal__sidebar-item {