Add topic messages UI (#61)
This commit is contained in:
parent
128c0d2e92
commit
f974febb5f
13 changed files with 322 additions and 49 deletions
165
kafka-ui-react-app/package-lock.json
generated
165
kafka-ui-react-app/package-lock.json
generated
|
@ -3369,8 +3369,7 @@
|
||||||
},
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3415,7 +3414,8 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||||
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
|
@ -4008,6 +4008,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
|
||||||
"integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
|
"integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.1",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
|
@ -4024,6 +4025,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
|
||||||
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
|
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
|
@ -4034,6 +4036,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.0.1"
|
||||||
}
|
}
|
||||||
|
@ -4043,6 +4046,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
}
|
}
|
||||||
|
@ -4051,19 +4055,22 @@
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"to-regex-range": {
|
"to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
}
|
}
|
||||||
|
@ -5100,6 +5107,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"date-fns": {
|
||||||
|
"version": "2.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.14.0.tgz",
|
||||||
|
"integrity": "sha512-1zD+68jhFgDIM0rF05rcwYO8cExdNqxjq4xP1QKM60Q45mnO6zaMWB4tOzrIr4M4GSLntsKeE4c9Bdl2jhL/yw=="
|
||||||
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||||
|
@ -5236,9 +5248,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6905,8 +6917,7 @@
|
||||||
},
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7243,11 +7254,100 @@
|
||||||
"worker-rpc": "^0.1.0"
|
"worker-rpc": "^0.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"anymatch": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary-extensions": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chokidar": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"anymatch": "~3.1.1",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.1.2",
|
||||||
|
"glob-parent": "~5.1.0",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"readdirp": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -8623,6 +8723,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"binary-extensions": "^2.0.0"
|
"binary-extensions": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -9762,9 +9863,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yargs-parser": {
|
"yargs-parser": {
|
||||||
"version": "15.0.0",
|
"version": "15.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz",
|
||||||
"integrity": "sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ==",
|
"integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"camelcase": "^5.0.0",
|
"camelcase": "^5.0.0",
|
||||||
|
@ -10983,9 +11084,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11104,9 +11205,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
|
@ -11203,20 +11304,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "^1.2.5"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"minimist": {
|
|
||||||
"version": "0.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"morgan": {
|
"morgan": {
|
||||||
|
@ -11323,9 +11416,9 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14610,6 +14703,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
|
||||||
"integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
|
"integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
}
|
}
|
||||||
|
@ -16062,8 +16156,7 @@
|
||||||
},
|
},
|
||||||
"kind-of": {
|
"kind-of": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
"resolved": "",
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"bulma-switch": "^2.0.0",
|
"bulma-switch": "^2.0.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"immer": "^6.0.5",
|
"immer": "^6.0.5",
|
||||||
|
"date-fns": "^2.14.0",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.15",
|
||||||
"pretty-ms": "^6.0.1",
|
"pretty-ms": "^6.0.1",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
|
|
|
@ -25,6 +25,6 @@ $navbar-width: 250px;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
padding: 20px 20px;
|
padding: 20px 20px;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,105 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ClusterName, TopicName } from 'redux/interfaces';
|
import { ClusterName, TopicMessage, TopicName } from 'redux/interfaces';
|
||||||
|
import PageLoader from 'components/common/PageLoader/PageLoader';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
clusterName: ClusterName;
|
clusterName: ClusterName;
|
||||||
topicName: TopicName;
|
topicName: TopicName;
|
||||||
|
isFetched: boolean;
|
||||||
|
fetchTopicMessages: (clusterName: ClusterName, topicName: TopicName) => void;
|
||||||
|
messages: TopicMessage[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Messages: React.FC<Props> = ({
|
const Messages: React.FC<Props> = ({
|
||||||
|
isFetched,
|
||||||
clusterName,
|
clusterName,
|
||||||
topicName,
|
topicName,
|
||||||
|
messages,
|
||||||
|
fetchTopicMessages,
|
||||||
}) => {
|
}) => {
|
||||||
|
React.useEffect(() => {
|
||||||
|
fetchTopicMessages(clusterName, topicName);
|
||||||
|
}, [fetchTopicMessages, clusterName, topicName]);
|
||||||
|
|
||||||
|
const [searchText, setSearchText] = React.useState<string>('');
|
||||||
|
|
||||||
|
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSearchText(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTimestampDate = (timestamp: number) => {
|
||||||
|
return format(new Date(timestamp * 1000), 'MM.dd.yyyy HH:mm:ss');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMessageContentHeaders = () => {
|
||||||
|
const message = messages[0];
|
||||||
|
const headers: JSX.Element[] = [];
|
||||||
|
const content = JSON.parse(message.content);
|
||||||
|
Object.keys(content).forEach((k) =>
|
||||||
|
headers.push(<th>{`content.${k}`}</th>)
|
||||||
|
);
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMessageContentBody = (content: string) => {
|
||||||
|
const c = JSON.parse(content);
|
||||||
|
const columns: JSX.Element[] = [];
|
||||||
|
Object.values(c).map((v) => columns.push(<td>{JSON.stringify(v)}</td>));
|
||||||
|
return columns;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<h1>
|
// eslint-disable-next-line no-nested-ternary
|
||||||
Messages from {clusterName}{topicName}
|
isFetched ? (
|
||||||
</h1>
|
messages.length > 0 ? (
|
||||||
|
<div>
|
||||||
|
<div className="columns">
|
||||||
|
<div className="column is-half is-offset-half">
|
||||||
|
<input
|
||||||
|
id="searchText"
|
||||||
|
type="text"
|
||||||
|
name="searchText"
|
||||||
|
className="input"
|
||||||
|
placeholder="Search"
|
||||||
|
value={searchText}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table className="table is-striped is-fullwidth">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Timestamp</th>
|
||||||
|
<th>Offset</th>
|
||||||
|
<th>Partition</th>
|
||||||
|
{getMessageContentHeaders()}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{messages
|
||||||
|
.filter(
|
||||||
|
(message) =>
|
||||||
|
!searchText || message?.content?.indexOf(searchText) >= 0
|
||||||
|
)
|
||||||
|
.map((message) => (
|
||||||
|
<tr key={message.timestamp}>
|
||||||
|
<td>{getTimestampDate(message.timestamp)}</td>
|
||||||
|
<td>{message.offset}</td>
|
||||||
|
<td>{message.partition}</td>
|
||||||
|
{getMessageContentBody(message.content)}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>No messages at selected topic</div>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<PageLoader isFullHeight={false} />
|
||||||
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,40 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { ClusterName, RootState, TopicName } from 'redux/interfaces';
|
||||||
|
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||||
|
import { fetchTopicMessages } from 'redux/actions';
|
||||||
|
import {
|
||||||
|
getIsTopicMessagesFetched,
|
||||||
|
getTopicMessages,
|
||||||
|
} from 'redux/reducers/topics/selectors';
|
||||||
|
|
||||||
import Messages from './Messages';
|
import Messages from './Messages';
|
||||||
import {ClusterName, RootState, TopicName} from 'redux/interfaces';
|
|
||||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
|
||||||
|
|
||||||
interface RouteProps {
|
interface RouteProps {
|
||||||
clusterName: ClusterName;
|
clusterName: ClusterName;
|
||||||
topicName: TopicName;
|
topicName: TopicName;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OwnProps extends RouteComponentProps<RouteProps> { }
|
type OwnProps = RouteComponentProps<RouteProps>;
|
||||||
|
|
||||||
const mapStateToProps = (state: RootState, { match: { params: { topicName, clusterName } } }: OwnProps) => ({
|
const mapStateToProps = (
|
||||||
|
state: RootState,
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
params: { topicName, clusterName },
|
||||||
|
},
|
||||||
|
}: OwnProps
|
||||||
|
) => ({
|
||||||
clusterName,
|
clusterName,
|
||||||
topicName,
|
topicName,
|
||||||
|
isFetched: getIsTopicMessagesFetched(state),
|
||||||
|
messages: getTopicMessages(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
fetchTopicMessages: (clusterName: ClusterName, topicName: TopicName) =>
|
||||||
|
fetchTopicMessages(clusterName, topicName),
|
||||||
|
};
|
||||||
|
|
||||||
export default withRouter(
|
export default withRouter(
|
||||||
connect(mapStateToProps)(Messages)
|
connect(mapStateToProps, mapDispatchToProps)(Messages)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,21 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import cx from 'classnames';
|
||||||
|
|
||||||
const PageLoader: React.FC = () => (
|
interface Props {
|
||||||
<section className="hero is-fullheight-with-navbar">
|
isFullHeight: boolean;
|
||||||
<div className="hero-body has-text-centered" style={{ justifyContent: 'center' }}>
|
}
|
||||||
|
|
||||||
|
const PageLoader: React.FC<Partial<Props>> = ({ isFullHeight = true }) => (
|
||||||
|
<section
|
||||||
|
className={cx(
|
||||||
|
'hero',
|
||||||
|
isFullHeight ? 'is-fullheight-with-navbar' : 'is-halfheight'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="hero-body has-text-centered"
|
||||||
|
style={{ justifyContent: 'center' }}
|
||||||
|
>
|
||||||
<div style={{ width: 300 }}>
|
<div style={{ width: 300 }}>
|
||||||
<div className="subtitle">Loading...</div>
|
<div className="subtitle">Loading...</div>
|
||||||
<progress
|
<progress
|
||||||
|
|
|
@ -15,6 +15,10 @@ enum ActionType {
|
||||||
GET_TOPICS__SUCCESS = 'GET_TOPICS__SUCCESS',
|
GET_TOPICS__SUCCESS = 'GET_TOPICS__SUCCESS',
|
||||||
GET_TOPICS__FAILURE = 'GET_TOPICS__FAILURE',
|
GET_TOPICS__FAILURE = 'GET_TOPICS__FAILURE',
|
||||||
|
|
||||||
|
GET_TOPIC_MESSAGES__REQUEST = 'GET_TOPIC_MESSAGES__REQUEST',
|
||||||
|
GET_TOPIC_MESSAGES__SUCCESS = 'GET_TOPIC_MESSAGES__SUCCESS',
|
||||||
|
GET_TOPIC_MESSAGES__FAILURE = 'GET_TOPIC_MESSAGES__FAILURE',
|
||||||
|
|
||||||
GET_TOPIC_DETAILS__REQUEST = 'GET_TOPIC_DETAILS__REQUEST',
|
GET_TOPIC_DETAILS__REQUEST = 'GET_TOPIC_DETAILS__REQUEST',
|
||||||
GET_TOPIC_DETAILS__SUCCESS = 'GET_TOPIC_DETAILS__SUCCESS',
|
GET_TOPIC_DETAILS__SUCCESS = 'GET_TOPIC_DETAILS__SUCCESS',
|
||||||
GET_TOPIC_DETAILS__FAILURE = 'GET_TOPIC_DETAILS__FAILURE',
|
GET_TOPIC_DETAILS__FAILURE = 'GET_TOPIC_DETAILS__FAILURE',
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Topic,
|
Topic,
|
||||||
TopicConfig,
|
TopicConfig,
|
||||||
TopicDetails,
|
TopicDetails,
|
||||||
|
TopicMessage,
|
||||||
TopicName,
|
TopicName,
|
||||||
ConsumerGroup,
|
ConsumerGroup,
|
||||||
ConsumerGroupDetails,
|
ConsumerGroupDetails,
|
||||||
|
@ -37,6 +38,12 @@ export const fetchTopicListAction = createAsyncAction(
|
||||||
ActionType.GET_TOPICS__FAILURE
|
ActionType.GET_TOPICS__FAILURE
|
||||||
)<undefined, Topic[], undefined>();
|
)<undefined, Topic[], undefined>();
|
||||||
|
|
||||||
|
export const fetchTopicMessagesAction = createAsyncAction(
|
||||||
|
ActionType.GET_TOPIC_MESSAGES__REQUEST,
|
||||||
|
ActionType.GET_TOPIC_MESSAGES__SUCCESS,
|
||||||
|
ActionType.GET_TOPIC_MESSAGES__FAILURE
|
||||||
|
)<undefined, TopicMessage[], undefined>();
|
||||||
|
|
||||||
export const fetchTopicDetailsAction = createAsyncAction(
|
export const fetchTopicDetailsAction = createAsyncAction(
|
||||||
ActionType.GET_TOPIC_DETAILS__REQUEST,
|
ActionType.GET_TOPIC_DETAILS__REQUEST,
|
||||||
ActionType.GET_TOPIC_DETAILS__SUCCESS,
|
ActionType.GET_TOPIC_DETAILS__SUCCESS,
|
||||||
|
|
|
@ -57,6 +57,19 @@ export const fetchTopicList = (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchTopicMessages = (
|
||||||
|
clusterName: ClusterName,
|
||||||
|
topicName: TopicName
|
||||||
|
): PromiseThunk<void> => async (dispatch) => {
|
||||||
|
dispatch(actions.fetchTopicMessagesAction.request());
|
||||||
|
try {
|
||||||
|
const messages = await api.getTopicMessages(clusterName, topicName);
|
||||||
|
dispatch(actions.fetchTopicMessagesAction.success(messages));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(actions.fetchTopicMessagesAction.failure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const fetchTopicDetails = (
|
export const fetchTopicDetails = (
|
||||||
clusterName: ClusterName,
|
clusterName: ClusterName,
|
||||||
topicName: TopicName
|
topicName: TopicName
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import {
|
import {
|
||||||
TopicName,
|
TopicName,
|
||||||
|
TopicMessage,
|
||||||
Topic,
|
Topic,
|
||||||
ClusterName,
|
ClusterName,
|
||||||
TopicDetails,
|
TopicDetails,
|
||||||
|
@ -46,6 +47,14 @@ export const getTopics = (clusterName: ClusterName): Promise<Topic[]> =>
|
||||||
...BASE_PARAMS,
|
...BASE_PARAMS,
|
||||||
}).then((res) => res.json());
|
}).then((res) => res.json());
|
||||||
|
|
||||||
|
export const getTopicMessages = (
|
||||||
|
clusterName: ClusterName,
|
||||||
|
topicName: TopicName
|
||||||
|
): Promise<TopicMessage[]> =>
|
||||||
|
fetch(`${BASE_URL}/clusters/${clusterName}/topics/${topicName}/messages`, {
|
||||||
|
...BASE_PARAMS,
|
||||||
|
}).then((res) => res.json());
|
||||||
|
|
||||||
export const postTopic = (
|
export const postTopic = (
|
||||||
clusterName: ClusterName,
|
clusterName: ClusterName,
|
||||||
form: TopicFormData
|
form: TopicFormData
|
||||||
|
|
|
@ -50,6 +50,16 @@ export interface Topic {
|
||||||
partitions: TopicPartition[];
|
partitions: TopicPartition[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TopicMessage {
|
||||||
|
partition: number;
|
||||||
|
offset: number;
|
||||||
|
timestamp: number;
|
||||||
|
timestampType: string;
|
||||||
|
key: string;
|
||||||
|
headers: Record<string, string>;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TopicFormCustomParam {
|
export interface TopicFormCustomParam {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -67,6 +77,7 @@ export interface TopicWithDetailedInfo extends Topic, TopicDetails {
|
||||||
export interface TopicsState {
|
export interface TopicsState {
|
||||||
byName: { [topicName: string]: TopicWithDetailedInfo };
|
byName: { [topicName: string]: TopicWithDetailedInfo };
|
||||||
allNames: TopicName[];
|
allNames: TopicName[];
|
||||||
|
messages: TopicMessage[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TopicFormFormattedParams {
|
export interface TopicFormFormattedParams {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import ActionType from 'redux/actionType';
|
||||||
export const initialState: TopicsState = {
|
export const initialState: TopicsState = {
|
||||||
byName: {},
|
byName: {},
|
||||||
allNames: [],
|
allNames: [],
|
||||||
|
messages: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTopicList = (state: TopicsState, payload: Topic[]): TopicsState => {
|
const updateTopicList = (state: TopicsState, payload: Topic[]): TopicsState => {
|
||||||
|
@ -48,6 +49,11 @@ const reducer = (state = initialState, action: Action): TopicsState => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
case ActionType.GET_TOPIC_MESSAGES__SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
messages: action.payload,
|
||||||
|
};
|
||||||
case ActionType.GET_TOPIC_CONFIG__SUCCESS:
|
case ActionType.GET_TOPIC_CONFIG__SUCCESS:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -12,11 +12,16 @@ const topicsState = ({ topics }: RootState): TopicsState => topics;
|
||||||
|
|
||||||
const getAllNames = (state: RootState) => topicsState(state).allNames;
|
const getAllNames = (state: RootState) => topicsState(state).allNames;
|
||||||
const getTopicMap = (state: RootState) => topicsState(state).byName;
|
const getTopicMap = (state: RootState) => topicsState(state).byName;
|
||||||
|
export const getTopicMessages = (state: RootState) =>
|
||||||
|
topicsState(state).messages;
|
||||||
|
|
||||||
const getTopicListFetchingStatus = createFetchingSelector('GET_TOPICS');
|
const getTopicListFetchingStatus = createFetchingSelector('GET_TOPICS');
|
||||||
const getTopicDetailsFetchingStatus = createFetchingSelector(
|
const getTopicDetailsFetchingStatus = createFetchingSelector(
|
||||||
'GET_TOPIC_DETAILS'
|
'GET_TOPIC_DETAILS'
|
||||||
);
|
);
|
||||||
|
const getTopicMessagesFetchingStatus = createFetchingSelector(
|
||||||
|
'GET_TOPIC_MESSAGES'
|
||||||
|
);
|
||||||
const getTopicConfigFetchingStatus = createFetchingSelector('GET_TOPIC_CONFIG');
|
const getTopicConfigFetchingStatus = createFetchingSelector('GET_TOPIC_CONFIG');
|
||||||
const getTopicCreationStatus = createFetchingSelector('POST_TOPIC');
|
const getTopicCreationStatus = createFetchingSelector('POST_TOPIC');
|
||||||
const getTopicUpdateStatus = createFetchingSelector('PATCH_TOPIC');
|
const getTopicUpdateStatus = createFetchingSelector('PATCH_TOPIC');
|
||||||
|
@ -31,6 +36,11 @@ export const getIsTopicDetailsFetched = createSelector(
|
||||||
(status) => status === FetchStatus.fetched
|
(status) => status === FetchStatus.fetched
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getIsTopicMessagesFetched = createSelector(
|
||||||
|
getTopicMessagesFetchingStatus,
|
||||||
|
(status) => status === FetchStatus.fetched
|
||||||
|
);
|
||||||
|
|
||||||
export const getTopicConfigFetched = createSelector(
|
export const getTopicConfigFetched = createSelector(
|
||||||
getTopicConfigFetchingStatus,
|
getTopicConfigFetchingStatus,
|
||||||
(status) => status === FetchStatus.fetched
|
(status) => status === FetchStatus.fetched
|
||||||
|
|
Loading…
Add table
Reference in a new issue