Skip to content

Commit

Permalink
VTAdmin(web): Make screens with JSON output more readable
Browse files Browse the repository at this point in the history
Signed-off-by: Noble Mittal <[email protected]>
  • Loading branch information
beingnoble03 committed Jan 2, 2025
1 parent a5cf92c commit 0667994
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 16 deletions.
95 changes: 95 additions & 0 deletions web/vtadmin/src/components/jsonViewTree/JSONViewTree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Copyright 2025 The Vitess Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React, { useState } from 'react';
import { JSONTree } from 'react-json-tree';

const vtAdminTheme = {
scheme: 'vtadmin',
author: 'custom',
base00: '#ffffff',
base01: '#f6f8fa',
base02: '#e6e8eb',
base03: '#8c8c8c',
base04: '#3c3c3c',
base05: '#2c2c2c',
base06: '#0057b8',
base07: '#000000',
base08: '#00875a',
base09: '#2c2c2c',
base0A: '#e44d26',
base0B: '#2c2c2c',
base0C: '#1a73e8',
base0D: '#3d5afe',
base0E: '#3cba54',
base0F: '#ff6f61',
};

interface JSONViewTreeProps {
data: any;
}

const JSONViewTree: React.FC<JSONViewTreeProps> = ({ data }) => {
const [expandAll, setExpandAll] = useState(false);
const [treeKey, setTreeKey] = useState(0);

const handleExpand = () => {
setExpandAll(true);
setTreeKey((prev) => prev + 1);
};

const handleCollapse = () => {
setExpandAll(false);
setTreeKey((prev) => prev + 1);
};

const getItemString = (type: string, data: any) => {
if (Array.isArray(data)) {
return `${type}[${data.length}]`;
}
return type;
};

if (!data) return null;
return (
<div className="p-1">
<div className="flex mt-2 gap-2">
<button onClick={handleExpand} className="btn btn-secondary btn-sm">
Expand All
</button>
<button onClick={handleCollapse} className="btn btn-danger bg-transparent text-red-500 btn-sm">
Collapse All
</button>
</div>
<JSONTree
key={treeKey}
data={data}
theme={{
extend: vtAdminTheme,
nestedNodeItemString: {
color: vtAdminTheme.base0C,
},
}}
invertTheme={false}
hideRoot={true}
getItemString={getItemString}
shouldExpandNodeInitially={() => expandAll}
/>
</div>
);
};

export default JSONViewTree;
3 changes: 2 additions & 1 deletion web/vtadmin/src/components/routes/VTExplain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import style from './VTExplain.module.scss';
import { Code } from '../Code';
import { useDocumentTitle } from '../../hooks/useDocumentTitle';
import { Label } from '../inputs/Label';
import JSONViewTree from '../jsonViewTree/JSONViewTree';

// TODO(doeg): persist form data in URL, error handling, loading state, um... hm. Most things still need doing.
// This whole component is the hastiest prototype ever. :')
Expand Down Expand Up @@ -107,7 +108,7 @@ export const VTExplain = () => {

{error && (
<section className={style.errorPanel}>
<Code code={JSON.stringify(error, null, 2)} />
<JSONViewTree data={error} />
</section>
)}

Expand Down
4 changes: 2 additions & 2 deletions web/vtadmin/src/components/routes/keyspace/Keyspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { Link, Redirect, Route } from 'react-router-dom';
import { useKeyspace } from '../../../hooks/api';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
import { isReadOnlyMode } from '../../../util/env';
import { Code } from '../../Code';
import { ContentContainer } from '../../layout/ContentContainer';
import { NavCrumbs } from '../../layout/NavCrumbs';
import { WorkspaceHeader } from '../../layout/WorkspaceHeader';
Expand All @@ -32,6 +31,7 @@ import { Advanced } from './Advanced';
import style from './Keyspace.module.scss';
import { KeyspaceShards } from './KeyspaceShards';
import { KeyspaceVSchema } from './KeyspaceVSchema';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';

interface RouteParams {
clusterID: string;
Expand Down Expand Up @@ -111,7 +111,7 @@ export const Keyspace = () => {

<Route path={`${path}/json`}>
<QueryLoadingPlaceholder query={kq} />
<Code code={JSON.stringify(keyspace, null, 2)} />
<JSONViewTree data={keyspace} />
</Route>

{!isReadOnlyMode() && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { useVSchema } from '../../../hooks/api';
import { Code } from '../../Code';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';
import { QueryErrorPlaceholder } from '../../placeholders/QueryErrorPlaceholder';
import { QueryLoadingPlaceholder } from '../../placeholders/QueryLoadingPlaceholder';

Expand All @@ -30,7 +30,7 @@ export const KeyspaceVSchema = ({ clusterID, name }: Props) => {
<div>
<QueryLoadingPlaceholder query={query} />
<QueryErrorPlaceholder query={query} title="Couldn't load VSchema" />
{query.isSuccess && <Code code={JSON.stringify(query.data, null, 2)} />}
{query.isSuccess && <JSONViewTree data={query.data} />}
</div>
);
};
4 changes: 2 additions & 2 deletions web/vtadmin/src/components/routes/shard/Shard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import { WorkspaceTitle } from '../../layout/WorkspaceTitle';
import { ContentContainer } from '../../layout/ContentContainer';
import { Tab } from '../../tabs/Tab';
import { TabContainer } from '../../tabs/TabContainer';
import { Code } from '../../Code';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
import { KeyspaceLink } from '../../links/KeyspaceLink';
import { useKeyspace } from '../../../hooks/api';
import { ShardTablets } from './ShardTablets';
import Advanced from './Advanced';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';

interface RouteParams {
clusterID: string;
Expand Down Expand Up @@ -122,7 +122,7 @@ export const Shard = () => {
<ShardTablets {...params} />
</Route>

<Route path={`${path}/json`}>{shard && <Code code={JSON.stringify(shard, null, 2)} />}</Route>
<Route path={`${path}/json`}>{shard && <JSONViewTree data={shard} />}</Route>
<Route path={`${path}/advanced`}>
<Advanced />
</Route>
Expand Down
4 changes: 2 additions & 2 deletions web/vtadmin/src/components/routes/stream/Stream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import { Link, useParams } from 'react-router-dom';
import { useWorkflow } from '../../../hooks/api';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
import { formatStreamKey, getStream } from '../../../util/workflows';
import { Code } from '../../Code';
import { ContentContainer } from '../../layout/ContentContainer';
import { NavCrumbs } from '../../layout/NavCrumbs';
import { WorkspaceHeader } from '../../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../../layout/WorkspaceTitle';
import style from './Stream.module.scss';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';

interface RouteParams {
clusterID: string;
Expand Down Expand Up @@ -72,7 +72,7 @@ export const Stream = () => {
</div>
</WorkspaceHeader>
<ContentContainer>
<Code code={JSON.stringify(stream, null, 2)} />
<JSONViewTree data={stream} />
</ContentContainer>
</div>
);
Expand Down
8 changes: 3 additions & 5 deletions web/vtadmin/src/components/routes/tablet/Tablet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { useExperimentalTabletDebugVars, useTablet } from '../../../hooks/api';
import { useDocumentTitle } from '../../../hooks/useDocumentTitle';
import { isReadOnlyMode } from '../../../util/env';
import { formatDisplayType, formatState } from '../../../util/tablets';
import { Code } from '../../Code';
import { ContentContainer } from '../../layout/ContentContainer';
import { NavCrumbs } from '../../layout/NavCrumbs';
import { WorkspaceHeader } from '../../layout/WorkspaceHeader';
Expand All @@ -34,6 +33,7 @@ import style from './Tablet.module.scss';
import { TabletCharts } from './TabletCharts';
import { env } from '../../../util/env';
import FullStatus from './FullStatus';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';

interface RouteParams {
alias: string;
Expand Down Expand Up @@ -120,11 +120,9 @@ export const Tablet = () => {

<Route path={`${path}/json`}>
<div>
<Code code={JSON.stringify(tablet, null, 2)} />
<JSONViewTree data={tablet} />

{env().VITE_ENABLE_EXPERIMENTAL_TABLET_DEBUG_VARS && (
<Code code={JSON.stringify(debugVars, null, 2)} />
)}
{env().VITE_ENABLE_EXPERIMENTAL_TABLET_DEBUG_VARS && <JSONViewTree data={debugVars} />}
</div>
</Route>

Expand Down
4 changes: 2 additions & 2 deletions web/vtadmin/src/components/routes/workflow/Workflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import { ContentContainer } from '../../layout/ContentContainer';
import { TabContainer } from '../../tabs/TabContainer';
import { Tab } from '../../tabs/Tab';
import { getStreams } from '../../../util/workflows';
import { Code } from '../../Code';
import { ShardLink } from '../../links/ShardLink';
import { WorkflowVDiff } from './WorkflowVDiff';
import { Select } from '../../inputs/Select';
import { formatDateTimeShort } from '../../../util/time';
import JSONViewTree from '../../jsonViewTree/JSONViewTree';

interface RouteParams {
clusterID: string;
Expand Down Expand Up @@ -189,7 +189,7 @@ export const Workflow = () => {
</Route>

<Route path={`${path}/json`}>
<Code code={JSON.stringify(data, null, 2)} />
<JSONViewTree data={data} />
</Route>

<Redirect exact from={path} to={`${path}/streams`} />
Expand Down

0 comments on commit 0667994

Please sign in to comment.