Feature#108: Topic message content tree view (#110)

* Implemented topic message content tree view.

* Cleanup.

* Attempt to fix build.
This commit is contained in:
soffest 2020-11-10 13:38:19 +03:00 committed by GitHub
parent 15c818fa70
commit cee189a861
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 41 deletions

View file

@ -1803,6 +1803,11 @@
"@babel/types": "^7.3.0"
}
},
"@types/base16": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.2.tgz",
"integrity": "sha512-oYO/U4VD1DavwrKuCSQWdLG+5K22SLPem2OQaHmFcQuwHoVeGC+JGVRji2MUqZUAIQZHEonOeVfAX09hYiLsdg=="
},
"@types/classnames": {
"version": "2.2.9",
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.9.tgz",
@ -1902,8 +1907,15 @@
"@types/lodash": {
"version": "4.14.149",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
"dev": true
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ=="
},
"@types/lodash.curry": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/lodash.curry/-/lodash.curry-4.1.6.tgz",
"integrity": "sha512-x3ctCcmOYqRrihNNnQJW6fe/yZFCgnrIa6p80AiPQRO8Jis29bBdy1dEw1FwngoF/mCZa3Bx+33fUZvOEE635Q==",
"requires": {
"@types/lodash": "*"
}
},
"@types/minimatch": {
"version": "3.0.3",
@ -3393,6 +3405,11 @@
}
}
},
"base16": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
"integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA="
},
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
@ -4346,7 +4363,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz",
"integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==",
"dev": true,
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.2"
@ -4356,7 +4372,6 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
@ -4364,14 +4379,12 @@
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
"integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
"dev": true,
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@ -10560,6 +10573,11 @@
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=",
"dev": true
},
"lodash.curry": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
"integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -14055,6 +14073,26 @@
"whatwg-fetch": "^3.0.0"
}
},
"react-base16-styling": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.8.0.tgz",
"integrity": "sha512-ElvciPaL4xpWh7ISX7ugkNS/dvoh7DpVMp4t93ngnEsS2LkMd8Gu+cDDOLis2rj4889CNK662UdjOfv3wvZg9w==",
"requires": {
"@types/base16": "^1.0.2",
"@types/lodash.curry": "^4.1.6",
"base16": "^1.0.0",
"color": "^3.1.2",
"csstype": "^3.0.2",
"lodash.curry": "^4.1.1"
},
"dependencies": {
"csstype": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz",
"integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA=="
}
}
},
"react-datepicker": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-3.0.0.tgz",
@ -14344,6 +14382,16 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q=="
},
"react-json-tree": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.13.0.tgz",
"integrity": "sha512-FPJUQzYWi7pvBUAnMd9ENOnAUT2mXLhe01VUbPfKH9Q4gk4FQ0fpS1e1WZ3o7g6zfYJpYJeBTo1WwlMHlMlZOw==",
"requires": {
"@types/prop-types": "^15.7.3",
"prop-types": "^15.7.2",
"react-base16-styling": "^0.8.0"
}
},
"react-multi-select-component": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/react-multi-select-component/-/react-multi-select-component-2.0.12.tgz",
@ -16076,7 +16124,6 @@
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"dev": true,
"requires": {
"is-arrayish": "^0.3.1"
},
@ -16084,8 +16131,7 @@
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"dev": true
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},

View file

@ -16,6 +16,7 @@
"react-datepicker": "^3.0.0",
"react-dom": "^16.12.0",
"react-hook-form": "^4.5.5",
"react-json-tree": "^0.13.0",
"react-multi-select-component": "^2.0.12",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
@ -75,6 +76,7 @@
"@types/redux-thunk": "^2.1.0",
"@typescript-eslint/eslint-plugin": "^2.27.0",
"@typescript-eslint/parser": "^2.27.0",
"dotenv": "^8.2.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-config-prettier": "^6.10.1",
@ -90,8 +92,7 @@
"node-sass": "^4.13.1",
"prettier": "^2.0.4",
"react-scripts": "3.4.0",
"typescript": "~3.7.4",
"dotenv": "^8.2.0"
"typescript": "~3.7.4"
},
"proxy": "http://localhost:8080"
}

View file

@ -11,7 +11,7 @@ import {
import PageLoader from 'components/common/PageLoader/PageLoader';
import { format } from 'date-fns';
import DatePicker from 'react-datepicker';
import JSONTree from 'react-json-tree';
import 'react-datepicker/dist/react-datepicker.css';
import CustomParamButton, {
CustomParamButtonType,
@ -176,34 +176,35 @@ const Messages: React.FC<Props> = ({
return format(Date.parse(timestamp), 'yyyy-MM-dd HH:mm:ss');
};
const getMessageContentHeaders = React.useMemo(() => {
const message = messages[0];
const headers: JSX.Element[] = [];
try {
const content =
typeof message.content !== 'object'
? JSON.parse(message.content)
: message.content;
Object.keys(content).forEach((k) =>
headers.push(<th key={Math.random()}>{`content.${k}`}</th>)
);
} catch (e) {
headers.push(<th>Content</th>);
}
return headers;
}, [messages]);
const getMessageContentBody = (content: any) => {
const columns: JSX.Element[] = [];
try {
const c = typeof content !== 'object' ? JSON.parse(content) : content;
Object.values(c).map((v) =>
columns.push(<td key={Math.random()}>{JSON.stringify(v)}</td>)
const contentObj =
typeof content !== 'object' ? JSON.parse(content) : content;
return (
<JSONTree
data={contentObj}
hideRoot
invertTheme={false}
theme={{
tree: ({ style }) => ({
style: {
...style,
backgroundColor: undefined,
marginLeft: 0,
marginTop: 0,
},
}),
value: ({ style }) => ({
style: { ...style, marginLeft: 0 },
}),
base0D: '#3273dc',
base0B: '#363636',
}}
/>
);
} catch (e) {
columns.push(<td>{content}</td>);
return content;
}
return columns;
};
const onNext = (event: React.MouseEvent<HTMLButtonElement>) => {
@ -241,16 +242,20 @@ const Messages: React.FC<Props> = ({
<th>Timestamp</th>
<th>Offset</th>
<th>Partition</th>
{getMessageContentHeaders}
<th>Content</th>
</tr>
</thead>
<tbody>
{messages.map((message) => (
<tr key={`${message.timestamp}${Math.random()}`}>
<td>{getTimestampDate(message.timestamp)}</td>
<td>{message.offset}</td>
<td>{message.partition}</td>
{getMessageContentBody(message.content)}
<td style={{ width: 200 }}>
{getTimestampDate(message.timestamp)}
</td>
<td style={{ width: 150 }}>{message.offset}</td>
<td style={{ width: 100 }}>{message.partition}</td>
<td key={Math.random()} style={{ wordBreak: 'break-word' }}>
{getMessageContentBody(message.content)}
</td>
</tr>
))}
</tbody>