Add support for Subsections

Summary:
in the figma design we have the concept of subsections which are single level deep objects shown inline
{F1126292520}

More complex nested objects are shown a a preview that you have to click on and will come later

Reviewed By: lblasa

Differential Revision: D50595984

fbshipit-source-id: ea831731b87ce9968516129cf177953e200cf4d5
This commit is contained in:
Luke De Feo
2023-10-26 05:24:30 -07:00
committed by Facebook GitHub Bot
parent b184500d94
commit 65de40be7c

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {Input, Typography} from 'antd'; import {Divider, Input, Typography} from 'antd';
import {Panel, theme, Layout} from 'flipper-plugin'; import {Panel, theme, Layout} from 'flipper-plugin';
import React from 'react'; import React from 'react';
import { import {
@@ -19,7 +19,8 @@ import {
import {MetadataMap} from '../../DesktopTypes'; import {MetadataMap} from '../../DesktopTypes';
import {NoData} from '../sidebar/inspector/NoData'; import {NoData} from '../sidebar/inspector/NoData';
import {css, cx} from '@emotion/css'; import {css, cx} from '@emotion/css';
import {upperFirst} from 'lodash'; import {upperFirst, sortBy} from 'lodash';
import {any} from 'lodash/fp';
export function AttributesInspector({ export function AttributesInspector({
node, node,
@@ -64,40 +65,63 @@ function AttributeSection(
name: string, name: string,
inspectable: InspectableObject, inspectable: InspectableObject,
) { ) {
const children = Object.keys(inspectable.fields) const attributesOrSubSubsections = Object.entries(inspectable.fields).map(
.map((key) => { ([fieldKey, attributeValue]) => {
const metadataId: number = Number(key); const metadataId: number = Number(fieldKey);
const attributeMetadata = metadataMap.get(metadataId); const attributeMetadata = metadataMap.get(metadataId);
const attributeName =
upperFirst(attributeMetadata?.name) ?? String(metadataId);
//subsections are complex types that are only 1 level deep
const isSubSection =
attributeValue.type === 'object' &&
!any(
(inspectable) =>
inspectable.type === 'array' || inspectable.type === 'object',
Object.values(attributeValue.fields),
);
return {
attributeName,
attributeMetadata,
isSubSection,
attributeValue,
metadataId,
};
},
);
//push sub sections to the end
const sortedAttributesOrSubsections = sortBy(
attributesOrSubSubsections,
[(item) => item.isSubSection],
(item) => item.attributeName,
);
const children = sortedAttributesOrSubsections
.map(({isSubSection, attributeValue, attributeMetadata, attributeName}) => {
if (attributeMetadata == null) { if (attributeMetadata == null) {
return null; return null;
} }
const attributeValue = inspectable.fields[metadataId];
const attributeName = if (isSubSection) {
upperFirst(attributeMetadata?.name) ?? String(metadataId); if (attributeValue.type === 'object') {
return ( return (
<Layout.Horizontal key={key} gap="small"> <SubSection
<Typography.Text attributeName={attributeName}
style={{ inspectableObject={attributeValue}
marginTop: 3, //to center with top input when multiline
flex: '0 0 30%', //take 30% of the width
color: theme.textColorSecondary,
fontWeight: 50,
}}>
{attributeName}
</Typography.Text>
<Layout.Container style={{flex: '1 1 auto'}}>
<AttributeValue
name={attributeName}
attributeMetadata={attributeMetadata}
metadataMap={metadataMap} metadataMap={metadataMap}
inspectable={attributeValue}
level={1}
/> />
</Layout.Container> );
</Layout.Horizontal> }
}
return (
<NamedAttribute
attributeMetadata={attributeMetadata}
key={attributeName}
metadataMap={metadataMap}
name={attributeName}
value={attributeValue}
/>
); );
}) })
.filter((attr) => attr != null); .filter((attr) => attr != null);
@@ -115,6 +139,81 @@ function AttributeSection(
} }
} }
function SubSection({
attributeName,
inspectableObject,
metadataMap,
}: {
attributeName: string;
inspectableObject: InspectableObject;
metadataMap: MetadataMap;
}) {
return (
<Layout.Container gap="small" padv="small">
<Divider style={{margin: 0}} />
<Typography.Text>{attributeName}</Typography.Text>
{Object.entries(inspectableObject.fields).map(([key, value]) => {
const metadataId: number = Number(key);
const attributeMetadata = metadataMap.get(metadataId);
if (attributeMetadata == null) {
return null;
}
const attributeName =
upperFirst(attributeMetadata?.name) ?? String(metadataId);
return (
<NamedAttribute
key={key}
name={attributeName}
value={value}
attributeMetadata={attributeMetadata}
metadataMap={metadataMap}
/>
);
})}
</Layout.Container>
);
}
function NamedAttribute({
key,
name,
value,
metadataMap,
attributeMetadata,
}: {
name: string;
value: Inspectable;
attributeMetadata: Metadata;
metadataMap: MetadataMap;
key: string;
}) {
return (
<Layout.Horizontal key={key} gap="small">
<Typography.Text
style={{
marginTop: 3, //to center with top input when multiline
flex: '0 0 30%', //take 30% of the width
color: theme.textColorSecondary,
opacity: 0.7,
fontWeight: 50,
}}>
{name}
</Typography.Text>
<Layout.Container style={{flex: '1 1 auto'}}>
<AttributeValue
name={name}
attributeMetadata={attributeMetadata}
metadataMap={metadataMap}
inspectable={value}
level={1}
/>
</Layout.Container>
</Layout.Horizontal>
);
}
/** /**
* disables hover and focsued states * disables hover and focsued states
*/ */