(Partial) removal of WrapperProps (part 3) (#4515)

This commit is contained in:
Dimitri Mitropoulos 2022-02-25 07:21:35 -06:00 committed by GitHub
parent 6024d1ecdf
commit a8deb41f23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 309 additions and 197 deletions

View File

@ -2,22 +2,24 @@ import { autoBindMethodsForReact } from 'class-autobind-decorator';
import clone from 'clone';
import { cookieToString } from 'insomnia-cookies';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
import * as toughCookie from 'tough-cookie';
import { AUTOBIND_CFG, DEBOUNCE_MILLIS } from '../../../common/constants';
import * as models from '../../../models';
import type { Cookie, CookieJar } from '../../../models/cookie-jar';
import type { Workspace } from '../../../models/workspace';
import { Modal, ModalProps } from '../base/modal';
import { RootState } from '../../redux/modules';
import { selectActiveCookieJar } from '../../redux/selectors';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
import { ModalFooter } from '../base/modal-footer';
import { ModalHeader } from '../base/modal-header';
import { OneLineEditor } from '../codemirror/one-line-editor';
interface Props extends ModalProps {
workspace: Workspace;
cookieJar: CookieJar;
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
}
interface State {
@ -26,7 +28,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class CookieModifyModal extends PureComponent<Props, State> {
export class UnconnectedCookieModifyModal extends PureComponent<Props, State> {
modal: Modal | null = null;
_rawTimeout: NodeJS.Timeout | null = null;
_cookieUpdateTimeout: NodeJS.Timeout | null = null;
@ -43,17 +45,15 @@ export class CookieModifyModal extends PureComponent<Props, State> {
async show(cookie: Cookie) {
// Dunno why this is sent as an array
cookie = cookie[0] || cookie;
const { cookieJar } = this.props;
const oldCookie = cookieJar.cookies.find(c => c.id === cookie.id);
const { activeCookeJar } = this.props;
const prevCookie = activeCookeJar?.cookies.find(c => c.id === cookie.id);
if (!oldCookie) {
if (!prevCookie) {
// Cookie not found in jar
return;
}
this.setState({
cookie,
});
this.setState({ cookie });
this.modal?.show();
}
@ -65,13 +65,13 @@ export class CookieModifyModal extends PureComponent<Props, State> {
await models.cookieJar.update(cookieJar);
}
_handleChangeRawValue(e: React.SyntheticEvent<HTMLInputElement>) {
const value = e.currentTarget.value;
_handleChangeRawValue(event: React.SyntheticEvent<HTMLInputElement>) {
const value = event.currentTarget.value;
if (this._rawTimeout !== null) {
clearTimeout(this._rawTimeout);
}
this._rawTimeout = setTimeout(async () => {
const oldCookie = this.state.cookie;
const prevCookie = this.state.cookie;
let cookie;
try {
@ -83,25 +83,26 @@ export class CookieModifyModal extends PureComponent<Props, State> {
return;
}
if (!this.state.cookie || !oldCookie) {
if (!this.state.cookie || !prevCookie) {
return;
}
// Make sure cookie has an id
cookie.id = oldCookie.id;
cookie.id = prevCookie.id;
await this._handleCookieUpdate(cookie);
}, DEBOUNCE_MILLIS * 2);
}
async _handleCookieUpdate(newCookie: Cookie) {
const oldCookie = this.state.cookie;
async _handleCookieUpdate(nextCookie: Cookie) {
const prevCookie = this.state.cookie;
const { activeCookeJar: prevCookieJar } = this.props;
if (!oldCookie) {
if (!prevCookie || !prevCookieJar) {
// We don't have a cookie to edit
return;
}
const cookie = clone(newCookie);
const cookie = clone(nextCookie);
// Sanitize expires field
const expires = new Date(cookie.expires || '').getTime();
@ -112,7 +113,7 @@ export class CookieModifyModal extends PureComponent<Props, State> {
}
// Clone so we don't modify the original
const cookieJar = clone(this.props.cookieJar);
const cookieJar = clone(prevCookieJar);
const { cookies } = cookieJar;
const index = cookies.findIndex(c => c.id === cookie.id);
@ -122,9 +123,7 @@ export class CookieModifyModal extends PureComponent<Props, State> {
}
cookieJar.cookies = [...cookies.slice(0, index), cookie, ...cookies.slice(index + 1)];
this.setState({
cookie,
});
this.setState({ cookie });
await CookieModifyModal._saveChanges(cookieJar);
return cookie;
}
@ -153,9 +152,7 @@ export class CookieModifyModal extends PureComponent<Props, State> {
}
this._cookieUpdateTimeout = setTimeout(async () => {
await this._handleCookieUpdate(newCookie);
this.setState({
cookie: newCookie,
});
this.setState({ cookie: newCookie });
}, DEBOUNCE_MILLIS * 2);
}
@ -202,14 +199,14 @@ export class CookieModifyModal extends PureComponent<Props, State> {
}
render() {
const { cookieJar } = this.props;
const { activeCookeJar } = this.props;
const { cookie } = this.state;
const checkFields = ['secure', 'httpOnly'];
return (
<Modal ref={this._setModalRef} {...this.props}>
<ModalHeader>Edit Cookie</ModalHeader>
<ModalBody className="cookie-modify">
{cookieJar && cookie && (
{activeCookeJar && cookie && (
<Tabs>
<TabList>
<Tab tabIndex="-1">
@ -276,3 +273,14 @@ export class CookieModifyModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
activeCookeJar: selectActiveCookieJar(state),
});
export const CookieModifyModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedCookieModifyModal);

View File

@ -1,14 +1,15 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import deepEqual from 'deep-equal';
import React, { ChangeEvent, forwardRef, ForwardRefRenderFunction, PureComponent } from 'react';
import { useSelector } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { fuzzyMatch } from '../../../common/misc';
import { HandleRender } from '../../../common/render';
import * as models from '../../../models';
import type { Cookie, CookieJar } from '../../../models/cookie-jar';
import type { Workspace } from '../../../models/workspace';
import { useNunjucks } from '../../context/nunjucks/use-nunjucks';
import { selectActiveCookieJar } from '../../redux/selectors';
import { Modal, ModalProps } from '../base/modal';
import { ModalBody } from '../base/modal-body';
import { ModalFooter } from '../base/modal-footer';
@ -19,8 +20,7 @@ import { showModal } from '.';
interface Props extends ModalProps {
handleShowModifyCookieModal: CookieListProps['handleShowModifyCookieModal'];
handleRender: HandleRender;
cookieJar: CookieJar;
workspace: Workspace;
activeCookieJar: CookieJar | null;
}
interface State {
@ -47,28 +47,40 @@ class CookiesModal extends PureComponent<Props, State> {
}
async _saveChanges() {
const { cookieJar } = this.props;
await models.cookieJar.update(cookieJar);
const { activeCookieJar } = this.props;
if (!activeCookieJar) {
return;
}
await models.cookieJar.update(activeCookieJar);
}
async _handleCookieAdd(cookie: Cookie) {
const { cookieJar } = this.props;
const { cookies } = cookieJar;
cookieJar.cookies = [cookie, ...cookies];
const { activeCookieJar } = this.props;
if (!activeCookieJar) {
return;
}
const { cookies } = activeCookieJar;
activeCookieJar.cookies = [cookie, ...cookies];
await this._saveChanges();
}
async _handleDeleteAllCookies() {
const { cookieJar } = this.props;
cookieJar.cookies = [];
const { activeCookieJar } = this.props;
if (!activeCookieJar) {
return;
}
activeCookieJar.cookies = [];
await this._saveChanges();
}
async _handleCookieDelete(cookie: Cookie) {
const { cookieJar } = this.props;
const { cookies } = cookieJar;
const { activeCookieJar } = this.props;
if (!activeCookieJar) {
return;
}
const { cookies } = activeCookieJar;
// NOTE: This is sketchy because it relies on the same reference
cookieJar.cookies = cookies.filter(c => c.id !== cookie.id);
activeCookieJar.cookies = cookies.filter(c => c.id !== cookie.id);
await this._saveChanges();
}
@ -76,20 +88,28 @@ class CookiesModal extends PureComponent<Props, State> {
if (!(e.target instanceof HTMLInputElement)) {
return;
}
const { activeCookieJar } = this.props;
if (!activeCookieJar) {
return;
}
const filter = e.target.value;
this._applyFilter(filter, this.props.cookieJar.cookies);
this._applyFilter(filter, activeCookieJar.cookies);
}
// eslint-disable-next-line camelcase
UNSAFE_componentWillReceiveProps(nextProps: Props) {
const { activeCookieJar } = this.props;
if (!activeCookieJar || !nextProps.activeCookieJar) {
return;
}
// Re-filter if we received new cookies
// Compare cookies with Dates cast to strings
const sameCookies = deepEqual(this.props.cookieJar.cookies, nextProps.cookieJar.cookies);
const sameCookies = deepEqual(activeCookieJar.cookies, nextProps.activeCookieJar.cookies);
if (!sameCookies) {
this._applyFilter(this.state.filter, nextProps.cookieJar.cookies);
this._applyFilter(this.state.filter, nextProps.activeCookieJar.cookies);
}
}
@ -132,22 +152,29 @@ class CookiesModal extends PureComponent<Props, State> {
}
_getVisibleCookies(): Cookie[] {
const { cookieJar } = this.props;
const { activeCookieJar } = this.props;
const { visibleCookieIndexes } = this.state;
if (visibleCookieIndexes === null) {
return cookieJar.cookies;
if (!activeCookieJar) {
return [];
}
return cookieJar.cookies.filter((_, i) => visibleCookieIndexes.includes(i));
if (visibleCookieIndexes === null) {
return activeCookieJar.cookies;
}
return activeCookieJar.cookies.filter((_, i) => visibleCookieIndexes.includes(i));
}
async show() {
const { activeCookieJar } = this.props;
setTimeout(() => {
this.filterInput?.focus();
}, 100);
// make sure the filter is up to date
await this._applyFilter(this.state.filter, this.props.cookieJar.cookies);
await this._applyFilter(this.state.filter, activeCookieJar?.cookies || []);
this.modal?.show();
}
@ -156,7 +183,7 @@ class CookiesModal extends PureComponent<Props, State> {
}
render() {
const { handleShowModifyCookieModal, cookieJar } = this.props;
const { handleShowModifyCookieModal, activeCookieJar } = this.props;
const { filter } = this.state;
const cookies = this._getVisibleCookies();
@ -165,7 +192,7 @@ class CookiesModal extends PureComponent<Props, State> {
<Modal ref={this._setModalRef} wide tall {...this.props}>
<ModalHeader>Manage Cookies</ModalHeader>
<ModalBody noScroll>
{cookieJar && (
{activeCookieJar && (
<div className="cookie-list">
<div className="pad">
<div className="form-control form-control--outlined">
@ -207,9 +234,18 @@ class CookiesModal extends PureComponent<Props, State> {
}
}
const CookiesModalFCRF: ForwardRefRenderFunction<CookiesModal, Omit<Props, 'handleRender'>> = (props, ref) => {
const CookiesModalFCRF: ForwardRefRenderFunction<CookiesModal, Omit<Props, 'handleRender' | 'activeCookieJar'>> = (props, ref) => {
const { handleRender } = useNunjucks();
return <CookiesModal ref={ref} {...props} handleRender={handleRender} />;
const activeCookieJar = useSelector(selectActiveCookieJar);
return (
<CookiesModal
ref={ref}
activeCookieJar={activeCookieJar}
{...props}
handleRender={handleRender}
/>
);
};

View File

@ -101,10 +101,9 @@ class ProjectSettingsModal extends PureComponent<Props> {
}
}
const mapStateToProps = (state: RootState) => {
const project = selectActiveProject(state);
return { project };
};
const mapStateToProps = (state: RootState) => ({
project: selectActiveProject(state),
});
const mapDispatchToProps = dispatch => {
const boundProjectActions = bindActionCreators(projectActions, dispatch);

View File

@ -1,11 +1,14 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import * as React from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { database as db } from '../../../common/database';
import * as models from '../../../models';
import type { RequestGroup } from '../../../models/request-group';
import type { Workspace } from '../../../models/workspace';
import { RootState } from '../../redux/modules';
import { selectWorkspacesForActiveProject } from '../../redux/selectors';
import { DebouncedInput } from '../base/debounced-input';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
@ -13,8 +16,9 @@ import { ModalHeader } from '../base/modal-header';
import { HelpTooltip } from '../help-tooltip';
import { MarkdownEditor } from '../markdown-editor';
interface Props {
workspacesForActiveProject: Workspace[];
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
}
interface State {
@ -34,7 +38,7 @@ interface RequestGroupSettingsModalOptions {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class RequestGroupSettingsModal extends React.PureComponent<Props, State> {
export class UnconnectedRequestGroupSettingsModal extends React.PureComponent<Props, State> {
modal: Modal | null = null;
_editor: MarkdownEditor | null = null;
@ -326,3 +330,14 @@ export class RequestGroupSettingsModal extends React.PureComponent<Props, State>
);
}
}
const mapStateToProps = (state: RootState) => ({
workspacesForActiveProject: selectWorkspacesForActiveProject(state),
});
export const RequestGroupSettingsModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedRequestGroupSettingsModal);

View File

@ -1,5 +1,6 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { database as db } from '../../../common/database';
@ -8,6 +9,8 @@ import { GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
import * as requestOperations from '../../../models/helpers/request-operations';
import type { BaseRequest, Request } from '../../../models/request';
import { isWorkspace, Workspace } from '../../../models/workspace';
import { RootState } from '../../redux/modules';
import { selectWorkspacesForActiveProject } from '../../redux/selectors';
import { DebouncedInput } from '../base/debounced-input';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
@ -15,8 +18,9 @@ import { ModalHeader } from '../base/modal-header';
import { HelpTooltip } from '../help-tooltip';
import { MarkdownEditor } from '../markdown-editor';
interface Props {
workspacesForActiveProject: Workspace[];
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
}
interface State {
@ -36,7 +40,7 @@ interface RequestSettingsModalOptions {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class RequestSettingsModal extends PureComponent<Props, State> {
export class UnconnectedRequestSettingsModal extends PureComponent<Props, State> {
modal: Modal | null = null;
_editor: MarkdownEditor | null = null;
@ -463,3 +467,14 @@ export class RequestSettingsModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
workspacesForActiveProject: selectWorkspacesForActiveProject(state),
});
export const RequestSettingsModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedRequestSettingsModal);

View File

@ -29,18 +29,14 @@ import { MethodTag } from '../tags/method-tag';
type ReduxProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;
const mapStateToProps = (state: RootState) => {
const activeRequest = selectActiveRequest(state);
return {
activeRequest,
workspace: selectActiveWorkspace(state),
workspacesForActiveProject: selectWorkspacesForActiveProject(state),
requestMetas: selectRequestMetas(state),
grpcRequestMetas: selectGrpcRequestMetas(state),
workspaceRequestsAndRequestGroups: selectWorkspaceRequestsAndRequestGroups(state),
};
};
const mapStateToProps = (state: RootState) => ({
activeRequest: selectActiveRequest(state),
workspace: selectActiveWorkspace(state),
workspacesForActiveProject: selectWorkspacesForActiveProject(state),
requestMetas: selectRequestMetas(state),
grpcRequestMetas: selectGrpcRequestMetas(state),
workspaceRequestsAndRequestGroups: selectWorkspaceRequestsAndRequestGroups(state),
});
const mapDispatchToProps = dispatch => {
const bound = bindActionCreators({ activateWorkspace }, dispatch);

View File

@ -2,12 +2,14 @@ import { Curl } from '@getinsomnia/node-libcurl';
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import { HotKeyRegistry } from 'insomnia-common';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
import * as session from '../../../account/session';
import { AUTOBIND_CFG, getAppName, getAppVersion } from '../../../common/constants';
import * as models from '../../../models/index';
import { Settings } from '../../../models/settings';
import { RootState } from '../../redux/modules';
import { selectSettings } from '../../redux/selectors';
import { Button } from '../base/button';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
@ -26,8 +28,9 @@ export const TAB_INDEX_SHORTCUTS = 3;
export const TAB_INDEX_THEMES = 2;
export const TAB_INDEX_PLUGINS = 5;
interface Props {
settings: Settings;
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
}
interface State {
@ -35,7 +38,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SettingsModal extends PureComponent<Props, State> {
export class UnconnectedSettingsModal extends PureComponent<Props, State> {
state: State = {
currentTabIndex: null,
};
@ -136,3 +139,14 @@ export class SettingsModal extends PureComponent<Props, State> {
}
export const showSettingsModal = () => showModal(SettingsModal);
const mapStateToProps = (state: RootState) => ({
settings: selectSettings(state),
});
export const SettingsModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSettingsModal);

View File

@ -1,24 +1,23 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import classnames from 'classnames';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { database as db } from '../../../common/database';
import { Project } from '../../../models/project';
import type { Workspace } from '../../../models/workspace';
import type { StatusCandidate } from '../../../sync/types';
import { interceptAccessError } from '../../../sync/vcs/util';
import { VCS } from '../../../sync/vcs/vcs';
import { RootState } from '../../redux/modules';
import { selectSyncItems } from '../../redux/selectors';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
import { ModalHeader } from '../base/modal-header';
import { PromptButton } from '../base/prompt-button';
import { SyncPullButton } from '../sync-pull-button';
interface Props {
workspace: Workspace;
project: Project;
syncItems: StatusCandidate[];
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
vcs: VCS;
}
@ -31,7 +30,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SyncBranchesModal extends PureComponent<Props, State> {
export class UnconnectedSyncBranchesModal extends PureComponent<Props, State> {
modal: Modal | null = null;
state: State = {
@ -181,7 +180,7 @@ export class SyncBranchesModal extends PureComponent<Props, State> {
}
render() {
const { vcs, project } = this.props;
const { vcs } = this.props;
const { branches, remoteBranches, currentBranch, newBranchName, error } = this.state;
return (
<Modal ref={this._setModalRef}>
@ -301,7 +300,6 @@ export class SyncBranchesModal extends PureComponent<Props, State> {
<SyncPullButton
className="btn btn--micro btn--outlined space-left"
branch={name}
project={project}
onPull={this.refreshState}
disabled={name === currentBranch}
vcs={vcs}
@ -320,3 +318,14 @@ export class SyncBranchesModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
syncItems: selectSyncItems(state),
});
export const SyncBranchesModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSyncBranchesModal);

View File

@ -1,18 +1,21 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import { Button } from 'insomnia-components';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { strings } from '../../../common/strings';
import type { Workspace } from '../../../models/workspace';
import { interceptAccessError } from '../../../sync/vcs/util';
import { VCS } from '../../../sync/vcs/vcs';
import { RootState } from '../../redux/modules';
import { selectActiveWorkspace } from '../../redux/selectors';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
import { ModalHeader } from '../base/modal-header';
interface Props {
workspace: Workspace;
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
vcs: VCS;
}
@ -27,7 +30,7 @@ const INITIAL_STATE: State = {
};
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SyncDeleteModal extends PureComponent<Props, State> {
export class UnconnectedSyncDeleteModal extends PureComponent<Props, State> {
modal: Modal | null = null;
input: HTMLInputElement | null = null;
@ -89,14 +92,14 @@ export class SyncDeleteModal extends PureComponent<Props, State> {
render() {
const { error, workspaceName } = this.state;
const { workspace } = this.props;
const { activeWorkspace } = this.props;
const workspaceNameElement = (
<strong
style={{
whiteSpace: 'pre-wrap',
}}
>
{workspace.name}
{activeWorkspace?.name}
</strong>
);
return (
@ -118,7 +121,7 @@ export class SyncDeleteModal extends PureComponent<Props, State> {
onChange={this._updateWorkspaceName}
value={workspaceName}
/>
<Button bg="danger" disabled={workspaceName !== workspace.name}>
<Button bg="danger" disabled={workspaceName !== activeWorkspace?.name}>
Delete {strings.collection.singular}
</Button>
</div>
@ -128,3 +131,14 @@ export class SyncDeleteModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
activeWorkspace: selectActiveWorkspace(state),
});
export const SyncDeleteModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSyncDeleteModal);

View File

@ -3,7 +3,6 @@ import React, { Fragment, PureComponent } from 'react';
import * as session from '../../../account/session';
import { AUTOBIND_CFG } from '../../../common/constants';
import type { Workspace } from '../../../models/workspace';
import type { Snapshot } from '../../../sync/types';
import { VCS } from '../../../sync/vcs/vcs';
import { Modal } from '../base/modal';
@ -15,7 +14,6 @@ import { TimeFromNow } from '../time-from-now';
import { Tooltip } from '../tooltip';
interface Props {
workspace: Workspace;
vcs: VCS;
}

View File

@ -1,19 +1,21 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import type { Workspace } from '../../../models/workspace';
import type { DocumentKey, MergeConflict, StatusCandidate } from '../../../sync/types';
import type { DocumentKey, MergeConflict } from '../../../sync/types';
import { VCS } from '../../../sync/vcs/vcs';
import { RootState } from '../../redux/modules';
import { selectSyncItems } from '../../redux/selectors';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
import { ModalFooter } from '../base/modal-footer';
import { ModalHeader } from '../base/modal-header';
interface Props {
workspace: Workspace;
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
vcs: VCS;
syncItems: StatusCandidate[];
}
interface State {
@ -21,7 +23,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SyncMergeModal extends PureComponent<Props, State> {
export class UnconnectedSyncMergeModal extends PureComponent<Props, State> {
modal: Modal | null = null;
_handleDone: (arg0: MergeConflict[]) => void;
@ -126,3 +128,14 @@ export class SyncMergeModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
syncItems: selectSyncItems(state),
});
export const SyncMergeModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSyncMergeModal);

View File

@ -1,14 +1,16 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import React, { Fragment, PureComponent, ReactNode } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../../common/constants';
import { strings } from '../../../common/strings';
import * as models from '../../../models';
import { BaseModel } from '../../../models';
import type { Workspace } from '../../../models/workspace';
import type { DocumentKey, Stage, StageEntry, Status, StatusCandidate } from '../../../sync/types';
import type { DocumentKey, Stage, StageEntry, Status } from '../../../sync/types';
import { describeChanges } from '../../../sync/vcs/util';
import { VCS } from '../../../sync/vcs/vcs';
import { RootState } from '../../redux/modules';
import { selectSyncItems } from '../../redux/selectors';
import { IndeterminateCheckbox } from '../base/indeterminate-checkbox';
import { Modal } from '../base/modal';
import { ModalBody } from '../base/modal-body';
@ -16,9 +18,9 @@ import { ModalFooter } from '../base/modal-footer';
import { ModalHeader } from '../base/modal-header';
import { Tooltip } from '../tooltip';
interface Props {
workspace: Workspace;
syncItems: StatusCandidate[];
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
vcs: VCS;
}
@ -51,7 +53,7 @@ const _initialState: State = {
};
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SyncStagingModal extends PureComponent<Props, State> {
export class UnconnectedSyncStagingModal extends PureComponent<Props, State> {
modal: Modal | null = null;
_onSnapshot: (() => void) | null = null;
_handlePush: (() => Promise<void>) | null = null;
@ -398,3 +400,14 @@ export class SyncStagingModal extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
syncItems: selectSyncItems(state),
});
export const SyncStagingModal = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSyncStagingModal);

View File

@ -1,15 +1,18 @@
import { autoBindMethodsForReact } from 'class-autobind-decorator';
import React, { PureComponent, ReactNode } from 'react';
import { connect } from 'react-redux';
import { AUTOBIND_CFG } from '../../common/constants';
import { Project } from '../../models/project';
import { VCS } from '../../sync/vcs/vcs';
import { RootState } from '../redux/modules';
import { selectActiveProject } from '../redux/selectors';
import { showError } from './modals';
interface Props {
type ReduxProps = ReturnType<typeof mapStateToProps>;
interface Props extends ReduxProps {
vcs: VCS;
branch: string;
project: Project;
onPull: (...args: any[]) => any;
disabled?: boolean;
className?: string;
@ -21,7 +24,7 @@ interface State {
}
@autoBindMethodsForReact(AUTOBIND_CFG)
export class SyncPullButton extends PureComponent<Props, State> {
export class UnconnectedSyncPullButton extends PureComponent<Props, State> {
_timeout: NodeJS.Timeout | null = null;
state: State = {
@ -84,3 +87,14 @@ export class SyncPullButton extends PureComponent<Props, State> {
);
}
}
const mapStateToProps = (state: RootState) => ({
project: selectActiveProject(state),
});
export const SyncPullButton = connect(
mapStateToProps,
null,
null,
{ forwardRef: true },
)(UnconnectedSyncPullButton);

View File

@ -442,7 +442,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
activeEnvironment,
activeGitRepository,
activeWorkspace,
activeProject,
activeApiSpec,
activeWorkspaceClientCertificates,
activeActivity,
@ -451,11 +450,8 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
handleExportRequestsToFile,
handleInitializeEntities,
handleSidebarSort,
settings,
sidebarChildren,
syncItems,
vcs,
workspacesForActiveProject,
} = this.props;
// Setup git sync dropdown for use in Design/Debug pages
@ -487,7 +483,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
<AlertModal ref={registerModal} />
<ErrorModal ref={registerModal} />
<PromptModal ref={registerModal} />
<WrapperModal ref={registerModal} />
<LoginModal ref={registerModal} />
<AskModal ref={registerModal} />
@ -499,20 +494,9 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
<GenerateConfigModal ref={registerModal} />
<ProjectSettingsModal ref={registerModal} />
<WorkspaceDuplicateModal ref={registerModal} vcs={vcs || undefined} />
<CodePromptModal
ref={registerModal}
/>
<RequestSettingsModal
ref={registerModal}
workspacesForActiveProject={workspacesForActiveProject}
/>
<RequestGroupSettingsModal
ref={registerModal}
workspacesForActiveProject={workspacesForActiveProject}
/>
<CodePromptModal ref={registerModal} />
<RequestSettingsModal ref={registerModal} />
<RequestGroupSettingsModal ref={registerModal} />
{activeWorkspace ? <>
{/* TODO: Figure out why cookieJar is sometimes null */}
@ -520,14 +504,8 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
<CookiesModalFC
ref={registerModal}
handleShowModifyCookieModal={Wrapper._handleShowModifyCookieModal}
workspace={activeWorkspace}
cookieJar={activeCookieJar}
/>
<CookieModifyModal
ref={registerModal}
cookieJar={activeCookieJar}
workspace={activeWorkspace}
/>
<CookieModifyModal ref={registerModal} />
</> : null}
<NunjucksModal
@ -551,11 +529,7 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
environmentId={activeEnvironment ? activeEnvironment._id : 'n/a'}
/>
<SettingsModal
ref={registerModal}
settings={settings}
/>
<SettingsModal ref={registerModal} />
<ResponseDebugModal ref={registerModal} />
<RequestSwitcherModal
@ -588,27 +562,11 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
{activeWorkspace && vcs ? (
<Fragment>
<SyncStagingModal
ref={registerModal}
workspace={activeWorkspace}
vcs={vcs}
syncItems={syncItems}
/>
<SyncMergeModal
ref={registerModal}
workspace={activeWorkspace}
syncItems={syncItems}
vcs={vcs}
/>
<SyncBranchesModal
ref={registerModal}
workspace={activeWorkspace}
vcs={vcs}
project={activeProject}
syncItems={syncItems}
/>
<SyncDeleteModal ref={registerModal} workspace={activeWorkspace} vcs={vcs} />
<SyncHistoryModal ref={registerModal} workspace={activeWorkspace} vcs={vcs} />
<SyncStagingModal ref={registerModal} vcs={vcs} />
<SyncMergeModal ref={registerModal} vcs={vcs} />
<SyncBranchesModal ref={registerModal} vcs={vcs} />
<SyncDeleteModal ref={registerModal} vcs={vcs} />
<SyncHistoryModal ref={registerModal} vcs={vcs} />
</Fragment>
) : null}
@ -673,9 +631,7 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
handleImport={this._handleImport}
handleRequestCreate={this._handleCreateRequestInWorkspace}
handleRequestGroupCreate={this._handleCreateRequestGroupInWorkspace}
handleSendAndDownloadRequestWithActiveEnvironment={
this._handleSendAndDownloadRequestWithActiveEnvironment
}
handleSendAndDownloadRequestWithActiveEnvironment={this._handleSendAndDownloadRequestWithActiveEnvironment}
handleSendRequestWithActiveEnvironment={this._handleSendRequestWithActiveEnvironment}
handleSetActiveResponse={this._handleSetActiveResponse}
handleSetPreviewMode={this._handleSetPreviewMode}
@ -688,12 +644,8 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
handleUpdateRequestMethod={Wrapper._handleUpdateRequestMethod}
handleUpdateRequestParameters={Wrapper._handleUpdateRequestParameters}
handleUpdateRequestUrl={Wrapper._handleUpdateRequestUrl}
handleUpdateSettingsUseBulkHeaderEditor={
this._handleUpdateSettingsUseBulkHeaderEditor
}
handleUpdateSettingsUseBulkParametersEditor={
this._handleUpdateSettingsUseBulkParametersEditor
}
handleUpdateSettingsUseBulkHeaderEditor={this._handleUpdateSettingsUseBulkHeaderEditor}
handleUpdateSettingsUseBulkParametersEditor={this._handleUpdateSettingsUseBulkParametersEditor}
wrapperProps={this.props}
/>
)}

View File

@ -134,6 +134,19 @@ import {
import { selectPaneHeight, selectPaneWidth, selectSidebarChildren, selectSidebarFilter, selectSidebarHidden, selectSidebarWidth } from '../redux/sidebar-selectors';
import { AppHooks } from './app-hooks';
const updateRequestMetaByParentId = async (
requestId: string,
patch: Partial<GrpcRequestMeta> | Partial<RequestMeta>
) => {
const isGrpc = isGrpcRequestId(requestId);
if (isGrpc) {
return models.grpcRequestMeta.updateOrCreateByParentId(requestId, patch);
} else {
return models.requestMeta.updateOrCreateByParentId(requestId, patch);
}
};
export type AppProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;
interface State {
@ -528,16 +541,6 @@ class App extends PureComponent<AppProps, State> {
}
}
static async _updateRequestMetaByParentId(requestId, patch) {
const isGrpc = isGrpcRequestId(requestId);
if (isGrpc) {
return models.grpcRequestMeta.updateOrCreateByParentId(requestId, patch);
} else {
return models.requestMeta.updateOrCreateByParentId(requestId, patch);
}
}
async _updateShowVariableSourceAndValue() {
const { settings } = this.props;
await models.settings.update(settings, { showVariableSourceAndValue: !settings.showVariableSourceAndValue });
@ -563,7 +566,7 @@ class App extends PureComponent<AppProps, State> {
await this._updateActiveWorkspaceMeta({
activeRequestId,
});
await App._updateRequestMetaByParentId(activeRequestId, {
await updateRequestMetaByParentId(activeRequestId, {
lastActive: Date.now(),
});
}
@ -605,25 +608,25 @@ class App extends PureComponent<AppProps, State> {
}
async _handleSetRequestPinned(request, pinned) {
App._updateRequestMetaByParentId(request._id, {
updateRequestMetaByParentId(request._id, {
pinned,
});
}
_handleSetResponsePreviewMode(requestId, previewMode) {
App._updateRequestMetaByParentId(requestId, {
updateRequestMetaByParentId(requestId, {
previewMode,
});
}
_handleUpdateDownloadPath(requestId, downloadPath) {
App._updateRequestMetaByParentId(requestId, {
updateRequestMetaByParentId(requestId, {
downloadPath,
});
}
async _handleSetResponseFilter(requestId, responseFilter) {
await App._updateRequestMetaByParentId(requestId, {
await updateRequestMetaByParentId(requestId, {
responseFilter,
});
@ -646,7 +649,7 @@ class App extends PureComponent<AppProps, State> {
}
responseFilterHistory.unshift(responseFilter);
await App._updateRequestMetaByParentId(requestId, {
await updateRequestMetaByParentId(requestId, {
responseFilterHistory,
});
}, 2000);
@ -779,7 +782,7 @@ class App extends PureComponent<AppProps, State> {
});
} finally {
// Unset active response because we just made a new one
await App._updateRequestMetaByParentId(requestId, {
await updateRequestMetaByParentId(requestId, {
activeResponseId: null,
});
// Stop loading
@ -825,7 +828,7 @@ class App extends PureComponent<AppProps, State> {
}
// Unset active response because we just made a new one
await App._updateRequestMetaByParentId(requestId, {
await updateRequestMetaByParentId(requestId, {
activeResponseId: null,
});
// Stop loading
@ -835,7 +838,7 @@ class App extends PureComponent<AppProps, State> {
async _handleSetActiveResponse(requestId: string, activeResponse: Response | null = null) {
const { activeEnvironment } = this.props;
const activeResponseId = activeResponse ? activeResponse._id : null;
await App._updateRequestMetaByParentId(requestId, {
await updateRequestMetaByParentId(requestId, {
activeResponseId,
});

View File

@ -142,7 +142,7 @@ export const selectActiveWorkspaceMeta = createSelector(
selectEntitiesLists,
(activeWorkspace, entities) => {
const id = activeWorkspace ? activeWorkspace._id : 'n/a';
return entities.workspaceMetas.find(m => m.parentId === id);
return entities.workspaceMetas.find(workspaceMeta => workspaceMeta.parentId === id);
},
);

View File

@ -6123,6 +6123,18 @@
"@types/react": "*"
}
},
"@types/react-redux": {
"version": "7.1.22",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.22.tgz",
"integrity": "sha512-GxIA1kM7ClU73I6wg9IRTVwSO9GS+SAKZKe0Enj+82HMU6aoESFU2HNAdNi3+J53IaOHPiUfT3kSG4L828joDQ==",
"dev": true,
"requires": {
"@types/hoist-non-react-statics": "^3.3.0",
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0",
"redux": "^4.0.0"
}
},
"@types/react-tabs": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/react-tabs/-/react-tabs-2.3.2.tgz",

View File

@ -217,6 +217,7 @@
"@types/react": "^16.14.5",
"@types/react-dom": "^16.9.12",
"@types/react-tabs": "^2.3.2",
"@types/react-redux": "^7.1.22",
"@types/redux-mock-store": "^1.0.2",
"@types/styled-components": "^4.4.3",
"@types/swagger-ui-react": "^3.35.0",