mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-22 14:09:46 +03:00
Add feature toggle to the settings tab, make Search Panel responsive
This commit is contained in:
parent
c19c29af64
commit
606daf7fa0
|
@ -1,31 +1,33 @@
|
|||
import { LiftedAction, LiftedState } from '@redux-devtools/core';
|
||||
import { SchemeName, ThemeName } from '@redux-devtools/ui';
|
||||
import { AuthStates, States } from 'socketcluster-client/lib/clientsocket';
|
||||
import { Action } from 'redux';
|
||||
import { REHYDRATE } from 'redux-persist';
|
||||
import { AuthStates, States } from 'socketcluster-client/lib/clientsocket';
|
||||
import {
|
||||
CHANGE_SECTION,
|
||||
CHANGE_STATE_TREE_SETTINGS,
|
||||
CHANGE_THEME,
|
||||
SELECT_INSTANCE,
|
||||
SELECT_MONITOR,
|
||||
UPDATE_MONITOR_STATE,
|
||||
CLEAR_NOTIFICATION,
|
||||
ERROR,
|
||||
EXPORT,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_REQUEST,
|
||||
GET_REPORT_SUCCESS,
|
||||
LIFTED_ACTION,
|
||||
MONITOR_ACTION,
|
||||
EXPORT,
|
||||
TOGGLE_SYNC,
|
||||
TOGGLE_SLIDER,
|
||||
REMOVE_INSTANCE,
|
||||
SELECT_INSTANCE,
|
||||
SELECT_MONITOR,
|
||||
SET_PERSIST,
|
||||
SET_STATE,
|
||||
SHOW_NOTIFICATION,
|
||||
TOGGLE_DISPATCHER,
|
||||
TOGGLE_PERSIST,
|
||||
GET_REPORT_REQUEST,
|
||||
SHOW_NOTIFICATION,
|
||||
CLEAR_NOTIFICATION,
|
||||
UPDATE_STATE,
|
||||
TOGGLE_SLIDER,
|
||||
TOGGLE_SYNC,
|
||||
UPDATE_MONITOR_STATE,
|
||||
UPDATE_REPORTS,
|
||||
REMOVE_INSTANCE,
|
||||
SET_STATE,
|
||||
GET_REPORT_ERROR,
|
||||
GET_REPORT_SUCCESS,
|
||||
ERROR,
|
||||
SET_PERSIST,
|
||||
CHANGE_STATE_TREE_SETTINGS,
|
||||
UPDATE_STATE,
|
||||
} from '../constants/actionTypes';
|
||||
import {
|
||||
AUTH_ERROR,
|
||||
|
@ -43,12 +45,9 @@ import {
|
|||
SUBSCRIBE_SUCCESS,
|
||||
UNSUBSCRIBE,
|
||||
} from '../constants/socketActionTypes';
|
||||
import { Action } from 'redux';
|
||||
import { Features, State } from '../reducers/instances';
|
||||
import { MonitorStateMonitorState } from '../reducers/monitor';
|
||||
import { LiftedAction } from '@redux-devtools/core';
|
||||
import { Data } from '../reducers/reports';
|
||||
import { LiftedState } from '@redux-devtools/core';
|
||||
|
||||
let monitorReducer: (
|
||||
monitorProps: unknown,
|
||||
|
@ -86,6 +85,7 @@ export function changeTheme(data: ChangeThemeData): ChangeThemeAction {
|
|||
interface ChangeStateTreeSettingsFormData {
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
readonly enableSearchPanel: boolean;
|
||||
}
|
||||
|
||||
interface ChangeStateTreeSettingsData {
|
||||
|
@ -96,6 +96,7 @@ export interface ChangeStateTreeSettingsAction {
|
|||
readonly type: typeof CHANGE_STATE_TREE_SETTINGS;
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
readonly enableSearchPanel: boolean;
|
||||
}
|
||||
|
||||
export function changeStateTreeSettings(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect, ResolveThunks } from 'react-redux';
|
||||
import { Container, Form } from '@redux-devtools/ui';
|
||||
import React, { Component } from 'react';
|
||||
import { ResolveThunks, connect } from 'react-redux';
|
||||
import { changeStateTreeSettings } from '../../actions';
|
||||
import { StoreState } from '../../reducers';
|
||||
|
||||
|
@ -14,6 +14,7 @@ export class StateTree extends Component<Props> {
|
|||
const formData = {
|
||||
sortAlphabetically: stateTree.sortAlphabetically,
|
||||
disableCollection: stateTree.disableCollection,
|
||||
enableSearchPanel: stateTree.enableSearchPanel,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -30,6 +31,10 @@ export class StateTree extends Component<Props> {
|
|||
title: 'Disable collapsing of nodes',
|
||||
type: 'boolean',
|
||||
},
|
||||
enableSearchPanel: {
|
||||
title: 'Show search panel in State tab',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
}}
|
||||
formData={formData}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { Component } from 'react';
|
||||
import { withTheme } from 'styled-components';
|
||||
import { LiftedAction, LiftedState } from '@redux-devtools/core';
|
||||
import { ThemeFromProvider } from '@redux-devtools/ui';
|
||||
import React, { Component } from 'react';
|
||||
import { Action } from 'redux';
|
||||
import getMonitor from '../utils/getMonitor';
|
||||
import { withTheme } from 'styled-components';
|
||||
import { InitMonitorAction } from '../actions';
|
||||
import { Features, State } from '../reducers/instances';
|
||||
import { MonitorStateMonitorState } from '../reducers/monitor';
|
||||
import { ThemeFromProvider } from '@redux-devtools/ui';
|
||||
import { StateTreeSettings } from '../reducers/stateTreeSettings';
|
||||
import getMonitor from '../utils/getMonitor';
|
||||
|
||||
interface Props {
|
||||
monitor: string;
|
||||
|
@ -118,6 +118,7 @@ class DevTools extends Component<Props> {
|
|||
disableStateTreeCollection={
|
||||
this.props.stateTreeSettings.disableCollection
|
||||
}
|
||||
enableSearchPanel={this.props.stateTreeSettings.enableSearchPanel}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import { CHANGE_STATE_TREE_SETTINGS } from '../constants/actionTypes';
|
||||
import { StoreAction } from '../actions';
|
||||
import { CHANGE_STATE_TREE_SETTINGS } from '../constants/actionTypes';
|
||||
|
||||
export interface StateTreeSettings {
|
||||
readonly sortAlphabetically: boolean;
|
||||
readonly disableCollection: boolean;
|
||||
readonly enableSearchPanel: boolean;
|
||||
}
|
||||
|
||||
export function stateTreeSettings(
|
||||
state: StateTreeSettings = {
|
||||
sortAlphabetically: false,
|
||||
disableCollection: false,
|
||||
enableSearchPanel: false,
|
||||
},
|
||||
action: StoreAction,
|
||||
) {
|
||||
|
@ -17,6 +19,7 @@ export function stateTreeSettings(
|
|||
return {
|
||||
sortAlphabetically: action.sortAlphabetically,
|
||||
disableCollection: action.disableCollection,
|
||||
enableSearchPanel: action.enableSearchPanel,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Base16Theme } from 'redux-devtools-themes';
|
||||
import { Action } from 'redux';
|
||||
import type { StylingFunction } from 'react-base16-styling';
|
||||
import type { LabelRenderer } from 'react-json-tree';
|
||||
import { PerformAction } from '@redux-devtools/core';
|
||||
import { Delta } from 'jsondiffpatch';
|
||||
import { DEFAULT_STATE, DevtoolsInspectorState } from './redux';
|
||||
import React, { Component } from 'react';
|
||||
import type { StylingFunction } from 'react-base16-styling';
|
||||
import type { LabelRenderer } from 'react-json-tree';
|
||||
import { Action } from 'redux';
|
||||
import { Base16Theme } from 'redux-devtools-themes';
|
||||
import ActionPreviewHeader from './ActionPreviewHeader';
|
||||
import { DEFAULT_STATE, DevtoolsInspectorState } from './redux';
|
||||
import ActionTab from './tabs/ActionTab';
|
||||
import DiffTab from './tabs/DiffTab';
|
||||
import StateTab from './tabs/StateTab';
|
||||
import ActionTab from './tabs/ActionTab';
|
||||
|
||||
export interface TabComponentProps<S, A extends Action<unknown>> {
|
||||
labelRenderer: LabelRenderer;
|
||||
|
@ -23,6 +23,7 @@ export interface TabComponentProps<S, A extends Action<unknown>> {
|
|||
isWideLayout: boolean;
|
||||
sortStateTreeAlphabetically: boolean;
|
||||
disableStateTreeCollection: boolean;
|
||||
enableSearchPanel: boolean;
|
||||
dataTypeKey: string | symbol | undefined;
|
||||
delta: Delta | null | undefined | false;
|
||||
action: A;
|
||||
|
@ -74,6 +75,7 @@ interface Props<S, A extends Action<unknown>> {
|
|||
onSelectTab: (tabName: string) => void;
|
||||
sortStateTreeAlphabetically: boolean;
|
||||
disableStateTreeCollection: boolean;
|
||||
enableSearchPanel: boolean;
|
||||
}
|
||||
|
||||
class ActionPreview<S, A extends Action<unknown>> extends Component<
|
||||
|
@ -107,6 +109,7 @@ class ActionPreview<S, A extends Action<unknown>> extends Component<
|
|||
updateMonitorState,
|
||||
sortStateTreeAlphabetically,
|
||||
disableStateTreeCollection,
|
||||
enableSearchPanel,
|
||||
} = this.props;
|
||||
|
||||
const renderedTabs: Tab<S, A>[] =
|
||||
|
@ -141,6 +144,7 @@ class ActionPreview<S, A extends Action<unknown>> extends Component<
|
|||
isWideLayout,
|
||||
sortStateTreeAlphabetically,
|
||||
disableStateTreeCollection,
|
||||
enableSearchPanel,
|
||||
dataTypeKey,
|
||||
delta,
|
||||
action,
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Base16Theme } from 'redux-devtools-themes';
|
||||
import {
|
||||
getBase16Theme,
|
||||
invertTheme,
|
||||
StylingFunction,
|
||||
} from 'react-base16-styling';
|
||||
import {
|
||||
ActionCreators,
|
||||
LiftedAction,
|
||||
LiftedState,
|
||||
} from '@redux-devtools/core';
|
||||
import { Action, Dispatch } from 'redux';
|
||||
import { Delta, DiffContext } from 'jsondiffpatch';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
createStylingFromTheme,
|
||||
base16Themes,
|
||||
} from './utils/createStylingFromTheme';
|
||||
StylingFunction,
|
||||
getBase16Theme,
|
||||
invertTheme,
|
||||
} from 'react-base16-styling';
|
||||
import { Action, Dispatch } from 'redux';
|
||||
import { Base16Theme } from 'redux-devtools-themes';
|
||||
import ActionList from './ActionList';
|
||||
import ActionPreview, { Tab } from './ActionPreview';
|
||||
import getInspectedState from './utils/getInspectedState';
|
||||
import createDiffPatcher from './createDiffPatcher';
|
||||
import {
|
||||
DevtoolsInspectorAction,
|
||||
|
@ -27,6 +22,11 @@ import {
|
|||
reducer,
|
||||
updateMonitorState,
|
||||
} from './redux';
|
||||
import {
|
||||
base16Themes,
|
||||
createStylingFromTheme,
|
||||
} from './utils/createStylingFromTheme';
|
||||
import getInspectedState from './utils/getInspectedState';
|
||||
|
||||
const {
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
|
@ -153,6 +153,7 @@ export interface ExternalProps<S, A extends Action<unknown>> {
|
|||
invertTheme: boolean;
|
||||
sortStateTreeAlphabetically: boolean;
|
||||
disableStateTreeCollection: boolean;
|
||||
enableSearchPanel: boolean;
|
||||
dataTypeKey?: string | symbol;
|
||||
tabs: Tab<S, A>[] | ((tabs: Tab<S, A>[]) => Tab<S, A>[]);
|
||||
}
|
||||
|
@ -181,6 +182,7 @@ export interface DevtoolsInspectorProps<S, A extends Action<unknown>>
|
|||
hideActionButtons?: boolean;
|
||||
sortStateTreeAlphabetically: boolean;
|
||||
disableStateTreeCollection: boolean;
|
||||
enableSearchPanel: boolean;
|
||||
invertTheme: boolean;
|
||||
dataTypeKey?: string | symbol;
|
||||
tabs: Tab<S, A>[] | ((tabs: Tab<S, A>[]) => Tab<S, A>[]);
|
||||
|
@ -226,6 +228,7 @@ class DevtoolsInspector<S, A extends Action<unknown>> extends PureComponent<
|
|||
invertTheme: PropTypes.bool,
|
||||
sortStateTreeAlphabetically: PropTypes.bool,
|
||||
disableStateTreeCollection: PropTypes.bool,
|
||||
enableSearchPanel: PropTypes.bool,
|
||||
skippedActionIds: PropTypes.array,
|
||||
dataTypeKey: PropTypes.any,
|
||||
tabs: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
|
||||
|
@ -313,6 +316,7 @@ class DevtoolsInspector<S, A extends Action<unknown>> extends PureComponent<
|
|||
hideActionButtons,
|
||||
sortStateTreeAlphabetically,
|
||||
disableStateTreeCollection,
|
||||
enableSearchPanel,
|
||||
} = this.props;
|
||||
const { selectedActionId, startActionId, searchValue, tabName } =
|
||||
monitorState;
|
||||
|
@ -374,6 +378,7 @@ class DevtoolsInspector<S, A extends Action<unknown>> extends PureComponent<
|
|||
dataTypeKey,
|
||||
sortStateTreeAlphabetically,
|
||||
disableStateTreeCollection,
|
||||
enableSearchPanel,
|
||||
}}
|
||||
monitorState={this.props.monitorState}
|
||||
updateMonitorState={this.updateMonitorState}
|
||||
|
|
|
@ -114,6 +114,7 @@ function SearchPanel({
|
|||
{searchStatus === 'pending' && 'Searching...'}
|
||||
{searchStatus === 'done' && (
|
||||
<>
|
||||
<div {...styling('jumpResultContainer')}>
|
||||
<JumpSearchResultButton
|
||||
buttonDirection={BUTTON_DIRECTION.LEFT}
|
||||
buttonDisabled={!results || results.length < 2}
|
||||
|
@ -149,6 +150,7 @@ function SearchPanel({
|
|||
/>
|
||||
{results &&
|
||||
`${results.length ? resultIndex + 1 : 0}/${results.length}`}
|
||||
</div>
|
||||
<button {...styling('searchButton')} onClick={() => reset()}>
|
||||
Reset
|
||||
</button>
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { JSONTree } from 'react-json-tree';
|
||||
import { Action } from 'redux';
|
||||
import getItemString from './getItemString';
|
||||
import getJsonTreeTheme from './getJsonTreeTheme';
|
||||
import { TabComponentProps } from '../ActionPreview';
|
||||
import SearchPanel from '../searchPanel/SearchPanel';
|
||||
import getItemString from './getItemString';
|
||||
import getJsonTreeTheme from './getJsonTreeTheme';
|
||||
|
||||
interface SearchState {
|
||||
searchResult: string[];
|
||||
searchInProgress: boolean;
|
||||
}
|
||||
|
||||
const StateTab: React.FunctionComponent<
|
||||
TabComponentProps<any, Action<unknown>>
|
||||
|
@ -19,11 +24,8 @@ const StateTab: React.FunctionComponent<
|
|||
isWideLayout,
|
||||
sortStateTreeAlphabetically,
|
||||
disableStateTreeCollection,
|
||||
enableSearchPanel,
|
||||
}) => {
|
||||
interface SearchState {
|
||||
searchResult: string[];
|
||||
searchInProgress: boolean;
|
||||
}
|
||||
const [searchState, setSearchState] = useState<SearchState>({
|
||||
searchResult: [],
|
||||
searchInProgress: false,
|
||||
|
@ -32,7 +34,11 @@ const StateTab: React.FunctionComponent<
|
|||
const displayedResult = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (searchState.searchInProgress && displayedResult.current) {
|
||||
if (
|
||||
enableSearchPanel &&
|
||||
searchState.searchInProgress &&
|
||||
displayedResult.current
|
||||
) {
|
||||
displayedResult.current.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center',
|
||||
|
@ -40,10 +46,11 @@ const StateTab: React.FunctionComponent<
|
|||
});
|
||||
setSearchState({ ...searchState, searchInProgress: false });
|
||||
}
|
||||
}, [searchState, setSearchState]);
|
||||
}, [searchState, setSearchState, enableSearchPanel]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{enableSearchPanel && (
|
||||
<SearchPanel
|
||||
onSubmit={setSearchState}
|
||||
onReset={() =>
|
||||
|
@ -55,6 +62,7 @@ const StateTab: React.FunctionComponent<
|
|||
styling={styling}
|
||||
state={nextState}
|
||||
/>
|
||||
)}
|
||||
<JSONTree
|
||||
labelRenderer={(keyPath, nodeType, expanded, expandable) => {
|
||||
return isMatch(searchState.searchResult, [...keyPath].reverse()) ? (
|
||||
|
|
|
@ -271,11 +271,11 @@ const getSheetFromColorMap = (map: ColorMap) => ({
|
|||
|
||||
searchPanel: {
|
||||
display: 'flex',
|
||||
'flex-wrap': 'wrap',
|
||||
position: 'sticky',
|
||||
top: 0,
|
||||
width: '100%',
|
||||
'z-index': 1,
|
||||
height: '2em',
|
||||
gap: '1em',
|
||||
padding: '5px 10px',
|
||||
'align-items': 'center',
|
||||
|
@ -286,12 +286,6 @@ const getSheetFromColorMap = (map: ColorMap) => ({
|
|||
'border-bottom-color': map.HEADER_BORDER_COLOR,
|
||||
},
|
||||
|
||||
searchForm: {
|
||||
display: 'flex',
|
||||
gap: '1em',
|
||||
'align-items': 'center',
|
||||
},
|
||||
|
||||
searchPanelParameterSelection: {
|
||||
display: 'inline-grid',
|
||||
color: map.SEARCH_BUTTON_COLOR,
|
||||
|
@ -336,6 +330,12 @@ const getSheetFromColorMap = (map: ColorMap) => ({
|
|||
color: map.TEXT_COLOR,
|
||||
},
|
||||
|
||||
jumpResultContainer: {
|
||||
display: 'flex',
|
||||
gap: '1em',
|
||||
'align-items': 'center',
|
||||
},
|
||||
|
||||
jumpResultButton: {
|
||||
'background-color': map.SEARCH_BUTTON_COLOR,
|
||||
'border-color': 'transparent',
|
||||
|
|
Loading…
Reference in New Issue
Block a user