Sidebar
Summary: This is mostly only moving the Sidebar from the old LayoutInspctor to a separate file. The old file was part of the UI component, however, it was super specific to the layout inspector, so I felt it makes sense moving it there. Here is a diff between the new `src/plugins/layout/layout2/InspectorSidebar.js` and `src/ui/components/elements-inspector/sidebar.js`: P60951781 The old file is still kept around, as long as the old and new layout inspector are run side by side. Reviewed By: passy Differential Revision: D14100537 fbshipit-source-id: b5a6fbae9866732800bb9b2b8fb1b996b9861db6
This commit is contained in:
committed by
Facebook Github Bot
parent
4f425b05b4
commit
649688db2a
193
src/plugins/layout/layout2/InspectorSidebar.js
Normal file
193
src/plugins/layout/layout2/InspectorSidebar.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2018-present Facebook.
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
* @format
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {Element} from 'flipper';
|
||||||
|
import type {PluginClient} from 'flipper';
|
||||||
|
import type Client from '../../../Client.js';
|
||||||
|
import type {Logger} from '../../../fb-interfaces/Logger.js';
|
||||||
|
|
||||||
|
import {
|
||||||
|
GK,
|
||||||
|
ManagedDataInspector,
|
||||||
|
Console,
|
||||||
|
Panel,
|
||||||
|
FlexCenter,
|
||||||
|
styled,
|
||||||
|
colors,
|
||||||
|
} from 'flipper';
|
||||||
|
import {Component} from 'react';
|
||||||
|
|
||||||
|
const deepEqual = require('deep-equal');
|
||||||
|
|
||||||
|
const NoData = styled(FlexCenter)({
|
||||||
|
fontSize: 18,
|
||||||
|
color: colors.macOSTitleBarIcon,
|
||||||
|
});
|
||||||
|
|
||||||
|
type OnValueChanged = (path: Array<string>, val: any) => void;
|
||||||
|
|
||||||
|
type InspectorSidebarSectionProps = {
|
||||||
|
data: any,
|
||||||
|
id: string,
|
||||||
|
onValueChanged: ?OnValueChanged,
|
||||||
|
tooltips?: Object,
|
||||||
|
};
|
||||||
|
|
||||||
|
class InspectorSidebarSection extends Component<InspectorSidebarSectionProps> {
|
||||||
|
setValue = (path: Array<string>, value: any) => {
|
||||||
|
if (this.props.onValueChanged) {
|
||||||
|
this.props.onValueChanged([this.props.id, ...path], value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: InspectorSidebarSectionProps) {
|
||||||
|
return (
|
||||||
|
!deepEqual(nextProps, this.props) ||
|
||||||
|
this.props.id !== nextProps.id ||
|
||||||
|
this.props.onValueChanged !== nextProps.onValueChanged
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extractValue = (val: any, depth: number) => {
|
||||||
|
if (val && val.__type__) {
|
||||||
|
return {
|
||||||
|
mutable: Boolean(val.__mutable__),
|
||||||
|
type: val.__type__ === 'auto' ? typeof val.value : val.__type__,
|
||||||
|
value: val.value,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
mutable: typeof val === 'object',
|
||||||
|
type: typeof val,
|
||||||
|
value: val,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {id} = this.props;
|
||||||
|
return (
|
||||||
|
<Panel heading={id} floating={false} grow={false}>
|
||||||
|
<ManagedDataInspector
|
||||||
|
data={this.props.data}
|
||||||
|
setValue={this.props.onValueChanged ? this.setValue : undefined}
|
||||||
|
extractValue={this.extractValue}
|
||||||
|
expandRoot={true}
|
||||||
|
collapsed={true}
|
||||||
|
tooltips={this.props.tooltips}
|
||||||
|
/>
|
||||||
|
</Panel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {|
|
||||||
|
element: ?Element,
|
||||||
|
tooltips?: Object,
|
||||||
|
onValueChanged: ?OnValueChanged,
|
||||||
|
client: PluginClient,
|
||||||
|
realClient: Client,
|
||||||
|
logger: Logger,
|
||||||
|
extensions?: Array<Function>,
|
||||||
|
|};
|
||||||
|
|
||||||
|
type State = {|
|
||||||
|
isConsoleEnabled: boolean,
|
||||||
|
|};
|
||||||
|
|
||||||
|
export default class Sidebar extends Component<Props, State> {
|
||||||
|
state = {
|
||||||
|
isConsoleEnabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.checkIfConsoleIsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps: Props, prevState: State) {
|
||||||
|
if (prevProps.client !== this.props.client) {
|
||||||
|
this.checkIfConsoleIsEnabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIfConsoleIsEnabled() {
|
||||||
|
this.props.client
|
||||||
|
.call('isConsoleEnabled')
|
||||||
|
.then((result: {isEnabled: boolean}) => {
|
||||||
|
this.setState({isConsoleEnabled: result.isEnabled});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {element, extensions} = this.props;
|
||||||
|
if (!element || !element.data) {
|
||||||
|
return <NoData grow>No data</NoData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sections: Array<any> =
|
||||||
|
(extensions &&
|
||||||
|
extensions.map(ext =>
|
||||||
|
ext(
|
||||||
|
this.props.client,
|
||||||
|
this.props.realClient,
|
||||||
|
element.id,
|
||||||
|
this.props.logger,
|
||||||
|
),
|
||||||
|
)) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
for (const key in element.data) {
|
||||||
|
if (key === 'Extra Sections') {
|
||||||
|
for (const extraSection in element.data[key]) {
|
||||||
|
let data = element.data[key][extraSection];
|
||||||
|
|
||||||
|
// data might be sent as stringified JSON, we want to parse it for a nicer persentation.
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
// data was not a valid JSON, type is required to be an object
|
||||||
|
console.error(
|
||||||
|
`ElementsInspector unable to parse extra section: ${extraSection}`,
|
||||||
|
);
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sections.push(
|
||||||
|
<InspectorSidebarSection
|
||||||
|
tooltips={this.props.tooltips}
|
||||||
|
key={extraSection}
|
||||||
|
id={extraSection}
|
||||||
|
data={data}
|
||||||
|
onValueChanged={this.props.onValueChanged}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sections.push(
|
||||||
|
<InspectorSidebarSection
|
||||||
|
tooltips={this.props.tooltips}
|
||||||
|
key={key}
|
||||||
|
id={key}
|
||||||
|
data={element.data[key]}
|
||||||
|
onValueChanged={this.props.onValueChanged}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GK.get('sonar_show_console_plugin') && this.state.isConsoleEnabled) {
|
||||||
|
sections.push(
|
||||||
|
<Panel heading="JS Console" floating={false} grow={false}>
|
||||||
|
<Console client={this.props.client} getContext={() => element.id} />
|
||||||
|
</Panel>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,9 +15,11 @@ import {
|
|||||||
Sidebar,
|
Sidebar,
|
||||||
Link,
|
Link,
|
||||||
Glyph,
|
Glyph,
|
||||||
|
DetailSidebar,
|
||||||
} from 'flipper';
|
} from 'flipper';
|
||||||
import Inspector from './Inspector';
|
import Inspector from './Inspector';
|
||||||
import ToolbarIcon from './ToolbarIcon';
|
import ToolbarIcon from './ToolbarIcon';
|
||||||
|
import InspectorSidebar from './InspectorSidebar';
|
||||||
|
|
||||||
type State = {|
|
type State = {|
|
||||||
init: boolean,
|
init: boolean,
|
||||||
@@ -116,6 +118,15 @@ export default class Layout extends FlipperPlugin<State, void, PersistedState> {
|
|||||||
onDataValueChanged: this.onDataValueChanged,
|
onDataValueChanged: this.onDataValueChanged,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let element;
|
||||||
|
if (this.state.inAXMode && this.state.selectedAXElement) {
|
||||||
|
element = this.props.persistedState.AXelements[
|
||||||
|
this.state.selectedAXElement
|
||||||
|
];
|
||||||
|
} else if (this.state.selectedElement) {
|
||||||
|
element = this.props.persistedState.elements[this.state.selectedElement];
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlexColumn grow={true}>
|
<FlexColumn grow={true}>
|
||||||
{this.state.init && (
|
{this.state.init && (
|
||||||
@@ -162,8 +173,18 @@ export default class Layout extends FlipperPlugin<State, void, PersistedState> {
|
|||||||
</Sidebar>
|
</Sidebar>
|
||||||
)}
|
)}
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
|
<DetailSidebar>
|
||||||
|
<InspectorSidebar
|
||||||
|
client={this.client}
|
||||||
|
realClient={this.realClient}
|
||||||
|
element={element}
|
||||||
|
onValueChanged={this.onDataValueChanged}
|
||||||
|
logger={this.props.logger}
|
||||||
|
/>
|
||||||
|
</DetailSidebar>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{/* TODO: Remove this when rolling out publicly */}
|
||||||
<Toolbar position="bottom" compact>
|
<Toolbar position="bottom" compact>
|
||||||
<Glyph name="beta" color="#8157C7" />
|
<Glyph name="beta" color="#8157C7" />
|
||||||
<strong>Version 2.0:</strong> Provide feedback about this plugin
|
<strong>Version 2.0:</strong> Provide feedback about this plugin
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
"lodash.debounce": "^4.0.8"
|
"lodash.debounce": "^4.0.8"
|
||||||
},
|
},
|
||||||
"title": "Layout",
|
"title": "Layout",
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
deep-equal@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||||
|
integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
|
||||||
|
|
||||||
lodash.debounce@^4.0.8:
|
lodash.debounce@^4.0.8:
|
||||||
version "4.0.8"
|
version "4.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
|
|||||||
Reference in New Issue
Block a user