Allow to Edit Cell in Detail Sidebar
Summary: This diff adds edit button to detail sidebar to allow user to edit column he/she wants to Reviewed By: jknoxville Differential Revision: D21788243 fbshipit-source-id: 4bdcef62114d5a6282ba85bc2bd1b5d039322e50
This commit is contained in:
committed by
Facebook GitHub Bot
parent
5a2221e6cd
commit
b57612a116
@@ -7,9 +7,10 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import React, {useMemo} from 'react';
|
||||
import React, {useMemo, useState, useEffect, useReducer} from 'react';
|
||||
import {
|
||||
Text,
|
||||
Input,
|
||||
DetailSidebar,
|
||||
Panel,
|
||||
ManagedTable,
|
||||
@@ -17,14 +18,29 @@ import {
|
||||
TableBodyRow,
|
||||
ManagedDataInspector,
|
||||
Value,
|
||||
valueToNullableString,
|
||||
renderValue,
|
||||
Layout,
|
||||
Button,
|
||||
styled,
|
||||
produce,
|
||||
} from 'flipper';
|
||||
|
||||
type DatabaseDetailSidebarProps = {
|
||||
columnLabels: Array<string>;
|
||||
columnValues: Array<Value>;
|
||||
onSave?: ((changes: {[key: string]: string | null}) => void) | undefined;
|
||||
};
|
||||
|
||||
const EditTriggerSection = styled.div({
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
width: '100%',
|
||||
paddingTop: '3px',
|
||||
paddingBottom: '3px',
|
||||
paddingRight: '10px',
|
||||
});
|
||||
|
||||
function sidebarRows(labels: Array<string>, values: Array<Value>): TableRows {
|
||||
return labels.map((label, idx) => buildSidebarRow(label, values[idx]));
|
||||
}
|
||||
@@ -51,6 +67,56 @@ function buildSidebarRow(key: string, val: Value): TableBodyRow {
|
||||
};
|
||||
}
|
||||
|
||||
function sidebarEditableRows(
|
||||
labels: Array<string>,
|
||||
values: Array<Value>,
|
||||
rowDispatch: (action: RowAction) => void,
|
||||
): TableRows {
|
||||
return labels.map((label, idx) =>
|
||||
buildSidebarEditableRow(
|
||||
label,
|
||||
valueToNullableString(values[idx]),
|
||||
(value: string | null) => rowDispatch({type: 'set', key: label, value}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function buildSidebarEditableRow(
|
||||
key: string,
|
||||
value: string | null,
|
||||
onUpdateValue: (value: string | null) => void,
|
||||
): TableBodyRow {
|
||||
return {
|
||||
columns: {
|
||||
col: {value: <Text>{key}</Text>},
|
||||
val: {
|
||||
value: <EditField initialValue={value} onUpdateValue={onUpdateValue} />,
|
||||
},
|
||||
},
|
||||
key: key,
|
||||
};
|
||||
}
|
||||
|
||||
const EditField = React.memo(
|
||||
(props: {
|
||||
initialValue: string | null;
|
||||
onUpdateValue: (value: string | null) => void;
|
||||
}) => {
|
||||
const {initialValue, onUpdateValue} = props;
|
||||
const [value, setValue] = useState<string | null>(initialValue);
|
||||
useEffect(() => setValue(initialValue), [initialValue]);
|
||||
return (
|
||||
<Input
|
||||
value={value || ''}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
onUpdateValue(e.target.value);
|
||||
}}
|
||||
placeholder={value === null ? 'NULL' : undefined}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
const cols = {
|
||||
col: {
|
||||
value: 'Column',
|
||||
@@ -66,14 +132,41 @@ const colSizes = {
|
||||
val: 'flex',
|
||||
};
|
||||
|
||||
type RowState = {changes: {[key: string]: string | null}; updated: boolean};
|
||||
type RowAction =
|
||||
| {type: 'set'; key: string; value: string | null}
|
||||
| {type: 'reset'};
|
||||
|
||||
const rowStateReducer = produce((draftState: RowState, action: RowAction) => {
|
||||
switch (action.type) {
|
||||
case 'set':
|
||||
draftState.changes[action.key] = action.value;
|
||||
draftState.updated = true;
|
||||
return;
|
||||
case 'reset':
|
||||
draftState.changes = {};
|
||||
draftState.updated = false;
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
export default React.memo(function DatabaseDetailSidebar(
|
||||
props: DatabaseDetailSidebarProps,
|
||||
) {
|
||||
const {columnLabels, columnValues} = props;
|
||||
const rows = useMemo(() => sidebarRows(columnLabels, columnValues), [
|
||||
columnLabels,
|
||||
columnValues,
|
||||
]);
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [rowState, rowDispatch] = useReducer(rowStateReducer, {
|
||||
changes: {},
|
||||
updated: false,
|
||||
});
|
||||
const {columnLabels, columnValues, onSave} = props;
|
||||
useEffect(() => rowDispatch({type: 'reset'}), [columnLabels, columnValues]);
|
||||
const rows = useMemo(
|
||||
() =>
|
||||
editing
|
||||
? sidebarEditableRows(columnLabels, columnValues, rowDispatch)
|
||||
: sidebarRows(columnLabels, columnValues),
|
||||
[columnLabels, columnValues, editing],
|
||||
);
|
||||
return (
|
||||
<DetailSidebar>
|
||||
<Panel
|
||||
@@ -81,16 +174,38 @@ export default React.memo(function DatabaseDetailSidebar(
|
||||
floating={false}
|
||||
collapsable={true}
|
||||
padded={false}>
|
||||
<ManagedTable
|
||||
highlightableRows={false}
|
||||
columnSizes={colSizes}
|
||||
multiline={true}
|
||||
columns={cols}
|
||||
autoHeight={true}
|
||||
floating={false}
|
||||
zebra={false}
|
||||
rows={rows}
|
||||
/>
|
||||
<Layout.Top>
|
||||
{onSave && (
|
||||
<EditTriggerSection>
|
||||
{editing ? (
|
||||
<>
|
||||
<Button
|
||||
disabled={!rowState.updated}
|
||||
onClick={() => {
|
||||
console.log(rowState);
|
||||
onSave(rowState.changes);
|
||||
setEditing(false);
|
||||
}}>
|
||||
Save
|
||||
</Button>
|
||||
<Button onClick={() => setEditing(false)}>Close</Button>
|
||||
</>
|
||||
) : (
|
||||
<Button onClick={() => setEditing(true)}>Edit</Button>
|
||||
)}
|
||||
</EditTriggerSection>
|
||||
)}
|
||||
<ManagedTable
|
||||
highlightableRows={false}
|
||||
columnSizes={colSizes}
|
||||
multiline={true}
|
||||
columns={cols}
|
||||
autoHeight={true}
|
||||
floating={false}
|
||||
zebra={false}
|
||||
rows={rows}
|
||||
/>
|
||||
</Layout.Top>
|
||||
</Panel>
|
||||
</DetailSidebar>
|
||||
);
|
||||
|
||||
@@ -1127,6 +1127,7 @@ export default class DatabasesPlugin extends FlipperPlugin<
|
||||
<DatabaseDetailSidebar
|
||||
columnLabels={page.columns}
|
||||
columnValues={page.rows[page.highlightedRows[0]]}
|
||||
onSave={this.onRowEdited.bind(this)}
|
||||
/>
|
||||
)}
|
||||
</FlexRow>
|
||||
|
||||
Reference in New Issue
Block a user