Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cldn 1968 (Display JSON data inline) #268

Merged
merged 21 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
79388a2
Add buttons to expand and minimize JSON data as well as ability to ex…
cccs-Dustin Feb 8, 2023
6a43dfd
[CLDN-1968] Added expand button for full row
cccs-Dustin Feb 22, 2023
6031b34
[CLDN-1968] Resize JSON columns
cccs-Dustin Feb 24, 2023
dabc3da
[CLDN-1968] Added new array which tracks JSON cell state
cccs-Dustin Feb 27, 2023
2bc1814
Revert "[CLDN-1968] Added new array which tracks JSON cell state"
cccs-Dustin Feb 28, 2023
57b0ffd
[CLDN-1968] Added ability for row level expand all button to track if…
cccs-Dustin Feb 28, 2023
ca35c08
Merge branch 'cccs-2.0' into feature/CLDN-1968
cccs-Dustin Feb 28, 2023
05f8191
[CLDN-1968] Ran pre-commit hook
cccs-Dustin Mar 1, 2023
24d16a8
[CLDN-1968] Improved UI
cccs-Dustin Mar 1, 2023
60834d1
[CLDN-1968] Update image tag for testing
cccs-Dustin Mar 2, 2023
71f823b
[CLDN-1968] Revert image tag for testing
cccs-Dustin Mar 2, 2023
bc41022
[CLDN-1968] Added multiple UI/UX changes based on QA feedback
cccs-Dustin Mar 6, 2023
a3e8eb7
[CLDN-1968] Added more UI/UX changes based on QA feedback
cccs-Dustin Mar 6, 2023
57490bd
[CLDN-1968] Temp change to image
cccs-Dustin Mar 6, 2023
a2c6469
Revert "[CLDN-1968] Temp change to image"
cccs-Dustin Mar 7, 2023
ae44712
Update superset-frontend/src/cccs-viz/plugins/plugin-chart-cccs-grid/…
cccs-Dustin Mar 8, 2023
269e04a
[CLDN-1968] Remove 'TODO's as they are no longer needed
cccs-Dustin Mar 8, 2023
ae3fd27
[CLDN-1968] Changed a variable name, and condensed a few lines
cccs-Dustin Mar 8, 2023
8b415fa
[CLDN-1968] Modified a setState so that only one is needed instead of 2
cccs-Dustin Mar 8, 2023
3b7c350
[CLDN-1968] Fixed merge conflicts
cccs-Dustin Mar 13, 2023
6c89332
Merge branch 'cccs-2.0' into feature/CLDN-1968
cccs-Dustin Mar 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.Button {
background-color: transparent;
border: solid rgb(137, 137, 137);
border-width: 0 2px 2px 0;
display: inline-block;
padding-right: 3px;
padding-left: 3px;
padding-top: 3px;
padding-bottom: 3px;
vertical-align: middle;
margin-right: 10px;
margin-left: 5px;
}

.Expand {
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}

.Collapse {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}

.Row-Expand {
background-color: transparent;
text-decoration: underline;
vertical-align: middle;
border: none;
color: rgb(31, 167, 201);
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { GroupCellRenderer } from '@ag-grid-enterprise/all-modules';
import React, { Component } from 'react';
import './Buttons.css';

// Show a button to collapse all of the JSON blobs in the row
function collapseJSON(this: any, reverseState: any) {
return (
<button className="Row-Expand" type="button" onClick={reverseState}>
Collapse Row
</button>
);
}

// Show a button to expand all of the JSON blobs in the row
function expandJSON(this: any, reverseState: any) {
return (
<>
<button className="Row-Expand" type="button" onClick={reverseState}>
Expand Row
</button>
</>
);
}

export default class ExpandAllValueRenderer extends Component<
{},
{ api: any; expanded: boolean; rowIndex: number }
> {
constructor(props: any) {
super(props);

this.state = {
api: props.api,
expanded: false,
rowIndex: props.rowIndex,
};
}

// Get all of the cells in the AG Grid and only keep the ones that
// are in the same row as the current expand all button, and make
// sure that they have a JSON blob
getJSONCells = () => {
const instances = this.state.api.getCellRendererInstances();

// Make sure row grouping is not enabled, but if it is, don't
// try to find all of the JSON blobs in the row
if (
instances.filter((instance: any) => instance instanceof GroupCellRenderer)
.length === 0
) {
const newInstances = instances.filter(
(instance: any) =>
instance.params.rowIndex === this.state.rowIndex &&
instance.params.column.colDef.cellRenderer === 'jsonValueRenderer',
);

return newInstances;
}
return [];
};

// Set the current `expanded` field to the opposite of what it currently is
// as well as go through each cell renderer and if it's in the same row &
// it's a cell with a JSON blob, update whether it is expanded or not
reverseState = () => {
this.setState(prevState => ({
...prevState,
expanded: !prevState.expanded,
}));

const newInstances = this.getJSONCells();

newInstances.map((instance: any) =>
instance.componentInstance.updateState(!this.state.expanded),
);
};

// Set the current `expanded` field to be equal to the boolean being passed in
// as well as go through each cell renderer and if it's in the same row &
// it's a cell with a JSON blob, update whether it is expanded or not
updateState = (newFlag: any) => {
this.setState(prevState => ({
...prevState,
expanded: newFlag,
}));

const newInstances = this.getJSONCells();

newInstances.map((instance: any) =>
instance.componentInstance.updateState(newFlag),
);
};

// Get all of the cells in the AG Grid and only keep the ones
// that are in the same row as the current expand all button and
// make sure that they have a JSON blob (and see whether they are
// expanded or not)
checkState = () => {
const newInstances = this.getJSONCells();

const jsonCells = newInstances.map((instance: any) =>
cccs-Dustin marked this conversation as resolved.
Show resolved Hide resolved
instance.componentInstance.getExpandedValue(),
);

// If there is at least one cell that can expand, the expand all
// button for the row should show 'Expand'
if (jsonCells.includes(false)) {
this.setState(prevState => ({
...prevState,
expanded: false,
}));
} else {
this.setState(prevState => ({
...prevState,
expanded: true,
}));
}
cccs-Dustin marked this conversation as resolved.
Show resolved Hide resolved
};

// Show either the expand or collapse button dependent
// on the value of the `expanded` field
render() {
if (this.state.expanded === false) {
return expandJSON(this.reverseState);
}
return collapseJSON(this.reverseState);
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,7 @@
import { GroupCellRenderer } from '@ag-grid-enterprise/all-modules';
import React, { Component } from 'react';
import ModalTrigger from 'src/components/ModalTrigger';
import JSONTree from 'react-json-tree';
import Button from 'src/components/Button';
import CopyToClipboard from 'src/components/CopyToClipboard';

const JSON_TREE_THEME = {
scheme: 'monokai',
base00: '#272822',
base01: '#383830',
base02: '#49483e',
base03: '#75715e',
base04: '#a59f85',
base05: '#f8f8f2',
base06: '#f5f4f1',
base07: '#f9f8f5',
base08: '#f92672',
base09: '#fd971f',
base0A: '#f4bf75',
base0B: '#a6e22e',
base0C: '#a1efe4',
base0D: '#66d9ef',
base0E: '#ae81ff',
base0F: '#cc6633',
};
import './Buttons.css';

function safeJsonObjectParse(
data: unknown,
Expand All @@ -48,34 +27,60 @@ function safeJsonObjectParse(
}
}

function addJsonModal(
node: React.ReactNode,
jsonObject: Record<string, unknown> | unknown[],
jsonString: String,
) {
// JSX which shows the JSON tree inline, and a button to collapse it
function collapseJSON(this: any, reverseState: any, jsonObject: any) {
return (
<ModalTrigger
modalBody={<JSONTree data={jsonObject} theme={JSON_TREE_THEME} />}
modalFooter={
<Button>
<CopyToClipboard shouldShowText={false} text={jsonString} />
</Button>
}
modalTitle="Cell content as JSON"
triggerNode={node}
/>
<>
<div style={{ float: 'left' }}>
<button
className="Button Collapse"
type="button"
title="Collapse"
onClick={reverseState}
>
{' '}
</button>
</div>
<div style={{ float: 'left' }}>
<JSONTree
data={jsonObject}
theme="default"
shouldExpandNode={() => true}
/>
</div>
</>
);
}

// JSX which shows the JSON data on one line, and a button to open the JSON tree
function expandJSON(this: any, reverseState: any, cellData: any) {
return (
<>
<button
className="Button Expand"
type="button"
title="Expand"
onClick={reverseState}
>
{' '}
</button>
{cellData}
</>
);
}

export default class JsonValueRenderer extends Component<
{},
{ cellValue: any }
{ api: any; cellValue: any; expanded: boolean; rowIndex: number }
> {
constructor(props: any) {
super(props);

this.state = {
api: props.api,
cellValue: JsonValueRenderer.getValueToDisplay(props),
expanded: false,
rowIndex: props.rowIndex,
};
}

Expand All @@ -86,14 +91,62 @@ export default class JsonValueRenderer extends Component<
};
}

// Set the current `expanded` field to the opposite of what it currently is
// and trigger the 'checkState` function in the expand all button for the row
reverseState = () => {
this.setState(
prevState => ({
...prevState,
expanded: !prevState.expanded,
}),
() => {
const instances = this.state.api.getCellRendererInstances();

// Make sure row grouping is not enabled, but if it is, don't
// trigger the 'checkState` function in the expand all button for the row
if (
instances.filter(
(instance: any) => instance instanceof GroupCellRenderer,
).length === 0
) {
instances
.filter(
(instance: any) =>
instance.params.rowIndex === this.state.rowIndex &&
instance.params.column.colDef.cellRenderer ===
'expandAllValueRenderer',
)
.map((instance: any) => instance.componentInstance.checkState());
}
},
);
};

// Take the boolean value passed in and set the `expanded` field equal to it
updateState = (newFlag: any) => {
this.setState(prevState => ({
...prevState,
expanded: newFlag,
}));
};

// Return whether 'expanded' is set to true or false
getExpandedValue = () => this.state.expanded;

render() {
const cellData = this.state.cellValue;
const jsonObject = safeJsonObjectParse(this.state.cellValue);
const cellNode = <div>{cellData}</div>;

// If there is a JSON object, either show it expanded or collapsed based
// on the value which the `expanded` field is set to
if (jsonObject) {
return addJsonModal(cellNode, jsonObject, cellData);
if (this.state.expanded === false) {
return expandJSON(this.reverseState, cellData);
}
return collapseJSON(this.reverseState, jsonObject);
}
return cellData ?? null;
// If the cellData is set to 'null' or undefined, return null
return cellData !== 'null' && cellData !== undefined ? cellData : null;
}

static getValueToDisplay(params: { valueFormatted: any; value: any }) {
Expand Down
Loading