mirror of https://github.com/apache/druid.git
Web console: Misc table fixes (#12489)
* Misc table fixes * extract default className * table spacing updates * fix e2e action selector * try more times * make the web console exist again
This commit is contained in:
parent
de14f511d6
commit
fb08bac01a
|
@ -48,6 +48,13 @@
|
|||
<artifactId>druid-gcp-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- This is needed to bundle the web console -->
|
||||
<groupId>org.apache.druid</groupId>
|
||||
<artifactId>druid-console</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.druid</groupId>
|
||||
|
|
|
@ -128,7 +128,7 @@ As part of this directory:
|
|||
|
||||
- `assets/` - The images (and other assets) used within the console
|
||||
- `e2e-tests/` - End-to-end tests for the console
|
||||
- `lib/` - A place where some overrides to the react-table stylus files live, this is outside of the normal SCSS build system.
|
||||
- `lib/` - A place where keywords and generated docs live.
|
||||
- `public/` - The compiled destination for the files powering this console
|
||||
- `script/` - Some helper bash scripts for running this console
|
||||
- `src/` - This directory (together with `lib`) constitutes all the source code for this console
|
||||
|
|
|
@ -124,7 +124,7 @@ export class DatasourcesOverview {
|
|||
throw new Error(`Could not find datasource: ${datasourceName}`);
|
||||
}
|
||||
|
||||
const editActions = await this.page.$$('span[icon=wrench]');
|
||||
const editActions = await this.page.$$('.action-cell span[icon=more]');
|
||||
await editActions[index].click();
|
||||
await this.waitForPopupMenu();
|
||||
}
|
||||
|
|
|
@ -1,340 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
// This is a heavily modified version of the style file originally distributed here:
|
||||
// https://github.com/react-tools/react-table/blob/master/src/index.styl
|
||||
// Released originally under the MIT License https://github.com/react-tools/react-table/blob/master/LICENSE
|
||||
|
||||
$easeOutQuad = cubic-bezier(0.250, 0.460, 0.450, 0.940)
|
||||
$easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
|
||||
$expandSize = 7px
|
||||
$border-color = alpha(black, 0.15)
|
||||
|
||||
input-select-style()
|
||||
border: 1px solid rgba(0,0,0,0.1)
|
||||
background: white
|
||||
padding: 5px 7px
|
||||
font-size: inherit
|
||||
border-radius: 3px
|
||||
font-weight: normal
|
||||
outline:none
|
||||
|
||||
.ReactTable
|
||||
position:relative
|
||||
display: flex
|
||||
flex-direction: column
|
||||
*
|
||||
box-sizing: border-box
|
||||
.rt-table
|
||||
flex: auto 1
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
width: 100%
|
||||
border-collapse: collapse
|
||||
overflow: auto
|
||||
|
||||
.rt-thead
|
||||
flex: 1 0 auto
|
||||
display: flex
|
||||
flex-direction: column
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&.-headerGroups
|
||||
background: alpha(black, .03)
|
||||
border-bottom: 1px solid $border-color
|
||||
|
||||
&.-filters
|
||||
border-bottom: 1px solid $border-color
|
||||
|
||||
//input
|
||||
//select
|
||||
// input-select-style();
|
||||
|
||||
.rt-th
|
||||
border-right: 1px solid $border-color
|
||||
|
||||
&.-header
|
||||
box-shadow: 0 1px 0 0 $border-color
|
||||
|
||||
.rt-tr
|
||||
text-align: left
|
||||
|
||||
.rt-th
|
||||
.rt-td
|
||||
padding: 5px 5px
|
||||
line-height: normal
|
||||
position: relative
|
||||
border-right: 1px solid $border-color
|
||||
transition box-shadow .3s $easeOutBack
|
||||
box-shadow:inset 0 0 0 0 transparent
|
||||
&.-sort-asc
|
||||
box-shadow:inset 0 3px 0 0 #8489A1
|
||||
&.-sort-desc
|
||||
box-shadow:inset 0 -3px 0 0 #8489A1
|
||||
&.-cursor-pointer
|
||||
cursor: pointer
|
||||
&:last-child
|
||||
border-right: 0
|
||||
|
||||
.rt-resizable-header
|
||||
overflow: visible
|
||||
&:last-child
|
||||
overflow: hidden
|
||||
|
||||
.rt-resizable-header-content
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
||||
.rt-header-pivot
|
||||
border-right-color: $border-color
|
||||
|
||||
.rt-header-pivot:after, .rt-header-pivot:before
|
||||
left: 100%
|
||||
top: 50%
|
||||
border: solid transparent
|
||||
content: " "
|
||||
height: 0
|
||||
width: 0
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
|
||||
.rt-header-pivot:after
|
||||
border-color: rgba(255, 255, 255, 0)
|
||||
border-left-color: #FFF
|
||||
border-width: 8px
|
||||
margin-top: -8px
|
||||
|
||||
.rt-header-pivot:before
|
||||
border-color: rgba(102, 102, 102, 0)
|
||||
border-left-color: #f7f7f7
|
||||
border-width: 10px
|
||||
margin-top: -10px
|
||||
|
||||
.rt-tbody
|
||||
flex: 99999 1 auto
|
||||
display: flex
|
||||
flex-direction: column
|
||||
overflow: auto
|
||||
// z-index:0
|
||||
.rt-tr-group
|
||||
border-bottom: 1px solid $border-color
|
||||
&:last-child
|
||||
border-bottom: 0
|
||||
.rt-td
|
||||
border-right:1px solid $border-color
|
||||
&:last-child
|
||||
border-right:0
|
||||
.rt-expandable
|
||||
cursor: pointer
|
||||
text-overflow: clip
|
||||
.rt-tr-group
|
||||
flex: 1 0 auto
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: stretch
|
||||
.rt-tr
|
||||
flex: 1 0 auto
|
||||
display: inline-flex
|
||||
.rt-th
|
||||
.rt-td
|
||||
flex: 1 0 0px
|
||||
white-space: nowrap
|
||||
text-overflow: ellipsis
|
||||
padding: 7px 5px
|
||||
overflow: hidden
|
||||
transition: .3s ease
|
||||
transition-property: width, min-width, padding, opacity
|
||||
|
||||
&.-hidden
|
||||
width: 0 !important
|
||||
min-width: 0 !important
|
||||
padding: 0 !important
|
||||
border:0 !important
|
||||
opacity: 0 !important
|
||||
|
||||
.rt-expander
|
||||
display: inline-block
|
||||
position:relative
|
||||
margin: 0
|
||||
color: transparent
|
||||
margin: 0 10px
|
||||
&:after
|
||||
content: ''
|
||||
position: absolute
|
||||
width: 0
|
||||
height: 0
|
||||
top:50%
|
||||
left:50%
|
||||
transform: translate(-50%, -50%) rotate(-90deg)
|
||||
border-left: ($expandSize * .72) solid transparent
|
||||
border-right: ($expandSize * .72) solid transparent
|
||||
border-top: $expandSize solid alpha(white, .8)
|
||||
transition: all .3s $easeOutBack
|
||||
cursor: pointer
|
||||
&.-open:after
|
||||
transform: translate(-50%, -50%) rotate(0deg)
|
||||
|
||||
.rt-resizer
|
||||
display: inline-block
|
||||
position: absolute
|
||||
width: 36px
|
||||
top: 0
|
||||
bottom: 0
|
||||
right: -18px
|
||||
cursor: col-resize
|
||||
z-index: 10
|
||||
|
||||
.rt-tfoot
|
||||
flex: 1 0 auto
|
||||
display: flex
|
||||
flex-direction: column
|
||||
box-shadow: 0 0px 15px 0px alpha(black, 0)
|
||||
|
||||
.rt-td
|
||||
border-right:1px solid $border-color
|
||||
&:last-child
|
||||
border-right:0
|
||||
|
||||
&.-striped
|
||||
.rt-tr.-odd
|
||||
background: alpha(white, .025)
|
||||
&.-highlight
|
||||
.rt-tbody
|
||||
.rt-tr:not(.-padRow):hover
|
||||
background: alpha(black, .05)
|
||||
|
||||
.-pagination
|
||||
z-index: 1
|
||||
display:flex
|
||||
justify-content: space-between
|
||||
align-items: stretch
|
||||
flex-wrap: wrap
|
||||
padding: 3px
|
||||
border-top: 1px solid $border-color
|
||||
|
||||
input
|
||||
select
|
||||
input-select-style()
|
||||
|
||||
.-btn
|
||||
appearance:none
|
||||
display:block
|
||||
width:100%
|
||||
height:100%
|
||||
border: 0
|
||||
border-radius: 3px
|
||||
padding: 6px
|
||||
font-size: 1em
|
||||
color: alpha(black, .6)
|
||||
background: alpha(black, .1)
|
||||
transition: all .1s ease
|
||||
cursor: pointer
|
||||
outline:none
|
||||
|
||||
&[disabled]
|
||||
opacity: .5
|
||||
cursor: default
|
||||
|
||||
&:not([disabled]):hover
|
||||
background: alpha(black, .3)
|
||||
color: white
|
||||
|
||||
.-previous
|
||||
.-next
|
||||
flex: 1
|
||||
text-align: center
|
||||
|
||||
.-center
|
||||
flex: 1.5
|
||||
text-align:center
|
||||
margin-bottom:0
|
||||
display: flex
|
||||
flex-direction: row
|
||||
flex-wrap: wrap
|
||||
align-items: center
|
||||
justify-content: space-around
|
||||
|
||||
.-pageInfo
|
||||
display: inline-block
|
||||
margin: 3px 10px
|
||||
white-space: nowrap
|
||||
|
||||
.-pageJump
|
||||
display:inline-block
|
||||
input
|
||||
width: 70px
|
||||
text-align:center
|
||||
|
||||
.-pageSizeOptions
|
||||
margin: 3px 10px
|
||||
|
||||
.rt-noData
|
||||
display:block
|
||||
position:absolute
|
||||
left:50%
|
||||
top:40%
|
||||
transform: translate(-50%, -50%)
|
||||
background: alpha(black, .4)
|
||||
transition: all .3s ease
|
||||
z-index: 1
|
||||
padding: 20px
|
||||
color: alpha(white, .5)
|
||||
border-radius: 5px
|
||||
|
||||
.-loading
|
||||
display:block
|
||||
position:absolute
|
||||
left:0
|
||||
right:0
|
||||
top:0
|
||||
bottom:0
|
||||
background: alpha(#4c4c4c, .8)
|
||||
transition: all .3s ease
|
||||
z-index: -1
|
||||
opacity: 0
|
||||
pointer-events: none
|
||||
|
||||
> div
|
||||
position:absolute
|
||||
display: block
|
||||
text-align:center
|
||||
width:100%
|
||||
top:50%
|
||||
left: 0
|
||||
font-size: 15px
|
||||
color: alpha(black, .6)
|
||||
transform: translateY(-52%)
|
||||
transition: all .3s $easeOutQuad
|
||||
|
||||
&.-active
|
||||
opacity: 1
|
||||
z-index: 2
|
||||
pointer-events: all
|
||||
> div
|
||||
transform: translateY(50%)
|
||||
|
||||
.rt-resizing
|
||||
.rt-th
|
||||
.rt-td
|
||||
transition: none!important
|
||||
cursor: col-resize
|
||||
user-select none
|
|
@ -7762,26 +7762,6 @@
|
|||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"css": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
|
||||
"integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"source-map": "^0.6.1",
|
||||
"source-map-resolve": "^0.5.2",
|
||||
"urix": "^0.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-blank-pseudo": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
|
||||
|
@ -7980,15 +7960,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"css-parse": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz",
|
||||
"integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"css-prefers-color-scheme": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz",
|
||||
|
@ -19734,12 +19705,6 @@
|
|||
"neo-async": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
},
|
||||
"saxes": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
|
||||
|
@ -21512,36 +21477,6 @@
|
|||
"postcss-value-parser": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"stylus": {
|
||||
"version": "0.54.7",
|
||||
"resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.7.tgz",
|
||||
"integrity": "sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-parse": "~2.0.0",
|
||||
"debug": "~3.1.0",
|
||||
"glob": "^7.1.3",
|
||||
"mkdirp": "~0.5.x",
|
||||
"safer-buffer": "^2.1.2",
|
||||
"sax": "~1.2.4",
|
||||
"semver": "^6.0.0",
|
||||
"source-map": "^0.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"sugarss": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz",
|
||||
|
|
|
@ -163,7 +163,6 @@
|
|||
"snarkdown": "^2.0.0",
|
||||
"style-loader": "^2.0.0",
|
||||
"stylelint": "^13.12.0",
|
||||
"stylus": "^0.54.7",
|
||||
"ts-jest": "^27.1.3",
|
||||
"ts-loader": "^8.1.0",
|
||||
"ts-node": "^8.4.1",
|
||||
|
|
|
@ -21,9 +21,6 @@ set -e
|
|||
echo "Adding SQL docs..."
|
||||
./script/create-sql-docs.js
|
||||
|
||||
echo "Transpiling ReactTable CSS..."
|
||||
./node_modules/.bin/stylus lib/react-table.styl -o lib/react-table.css
|
||||
|
||||
# add BUNDLE_ANALYZER_PLUGIN='TRUE' here to enable webpack-bundle-analyzer as a plugin
|
||||
echo "Webpacking everything..."
|
||||
NODE_ENV=production ./node_modules/.bin/webpack -c webpack.config.js --mode=production
|
||||
|
|
|
@ -110,7 +110,7 @@ function start() {
|
|||
echo "$pid" > "$DRUID_PID_FILE"
|
||||
_log "Druid started with pid ${pid}"
|
||||
|
||||
_wait_for_200_response "http://localhost:8888/unified-console.html" 3 20
|
||||
_wait_for_200_response "http://localhost:8888/unified-console.html" 3 30
|
||||
}
|
||||
|
||||
function stop() {
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Button, Classes, HTMLSelect } from '@blueprintjs/core';
|
||||
import React from 'react';
|
||||
|
||||
import './react-table-custom-pagination.scss';
|
||||
|
||||
interface ReactTableCustomPaginationProps {
|
||||
pages: number;
|
||||
page: number;
|
||||
showPageSizeOptions: boolean;
|
||||
pageSizeOptions: number[];
|
||||
pageSize: number;
|
||||
showPageJump: boolean;
|
||||
canPrevious: boolean;
|
||||
canNext: boolean;
|
||||
onPageSizeChange: any;
|
||||
previousText: string;
|
||||
nextText: string;
|
||||
onPageChange: any;
|
||||
ofText: string;
|
||||
pageText: string;
|
||||
rowsText: string;
|
||||
style: Record<string, any>;
|
||||
}
|
||||
|
||||
interface ReactTableCustomPaginationState {
|
||||
tempPage?: string;
|
||||
}
|
||||
|
||||
export class ReactTableCustomPagination extends React.PureComponent<
|
||||
ReactTableCustomPaginationProps,
|
||||
ReactTableCustomPaginationState
|
||||
> {
|
||||
constructor(props: ReactTableCustomPaginationProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
private readonly changePage = (page: number) => {
|
||||
page = Math.min(Math.max(page, 0), this.props.pages - 1);
|
||||
if (this.props.page !== page) {
|
||||
this.props.onPageChange(page);
|
||||
}
|
||||
};
|
||||
|
||||
private readonly applyTempPage = (e: any) => {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
const { tempPage } = this.state;
|
||||
if (!tempPage) return;
|
||||
this.setState({ tempPage: undefined });
|
||||
this.changePage(parseInt(tempPage, 10) - 1);
|
||||
};
|
||||
|
||||
render(): JSX.Element {
|
||||
const {
|
||||
pages,
|
||||
page,
|
||||
showPageSizeOptions,
|
||||
pageSizeOptions,
|
||||
pageSize,
|
||||
showPageJump,
|
||||
canPrevious,
|
||||
canNext,
|
||||
onPageSizeChange,
|
||||
style,
|
||||
previousText,
|
||||
nextText,
|
||||
ofText,
|
||||
pageText,
|
||||
rowsText,
|
||||
} = this.props;
|
||||
const { tempPage } = this.state;
|
||||
|
||||
return (
|
||||
<div className="-pagination" style={style}>
|
||||
<div className="-previous">
|
||||
<Button
|
||||
fill
|
||||
onClick={() => {
|
||||
if (!canPrevious) return;
|
||||
this.changePage(page - 1);
|
||||
}}
|
||||
disabled={!canPrevious}
|
||||
>
|
||||
{previousText}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="-center">
|
||||
<span className="-pageInfo">
|
||||
{pageText}{' '}
|
||||
{showPageJump ? (
|
||||
<div className="-pageJump">
|
||||
<input
|
||||
className={Classes.INPUT}
|
||||
type="number"
|
||||
min="1"
|
||||
onChange={e => {
|
||||
const val: string = e.target.value;
|
||||
this.setState({
|
||||
tempPage: val,
|
||||
});
|
||||
}}
|
||||
value={tempPage || String(page + 1)}
|
||||
onBlur={this.applyTempPage}
|
||||
onKeyPress={e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.applyTempPage(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span className="-currentPage">{page + 1}</span>
|
||||
)}{' '}
|
||||
{ofText} <span className="-totalPages">{pages || 1}</span>
|
||||
</span>
|
||||
{showPageSizeOptions && (
|
||||
<span className="select-wrap -pageSizeOptions">
|
||||
<HTMLSelect onChange={e => onPageSizeChange(Number(e.target.value))} value={pageSize}>
|
||||
{pageSizeOptions.map((option: any, i: number) => (
|
||||
<option key={i} value={option}>
|
||||
{`${option} ${rowsText}`}
|
||||
</option>
|
||||
))}
|
||||
</HTMLSelect>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="-next">
|
||||
<Button
|
||||
fill
|
||||
onClick={() => {
|
||||
if (!canNext) return;
|
||||
this.changePage(page + 1);
|
||||
}}
|
||||
disabled={!canNext}
|
||||
>
|
||||
{nextText}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -20,9 +20,13 @@ import React from 'react';
|
|||
import { Filter, ReactTableDefaults } from 'react-table';
|
||||
|
||||
import { Loader } from '../components';
|
||||
import { booleanCustomTableFilter, countBy, makeTextFilter } from '../utils';
|
||||
|
||||
import { ReactTableCustomPagination } from './react-table-custom-pagination';
|
||||
import {
|
||||
booleanCustomTableFilter,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
GenericFilterInput,
|
||||
ReactTablePagination,
|
||||
} from '../react-table';
|
||||
import { countBy } from '../utils';
|
||||
|
||||
const NoData = React.memo(function NoData(props) {
|
||||
const { children } = props;
|
||||
|
@ -32,7 +36,7 @@ const NoData = React.memo(function NoData(props) {
|
|||
|
||||
export function bootstrapReactTable() {
|
||||
Object.assign(ReactTableDefaults, {
|
||||
className: '-striped -highlight',
|
||||
className: DEFAULT_TABLE_CLASS_NAME,
|
||||
defaultFilterMethod: (filter: Filter, row: any) => {
|
||||
const id = filter.pivotId || filter.id;
|
||||
return booleanCustomTableFilter(filter, row[id]);
|
||||
|
@ -40,8 +44,8 @@ export function bootstrapReactTable() {
|
|||
LoadingComponent: Loader,
|
||||
loadingText: '',
|
||||
NoDataComponent: NoData,
|
||||
FilterComponent: makeTextFilter(),
|
||||
PaginationComponent: ReactTableCustomPagination,
|
||||
FilterComponent: GenericFilterInput,
|
||||
PaginationComponent: ReactTablePagination,
|
||||
AggregatedComponent: function Aggregated(opt: any) {
|
||||
const { subRows, column } = opt;
|
||||
const previewValues = subRows
|
||||
|
|
|
@ -16,7 +16,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import '../../variables';
|
||||
|
||||
.action-cell {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
|
||||
& > * {
|
||||
margin-right: 10px;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export const ActionCell = React.memo(function ActionCell(props: ActionCellProps)
|
|||
{onDetail && <ActionIcon icon={IconNames.SEARCH_TEMPLATE} onClick={onDetail} />}
|
||||
{actionsMenu && (
|
||||
<Popover2 content={actionsMenu} position={Position.BOTTOM_RIGHT}>
|
||||
<ActionIcon icon={IconNames.WRENCH} />
|
||||
<ActionIcon icon={IconNames.MORE} />
|
||||
</Popover2>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { max } from 'd3-array';
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
|
@ -24,6 +25,7 @@ import './braced-text.scss';
|
|||
const THOUSANDS_SEPARATOR = ','; // Maybe one day make this locale aware
|
||||
|
||||
export interface BracedTextProps {
|
||||
className?: string;
|
||||
text: string;
|
||||
braces: string[];
|
||||
padFractionalPart?: boolean;
|
||||
|
@ -80,7 +82,7 @@ function hideThousandsSeparator(text: string) {
|
|||
}
|
||||
|
||||
export const BracedText = React.memo(function BracedText(props: BracedTextProps) {
|
||||
const { text, braces, padFractionalPart, unselectableThousandsSeparator } = props;
|
||||
const { className, text, braces, padFractionalPart, unselectableThousandsSeparator } = props;
|
||||
|
||||
let effectiveBraces = braces.concat(text);
|
||||
|
||||
|
@ -110,7 +112,7 @@ export const BracedText = React.memo(function BracedText(props: BracedTextProps)
|
|||
}
|
||||
|
||||
return (
|
||||
<span className="braced-text">
|
||||
<span className={classNames('braced-text', className)}>
|
||||
<span className="brace-text">{findMostNumbers(effectiveBraces)}</span>
|
||||
<span className="real-text">
|
||||
{unselectableThousandsSeparator ? hideThousandsSeparator(text) : text}
|
||||
|
|
|
@ -67,10 +67,14 @@ exports[`DatasourceColumnsTable matches snapshot on error 1`] = `
|
|||
Object {
|
||||
"Header": "Column name",
|
||||
"accessor": "COLUMN_NAME",
|
||||
"className": "padded",
|
||||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Header": "Data type",
|
||||
"accessor": "DATA_TYPE",
|
||||
"className": "padded",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -224,10 +228,14 @@ exports[`DatasourceColumnsTable matches snapshot on init 1`] = `
|
|||
Object {
|
||||
"Header": "Column name",
|
||||
"accessor": "COLUMN_NAME",
|
||||
"className": "padded",
|
||||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Header": "Data type",
|
||||
"accessor": "DATA_TYPE",
|
||||
"className": "padded",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -393,10 +401,14 @@ exports[`DatasourceColumnsTable matches snapshot on no data 1`] = `
|
|||
Object {
|
||||
"Header": "Column name",
|
||||
"accessor": "COLUMN_NAME",
|
||||
"className": "padded",
|
||||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Header": "Data type",
|
||||
"accessor": "DATA_TYPE",
|
||||
"className": "padded",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -550,10 +562,14 @@ exports[`DatasourceColumnsTable matches snapshot on some data 1`] = `
|
|||
Object {
|
||||
"Header": "Column name",
|
||||
"accessor": "COLUMN_NAME",
|
||||
"className": "padded",
|
||||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Header": "Data type",
|
||||
"accessor": "DATA_TYPE",
|
||||
"className": "padded",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -21,12 +21,8 @@ import React from 'react';
|
|||
import ReactTable from 'react-table';
|
||||
|
||||
import { useQueryManager } from '../../hooks';
|
||||
import {
|
||||
ColumnMetadata,
|
||||
queryDruidSql,
|
||||
SMALL_TABLE_PAGE_SIZE,
|
||||
SMALL_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../utils';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { ColumnMetadata, queryDruidSql } from '../../utils';
|
||||
import { Loader } from '../loader/loader';
|
||||
|
||||
import './datasource-columns-table.scss';
|
||||
|
@ -67,10 +63,14 @@ export const DatasourceColumnsTable = React.memo(function DatasourceColumnsTable
|
|||
{
|
||||
Header: 'Column name',
|
||||
accessor: 'COLUMN_NAME',
|
||||
width: 300,
|
||||
className: 'padded',
|
||||
},
|
||||
{
|
||||
Header: 'Data type',
|
||||
accessor: 'DATA_TYPE',
|
||||
width: 200,
|
||||
className: 'padded',
|
||||
},
|
||||
]}
|
||||
noDataText={columnsState.getErrorMessage() || 'No column data found'}
|
||||
|
|
|
@ -42,6 +42,8 @@ export * from './show-json/show-json';
|
|||
export * from './show-log/show-log';
|
||||
export * from './suggestion-menu/suggestion-menu';
|
||||
export * from './table-cell/table-cell';
|
||||
export * from './table-clickable-cell/table-clickable-cell';
|
||||
export * from './table-column-selector/table-column-selector';
|
||||
export * from './table-filterable-cell/table-filterable-cell';
|
||||
export * from './timed-button/timed-button';
|
||||
export * from './view-control-bar/view-control-bar';
|
||||
|
|
|
@ -21,7 +21,8 @@ import React from 'react';
|
|||
import ReactTable from 'react-table';
|
||||
|
||||
import { useQueryManager } from '../../hooks';
|
||||
import { queryDruidSql, SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../utils';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { queryDruidSql } from '../../utils';
|
||||
import { Loader } from '../loader/loader';
|
||||
|
||||
import './lookup-values-table.scss';
|
||||
|
@ -57,20 +58,23 @@ export const LookupValuesTable = React.memo(function LookupValuesTable(
|
|||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={entries.length > SMALL_TABLE_PAGE_SIZE}
|
||||
filterable
|
||||
columns={[
|
||||
{
|
||||
Header: 'Key',
|
||||
accessor: 'k',
|
||||
},
|
||||
{
|
||||
Header: 'Value',
|
||||
accessor: 'v',
|
||||
},
|
||||
]}
|
||||
noDataText={
|
||||
entriesState.getErrorMessage() ||
|
||||
'Lookup data not found. If this is a new lookup it might not have propagated yet.'
|
||||
}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Key',
|
||||
accessor: 'k',
|
||||
className: 'padded',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
Header: 'Value',
|
||||
accessor: 'v',
|
||||
className: 'padded',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -81,13 +81,17 @@ exports[`SupervisorStatisticsTable matches snapshot on error 1`] = `
|
|||
Object {
|
||||
"Header": "Task ID",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "task_id",
|
||||
"width": 400,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Totals",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "total",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -255,13 +259,17 @@ exports[`SupervisorStatisticsTable matches snapshot on init 1`] = `
|
|||
Object {
|
||||
"Header": "Task ID",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "task_id",
|
||||
"width": 400,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Totals",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "total",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -455,13 +463,17 @@ exports[`SupervisorStatisticsTable matches snapshot on no data 1`] = `
|
|||
Object {
|
||||
"Header": "Task ID",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "task_id",
|
||||
"width": 400,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Totals",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "total",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -629,31 +641,41 @@ exports[`SupervisorStatisticsTable matches snapshot on some data 1`] = `
|
|||
Object {
|
||||
"Header": "Task ID",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "task_id",
|
||||
"width": 400,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Totals",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "total",
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "1m",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "1m",
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "5m",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "5m",
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "15m",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "15m",
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ import React from 'react';
|
|||
import ReactTable, { CellInfo, Column } from 'react-table';
|
||||
|
||||
import { useQueryManager } from '../../hooks';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { Api, UrlBaser } from '../../singletons';
|
||||
import { deepGet, SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../utils';
|
||||
import { deepGet } from '../../utils';
|
||||
import { Loader } from '../loader/loader';
|
||||
|
||||
import './supervisor-statistics-table.scss';
|
||||
|
@ -86,11 +87,15 @@ export const SupervisorStatisticsTable = React.memo(function SupervisorStatistic
|
|||
{
|
||||
Header: 'Task ID',
|
||||
id: 'task_id',
|
||||
className: 'padded',
|
||||
accessor: d => d.taskId,
|
||||
width: 400,
|
||||
},
|
||||
{
|
||||
Header: 'Totals',
|
||||
id: 'total',
|
||||
className: 'padded',
|
||||
width: 200,
|
||||
accessor: d => {
|
||||
return deepGet(d, 'summary.totals.buildSegments') as StatsEntry;
|
||||
},
|
||||
|
@ -110,6 +115,8 @@ export const SupervisorStatisticsTable = React.memo(function SupervisorStatistic
|
|||
return {
|
||||
Header: interval,
|
||||
id: interval,
|
||||
className: 'padded',
|
||||
width: 200,
|
||||
accessor: d => {
|
||||
return deepGet(d, `summary.movingAverages.buildSegments.${interval}`);
|
||||
},
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,7 +16,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import '../../variables';
|
||||
|
||||
.table-cell {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
|
||||
&.null {
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -41,8 +45,8 @@
|
|||
|
||||
.action-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
top: $table-cell-v-padding;
|
||||
right: $table-cell-h-padding;
|
||||
color: #f5f8fa;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,28 +64,28 @@ export const TableCell = React.memo(function TableCell(props: TableCellProps) {
|
|||
|
||||
function renderTruncated(str: string): JSX.Element {
|
||||
if (str.length <= MAX_CHARS_TO_SHOW) {
|
||||
return <span className="table-cell plain">{str}</span>;
|
||||
return <div className="table-cell plain">{str}</div>;
|
||||
}
|
||||
|
||||
if (unlimited) {
|
||||
return (
|
||||
<span className="table-cell plain">
|
||||
<div className="table-cell plain">
|
||||
{str.length < ABSOLUTE_MAX_CHARS_TO_SHOW
|
||||
? str
|
||||
: `${str.substr(0, ABSOLUTE_MAX_CHARS_TO_SHOW)}...`}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { prefix, omitted, suffix } = shortenString(str);
|
||||
return (
|
||||
<span className="table-cell truncated">
|
||||
<div className="table-cell truncated">
|
||||
{prefix}
|
||||
<span className="omitted">{omitted}</span>
|
||||
{suffix}
|
||||
<ActionIcon icon={IconNames.MORE} onClick={() => setShowValue(str)} />
|
||||
{renderShowValueDialog()}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -93,9 +93,9 @@ export const TableCell = React.memo(function TableCell(props: TableCellProps) {
|
|||
if (value instanceof Date) {
|
||||
const dateValue = value.valueOf();
|
||||
return (
|
||||
<span className="table-cell timestamp" title={String(value.valueOf())}>
|
||||
<div className="table-cell timestamp" title={String(value.valueOf())}>
|
||||
{isNaN(dateValue) ? 'Unusable date' : value.toISOString()}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
} else if (Array.isArray(value)) {
|
||||
return renderTruncated(`[${value.join(', ')}]`);
|
||||
|
@ -105,6 +105,6 @@ export const TableCell = React.memo(function TableCell(props: TableCellProps) {
|
|||
return renderTruncated(String(value));
|
||||
}
|
||||
} else {
|
||||
return <span className="table-cell null">null</span>;
|
||||
return <div className="table-cell null">null</div>;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,31 +16,23 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import '../variables';
|
||||
@import '../../variables';
|
||||
|
||||
.ReactTable {
|
||||
.-pageJump {
|
||||
.#{$bp-ns}-input {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
border: none;
|
||||
.table-clickable-cell {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.#{$bp-ns}-dark & {
|
||||
background-color: $dark-gray4;
|
||||
}
|
||||
}
|
||||
.hover-icon {
|
||||
position: absolute;
|
||||
top: $table-cell-v-padding;
|
||||
right: $table-cell-h-padding;
|
||||
color: #f5f8fa;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.-pageSizeOptions {
|
||||
.#{$bp-ns}-html-select select {
|
||||
width: 90px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
border: none;
|
||||
|
||||
.#{$bp-ns}-dark & {
|
||||
background-color: $dark-gray4;
|
||||
}
|
||||
}
|
||||
&:hover .hover-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Icon, IconName } from '@blueprintjs/core';
|
||||
import React, { MouseEventHandler, ReactNode } from 'react';
|
||||
|
||||
import './table-clickable-cell.scss';
|
||||
|
||||
export interface TableClickableCellProps {
|
||||
onClick: MouseEventHandler<any>;
|
||||
hoverIcon?: IconName;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const TableClickableCell = React.memo(function TableClickableCell(
|
||||
props: TableClickableCellProps,
|
||||
) {
|
||||
const { onClick, hoverIcon, children } = props;
|
||||
|
||||
return (
|
||||
<div className="table-clickable-cell" onClick={onClick}>
|
||||
{children}
|
||||
{hoverIcon && <Icon className="hover-icon" icon={hoverIcon} />}
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 '../../variables';
|
||||
|
||||
.table-filterable-cell {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&.bp4-popover2-target {
|
||||
display: block; // extra nesting for stronger CSS selectors
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Menu, MenuDivider, MenuItem } from '@blueprintjs/core';
|
||||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { Filter } from 'react-table';
|
||||
|
||||
import { addFilter, FilterMode, filterModeToIcon } from '../../react-table';
|
||||
import { Deferred } from '../deferred/deferred';
|
||||
|
||||
import './table-filterable-cell.scss';
|
||||
|
||||
const FILTER_MODES: FilterMode[] = ['=', '!=', '<=', '>='];
|
||||
const FILTER_MODES_NO_COMPARISONS: FilterMode[] = ['=', '!='];
|
||||
|
||||
export interface TableFilterableCellProps {
|
||||
field: string;
|
||||
value: string;
|
||||
filters: Filter[];
|
||||
onFiltersChange(filters: Filter[]): void;
|
||||
disableComparisons?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const TableFilterableCell = React.memo(function TableFilterableCell(
|
||||
props: TableFilterableCellProps,
|
||||
) {
|
||||
const { field, value, children, filters, disableComparisons, onFiltersChange } = props;
|
||||
|
||||
return (
|
||||
<Popover2
|
||||
className="table-filterable-cell"
|
||||
content={
|
||||
<Deferred
|
||||
content={() => (
|
||||
<Menu>
|
||||
<MenuDivider title="Filter" />
|
||||
{(disableComparisons ? FILTER_MODES_NO_COMPARISONS : FILTER_MODES).map((mode, i) => (
|
||||
<MenuItem
|
||||
key={i}
|
||||
icon={filterModeToIcon(mode)}
|
||||
text={value}
|
||||
onClick={() => onFiltersChange(addFilter(filters, field, mode, value))}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
)}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Popover2>
|
||||
);
|
||||
});
|
|
@ -22,8 +22,8 @@ import ReactTable, { Filter } from 'react-table';
|
|||
|
||||
import { Loader } from '../../components';
|
||||
import { useQueryManager } from '../../hooks';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { Api, UrlBaser } from '../../singletons';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../utils';
|
||||
|
||||
import './status-dialog.scss';
|
||||
|
||||
|
@ -86,15 +86,19 @@ export const StatusDialog = React.memo(function StatusDialog(props: StatusDialog
|
|||
Header: 'Extension name',
|
||||
accessor: 'artifact',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
Header: 'Fully qualified name',
|
||||
accessor: 'name',
|
||||
className: 'padded',
|
||||
},
|
||||
{
|
||||
Header: 'Version',
|
||||
accessor: 'version',
|
||||
width: 200,
|
||||
className: 'padded',
|
||||
},
|
||||
{
|
||||
Header: 'Fully qualified name',
|
||||
accessor: 'name',
|
||||
width: 500,
|
||||
className: 'padded',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function nonEmptyArray(a: any) {
|
||||
return Array.isArray(a) && Boolean(a.length);
|
||||
}
|
||||
import { nonEmptyArray } from '../utils';
|
||||
|
||||
export interface InputSource {
|
||||
type: string;
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
@import '~@blueprintjs/datetime/src/blueprint-datetime';
|
||||
@import '~@blueprintjs/popover2/src/blueprint-popover2';
|
||||
@import '~react-splitter-layout/lib/index';
|
||||
@import '../lib/react-table';
|
||||
@import './react-table/react-table-base-styles';
|
||||
@import './react-table/react-table-extra';
|
||||
|
||||
html,
|
||||
body {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
export * from './react-table-inputs';
|
||||
export * from './react-table-pagination/react-table-pagination';
|
||||
export * from './react-table-utils';
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
// This is a heavily modified version of the style file originally distributed here:
|
||||
// https://github.com/react-tools/react-table/blob/master/src/index.styl
|
||||
// Released originally under the MIT License https://github.com/react-tools/react-table/blob/master/LICENSE
|
||||
|
||||
@import '../variables';
|
||||
|
||||
$easeOutQuad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
$easeOutBack: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
$expandSize: 7px;
|
||||
$border-color: rgba(0, 0, 0, 0.15);
|
||||
|
||||
.ReactTable {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.rt-table {
|
||||
flex: auto 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.rt-thead {
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
|
||||
&.-headerGroups {
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
&.-filters {
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.rt-th {
|
||||
border-right: 1px solid $border-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.-header {
|
||||
box-shadow: 0 1px 0 0 $border-color;
|
||||
}
|
||||
|
||||
.rt-tr {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.rt-th,
|
||||
.rt-td {
|
||||
//padding: 5px 5px;
|
||||
line-height: normal;
|
||||
position: relative;
|
||||
border-right: 1px solid $border-color;
|
||||
transition: box-shadow 0.3s $easeOutBack;
|
||||
box-shadow: inset 0 0 0 0 transparent;
|
||||
|
||||
&.-sort-asc {
|
||||
box-shadow: inset 0 3px 0 0 #8489a1;
|
||||
}
|
||||
|
||||
&.-sort-desc {
|
||||
box-shadow: inset 0 -3px 0 0 #8489a1;
|
||||
}
|
||||
|
||||
&.-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.rt-resizable-header {
|
||||
overflow: visible;
|
||||
&:last-child {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.rt-resizable-header-content {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.rt-header-pivot {
|
||||
border-right-color: $border-color;
|
||||
}
|
||||
.rt-header-pivot:after,
|
||||
.rt-header-pivot:before {
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
border: solid transparent;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
.rt-header-pivot:after {
|
||||
border-color: rgba(255, 255, 255, 0);
|
||||
border-left-color: #fff;
|
||||
border-width: 8px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
.rt-header-pivot:before {
|
||||
border-color: rgba(102, 102, 102, 0);
|
||||
border-left-color: #f7f7f7;
|
||||
border-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
.rt-tbody {
|
||||
flex: 99999 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
overflow-x: hidden; // Prevents strange double horizontal scroll bar
|
||||
// z-index:0
|
||||
.rt-tr-group {
|
||||
border-bottom: 1px solid $border-color;
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
.rt-td {
|
||||
border-right: 1px solid $border-color;
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
.rt-expandable {
|
||||
cursor: pointer;
|
||||
text-overflow: clip;
|
||||
}
|
||||
}
|
||||
|
||||
.rt-tr-group {
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.rt-tr {
|
||||
flex: 1 0 auto;
|
||||
display: inline-flex;
|
||||
}
|
||||
.rt-th,
|
||||
.rt-td {
|
||||
flex: 1 0 0px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
&.-hidden {
|
||||
width: 0 !important;
|
||||
min-width: 0 !important;
|
||||
padding: 0 !important;
|
||||
border: 0 !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.rt-expander {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: transparent;
|
||||
margin: 0 10px;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) rotate(-90deg);
|
||||
border-left: ($expandSize * 0.72) solid transparent;
|
||||
border-right: ($expandSize * 0.72) solid transparent;
|
||||
border-top: $expandSize solid rgba(255, 255, 255, 0.8);
|
||||
transition: all 0.3s $easeOutBack;
|
||||
cursor: pointer;
|
||||
}
|
||||
&.-open:after {
|
||||
transform: translate(-50%, -50%) rotate(0deg);
|
||||
}
|
||||
}
|
||||
.rt-resizer {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 36px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: -18px;
|
||||
cursor: col-resize;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.rt-tfoot {
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 0px 15px 0px black;
|
||||
|
||||
.rt-td {
|
||||
border-right: 1px solid $border-color;
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.-striped {
|
||||
.rt-tr.-odd {
|
||||
background: rgba(255, 255, 255, 0.025);
|
||||
}
|
||||
}
|
||||
&.-highlight {
|
||||
.rt-tbody {
|
||||
.rt-tr:not(.-padRow):hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rt-noData {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 40%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1;
|
||||
padding: 20px;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.-loading {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: rgba(76, 76, 76, 0.8);
|
||||
transition: all 0.3s ease;
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
|
||||
* > div {
|
||||
position: absolute;
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
font-size: 15px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
transform: translateY(-52%);
|
||||
transition: all 0.3s $easeOutQuad;
|
||||
}
|
||||
&.-active {
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
pointer-events: all;
|
||||
* > div {
|
||||
transform: translateY(50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.rt-resizing {
|
||||
.rt-th,
|
||||
.rt-td {
|
||||
cursor: col-resize;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 'src/variables';
|
||||
|
||||
.ReactTable {
|
||||
.rt-tr {
|
||||
min-height: 38px;
|
||||
|
||||
.rt-th.padded,
|
||||
.rt-td.padded,
|
||||
.rt-expandable {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
}
|
||||
}
|
||||
|
||||
&.padded-header .rt-thead .rt-th {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
}
|
||||
|
||||
.braced-text.table-padding {
|
||||
display: inline-block;
|
||||
margin: $table-cell-v-padding $table-cell-h-padding;
|
||||
}
|
||||
|
||||
.generic-filter-input {
|
||||
&.hide-icon:not(:hover) {
|
||||
.filter-mode-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Button, HTMLSelect, Icon, InputGroup, Menu, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import classNames from 'classnames';
|
||||
import React, { useState } from 'react';
|
||||
import { Column, ReactTableFunction } from 'react-table';
|
||||
|
||||
import {
|
||||
combineModeAndNeedle,
|
||||
FILTER_MODES,
|
||||
FILTER_MODES_NO_COMPARISON,
|
||||
filterModeToIcon,
|
||||
filterModeToTitle,
|
||||
parseFilterModeAndNeedle,
|
||||
} from './react-table-utils';
|
||||
|
||||
interface FilterRendererProps {
|
||||
column: Column;
|
||||
filter: any;
|
||||
onChange: ReactTableFunction;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
export function GenericFilterInput({ column, filter, onChange, key }: FilterRendererProps) {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [focused, setFocused] = useState(false);
|
||||
|
||||
const disableComparisons = String(column.headerClassName).includes('disable-comparisons');
|
||||
|
||||
const { mode, needle } = (filter ? parseFilterModeAndNeedle(filter, true) : undefined) || {
|
||||
mode: '~',
|
||||
needle: '',
|
||||
};
|
||||
|
||||
return (
|
||||
<InputGroup
|
||||
className={classNames('generic-filter-input', {
|
||||
'hide-icon': !filter && !(menuOpen || focused),
|
||||
})}
|
||||
key={key}
|
||||
leftElement={
|
||||
<Popover2
|
||||
placement="bottom-start"
|
||||
minimal
|
||||
isOpen={menuOpen}
|
||||
onInteraction={setMenuOpen}
|
||||
content={
|
||||
<Menu>
|
||||
{(disableComparisons ? FILTER_MODES_NO_COMPARISON : FILTER_MODES).map((m, i) => (
|
||||
<MenuItem
|
||||
key={i}
|
||||
icon={filterModeToIcon(m)}
|
||||
text={filterModeToTitle(m)}
|
||||
onClick={() => onChange(combineModeAndNeedle(m, needle))}
|
||||
labelElement={m === mode ? <Icon icon={IconNames.TICK} /> : undefined}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button className="filter-mode-button" icon={filterModeToIcon(mode)} minimal />
|
||||
</Popover2>
|
||||
}
|
||||
value={needle}
|
||||
onChange={e => onChange(combineModeAndNeedle(mode, e.target.value))}
|
||||
rightElement={
|
||||
filter ? <Button icon={IconNames.CROSS} minimal onClick={() => onChange('')} /> : undefined
|
||||
}
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={e => {
|
||||
setFocused(false);
|
||||
if (filter && !e.target.value) onChange('');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function BooleanFilterInput({ filter, onChange, key }: FilterRendererProps) {
|
||||
const filterValue = filter ? filter.value : '';
|
||||
return (
|
||||
<HTMLSelect
|
||||
className="boolean-filter-input"
|
||||
key={key}
|
||||
style={{ width: '100%' }}
|
||||
onChange={(event: any) => onChange(event.target.value)}
|
||||
value={filterValue || 'all'}
|
||||
fill
|
||||
>
|
||||
<option value="all">Show all</option>
|
||||
<option value="true">true</option>
|
||||
<option value="false">false</option>
|
||||
</HTMLSelect>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Button, Classes, Dialog, FormGroup, Intent, NumericInput } from '@blueprintjs/core';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
interface PageJumpDialogProps {
|
||||
initPage: number;
|
||||
maxPage: number;
|
||||
onJump(page: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
export const PageJumpDialog = React.memo(function PageJumpDialog(props: PageJumpDialogProps) {
|
||||
const { initPage, maxPage, onJump, onClose } = props;
|
||||
|
||||
const [page, setPage] = useState<string>(String(initPage + 1));
|
||||
const pageAsNumber = parseInt(page, 10);
|
||||
const validPage = pageAsNumber >= 1;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
className="page-jump-dialog"
|
||||
onClose={onClose}
|
||||
isOpen
|
||||
title="Jump to page"
|
||||
canOutsideClickClose={false}
|
||||
>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<FormGroup>
|
||||
<NumericInput
|
||||
value={page}
|
||||
onValueChange={(_vn, vs) => setPage(vs)}
|
||||
autoFocus
|
||||
selectAllOnFocus
|
||||
min={1}
|
||||
max={maxPage}
|
||||
minorStepSize={1}
|
||||
fill
|
||||
/>
|
||||
</FormGroup>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button text="Close" onClick={onClose} />
|
||||
<Button
|
||||
text="Go"
|
||||
intent={Intent.PRIMARY}
|
||||
disabled={!validPage}
|
||||
onClick={() => {
|
||||
onJump(pageAsNumber - 1);
|
||||
onClose();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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.
|
||||
*/
|
||||
|
||||
.react-table-pagination {
|
||||
position: relative;
|
||||
padding-top: 5px;
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { Button, ButtonGroup, Menu, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { formatInteger, nonEmptyArray } from '../../utils';
|
||||
|
||||
import { PageJumpDialog } from './page-jump-dialog/page-jump-dialog';
|
||||
|
||||
import './react-table-pagination.scss';
|
||||
|
||||
interface ReactTablePaginationProps {
|
||||
pages: number;
|
||||
page: number;
|
||||
showPageSizeOptions: boolean;
|
||||
pageSizeOptions: number[];
|
||||
pageSize: number;
|
||||
showPageJump: boolean;
|
||||
canPrevious: boolean;
|
||||
canNext: boolean;
|
||||
onPageSizeChange: any;
|
||||
previousText: string;
|
||||
nextText: string;
|
||||
onPageChange: any;
|
||||
ofText: string;
|
||||
pageText: string;
|
||||
rowsText: string;
|
||||
sortedData?: any[];
|
||||
style: Record<string, any>;
|
||||
}
|
||||
|
||||
export const ReactTablePagination = React.memo(function ReactTablePagination(
|
||||
props: ReactTablePaginationProps,
|
||||
) {
|
||||
const {
|
||||
page,
|
||||
pages,
|
||||
onPageChange,
|
||||
pageSize,
|
||||
onPageSizeChange,
|
||||
pageSizeOptions,
|
||||
showPageJump,
|
||||
showPageSizeOptions,
|
||||
canPrevious,
|
||||
canNext,
|
||||
style,
|
||||
ofText,
|
||||
sortedData,
|
||||
} = props;
|
||||
const [showPageJumpDialog, setShowPageJumpDialog] = useState(false);
|
||||
|
||||
function changePage(newPage: number) {
|
||||
newPage = Math.min(Math.max(newPage, 0), pages - 1);
|
||||
if (page !== newPage) {
|
||||
onPageChange(newPage);
|
||||
}
|
||||
}
|
||||
|
||||
function renderPageJumpMenuItem() {
|
||||
if (!showPageJump) return;
|
||||
return <MenuItem text="Jump to page..." onClick={() => setShowPageJumpDialog(true)} />;
|
||||
}
|
||||
|
||||
function renderPageSizeChangeMenuItem() {
|
||||
if (!showPageSizeOptions) return;
|
||||
return (
|
||||
<MenuItem text={`Page size: ${pageSize}`}>
|
||||
{pageSizeOptions.map((option, i) => (
|
||||
<MenuItem
|
||||
key={i}
|
||||
icon={option === pageSize ? IconNames.TICK : IconNames.BLANK}
|
||||
text={String(option)}
|
||||
onClick={() => {
|
||||
if (option === pageSize) return;
|
||||
onPageSizeChange(option);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
const start = page * pageSize + 1;
|
||||
const end =
|
||||
page * pageSize +
|
||||
(nonEmptyArray(sortedData) ? Math.min(sortedData.length, pageSize) : pageSize);
|
||||
|
||||
let pageInfo = 'Showing';
|
||||
if (end) {
|
||||
pageInfo += ` ${formatInteger(start)}-${formatInteger(end)}`;
|
||||
} else {
|
||||
pageInfo += '...';
|
||||
}
|
||||
if (ofText && Array.isArray(sortedData)) {
|
||||
pageInfo += ` ${ofText} ${formatInteger(sortedData.length)}`;
|
||||
}
|
||||
|
||||
const pageJumpMenuItem = renderPageJumpMenuItem();
|
||||
const pageSizeChangeMenuItem = renderPageSizeChangeMenuItem();
|
||||
|
||||
return (
|
||||
<div className="react-table-pagination" style={style}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
icon={IconNames.CHEVRON_LEFT}
|
||||
minimal
|
||||
disabled={!canPrevious}
|
||||
onClick={() => changePage(page - 1)}
|
||||
/>
|
||||
<Button
|
||||
icon={IconNames.CHEVRON_RIGHT}
|
||||
minimal
|
||||
disabled={!canNext}
|
||||
onClick={() => changePage(page + 1)}
|
||||
/>
|
||||
<Popover2
|
||||
position="top-left"
|
||||
disabled={!pageJumpMenuItem && !pageSizeChangeMenuItem}
|
||||
content={
|
||||
<Menu>
|
||||
{pageJumpMenuItem}
|
||||
{pageSizeChangeMenuItem}
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button minimal text={pageInfo} />
|
||||
</Popover2>
|
||||
</ButtonGroup>
|
||||
{showPageJumpDialog && (
|
||||
<PageJumpDialog
|
||||
initPage={page}
|
||||
maxPage={pages}
|
||||
onJump={changePage}
|
||||
onClose={() => setShowPageJumpDialog(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { sqlQueryCustomTableFilter } from './react-table-utils';
|
||||
|
||||
describe('react-table-utils', () => {
|
||||
describe('sqlQueryCustomTableFilter', () => {
|
||||
it('works with contains', () => {
|
||||
expect(
|
||||
String(
|
||||
sqlQueryCustomTableFilter({
|
||||
id: 'datasource',
|
||||
value: `Hello`,
|
||||
}),
|
||||
),
|
||||
).toEqual(`LOWER("datasource") LIKE '%hello%'`);
|
||||
});
|
||||
|
||||
it('works with exact', () => {
|
||||
expect(
|
||||
String(
|
||||
sqlQueryCustomTableFilter({
|
||||
id: 'datasource',
|
||||
value: `=Hello`,
|
||||
}),
|
||||
),
|
||||
).toEqual(`"datasource" = 'Hello'`);
|
||||
});
|
||||
|
||||
it('works with less than or equal', () => {
|
||||
expect(
|
||||
String(
|
||||
sqlQueryCustomTableFilter({
|
||||
id: 'datasource',
|
||||
value: `<=Hello`,
|
||||
}),
|
||||
),
|
||||
).toEqual(`"datasource" <= 'Hello'`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you 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 { IconName } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlRef } from 'druid-query-toolkit';
|
||||
import { Filter } from 'react-table';
|
||||
|
||||
import { addOrUpdate, caseInsensitiveContains } from '../utils';
|
||||
|
||||
export const DEFAULT_TABLE_CLASS_NAME = '-striped -highlight padded-header';
|
||||
|
||||
export const STANDARD_TABLE_PAGE_SIZE = 50;
|
||||
export const STANDARD_TABLE_PAGE_SIZE_OPTIONS = [50, 100, 200];
|
||||
|
||||
export const SMALL_TABLE_PAGE_SIZE = 25;
|
||||
export const SMALL_TABLE_PAGE_SIZE_OPTIONS = [25, 50, 100];
|
||||
|
||||
export type FilterMode = '~' | '=' | '!=' | '<=' | '>=';
|
||||
|
||||
export const FILTER_MODES: FilterMode[] = ['~', '=', '!=', '<=', '>='];
|
||||
export const FILTER_MODES_NO_COMPARISON: FilterMode[] = ['~', '=', '!='];
|
||||
|
||||
export function filterModeToIcon(mode: FilterMode): IconName {
|
||||
switch (mode) {
|
||||
case '~':
|
||||
return IconNames.SEARCH;
|
||||
case '=':
|
||||
return IconNames.EQUALS;
|
||||
case '!=':
|
||||
return IconNames.NOT_EQUAL_TO;
|
||||
case '<=':
|
||||
return IconNames.LESS_THAN_OR_EQUAL_TO;
|
||||
case '>=':
|
||||
return IconNames.GREATER_THAN_OR_EQUAL_TO;
|
||||
default:
|
||||
return IconNames.BLANK;
|
||||
}
|
||||
}
|
||||
|
||||
export function filterModeToTitle(mode: FilterMode): string {
|
||||
switch (mode) {
|
||||
case '~':
|
||||
return 'Search';
|
||||
case '=':
|
||||
return 'Equals';
|
||||
case '!=':
|
||||
return 'Not equals';
|
||||
case '<=':
|
||||
return 'Less than or equal';
|
||||
case '>=':
|
||||
return 'Greater than or equal';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
interface FilterModeAndNeedle {
|
||||
mode: FilterMode;
|
||||
needle: string;
|
||||
}
|
||||
|
||||
export function addFilter(
|
||||
filters: readonly Filter[],
|
||||
id: string,
|
||||
mode: FilterMode,
|
||||
needle: string,
|
||||
): Filter[] {
|
||||
return addOrUpdateFilter(filters, { id, value: combineModeAndNeedle(mode, needle) });
|
||||
}
|
||||
|
||||
export function parseFilterModeAndNeedle(
|
||||
filter: Filter,
|
||||
loose = false,
|
||||
): FilterModeAndNeedle | undefined {
|
||||
const m = String(filter.value).match(/^(~|=|!=|<=|>=)?(.*)$/);
|
||||
if (!m) return;
|
||||
if (!loose && !m[2]) return;
|
||||
const mode = (m[1] as FilterMode) || '~';
|
||||
return {
|
||||
mode,
|
||||
needle: m[2] || '',
|
||||
};
|
||||
}
|
||||
|
||||
export function combineModeAndNeedle(mode: FilterMode, needle: string): string {
|
||||
return `${mode}${needle}`;
|
||||
}
|
||||
|
||||
export function addOrUpdateFilter(filters: readonly Filter[], filter: Filter): Filter[] {
|
||||
return addOrUpdate(filters, filter, f => f.id);
|
||||
}
|
||||
|
||||
export function syncFilterClauseById(
|
||||
target: readonly Filter[],
|
||||
source: readonly Filter[],
|
||||
id: string,
|
||||
): Filter[] {
|
||||
const clause = source.find(filter => filter.id === id);
|
||||
return clause ? addOrUpdateFilter(target, clause) : target.filter(filter => filter.id !== id);
|
||||
}
|
||||
|
||||
export function booleanCustomTableFilter(filter: Filter, value: any): boolean {
|
||||
if (value == null) return false;
|
||||
const modeAndNeedle = parseFilterModeAndNeedle(filter);
|
||||
if (!modeAndNeedle) return true;
|
||||
const { mode, needle } = modeAndNeedle;
|
||||
switch (mode) {
|
||||
case '=':
|
||||
return String(value) === needle;
|
||||
|
||||
case '!=':
|
||||
return String(value) !== needle;
|
||||
|
||||
case '<=':
|
||||
return String(value) <= needle;
|
||||
|
||||
case '>=':
|
||||
return String(value) >= needle;
|
||||
|
||||
default:
|
||||
return caseInsensitiveContains(String(value), needle);
|
||||
}
|
||||
}
|
||||
|
||||
export function sqlQueryCustomTableFilter(filter: Filter): SqlExpression | undefined {
|
||||
const modeAndNeedle = parseFilterModeAndNeedle(filter);
|
||||
if (!modeAndNeedle) return;
|
||||
const { mode, needle } = modeAndNeedle;
|
||||
const column = SqlRef.columnWithQuotes(filter.id);
|
||||
const needleLiteral = SqlLiteral.create(needle);
|
||||
switch (mode) {
|
||||
case '=':
|
||||
return column.equal(needleLiteral);
|
||||
|
||||
case '!=':
|
||||
return column.unequal(needleLiteral);
|
||||
|
||||
case '<=':
|
||||
return column.lessThanOrEqual(needleLiteral);
|
||||
|
||||
case '>=':
|
||||
return column.greaterThanOrEqual(needleLiteral);
|
||||
|
||||
default:
|
||||
return SqlFunction.simple('LOWER', [column]).like(
|
||||
SqlLiteral.create(`%${needle.toLowerCase()}%`),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -31,6 +31,8 @@ export function dataTypeToIcon(dataType: string): IconName {
|
|||
return IconNames.FONT;
|
||||
|
||||
case 'BIGINT':
|
||||
case 'DECIMAL':
|
||||
case 'REAL':
|
||||
case 'LONG':
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
|
@ -53,3 +55,40 @@ export function dataTypeToIcon(dataType: string): IconName {
|
|||
return IconNames.HELP;
|
||||
}
|
||||
}
|
||||
|
||||
export function dataTypeToColumnWidth(dataType: string | undefined): number {
|
||||
const typeUpper = String(dataType).toUpperCase();
|
||||
|
||||
switch (typeUpper) {
|
||||
case 'TIMESTAMP':
|
||||
return 180;
|
||||
|
||||
case 'VARCHAR':
|
||||
case 'STRING':
|
||||
return 150;
|
||||
|
||||
case 'BIGINT':
|
||||
case 'DECIMAL':
|
||||
case 'REAL':
|
||||
case 'LONG':
|
||||
case 'FLOAT':
|
||||
case 'DOUBLE':
|
||||
return 120;
|
||||
|
||||
case 'ARRAY<STRING>':
|
||||
return 200;
|
||||
|
||||
case 'ARRAY<LONG>':
|
||||
case 'ARRAY<FLOAT>':
|
||||
case 'ARRAY<DOUBLE>':
|
||||
return 180;
|
||||
|
||||
case 'COMPLEX<JSON>':
|
||||
return 300;
|
||||
|
||||
default:
|
||||
if (typeUpper.startsWith('ARRAY')) return 200;
|
||||
if (typeUpper.startsWith('COMPLEX')) return 150;
|
||||
return 180;
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ import {
|
|||
moveToIndex,
|
||||
objectHash,
|
||||
parseCsvLine,
|
||||
sqlQueryCustomTableFilter,
|
||||
swapElements,
|
||||
} from './general';
|
||||
|
||||
|
@ -56,30 +55,6 @@ describe('general', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('sqlQueryCustomTableFilter', () => {
|
||||
it('works with contains', () => {
|
||||
expect(
|
||||
String(
|
||||
sqlQueryCustomTableFilter({
|
||||
id: 'datasource',
|
||||
value: `Hello`,
|
||||
}),
|
||||
),
|
||||
).toEqual(`LOWER("datasource") LIKE '%hello%'`);
|
||||
});
|
||||
|
||||
it('works with exact', () => {
|
||||
expect(
|
||||
String(
|
||||
sqlQueryCustomTableFilter({
|
||||
id: 'datasource',
|
||||
value: `"Hello"`,
|
||||
}),
|
||||
),
|
||||
).toEqual(`"datasource" = 'Hello'`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('swapElements', () => {
|
||||
const array = ['a', 'b', 'c', 'd', 'e'];
|
||||
|
||||
|
|
|
@ -16,25 +16,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button, HTMLSelect, InputGroup, Intent } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlRef } from 'druid-query-toolkit';
|
||||
import FileSaver from 'file-saver';
|
||||
import hasOwnProp from 'has-own-prop';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
import numeral from 'numeral';
|
||||
import React from 'react';
|
||||
import { Filter, FilterRender } from 'react-table';
|
||||
|
||||
import { AppToaster } from '../singletons';
|
||||
|
||||
export const STANDARD_TABLE_PAGE_SIZE = 50;
|
||||
export const STANDARD_TABLE_PAGE_SIZE_OPTIONS = [50, 100, 200];
|
||||
|
||||
export const SMALL_TABLE_PAGE_SIZE = 25;
|
||||
export const SMALL_TABLE_PAGE_SIZE_OPTIONS = [25, 50, 100];
|
||||
|
||||
// These constants are used to make sure that they are not constantly recreated thrashing the pure components
|
||||
export const EMPTY_OBJECT: any = {};
|
||||
export const EMPTY_ARRAY: any[] = [];
|
||||
|
@ -45,108 +36,31 @@ export function isNumberLikeNaN(x: NumberLike): boolean {
|
|||
return isNaN(Number(x));
|
||||
}
|
||||
|
||||
export function nonEmptyArray(a: any): a is unknown[] {
|
||||
return Array.isArray(a) && Boolean(a.length);
|
||||
}
|
||||
|
||||
export function wait(ms: number): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
export function addFilter(filters: Filter[], id: string, value: string): Filter[] {
|
||||
return addFilterRaw(filters, id, `"${value}"`);
|
||||
}
|
||||
|
||||
export function addFilterRaw(filters: Filter[], id: string, value: string): Filter[] {
|
||||
const currentFilter = filters.find(f => f.id === id);
|
||||
if (currentFilter) {
|
||||
filters = filters.filter(f => f.id !== id);
|
||||
if (currentFilter.value !== value) {
|
||||
filters = filters.concat({ id, value });
|
||||
export function addOrUpdate<T>(xs: readonly T[], x: T, keyFn: (x: T) => string | number): T[] {
|
||||
const keyX = keyFn(x);
|
||||
let added = false;
|
||||
const newXs = xs.map(currentX => {
|
||||
if (keyFn(currentX) === keyX) {
|
||||
added = true;
|
||||
return x;
|
||||
} else {
|
||||
return currentX;
|
||||
}
|
||||
} else {
|
||||
filters = filters.concat({ id, value });
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
export function makeTextFilter(placeholder = ''): FilterRender {
|
||||
return function TextFilter({ filter, onChange, key }) {
|
||||
const filterValue = filter ? filter.value : '';
|
||||
return (
|
||||
<InputGroup
|
||||
key={key}
|
||||
onChange={(e: any) => onChange(e.target.value)}
|
||||
value={filterValue}
|
||||
rightElement={
|
||||
filterValue && <Button icon={IconNames.CROSS} minimal onClick={() => onChange('')} />
|
||||
}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function makeBooleanFilter(): FilterRender {
|
||||
return function BooleanFilter({ filter, onChange, key }) {
|
||||
const filterValue = filter ? filter.value : '';
|
||||
return (
|
||||
<HTMLSelect
|
||||
key={key}
|
||||
style={{ width: '100%' }}
|
||||
onChange={(event: any) => onChange(event.target.value)}
|
||||
value={filterValue || 'all'}
|
||||
fill
|
||||
>
|
||||
<option value="all">Show all</option>
|
||||
<option value="true">true</option>
|
||||
<option value="false">false</option>
|
||||
</HTMLSelect>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
||||
interface NeedleAndMode {
|
||||
needle: string;
|
||||
mode: 'exact' | 'includes';
|
||||
}
|
||||
|
||||
export function getNeedleAndMode(filter: Filter): NeedleAndMode {
|
||||
const input = filter.value;
|
||||
if (input.startsWith(`"`) && input.endsWith(`"`)) {
|
||||
return {
|
||||
needle: input.slice(1, -1),
|
||||
mode: 'exact',
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
needle: input.replace(/^"/, '').toLowerCase(),
|
||||
mode: 'includes',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function booleanCustomTableFilter(filter: Filter, value: any): boolean {
|
||||
if (value == null) return false;
|
||||
const needleAndMode: NeedleAndMode = getNeedleAndMode(filter);
|
||||
const needle = needleAndMode.needle;
|
||||
if (needleAndMode.mode === 'exact') {
|
||||
return needle === String(value);
|
||||
} else {
|
||||
return String(value).toLowerCase().includes(needle);
|
||||
}
|
||||
}
|
||||
|
||||
export function sqlQueryCustomTableFilter(filter: Filter): SqlExpression {
|
||||
const needleAndMode: NeedleAndMode = getNeedleAndMode(filter);
|
||||
const needle = needleAndMode.needle;
|
||||
if (needleAndMode.mode === 'exact') {
|
||||
return SqlRef.columnWithQuotes(filter.id).equal(SqlLiteral.create(needle));
|
||||
} else {
|
||||
return SqlFunction.simple('LOWER', [SqlRef.columnWithQuotes(filter.id)]).like(
|
||||
SqlLiteral.create(`%${needle}%`),
|
||||
);
|
||||
});
|
||||
if (!added) {
|
||||
newXs.push(x);
|
||||
}
|
||||
return newXs;
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
export * from './capabilities';
|
||||
export * from './column-metadata';
|
||||
export * from './data-type-utils';
|
||||
export * from './date';
|
||||
export * from './druid-lookup';
|
||||
export * from './druid-query';
|
||||
|
|
|
@ -185,18 +185,17 @@ export class QueryManager<Q, R, I = never, E extends Error = Error> {
|
|||
}
|
||||
|
||||
private trigger() {
|
||||
const currentlyLoading = Boolean(this.currentRunCancelFn);
|
||||
|
||||
this.setState(
|
||||
new QueryState<R, E>({
|
||||
loading: true,
|
||||
lastData: this.state.getSomeData(),
|
||||
}),
|
||||
);
|
||||
|
||||
if (currentlyLoading) {
|
||||
if (this.currentRunCancelFn) {
|
||||
// Currently loading
|
||||
this.runWhenLoading();
|
||||
} else {
|
||||
this.setState(
|
||||
new QueryState<R, E>({
|
||||
loading: true,
|
||||
lastData: this.state.getSomeData(),
|
||||
}),
|
||||
);
|
||||
|
||||
this.runWhenIdle();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,11 @@ $druid-brand: #2ceefb;
|
|||
$druid-brand2: #00b6bf;
|
||||
$druid-brand-background: #1c1c26;
|
||||
|
||||
// ReactTable related
|
||||
|
||||
$table-cell-v-padding: 10px;
|
||||
$table-cell-h-padding: 5px;
|
||||
|
||||
@mixin card-background {
|
||||
background: $white;
|
||||
border-radius: $pt-border-radius;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`DatasourcesView matches snapshot 1`] = `
|
||||
<div
|
||||
className="datasource-view app-view"
|
||||
className="datasources-view app-view"
|
||||
>
|
||||
<Memo(ViewControlBar)
|
||||
label="Datasources"
|
||||
|
@ -164,10 +164,11 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Availability",
|
||||
"accessor": "num_segments",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"minWidth": 200,
|
||||
"show": true,
|
||||
"sortMethod": [Function],
|
||||
"width": 220,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -177,9 +178,10 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
detail
|
||||
</React.Fragment>,
|
||||
"accessor": "num_segments_to_load",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"minWidth": 100,
|
||||
"show": true,
|
||||
"width": 180,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -189,6 +191,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
data size
|
||||
</React.Fragment>,
|
||||
"accessor": "total_data_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 100,
|
||||
|
@ -201,6 +204,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
minimum / average / maximum
|
||||
</React.Fragment>,
|
||||
"accessor": "avg_segment_rows",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 220,
|
||||
|
@ -213,6 +217,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
minimum / average / maximum
|
||||
</React.Fragment>,
|
||||
"accessor": "avg_segment_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": false,
|
||||
"width": 270,
|
||||
|
@ -225,6 +230,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
granularity
|
||||
</React.Fragment>,
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "segment_granularity",
|
||||
"show": false,
|
||||
|
@ -238,6 +244,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
rows
|
||||
</React.Fragment>,
|
||||
"accessor": "total_rows",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 100,
|
||||
|
@ -250,6 +257,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
(bytes)
|
||||
</React.Fragment>,
|
||||
"accessor": "avg_row_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 100,
|
||||
|
@ -262,6 +270,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
size
|
||||
</React.Fragment>,
|
||||
"accessor": "replicated_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 100,
|
||||
|
@ -283,6 +292,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
bytes / segments / intervals
|
||||
</React.Fragment>,
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "percentCompacted",
|
||||
"show": true,
|
||||
|
@ -296,6 +306,7 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
compacted
|
||||
</React.Fragment>,
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "leftToBeCompacted",
|
||||
"show": true,
|
||||
|
@ -307,8 +318,8 @@ exports[`DatasourcesView matches snapshot 1`] = `
|
|||
"accessor": [Function],
|
||||
"filterable": false,
|
||||
"id": "retention",
|
||||
"minWidth": 100,
|
||||
"show": true,
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
@import '../../variables';
|
||||
|
||||
.datasource-view {
|
||||
.datasources-view {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: auto;
|
|
@ -21,7 +21,7 @@ import React from 'react';
|
|||
|
||||
import { Capabilities } from '../../utils';
|
||||
|
||||
import { DatasourcesView } from './datasource-view';
|
||||
import { DatasourcesView } from './datasources-view';
|
||||
|
||||
describe('DatasourcesView', () => {
|
||||
it('matches snapshot', () => {
|
|
@ -28,11 +28,11 @@ import {
|
|||
ACTION_COLUMN_LABEL,
|
||||
ACTION_COLUMN_WIDTH,
|
||||
ActionCell,
|
||||
ActionIcon,
|
||||
BracedText,
|
||||
MoreButton,
|
||||
RefreshButton,
|
||||
SegmentTimeline,
|
||||
TableClickableCell,
|
||||
TableColumnSelector,
|
||||
ViewControlBar,
|
||||
} from '../../components';
|
||||
|
@ -44,9 +44,9 @@ import {
|
|||
formatCompactionConfigAndStatus,
|
||||
zeroCompactionStatus,
|
||||
} from '../../druid-models';
|
||||
import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { Api, AppToaster } from '../../singletons';
|
||||
import {
|
||||
addFilter,
|
||||
Capabilities,
|
||||
CapabilitiesMode,
|
||||
compact,
|
||||
|
@ -67,14 +67,12 @@ import {
|
|||
queryDruidSql,
|
||||
QueryManager,
|
||||
QueryState,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
twoLines,
|
||||
} from '../../utils';
|
||||
import { BasicAction } from '../../utils/basic-action';
|
||||
import { Rule, RuleUtil } from '../../utils/load-rule';
|
||||
|
||||
import './datasource-view.scss';
|
||||
import './datasources-view.scss';
|
||||
|
||||
const tableColumns: Record<CapabilitiesMode, string[]> = {
|
||||
'full': [
|
||||
|
@ -931,7 +929,7 @@ ORDER BY 1`;
|
|||
}
|
||||
}
|
||||
|
||||
renderRetentionDialog(): JSX.Element | undefined {
|
||||
private renderRetentionDialog(): JSX.Element | undefined {
|
||||
const { retentionDialogOpenOn, tiersState, datasourcesAndDefaultRulesState } = this.state;
|
||||
const { defaultRules } = datasourcesAndDefaultRulesState.data || {
|
||||
datasources: [],
|
||||
|
@ -952,7 +950,7 @@ ORDER BY 1`;
|
|||
);
|
||||
}
|
||||
|
||||
renderCompactionDialog() {
|
||||
private renderCompactionDialog() {
|
||||
const { datasourcesAndDefaultRulesState, compactionDialogOpenOn } = this.state;
|
||||
if (!compactionDialogOpenOn || !datasourcesAndDefaultRulesState.data) return;
|
||||
|
||||
|
@ -967,7 +965,16 @@ ORDER BY 1`;
|
|||
);
|
||||
}
|
||||
|
||||
renderDatasourceTable() {
|
||||
private onDetail(datasource: Datasource): void {
|
||||
const { unused, rules, compactionConfig } = datasource;
|
||||
|
||||
this.setState({
|
||||
datasourceTableActionDialogId: datasource.datasource,
|
||||
actions: this.getDatasourceActions(datasource.datasource, unused, rules, compactionConfig),
|
||||
});
|
||||
}
|
||||
|
||||
private renderDatasourcesTable() {
|
||||
const { goToSegments, capabilities } = this.props;
|
||||
const { datasourcesAndDefaultRulesState, datasourceFilter, showUnused, visibleColumns } =
|
||||
this.state;
|
||||
|
@ -1005,452 +1012,443 @@ ORDER BY 1`;
|
|||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ReactTable
|
||||
data={datasources}
|
||||
loading={datasourcesAndDefaultRulesState.loading}
|
||||
noDataText={
|
||||
datasourcesAndDefaultRulesState.getErrorMessage() ||
|
||||
(!datasourcesAndDefaultRulesState.loading && datasources && !datasources.length
|
||||
? 'No datasources'
|
||||
: '')
|
||||
}
|
||||
filterable
|
||||
filtered={datasourceFilter}
|
||||
onFilteredChange={filtered => {
|
||||
this.setState({ datasourceFilter: filtered });
|
||||
}}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={STANDARD_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={datasources.length > STANDARD_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: twoLines('Datasource', 'name'),
|
||||
show: visibleColumns.shown('Datasource name'),
|
||||
accessor: 'datasource',
|
||||
width: 150,
|
||||
Cell: ({ value }) => {
|
||||
<ReactTable
|
||||
data={datasources}
|
||||
loading={datasourcesAndDefaultRulesState.loading}
|
||||
noDataText={
|
||||
datasourcesAndDefaultRulesState.getErrorMessage() ||
|
||||
(!datasourcesAndDefaultRulesState.loading && datasources && !datasources.length
|
||||
? 'No datasources'
|
||||
: '')
|
||||
}
|
||||
filterable
|
||||
filtered={datasourceFilter}
|
||||
onFilteredChange={filtered => {
|
||||
this.setState({ datasourceFilter: filtered });
|
||||
}}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={STANDARD_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={datasources.length > STANDARD_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: twoLines('Datasource', 'name'),
|
||||
show: visibleColumns.shown('Datasource name'),
|
||||
accessor: 'datasource',
|
||||
width: 150,
|
||||
Cell: row => (
|
||||
<TableClickableCell
|
||||
onClick={() => this.onDetail(row.original)}
|
||||
hoverIcon={IconNames.SEARCH_TEMPLATE}
|
||||
>
|
||||
{row.value}
|
||||
</TableClickableCell>
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: 'Availability',
|
||||
show: visibleColumns.shown('Availability'),
|
||||
filterable: false,
|
||||
width: 220,
|
||||
accessor: 'num_segments',
|
||||
className: 'padded',
|
||||
Cell: ({ value: num_segments, original }) => {
|
||||
const { datasource, unused, num_segments_to_load } = original as Datasource;
|
||||
if (unused) {
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
datasourceFilter: addFilter(datasourceFilter, 'datasource', value),
|
||||
});
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Availability',
|
||||
show: visibleColumns.shown('Availability'),
|
||||
filterable: false,
|
||||
minWidth: 200,
|
||||
accessor: 'num_segments',
|
||||
Cell: ({ value: num_segments, original }) => {
|
||||
const { datasource, unused, num_segments_to_load } = original as Datasource;
|
||||
if (unused) {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.UNUSED_COLOR }}>● </span>
|
||||
Unused
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const segmentsEl = (
|
||||
<a onClick={() => goToSegments(datasource)}>
|
||||
{pluralIfNeeded(num_segments, 'segment')}
|
||||
</a>
|
||||
);
|
||||
if (typeof num_segments_to_load !== 'number' || typeof num_segments !== 'number') {
|
||||
return '-';
|
||||
} else if (num_segments_to_load === 0) {
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.FULLY_AVAILABLE_COLOR }}>
|
||||
●
|
||||
</span>
|
||||
Fully available ({segmentsEl})
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
const numAvailableSegments = num_segments - num_segments_to_load;
|
||||
const percentAvailable = (
|
||||
Math.floor((numAvailableSegments / num_segments) * 1000) / 10
|
||||
).toFixed(1);
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.PARTIALLY_AVAILABLE_COLOR }}>
|
||||
{numAvailableSegments ? '\u25cf' : '\u25cb'}
|
||||
</span>
|
||||
{percentAvailable}% available ({segmentsEl})
|
||||
</span>
|
||||
);
|
||||
}
|
||||
},
|
||||
sortMethod: (d1, d2) => {
|
||||
const percentAvailable1 = d1.num_available / d1.num_total;
|
||||
const percentAvailable2 = d2.num_available / d2.num_total;
|
||||
return percentAvailable1 - percentAvailable2 || d1.num_total - d2.num_total;
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Availability', 'detail'),
|
||||
show: visibleColumns.shown('Availability detail'),
|
||||
accessor: 'num_segments_to_load',
|
||||
filterable: false,
|
||||
minWidth: 100,
|
||||
Cell: ({ original }) => {
|
||||
const { num_segments_to_load, num_segments_to_drop } = original as Datasource;
|
||||
return formatLoadDrop(num_segments_to_load, num_segments_to_drop);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Total', 'data size'),
|
||||
show: visibleColumns.shown('Total data size'),
|
||||
accessor: 'total_data_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
Cell: ({ value }) => (
|
||||
<BracedText text={formatTotalDataSize(value)} braces={totalDataSizeValues} />
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment rows', 'minimum / average / maximum'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment rows'),
|
||||
accessor: 'avg_segment_rows',
|
||||
filterable: false,
|
||||
width: 220,
|
||||
Cell: ({ value, original }) => {
|
||||
const { min_segment_rows, max_segment_rows } = original as Datasource;
|
||||
if (
|
||||
isNumberLikeNaN(value) ||
|
||||
isNumberLikeNaN(min_segment_rows) ||
|
||||
isNumberLikeNaN(max_segment_rows)
|
||||
)
|
||||
return '-';
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatSegmentRows(min_segment_rows)}
|
||||
braces={minSegmentRowsValues}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText text={formatSegmentRows(value)} braces={avgSegmentRowsValues} />{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatSegmentRows(max_segment_rows)}
|
||||
braces={maxSegmentRowsValues}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment size', 'minimum / average / maximum'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment size'),
|
||||
accessor: 'avg_segment_size',
|
||||
filterable: false,
|
||||
width: 270,
|
||||
Cell: ({ value, original }) => {
|
||||
const { min_segment_size, max_segment_size } = original as Datasource;
|
||||
if (
|
||||
isNumberLikeNaN(value) ||
|
||||
isNumberLikeNaN(min_segment_size) ||
|
||||
isNumberLikeNaN(max_segment_size)
|
||||
)
|
||||
return '-';
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatSegmentSize(min_segment_size)}
|
||||
braces={minSegmentSizeValues}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText text={formatSegmentSize(value)} braces={avgSegmentSizeValues} />{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatSegmentSize(max_segment_size)}
|
||||
braces={maxSegmentSizeValues}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment', 'granularity'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment granularity'),
|
||||
id: 'segment_granularity',
|
||||
accessor: segmentGranularityCountsToRank,
|
||||
filterable: false,
|
||||
width: 100,
|
||||
Cell: ({ original }) => {
|
||||
const {
|
||||
num_segments,
|
||||
minute_aligned_segments,
|
||||
hour_aligned_segments,
|
||||
day_aligned_segments,
|
||||
month_aligned_segments,
|
||||
year_aligned_segments,
|
||||
all_granularity_segments,
|
||||
} = original as Datasource;
|
||||
const segmentGranularities: string[] = [];
|
||||
if (!num_segments || isNumberLikeNaN(year_aligned_segments)) return '-';
|
||||
if (all_granularity_segments) {
|
||||
segmentGranularities.push('All');
|
||||
}
|
||||
if (year_aligned_segments) {
|
||||
segmentGranularities.push('Year');
|
||||
}
|
||||
if (month_aligned_segments !== year_aligned_segments) {
|
||||
segmentGranularities.push('Month');
|
||||
}
|
||||
if (day_aligned_segments !== month_aligned_segments) {
|
||||
segmentGranularities.push('Day');
|
||||
}
|
||||
if (hour_aligned_segments !== day_aligned_segments) {
|
||||
segmentGranularities.push('Hour');
|
||||
}
|
||||
if (minute_aligned_segments !== hour_aligned_segments) {
|
||||
segmentGranularities.push('Minute');
|
||||
}
|
||||
if (
|
||||
Number(num_segments) - Number(all_granularity_segments) !==
|
||||
Number(minute_aligned_segments)
|
||||
) {
|
||||
segmentGranularities.push('Sub minute');
|
||||
}
|
||||
return segmentGranularities.join(', ');
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Total', 'rows'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Total rows'),
|
||||
accessor: 'total_rows',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText
|
||||
text={formatTotalRows(value)}
|
||||
braces={totalRowsValues}
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Avg. row size', '(bytes)'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Avg. row size'),
|
||||
accessor: 'avg_row_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText
|
||||
text={formatAvgRowSize(value)}
|
||||
braces={avgRowSizeValues}
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Replicated', 'size'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Replicated size'),
|
||||
accessor: 'replicated_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText text={formatReplicatedSize(value)} braces={replicatedSizeValues} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Compaction',
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('Compaction'),
|
||||
id: 'compactionStatus',
|
||||
accessor: row => Boolean(row.compactionStatus),
|
||||
filterable: false,
|
||||
width: 150,
|
||||
Cell: ({ original }) => {
|
||||
const { datasource, compactionConfig, compactionStatus } = original as Datasource;
|
||||
return (
|
||||
<span
|
||||
className="clickable-cell"
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
compactionDialogOpenOn: {
|
||||
datasource,
|
||||
compactionConfig,
|
||||
},
|
||||
})
|
||||
}
|
||||
>
|
||||
{formatCompactionConfigAndStatus(compactionConfig, compactionStatus)}
|
||||
<ActionIcon icon={IconNames.EDIT} />
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.UNUSED_COLOR }}>● </span>
|
||||
Unused
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('% Compacted', 'bytes / segments / intervals'),
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('% Compacted'),
|
||||
id: 'percentCompacted',
|
||||
width: 200,
|
||||
accessor: ({ compactionStatus }) =>
|
||||
compactionStatus && compactionStatus.bytesCompacted
|
||||
? compactionStatus.bytesCompacted /
|
||||
(compactionStatus.bytesAwaitingCompaction + compactionStatus.bytesCompacted)
|
||||
: 0,
|
||||
filterable: false,
|
||||
Cell: ({ original }) => {
|
||||
const { compactionStatus } = original as Datasource;
|
||||
|
||||
if (!compactionStatus || zeroCompactionStatus(compactionStatus)) {
|
||||
return (
|
||||
<>
|
||||
<BracedText text="-" braces={PERCENT_BRACES} /> {' '}
|
||||
<BracedText text="-" braces={PERCENT_BRACES} /> {' '}
|
||||
<BracedText text="-" braces={PERCENT_BRACES} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const segmentsEl = (
|
||||
<a onClick={() => goToSegments(datasource)}>
|
||||
{pluralIfNeeded(num_segments, 'segment')}
|
||||
</a>
|
||||
);
|
||||
if (typeof num_segments_to_load !== 'number' || typeof num_segments !== 'number') {
|
||||
return '-';
|
||||
} else if (num_segments_to_load === 0) {
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.bytesCompacted,
|
||||
compactionStatus.bytesAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.segmentCountCompacted,
|
||||
compactionStatus.segmentCountAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.intervalCountCompacted,
|
||||
compactionStatus.intervalCountAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Left to be', 'compacted'),
|
||||
show:
|
||||
capabilities.hasCoordinatorAccess() && visibleColumns.shown('Left to be compacted'),
|
||||
id: 'leftToBeCompacted',
|
||||
width: 100,
|
||||
accessor: ({ compactionStatus }) =>
|
||||
(compactionStatus && compactionStatus.bytesAwaitingCompaction) || 0,
|
||||
filterable: false,
|
||||
Cell: ({ original }) => {
|
||||
const { compactionStatus } = original as Datasource;
|
||||
|
||||
if (!compactionStatus) {
|
||||
return <BracedText text="-" braces={leftToBeCompactedValues} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<BracedText
|
||||
text={formatLeftToBeCompacted(compactionStatus.bytesAwaitingCompaction)}
|
||||
braces={leftToBeCompactedValues}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Retention',
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('Retention'),
|
||||
id: 'retention',
|
||||
accessor: row => row.rules.length,
|
||||
filterable: false,
|
||||
minWidth: 100,
|
||||
Cell: ({ original }) => {
|
||||
const { datasource, rules } = original as Datasource;
|
||||
return (
|
||||
<span
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
retentionDialogOpenOn: {
|
||||
datasource,
|
||||
rules,
|
||||
},
|
||||
})
|
||||
}
|
||||
className="clickable-cell"
|
||||
>
|
||||
{rules.length
|
||||
? DatasourcesView.formatRules(rules)
|
||||
: `Cluster default: ${DatasourcesView.formatRules(defaultRules)}`}
|
||||
|
||||
<ActionIcon icon={IconNames.EDIT} />
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.FULLY_AVAILABLE_COLOR }}>
|
||||
●
|
||||
</span>
|
||||
Fully available ({segmentsEl})
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
show: visibleColumns.shown(ACTION_COLUMN_LABEL),
|
||||
accessor: 'datasource',
|
||||
id: ACTION_COLUMN_ID,
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: ({ value: datasource, original }) => {
|
||||
const { unused, rules, compactionConfig } = original as Datasource;
|
||||
const datasourceActions = this.getDatasourceActions(
|
||||
datasource,
|
||||
unused,
|
||||
rules,
|
||||
compactionConfig,
|
||||
);
|
||||
} else {
|
||||
const numAvailableSegments = num_segments - num_segments_to_load;
|
||||
const percentAvailable = (
|
||||
Math.floor((numAvailableSegments / num_segments) * 1000) / 10
|
||||
).toFixed(1);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => {
|
||||
this.setState({
|
||||
datasourceTableActionDialogId: datasource,
|
||||
actions: datasourceActions,
|
||||
});
|
||||
}}
|
||||
actions={datasourceActions}
|
||||
/>
|
||||
<span>
|
||||
<span style={{ color: DatasourcesView.PARTIALLY_AVAILABLE_COLOR }}>
|
||||
{numAvailableSegments ? '\u25cf' : '\u25cb'}
|
||||
</span>
|
||||
{percentAvailable}% available ({segmentsEl})
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{this.renderUnuseAction()}
|
||||
{this.renderUseAction()}
|
||||
{this.renderUseUnuseActionByInterval()}
|
||||
{this.renderKillAction()}
|
||||
{this.renderRetentionDialog()}
|
||||
{this.renderCompactionDialog()}
|
||||
{this.renderForceCompactAction()}
|
||||
</>
|
||||
sortMethod: (d1, d2) => {
|
||||
const percentAvailable1 = d1.num_available / d1.num_total;
|
||||
const percentAvailable2 = d2.num_available / d2.num_total;
|
||||
return percentAvailable1 - percentAvailable2 || d1.num_total - d2.num_total;
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Availability', 'detail'),
|
||||
show: visibleColumns.shown('Availability detail'),
|
||||
accessor: 'num_segments_to_load',
|
||||
filterable: false,
|
||||
width: 180,
|
||||
className: 'padded',
|
||||
Cell: ({ original }) => {
|
||||
const { num_segments_to_load, num_segments_to_drop } = original as Datasource;
|
||||
return formatLoadDrop(num_segments_to_load, num_segments_to_drop);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Total', 'data size'),
|
||||
show: visibleColumns.shown('Total data size'),
|
||||
accessor: 'total_data_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ value }) => (
|
||||
<BracedText text={formatTotalDataSize(value)} braces={totalDataSizeValues} />
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment rows', 'minimum / average / maximum'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment rows'),
|
||||
accessor: 'avg_segment_rows',
|
||||
filterable: false,
|
||||
width: 220,
|
||||
className: 'padded',
|
||||
Cell: ({ value, original }) => {
|
||||
const { min_segment_rows, max_segment_rows } = original as Datasource;
|
||||
if (
|
||||
isNumberLikeNaN(value) ||
|
||||
isNumberLikeNaN(min_segment_rows) ||
|
||||
isNumberLikeNaN(max_segment_rows)
|
||||
)
|
||||
return '-';
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatSegmentRows(min_segment_rows)}
|
||||
braces={minSegmentRowsValues}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText text={formatSegmentRows(value)} braces={avgSegmentRowsValues} />{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatSegmentRows(max_segment_rows)}
|
||||
braces={maxSegmentRowsValues}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment size', 'minimum / average / maximum'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment size'),
|
||||
accessor: 'avg_segment_size',
|
||||
filterable: false,
|
||||
width: 270,
|
||||
className: 'padded',
|
||||
Cell: ({ value, original }) => {
|
||||
const { min_segment_size, max_segment_size } = original as Datasource;
|
||||
if (
|
||||
isNumberLikeNaN(value) ||
|
||||
isNumberLikeNaN(min_segment_size) ||
|
||||
isNumberLikeNaN(max_segment_size)
|
||||
)
|
||||
return '-';
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatSegmentSize(min_segment_size)}
|
||||
braces={minSegmentSizeValues}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText text={formatSegmentSize(value)} braces={avgSegmentSizeValues} />{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatSegmentSize(max_segment_size)}
|
||||
braces={maxSegmentSizeValues}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Segment', 'granularity'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Segment granularity'),
|
||||
id: 'segment_granularity',
|
||||
accessor: segmentGranularityCountsToRank,
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ original }) => {
|
||||
const {
|
||||
num_segments,
|
||||
minute_aligned_segments,
|
||||
hour_aligned_segments,
|
||||
day_aligned_segments,
|
||||
month_aligned_segments,
|
||||
year_aligned_segments,
|
||||
all_granularity_segments,
|
||||
} = original as Datasource;
|
||||
const segmentGranularities: string[] = [];
|
||||
if (!num_segments || isNumberLikeNaN(year_aligned_segments)) return '-';
|
||||
if (all_granularity_segments) {
|
||||
segmentGranularities.push('All');
|
||||
}
|
||||
if (year_aligned_segments) {
|
||||
segmentGranularities.push('Year');
|
||||
}
|
||||
if (month_aligned_segments !== year_aligned_segments) {
|
||||
segmentGranularities.push('Month');
|
||||
}
|
||||
if (day_aligned_segments !== month_aligned_segments) {
|
||||
segmentGranularities.push('Day');
|
||||
}
|
||||
if (hour_aligned_segments !== day_aligned_segments) {
|
||||
segmentGranularities.push('Hour');
|
||||
}
|
||||
if (minute_aligned_segments !== hour_aligned_segments) {
|
||||
segmentGranularities.push('Minute');
|
||||
}
|
||||
if (
|
||||
Number(num_segments) - Number(all_granularity_segments) !==
|
||||
Number(minute_aligned_segments)
|
||||
) {
|
||||
segmentGranularities.push('Sub minute');
|
||||
}
|
||||
return segmentGranularities.join(', ');
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Total', 'rows'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Total rows'),
|
||||
accessor: 'total_rows',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText
|
||||
text={formatTotalRows(value)}
|
||||
braces={totalRowsValues}
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Avg. row size', '(bytes)'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Avg. row size'),
|
||||
accessor: 'avg_row_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText
|
||||
text={formatAvgRowSize(value)}
|
||||
braces={avgRowSizeValues}
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Replicated', 'size'),
|
||||
show: capabilities.hasSql() && visibleColumns.shown('Replicated size'),
|
||||
accessor: 'replicated_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
<BracedText text={formatReplicatedSize(value)} braces={replicatedSizeValues} />
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Compaction',
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('Compaction'),
|
||||
id: 'compactionStatus',
|
||||
accessor: row => Boolean(row.compactionStatus),
|
||||
filterable: false,
|
||||
width: 150,
|
||||
Cell: ({ original }) => {
|
||||
const { datasource, compactionConfig, compactionStatus } = original as Datasource;
|
||||
return (
|
||||
<TableClickableCell
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
compactionDialogOpenOn: {
|
||||
datasource,
|
||||
compactionConfig,
|
||||
},
|
||||
})
|
||||
}
|
||||
hoverIcon={IconNames.EDIT}
|
||||
>
|
||||
{formatCompactionConfigAndStatus(compactionConfig, compactionStatus)}
|
||||
</TableClickableCell>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('% Compacted', 'bytes / segments / intervals'),
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('% Compacted'),
|
||||
id: 'percentCompacted',
|
||||
width: 200,
|
||||
accessor: ({ compactionStatus }) =>
|
||||
compactionStatus && compactionStatus.bytesCompacted
|
||||
? compactionStatus.bytesCompacted /
|
||||
(compactionStatus.bytesAwaitingCompaction + compactionStatus.bytesCompacted)
|
||||
: 0,
|
||||
filterable: false,
|
||||
className: 'padded',
|
||||
Cell: ({ original }) => {
|
||||
const { compactionStatus } = original as Datasource;
|
||||
|
||||
if (!compactionStatus || zeroCompactionStatus(compactionStatus)) {
|
||||
return (
|
||||
<>
|
||||
<BracedText text="-" braces={PERCENT_BRACES} /> {' '}
|
||||
<BracedText text="-" braces={PERCENT_BRACES} /> {' '}
|
||||
<BracedText text="-" braces={PERCENT_BRACES} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.bytesCompacted,
|
||||
compactionStatus.bytesAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.segmentCountCompacted,
|
||||
compactionStatus.segmentCountAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>{' '}
|
||||
{' '}
|
||||
<BracedText
|
||||
text={formatPercent(
|
||||
progress(
|
||||
compactionStatus.intervalCountCompacted,
|
||||
compactionStatus.intervalCountAwaitingCompaction,
|
||||
),
|
||||
)}
|
||||
braces={PERCENT_BRACES}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: twoLines('Left to be', 'compacted'),
|
||||
show:
|
||||
capabilities.hasCoordinatorAccess() && visibleColumns.shown('Left to be compacted'),
|
||||
id: 'leftToBeCompacted',
|
||||
width: 100,
|
||||
accessor: ({ compactionStatus }) =>
|
||||
(compactionStatus && compactionStatus.bytesAwaitingCompaction) || 0,
|
||||
filterable: false,
|
||||
className: 'padded',
|
||||
Cell: ({ original }) => {
|
||||
const { compactionStatus } = original as Datasource;
|
||||
|
||||
if (!compactionStatus) {
|
||||
return <BracedText text="-" braces={leftToBeCompactedValues} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<BracedText
|
||||
text={formatLeftToBeCompacted(compactionStatus.bytesAwaitingCompaction)}
|
||||
braces={leftToBeCompactedValues}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Retention',
|
||||
show: capabilities.hasCoordinatorAccess() && visibleColumns.shown('Retention'),
|
||||
id: 'retention',
|
||||
accessor: row => row.rules.length,
|
||||
filterable: false,
|
||||
width: 200,
|
||||
Cell: ({ original }) => {
|
||||
const { datasource, rules } = original as Datasource;
|
||||
return (
|
||||
<TableClickableCell
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
retentionDialogOpenOn: {
|
||||
datasource,
|
||||
rules,
|
||||
},
|
||||
})
|
||||
}
|
||||
hoverIcon={IconNames.EDIT}
|
||||
>
|
||||
{rules.length
|
||||
? DatasourcesView.formatRules(rules)
|
||||
: `Cluster default: ${DatasourcesView.formatRules(defaultRules)}`}
|
||||
</TableClickableCell>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
show: visibleColumns.shown(ACTION_COLUMN_LABEL),
|
||||
accessor: 'datasource',
|
||||
id: ACTION_COLUMN_ID,
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: ({ value: datasource, original }) => {
|
||||
const { unused, rules, compactionConfig } = original as Datasource;
|
||||
const datasourceActions = this.getDatasourceActions(
|
||||
datasource,
|
||||
unused,
|
||||
rules,
|
||||
compactionConfig,
|
||||
);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => {
|
||||
this.onDetail(original);
|
||||
}}
|
||||
actions={datasourceActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1466,7 +1464,7 @@ ORDER BY 1`;
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classNames('datasource-view app-view', {
|
||||
className={classNames('datasources-view app-view', {
|
||||
'show-segment-timeline': showSegmentTimeline,
|
||||
})}
|
||||
>
|
||||
|
@ -1505,7 +1503,7 @@ ORDER BY 1`;
|
|||
/>
|
||||
</ViewControlBar>
|
||||
{showSegmentTimeline && <SegmentTimeline capabilities={capabilities} />}
|
||||
{this.renderDatasourceTable()}
|
||||
{this.renderDatasourcesTable()}
|
||||
{datasourceTableActionDialogId && (
|
||||
<DatasourceTableActionDialog
|
||||
datasourceId={datasourceTableActionDialogId}
|
||||
|
@ -1513,6 +1511,13 @@ ORDER BY 1`;
|
|||
onClose={() => this.setState({ datasourceTableActionDialogId: undefined })}
|
||||
/>
|
||||
)}
|
||||
{this.renderUnuseAction()}
|
||||
{this.renderUseAction()}
|
||||
{this.renderUseUnuseActionByInterval()}
|
||||
{this.renderKillAction()}
|
||||
{this.renderRetentionDialog()}
|
||||
{this.renderCompactionDialog()}
|
||||
{this.renderForceCompactAction()}
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './datasource-view/datasource-view';
|
||||
export * from './datasources-view/datasources-view';
|
||||
export * from './home-view/home-view';
|
||||
export * from './ingestion-view/ingestion-view';
|
||||
export * from './load-data-view/load-data-view';
|
||||
|
|
|
@ -154,6 +154,7 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Datasource",
|
||||
"accessor": "supervisor_id",
|
||||
"id": "datasource",
|
||||
|
@ -161,21 +162,23 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Type",
|
||||
"accessor": [Function],
|
||||
"id": "type",
|
||||
"accessor": "type",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Topic/Stream",
|
||||
"accessor": [Function],
|
||||
"id": "source",
|
||||
"accessor": "source",
|
||||
"show": true,
|
||||
"width": 300,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Status",
|
||||
"accessor": [Function],
|
||||
"accessor": "detailed_state",
|
||||
"id": "status",
|
||||
"show": true,
|
||||
"width": 300,
|
||||
|
@ -426,10 +429,11 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Task ID",
|
||||
"accessor": "task_id",
|
||||
"show": true,
|
||||
"width": 500,
|
||||
"width": 440,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
|
@ -451,16 +455,19 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
"Header": "Datasource",
|
||||
"accessor": "datasource",
|
||||
"show": true,
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Location",
|
||||
"accessor": "location",
|
||||
"filterMethod": [Function],
|
||||
"show": true,
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Created time",
|
||||
"accessor": "created_time",
|
||||
"show": true,
|
||||
|
@ -470,6 +477,7 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Status",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterMethod": [Function],
|
||||
"id": "status",
|
||||
"show": true,
|
||||
|
@ -481,9 +489,10 @@ exports[`IngestionView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Duration",
|
||||
"accessor": "duration",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 70,
|
||||
"width": 80,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
|
|
|
@ -29,7 +29,9 @@ import {
|
|||
ActionCell,
|
||||
MoreButton,
|
||||
RefreshButton,
|
||||
TableClickableCell,
|
||||
TableColumnSelector,
|
||||
TableFilterableCell,
|
||||
ViewControlBar,
|
||||
} from '../../components';
|
||||
import {
|
||||
|
@ -38,11 +40,14 @@ import {
|
|||
SupervisorTableActionDialog,
|
||||
TaskTableActionDialog,
|
||||
} from '../../dialogs';
|
||||
import {
|
||||
booleanCustomTableFilter,
|
||||
SMALL_TABLE_PAGE_SIZE,
|
||||
SMALL_TABLE_PAGE_SIZE_OPTIONS,
|
||||
syncFilterClauseById,
|
||||
} from '../../react-table';
|
||||
import { Api, AppToaster } from '../../singletons';
|
||||
import {
|
||||
addFilter,
|
||||
addFilterRaw,
|
||||
booleanCustomTableFilter,
|
||||
Capabilities,
|
||||
deepGet,
|
||||
formatDuration,
|
||||
|
@ -56,8 +61,6 @@ import {
|
|||
queryDruidSql,
|
||||
QueryManager,
|
||||
QueryState,
|
||||
SMALL_TABLE_PAGE_SIZE,
|
||||
SMALL_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../utils';
|
||||
import { BasicAction } from '../../utils/basic-action';
|
||||
|
||||
|
@ -88,7 +91,7 @@ interface SupervisorQueryResultRow {
|
|||
source: string;
|
||||
state: string;
|
||||
detailed_state: string;
|
||||
suspended: number;
|
||||
suspended: boolean;
|
||||
}
|
||||
|
||||
interface TaskQueryResultRow {
|
||||
|
@ -196,7 +199,7 @@ export class IngestionView extends React.PureComponent<IngestionViewProps, Inges
|
|||
};
|
||||
|
||||
static SUPERVISOR_SQL = `SELECT
|
||||
"supervisor_id", "type", "source", "state", "detailed_state", "suspended"
|
||||
"supervisor_id", "type", "source", "state", "detailed_state", "suspended" = 1 AS "suspended"
|
||||
FROM sys.supervisors
|
||||
ORDER BY "supervisor_id"`;
|
||||
|
||||
|
@ -266,7 +269,7 @@ ORDER BY "rank" DESC, "created_time" DESC`;
|
|||
'n/a',
|
||||
state: deepGet(sup, 'state'),
|
||||
detailed_state: deepGet(sup, 'detailedState'),
|
||||
suspended: Number(deepGet(sup, 'suspended')),
|
||||
suspended: Boolean(deepGet(sup, 'suspended')),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
|
@ -552,100 +555,129 @@ ORDER BY "rank" DESC, "created_time" DESC`;
|
|||
);
|
||||
}
|
||||
|
||||
renderSupervisorTable() {
|
||||
private renderSupervisorFilterableCell(field: string) {
|
||||
const { supervisorFilter } = this.state;
|
||||
|
||||
return (row: { value: any }) => (
|
||||
<TableFilterableCell
|
||||
field={field}
|
||||
value={row.value}
|
||||
filters={supervisorFilter}
|
||||
onFiltersChange={filters => this.setState({ supervisorFilter: filters })}
|
||||
>
|
||||
{row.value}
|
||||
</TableFilterableCell>
|
||||
);
|
||||
}
|
||||
|
||||
private onSupervisorDetail(supervisor: SupervisorQueryResultRow) {
|
||||
this.setState({
|
||||
supervisorTableActionDialogId: supervisor.supervisor_id,
|
||||
supervisorTableActionDialogActions: this.getSupervisorActions(
|
||||
supervisor.supervisor_id,
|
||||
supervisor.suspended,
|
||||
supervisor.type,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
private renderSupervisorTable() {
|
||||
const { supervisorsState, hiddenSupervisorColumns, taskFilter, supervisorFilter } = this.state;
|
||||
|
||||
const supervisors = supervisorsState.data || [];
|
||||
return (
|
||||
<>
|
||||
<ReactTable
|
||||
data={supervisors}
|
||||
loading={supervisorsState.loading}
|
||||
noDataText={
|
||||
supervisorsState.isEmpty() ? 'No supervisors' : supervisorsState.getErrorMessage() || ''
|
||||
}
|
||||
filtered={supervisorFilter}
|
||||
onFilteredChange={filtered => {
|
||||
const datasourceFilter = filtered.find(filter => filter.id === 'datasource');
|
||||
let newTaskFilter = taskFilter.filter(filter => filter.id !== 'datasource');
|
||||
if (datasourceFilter) {
|
||||
newTaskFilter = addFilterRaw(
|
||||
newTaskFilter,
|
||||
datasourceFilter.id,
|
||||
datasourceFilter.value,
|
||||
);
|
||||
}
|
||||
this.setState({ supervisorFilter: filtered, taskFilter: newTaskFilter });
|
||||
}}
|
||||
filterable
|
||||
defaultPageSize={SMALL_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={supervisors.length > SMALL_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Datasource',
|
||||
id: 'datasource',
|
||||
accessor: 'supervisor_id',
|
||||
width: 300,
|
||||
show: hiddenSupervisorColumns.shown('Datasource'),
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
id: 'type',
|
||||
accessor: row => row.type,
|
||||
show: hiddenSupervisorColumns.shown('Type'),
|
||||
},
|
||||
{
|
||||
Header: 'Topic/Stream',
|
||||
id: 'source',
|
||||
accessor: row => row.source,
|
||||
show: hiddenSupervisorColumns.shown('Topic/Stream'),
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
id: 'status',
|
||||
width: 300,
|
||||
accessor: row => row.detailed_state,
|
||||
Cell: row => (
|
||||
<ReactTable
|
||||
data={supervisors}
|
||||
loading={supervisorsState.loading}
|
||||
noDataText={
|
||||
supervisorsState.isEmpty() ? 'No supervisors' : supervisorsState.getErrorMessage() || ''
|
||||
}
|
||||
filtered={supervisorFilter}
|
||||
onFilteredChange={(filtered, column) => {
|
||||
this.setState({
|
||||
supervisorFilter: filtered,
|
||||
taskFilter:
|
||||
column.id === 'datasource'
|
||||
? syncFilterClauseById(taskFilter, filtered, 'datasource')
|
||||
: taskFilter,
|
||||
});
|
||||
}}
|
||||
filterable
|
||||
defaultPageSize={SMALL_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={supervisors.length > SMALL_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Datasource',
|
||||
id: 'datasource',
|
||||
accessor: 'supervisor_id',
|
||||
width: 300,
|
||||
show: hiddenSupervisorColumns.shown('Datasource'),
|
||||
Cell: ({ value, original }) => (
|
||||
<TableClickableCell
|
||||
onClick={() => this.onSupervisorDetail(original)}
|
||||
hoverIcon={IconNames.EDIT}
|
||||
>
|
||||
{value}
|
||||
</TableClickableCell>
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
accessor: 'type',
|
||||
width: 100,
|
||||
Cell: this.renderSupervisorFilterableCell('type'),
|
||||
show: hiddenSupervisorColumns.shown('Type'),
|
||||
},
|
||||
{
|
||||
Header: 'Topic/Stream',
|
||||
accessor: 'source',
|
||||
width: 300,
|
||||
Cell: this.renderSupervisorFilterableCell('source'),
|
||||
show: hiddenSupervisorColumns.shown('Topic/Stream'),
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
id: 'status',
|
||||
width: 300,
|
||||
accessor: 'detailed_state',
|
||||
Cell: row => (
|
||||
<TableFilterableCell
|
||||
field="status"
|
||||
value={row.value}
|
||||
filters={supervisorFilter}
|
||||
onFiltersChange={filters => this.setState({ supervisorFilter: filters })}
|
||||
>
|
||||
<span>
|
||||
<span style={{ color: stateToColor(row.original.state) }}>● </span>
|
||||
{row.value}
|
||||
</span>
|
||||
),
|
||||
show: hiddenSupervisorColumns.shown('Status'),
|
||||
</TableFilterableCell>
|
||||
),
|
||||
show: hiddenSupervisorColumns.shown('Status'),
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
id: ACTION_COLUMN_ID,
|
||||
accessor: 'supervisor_id',
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: row => {
|
||||
const id = row.value;
|
||||
const type = row.original.type;
|
||||
const supervisorSuspended = row.original.suspended;
|
||||
const supervisorActions = this.getSupervisorActions(id, supervisorSuspended, type);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => this.onSupervisorDetail(row.original)}
|
||||
actions={supervisorActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
id: ACTION_COLUMN_ID,
|
||||
accessor: 'supervisor_id',
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: row => {
|
||||
const id = row.value;
|
||||
const type = row.original.type;
|
||||
const supervisorSuspended = row.original.suspended;
|
||||
const supervisorActions = this.getSupervisorActions(id, supervisorSuspended, type);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() =>
|
||||
this.setState({
|
||||
supervisorTableActionDialogId: id,
|
||||
supervisorTableActionDialogActions: supervisorActions,
|
||||
})
|
||||
}
|
||||
actions={supervisorActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
show: hiddenSupervisorColumns.shown(ACTION_COLUMN_LABEL),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{this.renderResumeSupervisorAction()}
|
||||
{this.renderSuspendSupervisorAction()}
|
||||
{this.renderResetSupervisorAction()}
|
||||
{this.renderTerminateSupervisorAction()}
|
||||
</>
|
||||
show: hiddenSupervisorColumns.shown(ACTION_COLUMN_LABEL),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -712,208 +744,198 @@ ORDER BY "rank" DESC, "created_time" DESC`;
|
|||
);
|
||||
}
|
||||
|
||||
renderTaskTable() {
|
||||
private renderTaskFilterableCell(field: string) {
|
||||
const { taskFilter } = this.state;
|
||||
|
||||
return (row: { value: any }) => (
|
||||
<TableFilterableCell
|
||||
field={field}
|
||||
value={row.value}
|
||||
filters={taskFilter}
|
||||
onFiltersChange={filters => this.setState({ taskFilter: filters })}
|
||||
>
|
||||
{row.value}
|
||||
</TableFilterableCell>
|
||||
);
|
||||
}
|
||||
|
||||
private onTaskDetail(task: TaskQueryResultRow) {
|
||||
this.setState({
|
||||
taskTableActionDialogId: task.task_id,
|
||||
taskTableActionDialogStatus: task.status,
|
||||
taskTableActionDialogActions: this.getTaskActions(
|
||||
task.task_id,
|
||||
task.datasource,
|
||||
task.status,
|
||||
task.type,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
private renderTaskTable() {
|
||||
const { tasksState, taskFilter, groupTasksBy, hiddenTaskColumns, supervisorFilter } =
|
||||
this.state;
|
||||
|
||||
const tasks = tasksState.data || [];
|
||||
return (
|
||||
<>
|
||||
<ReactTable
|
||||
data={tasks}
|
||||
loading={tasksState.loading}
|
||||
noDataText={tasksState.isEmpty() ? 'No tasks' : tasksState.getErrorMessage() || ''}
|
||||
filterable
|
||||
filtered={taskFilter}
|
||||
onFilteredChange={filtered => {
|
||||
const datasourceFilter = filtered.find(filter => filter.id === 'datasource');
|
||||
let newSupervisorFilter = supervisorFilter.filter(filter => filter.id !== 'datasource');
|
||||
if (datasourceFilter) {
|
||||
newSupervisorFilter = addFilterRaw(
|
||||
newSupervisorFilter,
|
||||
datasourceFilter.id,
|
||||
datasourceFilter.value,
|
||||
<ReactTable
|
||||
data={tasks}
|
||||
loading={tasksState.loading}
|
||||
noDataText={tasksState.isEmpty() ? 'No tasks' : tasksState.getErrorMessage() || ''}
|
||||
filterable
|
||||
filtered={taskFilter}
|
||||
onFilteredChange={(filtered, column) => {
|
||||
this.setState({
|
||||
supervisorFilter:
|
||||
column.id === 'datasource'
|
||||
? syncFilterClauseById(supervisorFilter, filtered, 'datasource')
|
||||
: supervisorFilter,
|
||||
taskFilter: filtered,
|
||||
});
|
||||
}}
|
||||
defaultSorted={[{ id: 'status', desc: true }]}
|
||||
pivotBy={groupTasksBy ? [groupTasksBy] : []}
|
||||
defaultPageSize={SMALL_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={tasks.length > SMALL_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Task ID',
|
||||
accessor: 'task_id',
|
||||
width: 440,
|
||||
Cell: ({ value, original }) => (
|
||||
<TableClickableCell
|
||||
onClick={() => this.onTaskDetail(original)}
|
||||
hoverIcon={IconNames.EDIT}
|
||||
>
|
||||
{value}
|
||||
</TableClickableCell>
|
||||
),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Task ID'),
|
||||
},
|
||||
{
|
||||
Header: 'Group ID',
|
||||
accessor: 'group_id',
|
||||
width: 300,
|
||||
Cell: this.renderTaskFilterableCell('group_id'),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Group ID'),
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
accessor: 'type',
|
||||
width: 140,
|
||||
Cell: this.renderTaskFilterableCell('type'),
|
||||
show: hiddenTaskColumns.shown('Type'),
|
||||
},
|
||||
{
|
||||
Header: 'Datasource',
|
||||
accessor: 'datasource',
|
||||
width: 200,
|
||||
Cell: this.renderTaskFilterableCell('datasource'),
|
||||
show: hiddenTaskColumns.shown('Datasource'),
|
||||
},
|
||||
{
|
||||
Header: 'Location',
|
||||
accessor: 'location',
|
||||
width: 200,
|
||||
Cell: this.renderTaskFilterableCell('location'),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Location'),
|
||||
},
|
||||
{
|
||||
Header: 'Created time',
|
||||
accessor: 'created_time',
|
||||
width: 190,
|
||||
Cell: this.renderTaskFilterableCell('created_time'),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Created time'),
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
id: 'status',
|
||||
width: 110,
|
||||
className: 'padded',
|
||||
accessor: row => ({
|
||||
status: row.status,
|
||||
created_time: row.created_time,
|
||||
toString: () => row.status,
|
||||
}),
|
||||
Cell: row => {
|
||||
if (row.aggregated) return '';
|
||||
const { status } = row.original;
|
||||
const errorMsg = row.original.error_msg;
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: statusToColor(status) }}>● </span>
|
||||
{status}
|
||||
{errorMsg && (
|
||||
<a onClick={() => this.setState({ alertErrorMsg: errorMsg })} title={errorMsg}>
|
||||
?
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
this.setState({ supervisorFilter: newSupervisorFilter, taskFilter: filtered });
|
||||
}}
|
||||
defaultSorted={[{ id: 'status', desc: true }]}
|
||||
pivotBy={groupTasksBy ? [groupTasksBy] : []}
|
||||
defaultPageSize={SMALL_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={tasks.length > SMALL_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Task ID',
|
||||
accessor: 'task_id',
|
||||
width: 500,
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Task ID'),
|
||||
},
|
||||
{
|
||||
Header: 'Group ID',
|
||||
accessor: 'group_id',
|
||||
width: 300,
|
||||
Aggregated: () => '',
|
||||
Cell: row => {
|
||||
const value = row.value;
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({ taskFilter: addFilter(taskFilter, 'group_id', value) });
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
show: hiddenTaskColumns.shown('Group ID'),
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
accessor: 'type',
|
||||
width: 140,
|
||||
Cell: row => {
|
||||
const value = row.value;
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({ taskFilter: addFilter(taskFilter, 'type', value) });
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
show: hiddenTaskColumns.shown('Type'),
|
||||
},
|
||||
{
|
||||
Header: 'Datasource',
|
||||
accessor: 'datasource',
|
||||
Cell: row => {
|
||||
const value = row.value;
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({ taskFilter: addFilter(taskFilter, 'datasource', value) });
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
show: hiddenTaskColumns.shown('Datasource'),
|
||||
},
|
||||
sortMethod: (d1, d2) => {
|
||||
const typeofD1 = typeof d1;
|
||||
const typeofD2 = typeof d2;
|
||||
if (typeofD1 !== typeofD2) return 0;
|
||||
switch (typeofD1) {
|
||||
case 'string':
|
||||
return IngestionView.statusRanking[d1] - IngestionView.statusRanking[d2];
|
||||
|
||||
{
|
||||
Header: 'Location',
|
||||
accessor: 'location',
|
||||
Aggregated: () => '',
|
||||
filterMethod: (filter: Filter, row: any) => {
|
||||
return booleanCustomTableFilter(filter, row.location);
|
||||
},
|
||||
show: hiddenTaskColumns.shown('Location'),
|
||||
},
|
||||
{
|
||||
Header: 'Created time',
|
||||
accessor: 'created_time',
|
||||
width: 190,
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Created time'),
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
id: 'status',
|
||||
width: 110,
|
||||
accessor: row => ({
|
||||
status: row.status,
|
||||
created_time: row.created_time,
|
||||
toString: () => row.status,
|
||||
}),
|
||||
Cell: row => {
|
||||
if (row.aggregated) return '';
|
||||
const { status } = row.original;
|
||||
const errorMsg = row.original.error_msg;
|
||||
return (
|
||||
<span>
|
||||
<span style={{ color: statusToColor(status) }}>● </span>
|
||||
{status}
|
||||
{errorMsg && (
|
||||
<a
|
||||
onClick={() => this.setState({ alertErrorMsg: errorMsg })}
|
||||
title={errorMsg}
|
||||
>
|
||||
?
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
sortMethod: (d1, d2) => {
|
||||
const typeofD1 = typeof d1;
|
||||
const typeofD2 = typeof d2;
|
||||
if (typeofD1 !== typeofD2) return 0;
|
||||
switch (typeofD1) {
|
||||
case 'string':
|
||||
return IngestionView.statusRanking[d1] - IngestionView.statusRanking[d2];
|
||||
case 'object':
|
||||
return (
|
||||
IngestionView.statusRanking[d1.status] -
|
||||
IngestionView.statusRanking[d2.status] ||
|
||||
d1.created_time.localeCompare(d2.created_time)
|
||||
);
|
||||
|
||||
case 'object':
|
||||
return (
|
||||
IngestionView.statusRanking[d1.status] -
|
||||
IngestionView.statusRanking[d2.status] ||
|
||||
d1.created_time.localeCompare(d2.created_time)
|
||||
);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
filterMethod: (filter: Filter, row: any) => {
|
||||
return booleanCustomTableFilter(filter, row.status.status);
|
||||
},
|
||||
show: hiddenTaskColumns.shown('Status'),
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
{
|
||||
Header: 'Duration',
|
||||
accessor: 'duration',
|
||||
width: 70,
|
||||
filterable: false,
|
||||
Cell: row => (row.value > 0 ? formatDuration(row.value) : ''),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Duration'),
|
||||
filterMethod: (filter: Filter, row: any) => {
|
||||
return booleanCustomTableFilter(filter, row.status.status);
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
id: ACTION_COLUMN_ID,
|
||||
accessor: 'task_id',
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: row => {
|
||||
if (row.aggregated) return '';
|
||||
const id = row.value;
|
||||
const type = row.row.type;
|
||||
const { datasource, status } = row.original;
|
||||
const taskActions = this.getTaskActions(id, datasource, status, type);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() =>
|
||||
this.setState({
|
||||
taskTableActionDialogId: id,
|
||||
taskTableActionDialogStatus: status,
|
||||
taskTableActionDialogActions: taskActions,
|
||||
})
|
||||
}
|
||||
actions={taskActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown(ACTION_COLUMN_LABEL),
|
||||
show: hiddenTaskColumns.shown('Status'),
|
||||
},
|
||||
{
|
||||
Header: 'Duration',
|
||||
accessor: 'duration',
|
||||
width: 80,
|
||||
filterable: false,
|
||||
className: 'padded',
|
||||
Cell: row => (row.value > 0 ? formatDuration(row.value) : ''),
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown('Duration'),
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
id: ACTION_COLUMN_ID,
|
||||
accessor: 'task_id',
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: row => {
|
||||
if (row.aggregated) return '';
|
||||
const id = row.value;
|
||||
const type = row.row.type;
|
||||
const { datasource, status } = row.original;
|
||||
const taskActions = this.getTaskActions(id, datasource, status, type);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => this.onTaskDetail(row.original)}
|
||||
actions={taskActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{this.renderKillTaskAction()}
|
||||
</>
|
||||
Aggregated: () => '',
|
||||
show: hiddenTaskColumns.shown(ACTION_COLUMN_LABEL),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1164,6 +1186,11 @@ ORDER BY "rank" DESC, "created_time" DESC`;
|
|||
{this.renderTaskTable()}
|
||||
</div>
|
||||
</SplitterLayout>
|
||||
{this.renderResumeSupervisorAction()}
|
||||
{this.renderSuspendSupervisorAction()}
|
||||
{this.renderResetSupervisorAction()}
|
||||
{this.renderTerminateSupervisorAction()}
|
||||
{this.renderKillTaskAction()}
|
||||
{supervisorSpecDialogOpen && (
|
||||
<SpecDialog
|
||||
onClose={this.closeSpecDialogs}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`FilterTable matches snapshot 1`] = `
|
||||
<div
|
||||
class="ReactTable filter-table -striped -highlight"
|
||||
class="ReactTable filter-table -striped -highlight padded-header"
|
||||
>
|
||||
<div
|
||||
class="rt-table"
|
||||
|
@ -10,7 +10,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
>
|
||||
<div
|
||||
class="rt-thead -header"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr"
|
||||
|
@ -19,7 +19,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-th rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
|
@ -49,7 +49,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="rt-tbody"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr-group"
|
||||
|
@ -62,13 +62,13 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="table-cell plain"
|
||||
>
|
||||
hello
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,7 +83,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -102,7 +102,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -121,7 +121,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -140,7 +140,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -159,7 +159,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -178,7 +178,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -197,7 +197,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -216,7 +216,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -235,7 +235,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -254,7 +254,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -273,7 +273,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -292,7 +292,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -311,7 +311,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -330,7 +330,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -349,7 +349,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -368,7 +368,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -387,7 +387,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -406,7 +406,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -425,7 +425,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -444,7 +444,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -463,7 +463,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -482,7 +482,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -501,7 +501,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -520,7 +520,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -539,7 +539,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -558,7 +558,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -577,7 +577,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -596,7 +596,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -615,7 +615,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -634,7 +634,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -653,7 +653,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -672,7 +672,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -691,7 +691,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -710,7 +710,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -729,7 +729,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -748,7 +748,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -767,7 +767,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -786,7 +786,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -805,7 +805,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -824,7 +824,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -843,7 +843,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -862,7 +862,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -881,7 +881,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -900,7 +900,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -919,7 +919,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -938,7 +938,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -957,7 +957,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -976,7 +976,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -995,7 +995,7 @@ exports[`FilterTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ import ReactTable from 'react-table';
|
|||
import { TableCell } from '../../../components';
|
||||
import { DruidFilter, getFilterDimension } from '../../../druid-models';
|
||||
import {
|
||||
caseInsensitiveContains,
|
||||
filterMap,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../../utils';
|
||||
} from '../../../react-table';
|
||||
import { caseInsensitiveContains, filterMap } from '../../../utils';
|
||||
import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
|
||||
|
||||
import './filter-table.scss';
|
||||
|
@ -55,7 +55,7 @@ export const FilterTable = React.memo(function FilterTable(props: FilterTablePro
|
|||
|
||||
return (
|
||||
<ReactTable
|
||||
className="filter-table -striped -highlight"
|
||||
className={classNames('filter-table', DEFAULT_TABLE_CLASS_NAME)}
|
||||
data={sampleData.rows}
|
||||
sortable={false}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
|
@ -96,6 +96,7 @@ export const FilterTable = React.memo(function FilterTable(props: FilterTablePro
|
|||
className: columnClassName,
|
||||
id: String(i),
|
||||
accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
|
||||
width: 140,
|
||||
Cell: function FilterTableCell(row) {
|
||||
return <TableCell value={timestamp ? new Date(row.value) : row.value} />;
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`ParseDataTable matches snapshot 1`] = `
|
||||
<div
|
||||
class="ReactTable parse-data-table -striped -highlight"
|
||||
class="ReactTable parse-data-table -striped -highlight padded-header"
|
||||
>
|
||||
<div
|
||||
class="rt-table"
|
||||
|
@ -10,7 +10,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
>
|
||||
<div
|
||||
class="rt-thead -header"
|
||||
style="min-width: 135px;"
|
||||
style="min-width: 175px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr"
|
||||
|
@ -29,7 +29,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-th rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
|
@ -59,7 +59,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="rt-tbody"
|
||||
style="min-width: 135px;"
|
||||
style="min-width: 175px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr-group"
|
||||
|
@ -83,13 +83,13 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="table-cell plain"
|
||||
>
|
||||
hello
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -113,7 +113,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -141,7 +141,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -169,7 +169,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -197,7 +197,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -225,7 +225,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -253,7 +253,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -281,7 +281,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -309,7 +309,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -337,7 +337,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -365,7 +365,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -393,7 +393,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -421,7 +421,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -449,7 +449,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -477,7 +477,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -505,7 +505,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -533,7 +533,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -561,7 +561,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -589,7 +589,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -617,7 +617,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -645,7 +645,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -673,7 +673,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -701,7 +701,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -729,7 +729,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -757,7 +757,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -785,7 +785,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -813,7 +813,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -841,7 +841,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -869,7 +869,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -897,7 +897,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -925,7 +925,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -953,7 +953,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -981,7 +981,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1009,7 +1009,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1037,7 +1037,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1065,7 +1065,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1093,7 +1093,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1149,7 +1149,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1177,7 +1177,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1205,7 +1205,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1233,7 +1233,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1261,7 +1261,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1289,7 +1289,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1317,7 +1317,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1345,7 +1345,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1373,7 +1373,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1401,7 +1401,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1429,7 +1429,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -1457,7 +1457,7 @@ exports[`ParseDataTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ import { TableCell } from '../../../components';
|
|||
import { TableCellUnparseable } from '../../../components/table-cell-unparseable/table-cell-unparseable';
|
||||
import { FlattenField } from '../../../druid-models';
|
||||
import {
|
||||
caseInsensitiveContains,
|
||||
filterMap,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../../utils';
|
||||
} from '../../../react-table';
|
||||
import { caseInsensitiveContains, filterMap } from '../../../utils';
|
||||
import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
|
||||
|
||||
import './parse-data-table.scss';
|
||||
|
@ -58,7 +58,7 @@ export const ParseDataTable = React.memo(function ParseDataTable(props: ParseDat
|
|||
const key = useInput ? 'input' : 'parsed';
|
||||
return (
|
||||
<ReactTable
|
||||
className="parse-data-table -striped -highlight"
|
||||
className={classNames('parse-data-table', DEFAULT_TABLE_CLASS_NAME)}
|
||||
data={sampleData.rows}
|
||||
sortable={false}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
|
@ -86,6 +86,7 @@ export const ParseDataTable = React.memo(function ParseDataTable(props: ParseDat
|
|||
),
|
||||
id: String(i),
|
||||
accessor: (row: SampleEntry) => (row[key] ? row[key]![columnName] : null),
|
||||
width: 140,
|
||||
Cell: function ParseDataTableCell(row) {
|
||||
if (row.original.unparseable) {
|
||||
return <TableCellUnparseable />;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`ParseTimeTable matches snapshot 1`] = `
|
||||
<div
|
||||
class="ReactTable parse-time-table -striped -highlight"
|
||||
class="ReactTable parse-time-table -striped -highlight padded-header"
|
||||
>
|
||||
<div
|
||||
class="rt-table"
|
||||
|
@ -10,7 +10,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
>
|
||||
<div
|
||||
class="rt-thead -header"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr"
|
||||
|
@ -19,7 +19,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-th rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
|
@ -49,7 +49,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="rt-tbody"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr-group"
|
||||
|
@ -62,13 +62,13 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="table-cell plain"
|
||||
>
|
||||
hello
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,7 +83,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -102,7 +102,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -121,7 +121,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -140,7 +140,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -159,7 +159,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -178,7 +178,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -197,7 +197,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -216,7 +216,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -235,7 +235,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -254,7 +254,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -273,7 +273,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -292,7 +292,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -311,7 +311,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -330,7 +330,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -349,7 +349,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -368,7 +368,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -387,7 +387,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -406,7 +406,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -425,7 +425,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -444,7 +444,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -463,7 +463,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -482,7 +482,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -501,7 +501,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -520,7 +520,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -539,7 +539,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -558,7 +558,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -577,7 +577,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -596,7 +596,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -615,7 +615,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -634,7 +634,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -653,7 +653,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -672,7 +672,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -691,7 +691,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -710,7 +710,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -729,7 +729,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -748,7 +748,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -767,7 +767,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -786,7 +786,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -805,7 +805,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -824,7 +824,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -843,7 +843,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -862,7 +862,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -881,7 +881,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -900,7 +900,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -919,7 +919,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -938,7 +938,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -957,7 +957,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -976,7 +976,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -995,7 +995,7 @@ exports[`ParseTimeTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ import {
|
|||
TimestampSpec,
|
||||
} from '../../../druid-models';
|
||||
import {
|
||||
caseInsensitiveContains,
|
||||
filterMap,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../../utils';
|
||||
} from '../../../react-table';
|
||||
import { caseInsensitiveContains, filterMap } from '../../../utils';
|
||||
import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
|
||||
|
||||
import './parse-time-table.scss';
|
||||
|
@ -74,7 +74,7 @@ export const ParseTimeTable = React.memo(function ParseTimeTable(props: ParseTim
|
|||
|
||||
return (
|
||||
<ReactTable
|
||||
className="parse-time-table -striped -highlight"
|
||||
className={classNames('parse-time-table', DEFAULT_TABLE_CLASS_NAME)}
|
||||
data={headerAndRows.rows}
|
||||
sortable={false}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
|
@ -133,7 +133,7 @@ export const ParseTimeTable = React.memo(function ParseTimeTable(props: ParseTim
|
|||
}
|
||||
return <TableCell value={isTimestamp ? new Date(row.value) : row.value} />;
|
||||
},
|
||||
minWidth: isTimestamp ? 200 : 100,
|
||||
width: isTimestamp ? 200 : 140,
|
||||
resizable: !isTimestamp,
|
||||
};
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`SchemaTable matches snapshot 1`] = `
|
||||
<div
|
||||
class="ReactTable schema-table -striped -highlight"
|
||||
class="ReactTable schema-table -striped -highlight padded-header"
|
||||
>
|
||||
<div
|
||||
class="rt-table"
|
||||
|
@ -10,7 +10,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
>
|
||||
<div
|
||||
class="rt-thead -header"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr"
|
||||
|
@ -19,7 +19,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-th dimension string rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
|
@ -49,7 +49,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="rt-tbody"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr-group"
|
||||
|
@ -62,13 +62,13 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="table-cell plain"
|
||||
>
|
||||
hello
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,7 +83,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -102,7 +102,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -121,7 +121,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -140,7 +140,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -159,7 +159,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -178,7 +178,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -197,7 +197,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -216,7 +216,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -235,7 +235,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -254,7 +254,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -273,7 +273,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -292,7 +292,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -311,7 +311,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -330,7 +330,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -349,7 +349,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -368,7 +368,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -387,7 +387,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -406,7 +406,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -425,7 +425,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -444,7 +444,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -463,7 +463,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -482,7 +482,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -501,7 +501,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -520,7 +520,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -539,7 +539,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -558,7 +558,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -577,7 +577,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -596,7 +596,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -615,7 +615,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -634,7 +634,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -653,7 +653,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -672,7 +672,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -691,7 +691,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -710,7 +710,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -729,7 +729,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -748,7 +748,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -767,7 +767,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -786,7 +786,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -805,7 +805,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -824,7 +824,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -843,7 +843,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -862,7 +862,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -881,7 +881,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -900,7 +900,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -919,7 +919,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -938,7 +938,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -957,7 +957,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -976,7 +976,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -995,7 +995,7 @@ exports[`SchemaTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td dimension string"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px; max-width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ import {
|
|||
MetricSpec,
|
||||
} from '../../../druid-models';
|
||||
import {
|
||||
caseInsensitiveContains,
|
||||
filterMap,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../../utils';
|
||||
} from '../../../react-table';
|
||||
import { caseInsensitiveContains, filterMap } from '../../../utils';
|
||||
import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
|
||||
|
||||
import './schema-table.scss';
|
||||
|
@ -69,7 +69,7 @@ export const SchemaTable = React.memo(function SchemaTable(props: SchemaTablePro
|
|||
|
||||
return (
|
||||
<ReactTable
|
||||
className="schema-table -striped -highlight"
|
||||
className={classNames('schema-table', DEFAULT_TABLE_CLASS_NAME)}
|
||||
data={headerAndRows.rows}
|
||||
sortable={false}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
|
@ -101,6 +101,7 @@ export const SchemaTable = React.memo(function SchemaTable(props: SchemaTablePro
|
|||
className: columnClassName,
|
||||
id: String(i),
|
||||
accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
|
||||
width: 120,
|
||||
Cell: function SchemaTableCell({ value }) {
|
||||
return <TableCell value={value} />;
|
||||
},
|
||||
|
@ -145,7 +146,7 @@ export const SchemaTable = React.memo(function SchemaTable(props: SchemaTablePro
|
|||
headerClassName: columnClassName,
|
||||
className: columnClassName,
|
||||
id: String(i),
|
||||
width: isTimestamp ? 200 : 100,
|
||||
width: isTimestamp ? 200 : 140,
|
||||
accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
|
||||
Cell: function SchemaTableCell(row) {
|
||||
return <TableCell value={isTimestamp ? new Date(row.value) : row.value} />;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`TransformTable matches snapshot 1`] = `
|
||||
<div
|
||||
class="ReactTable transform-table -striped -highlight"
|
||||
class="ReactTable transform-table -striped -highlight padded-header"
|
||||
>
|
||||
<div
|
||||
class="rt-table"
|
||||
|
@ -10,7 +10,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
>
|
||||
<div
|
||||
class="rt-thead -header"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr"
|
||||
|
@ -19,7 +19,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-th rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
|
@ -49,7 +49,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
</div>
|
||||
<div
|
||||
class="rt-tbody"
|
||||
style="min-width: 100px;"
|
||||
style="min-width: 140px;"
|
||||
>
|
||||
<div
|
||||
class="rt-tr-group"
|
||||
|
@ -62,13 +62,13 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
class="table-cell plain"
|
||||
>
|
||||
hello
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,7 +83,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -102,7 +102,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -121,7 +121,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -140,7 +140,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -159,7 +159,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -178,7 +178,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -197,7 +197,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -216,7 +216,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -235,7 +235,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -254,7 +254,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -273,7 +273,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -292,7 +292,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -311,7 +311,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -330,7 +330,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -349,7 +349,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -368,7 +368,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -387,7 +387,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -406,7 +406,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -425,7 +425,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -444,7 +444,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -463,7 +463,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -482,7 +482,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -501,7 +501,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -520,7 +520,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -539,7 +539,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -558,7 +558,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -577,7 +577,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -596,7 +596,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -615,7 +615,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -634,7 +634,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -653,7 +653,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -672,7 +672,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -691,7 +691,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -710,7 +710,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -729,7 +729,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -748,7 +748,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -767,7 +767,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -786,7 +786,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -805,7 +805,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -824,7 +824,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -843,7 +843,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -862,7 +862,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -881,7 +881,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -900,7 +900,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -919,7 +919,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -938,7 +938,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -957,7 +957,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -976,7 +976,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
@ -995,7 +995,7 @@ exports[`TransformTable matches snapshot 1`] = `
|
|||
<div
|
||||
class="rt-td"
|
||||
role="gridcell"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
style="flex: 140 0 auto; width: 140px; max-width: 140px;"
|
||||
>
|
||||
<span>
|
||||
|
||||
|
|
|
@ -23,11 +23,11 @@ import ReactTable from 'react-table';
|
|||
import { TableCell } from '../../../components';
|
||||
import { Transform } from '../../../druid-models';
|
||||
import {
|
||||
caseInsensitiveContains,
|
||||
filterMap,
|
||||
DEFAULT_TABLE_CLASS_NAME,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../../utils';
|
||||
} from '../../../react-table';
|
||||
import { caseInsensitiveContains, filterMap } from '../../../utils';
|
||||
import { escapeColumnName } from '../../../utils/druid-expression';
|
||||
import { SampleEntry, SampleHeaderAndRows } from '../../../utils/sampler';
|
||||
|
||||
|
@ -64,7 +64,7 @@ export const TransformTable = React.memo(function TransformTable(props: Transfor
|
|||
|
||||
return (
|
||||
<ReactTable
|
||||
className="transform-table -striped -highlight"
|
||||
className={classNames('transform-table', DEFAULT_TABLE_CLASS_NAME)}
|
||||
data={sampleData.rows}
|
||||
sortable={false}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
|
@ -110,6 +110,7 @@ export const TransformTable = React.memo(function TransformTable(props: Transfor
|
|||
className: columnClassName,
|
||||
id: String(i),
|
||||
accessor: (row: SampleEntry) => (row.parsed ? row.parsed[columnName] : null),
|
||||
width: 140,
|
||||
Cell: function TransformTableCell(row) {
|
||||
return <TableCell value={timestamp ? new Date(row.value) : row.value} />;
|
||||
},
|
||||
|
|
|
@ -90,6 +90,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Lookup name",
|
||||
"accessor": "id",
|
||||
"filterable": true,
|
||||
|
@ -98,6 +99,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Lookup tier",
|
||||
"accessor": "tier",
|
||||
"filterable": true,
|
||||
|
@ -106,6 +108,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Type",
|
||||
"accessor": "spec.type",
|
||||
"filterable": true,
|
||||
|
@ -114,6 +117,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
"width": 150,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Version",
|
||||
"accessor": "version",
|
||||
"filterable": true,
|
||||
|
@ -125,15 +129,18 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Poll period",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "poolPeriod",
|
||||
"show": true,
|
||||
"width": 150,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Summary",
|
||||
"accessor": [Function],
|
||||
"id": "summary",
|
||||
"show": true,
|
||||
"width": 600,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -172,6 +179,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
filterable={true}
|
||||
filtered={Array []}
|
||||
freezeWhenExpanded={false}
|
||||
getLoadingProps={[Function]}
|
||||
getNoDataProps={[Function]}
|
||||
|
@ -205,6 +213,7 @@ exports[`LookupsView matches snapshot 1`] = `
|
|||
noDataText=""
|
||||
ofText="of"
|
||||
onFetchData={[Function]}
|
||||
onFilteredChange={[Function]}
|
||||
originalKey="_original"
|
||||
pageJumpText="jump to page"
|
||||
pageSizeOptions={
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { Button, Icon, Intent } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import ReactTable, { Filter } from 'react-table';
|
||||
|
||||
import {
|
||||
ACTION_COLUMN_ID,
|
||||
|
@ -27,12 +27,15 @@ import {
|
|||
ACTION_COLUMN_WIDTH,
|
||||
ActionCell,
|
||||
RefreshButton,
|
||||
TableClickableCell,
|
||||
TableColumnSelector,
|
||||
TableFilterableCell,
|
||||
ViewControlBar,
|
||||
} from '../../components';
|
||||
import { AsyncActionDialog, LookupEditDialog } from '../../dialogs/';
|
||||
import { LookupTableActionDialog } from '../../dialogs/lookup-table-action-dialog/lookup-table-action-dialog';
|
||||
import { LookupSpec, lookupSpecSummary } from '../../druid-models';
|
||||
import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { Api, AppToaster } from '../../singletons';
|
||||
import {
|
||||
deepGet,
|
||||
|
@ -43,8 +46,6 @@ import {
|
|||
LocalStorageKeys,
|
||||
QueryManager,
|
||||
QueryState,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../utils';
|
||||
import { BasicAction } from '../../utils/basic-action';
|
||||
|
||||
|
@ -89,6 +90,7 @@ export interface LookupsViewProps {}
|
|||
|
||||
export interface LookupsViewState {
|
||||
lookupEntriesAndTiersState: QueryState<LookupEntriesAndTiers>;
|
||||
lookupFilter: Filter[];
|
||||
|
||||
lookupEdit?: LookupEditInfo;
|
||||
isEdit: boolean;
|
||||
|
@ -109,6 +111,7 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
|
|||
super(props);
|
||||
this.state = {
|
||||
lookupEntriesAndTiersState: QueryState.INIT,
|
||||
lookupFilter: [],
|
||||
isEdit: false,
|
||||
actions: [],
|
||||
|
||||
|
@ -276,7 +279,7 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
|
|||
];
|
||||
}
|
||||
|
||||
renderDeleteLookupAction() {
|
||||
private renderDeleteLookupAction() {
|
||||
const { deleteLookupTier, deleteLookupName } = this.state;
|
||||
if (!deleteLookupTier || !deleteLookupName) return;
|
||||
|
||||
|
@ -305,8 +308,32 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
|
|||
);
|
||||
}
|
||||
|
||||
renderLookupsTable() {
|
||||
const { lookupEntriesAndTiersState, visibleColumns } = this.state;
|
||||
private onDetail(lookup: LookupEntry): void {
|
||||
const lookupId = lookup.id;
|
||||
const lookupTier = lookup.tier;
|
||||
this.setState({
|
||||
lookupTableActionDialogId: lookupId,
|
||||
actions: this.getLookupActions(lookupTier, lookupId),
|
||||
});
|
||||
}
|
||||
|
||||
private renderFilterableCell(field: string) {
|
||||
const { lookupFilter } = this.state;
|
||||
|
||||
return (row: { value: any }) => (
|
||||
<TableFilterableCell
|
||||
field={field}
|
||||
value={row.value}
|
||||
filters={lookupFilter}
|
||||
onFiltersChange={filters => this.setState({ lookupFilter: filters })}
|
||||
>
|
||||
{row.value}
|
||||
</TableFilterableCell>
|
||||
);
|
||||
}
|
||||
|
||||
private renderLookupsTable() {
|
||||
const { lookupEntriesAndTiersState, lookupFilter, visibleColumns } = this.state;
|
||||
const lookupEntriesAndTiers = lookupEntriesAndTiersState.data;
|
||||
const lookups = lookupEntriesAndTiers ? lookupEntriesAndTiers.lookupEntries : [];
|
||||
|
||||
|
@ -323,106 +350,119 @@ export class LookupsView extends React.PureComponent<LookupsViewProps, LookupsVi
|
|||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ReactTable
|
||||
data={lookups}
|
||||
loading={lookupEntriesAndTiersState.loading}
|
||||
noDataText={
|
||||
!lookupEntriesAndTiersState.loading && !lookups.length
|
||||
? 'No lookups'
|
||||
: lookupEntriesAndTiersState.getErrorMessage() || ''
|
||||
}
|
||||
filterable
|
||||
defaultSorted={[{ id: 'lookup_name', desc: false }]}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={STANDARD_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={lookups.length > STANDARD_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Lookup name',
|
||||
show: visibleColumns.shown('Lookup name'),
|
||||
id: 'lookup_name',
|
||||
accessor: 'id',
|
||||
filterable: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
Header: 'Lookup tier',
|
||||
show: visibleColumns.shown('Lookup tier'),
|
||||
id: 'tier',
|
||||
accessor: 'tier',
|
||||
filterable: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
show: visibleColumns.shown('Type'),
|
||||
id: 'type',
|
||||
accessor: 'spec.type',
|
||||
filterable: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
Header: 'Version',
|
||||
show: visibleColumns.shown('Version'),
|
||||
id: 'version',
|
||||
accessor: 'version',
|
||||
filterable: true,
|
||||
width: 190,
|
||||
},
|
||||
{
|
||||
Header: 'Poll period',
|
||||
show: visibleColumns.shown('Poll period'),
|
||||
id: 'poolPeriod',
|
||||
width: 150,
|
||||
accessor: row => deepGet(row, 'spec.extractionNamespace.pollPeriod'),
|
||||
Cell: ({ original }) => {
|
||||
if (original.spec.type === 'map') return 'Static map';
|
||||
const pollPeriod = deepGet(original, 'spec.extractionNamespace.pollPeriod');
|
||||
if (!pollPeriod) {
|
||||
return (
|
||||
<>
|
||||
<Icon icon={IconNames.WARNING_SIGN} intent={Intent.WARNING} /> No poll period
|
||||
set
|
||||
</>
|
||||
);
|
||||
}
|
||||
return pollPeriod;
|
||||
},
|
||||
},
|
||||
{
|
||||
Header: 'Summary',
|
||||
show: visibleColumns.shown('Summary'),
|
||||
id: 'summary',
|
||||
accessor: row => lookupSpecSummary(row.spec),
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
show: visibleColumns.shown(ACTION_COLUMN_LABEL),
|
||||
id: ACTION_COLUMN_ID,
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
accessor: 'id',
|
||||
Cell: ({ original }) => {
|
||||
const lookupId = original.id;
|
||||
const lookupTier = original.tier;
|
||||
const lookupActions = this.getLookupActions(lookupTier, lookupId);
|
||||
<ReactTable
|
||||
data={lookups}
|
||||
loading={lookupEntriesAndTiersState.loading}
|
||||
noDataText={
|
||||
!lookupEntriesAndTiersState.loading && !lookups.length
|
||||
? 'No lookups'
|
||||
: lookupEntriesAndTiersState.getErrorMessage() || ''
|
||||
}
|
||||
filterable
|
||||
filtered={lookupFilter}
|
||||
onFilteredChange={filtered => {
|
||||
this.setState({ lookupFilter: filtered });
|
||||
}}
|
||||
defaultSorted={[{ id: 'lookup_name', desc: false }]}
|
||||
defaultPageSize={STANDARD_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={STANDARD_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={lookups.length > STANDARD_TABLE_PAGE_SIZE}
|
||||
columns={[
|
||||
{
|
||||
Header: 'Lookup name',
|
||||
show: visibleColumns.shown('Lookup name'),
|
||||
id: 'lookup_name',
|
||||
accessor: 'id',
|
||||
filterable: true,
|
||||
width: 200,
|
||||
Cell: ({ value, original }) => (
|
||||
<TableClickableCell
|
||||
onClick={() => this.onDetail(original)}
|
||||
hoverIcon={IconNames.SEARCH_TEMPLATE}
|
||||
>
|
||||
{value}
|
||||
</TableClickableCell>
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: 'Lookup tier',
|
||||
show: visibleColumns.shown('Lookup tier'),
|
||||
id: 'tier',
|
||||
accessor: 'tier',
|
||||
filterable: true,
|
||||
width: 100,
|
||||
Cell: this.renderFilterableCell('tier'),
|
||||
},
|
||||
{
|
||||
Header: 'Type',
|
||||
show: visibleColumns.shown('Type'),
|
||||
id: 'type',
|
||||
accessor: 'spec.type',
|
||||
filterable: true,
|
||||
width: 150,
|
||||
Cell: this.renderFilterableCell('type'),
|
||||
},
|
||||
{
|
||||
Header: 'Version',
|
||||
show: visibleColumns.shown('Version'),
|
||||
id: 'version',
|
||||
accessor: 'version',
|
||||
filterable: true,
|
||||
width: 190,
|
||||
Cell: this.renderFilterableCell('version'),
|
||||
},
|
||||
{
|
||||
Header: 'Poll period',
|
||||
show: visibleColumns.shown('Poll period'),
|
||||
id: 'poolPeriod',
|
||||
width: 150,
|
||||
className: 'padded',
|
||||
accessor: row => deepGet(row, 'spec.extractionNamespace.pollPeriod'),
|
||||
Cell: ({ original }) => {
|
||||
if (original.spec.type === 'map') return 'Static map';
|
||||
const pollPeriod = deepGet(original, 'spec.extractionNamespace.pollPeriod');
|
||||
if (!pollPeriod) {
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => {
|
||||
this.setState({
|
||||
lookupTableActionDialogId: lookupId,
|
||||
actions: lookupActions,
|
||||
});
|
||||
}}
|
||||
actions={lookupActions}
|
||||
/>
|
||||
<>
|
||||
<Icon icon={IconNames.WARNING_SIGN} intent={Intent.WARNING} /> No poll period
|
||||
set
|
||||
</>
|
||||
);
|
||||
},
|
||||
}
|
||||
return pollPeriod;
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
Header: 'Summary',
|
||||
show: visibleColumns.shown('Summary'),
|
||||
id: 'summary',
|
||||
accessor: row => lookupSpecSummary(row.spec),
|
||||
width: 600,
|
||||
Cell: this.renderFilterableCell('summary'),
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
show: visibleColumns.shown(ACTION_COLUMN_LABEL),
|
||||
id: ACTION_COLUMN_ID,
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
accessor: 'id',
|
||||
Cell: ({ original }) => {
|
||||
const lookupId = original.id;
|
||||
const lookupTier = original.tier;
|
||||
const lookupActions = this.getLookupActions(lookupTier, lookupId);
|
||||
return (
|
||||
<ActionCell
|
||||
onDetail={() => {
|
||||
this.onDetail(original);
|
||||
}}
|
||||
actions={lookupActions}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import React, { ChangeEvent } from 'react';
|
|||
import { Loader } from '../../../components';
|
||||
import { Deferred } from '../../../components/deferred/deferred';
|
||||
import { ColumnMetadata, copyAndAlert, groupBy, oneOf, prettyPrintSql } from '../../../utils';
|
||||
import { dataTypeToIcon } from '../query-utils';
|
||||
import { dataTypeToIcon } from '../../../utils/data-type-utils';
|
||||
|
||||
import { NumberMenuItems, StringMenuItems, TimeMenuItems } from './column-tree-menu';
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,11 +20,6 @@
|
|||
@import '../../../blueprint-overrides/common/colors';
|
||||
|
||||
.query-output {
|
||||
&.more-results .-totalPages {
|
||||
// Hide the total page counter as it can be confusing due to the auto limit
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ReactTable {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
@ -65,8 +60,10 @@
|
|||
}
|
||||
|
||||
.clickable-cell {
|
||||
padding: $table-cell-v-padding $table-cell-h-padding;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.#{$bp-ns}-popover2-target {
|
||||
|
|
|
@ -26,16 +26,16 @@ import ReactTable from 'react-table';
|
|||
|
||||
import { BracedText, Deferred, TableCell } from '../../../components';
|
||||
import { ShowValueDialog } from '../../../dialogs/show-value-dialog/show-value-dialog';
|
||||
import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from '../../../react-table';
|
||||
import {
|
||||
changePage,
|
||||
copyAndAlert,
|
||||
dataTypeToColumnWidth,
|
||||
formatNumber,
|
||||
getNumericColumnBraces,
|
||||
Pagination,
|
||||
prettyPrintSql,
|
||||
QueryAction,
|
||||
SMALL_TABLE_PAGE_SIZE,
|
||||
SMALL_TABLE_PAGE_SIZE_OPTIONS,
|
||||
stringifyValue,
|
||||
} from '../../../utils';
|
||||
import { BasicAction, basicActionsToMenu } from '../../../utils/basic-action';
|
||||
|
@ -270,12 +270,12 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
<>
|
||||
{isComparable(value) && (
|
||||
<>
|
||||
{filterOnMenuItem(IconNames.FILTER_KEEP, ex.greaterThanOrEqual(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER_KEEP, ex.lessThanOrEqual(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER, ex.greaterThanOrEqual(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER, ex.lessThanOrEqual(val), having)}
|
||||
</>
|
||||
)}
|
||||
{filterOnMenuItem(IconNames.FILTER_KEEP, ex.equal(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER_REMOVE, ex.unequal(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER, ex.equal(val), having)}
|
||||
{filterOnMenuItem(IconNames.FILTER, ex.unequal(val), having)}
|
||||
</>
|
||||
)}
|
||||
{showFullValueMenuItem}
|
||||
|
@ -351,14 +351,15 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
return (
|
||||
<div className={classNames('query-output', { 'more-results': hasMoreResults })}>
|
||||
<ReactTable
|
||||
className="-striped -highlight"
|
||||
data={queryResult.rows as any[][]}
|
||||
ofText={hasMoreResults ? '' : 'of'}
|
||||
noDataText={queryResult.rows.length ? '' : 'Query returned no data'}
|
||||
page={pagination.page}
|
||||
pageSize={pagination.pageSize}
|
||||
onPageChange={page => changePagination(changePage(pagination, page))}
|
||||
onPageSizeChange={(pageSize, page) => changePagination({ page, pageSize })}
|
||||
sortable={false}
|
||||
ofText={hasMoreResults ? '' : 'of'}
|
||||
defaultPageSize={SMALL_TABLE_PAGE_SIZE}
|
||||
pageSizeOptions={SMALL_TABLE_PAGE_SIZE_OPTIONS}
|
||||
showPagination={
|
||||
|
@ -366,17 +367,16 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
}
|
||||
columns={queryResult.header.map((column, i) => {
|
||||
const h = column.name;
|
||||
const effectiveType = column.isTimeColumn() ? column.sqlType : column.nativeType;
|
||||
|
||||
return {
|
||||
Header:
|
||||
i === renamingColumn && parsedQuery
|
||||
? () => <ColumnRenameInput initialName={h} onDone={renameColumnTo} />
|
||||
: () => {
|
||||
return (
|
||||
<Popover2
|
||||
className="clickable-cell"
|
||||
content={<Deferred content={() => getHeaderMenu(h, i)} />}
|
||||
>
|
||||
<div>
|
||||
<Popover2 content={<Deferred content={() => getHeaderMenu(h, i)} />}>
|
||||
<div className="clickable-cell">
|
||||
{h}
|
||||
{hasFilterOnHeader(h, i) && (
|
||||
<Icon icon={IconNames.FILTER} iconSize={14} />
|
||||
|
@ -386,24 +386,24 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
);
|
||||
},
|
||||
headerClassName: getHeaderClassName(h, i),
|
||||
width: dataTypeToColumnWidth(effectiveType),
|
||||
accessor: String(i),
|
||||
Cell(row) {
|
||||
const value = row.value;
|
||||
return (
|
||||
<div>
|
||||
<Popover2 content={<Deferred content={() => getCellMenu(h, i, value)} />}>
|
||||
{numericColumnBraces[i] ? (
|
||||
<BracedText
|
||||
text={formatNumber(value)}
|
||||
braces={numericColumnBraces[i]}
|
||||
padFractionalPart
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
) : (
|
||||
<TableCell value={value} unlimited />
|
||||
)}
|
||||
</Popover2>
|
||||
</div>
|
||||
<Popover2 content={<Deferred content={() => getCellMenu(h, i, value)} />}>
|
||||
{numericColumnBraces[i] ? (
|
||||
<BracedText
|
||||
className="table-padding"
|
||||
text={formatNumber(value)}
|
||||
braces={numericColumnBraces[i]}
|
||||
padFractionalPart
|
||||
unselectableThousandsSeparator
|
||||
/>
|
||||
) : (
|
||||
<TableCell value={value} unlimited />
|
||||
)}
|
||||
</Popover2>
|
||||
);
|
||||
},
|
||||
className:
|
||||
|
|
|
@ -138,18 +138,20 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Segment ID",
|
||||
"accessor": "segment_id",
|
||||
"filterable": true,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
"width": 300,
|
||||
"width": 280,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Datasource",
|
||||
"accessor": "datasource",
|
||||
"show": true,
|
||||
"width": 140,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -169,7 +171,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
"filterable": true,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
"width": 120,
|
||||
"width": 160,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -179,16 +181,17 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
"filterable": true,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
"width": 120,
|
||||
"width": 160,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Version",
|
||||
"accessor": "version",
|
||||
"defaultSortDesc": true,
|
||||
"filterable": true,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
"width": 120,
|
||||
"width": 160,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -203,6 +206,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Shard type",
|
||||
"accessor": [Function],
|
||||
"headerClassName": "disable-comparisons",
|
||||
"id": "shard_type",
|
||||
"show": true,
|
||||
"sortable": false,
|
||||
|
@ -221,6 +225,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
Object {
|
||||
"Header": "Partition",
|
||||
"accessor": "partition_num",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
|
@ -230,18 +235,22 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Size",
|
||||
"accessor": "size",
|
||||
"className": "padded",
|
||||
"defaultSortDesc": true,
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"sortable": true,
|
||||
"width": 120,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
"Header": "Num rows",
|
||||
"accessor": "num_rows",
|
||||
"className": "padded",
|
||||
"defaultSortDesc": true,
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 120,
|
||||
},
|
||||
Object {
|
||||
"Cell": [Function],
|
||||
|
@ -251,6 +260,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
(bytes)
|
||||
</React.Fragment>,
|
||||
"accessor": "avg_row_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
"width": 100,
|
||||
|
@ -258,6 +268,7 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
Object {
|
||||
"Header": "Replicas",
|
||||
"accessor": "num_replicas",
|
||||
"className": "padded",
|
||||
"defaultSortDesc": true,
|
||||
"filterable": false,
|
||||
"show": true,
|
||||
|
@ -267,29 +278,37 @@ exports[`SegmentsView matches snapshot 1`] = `
|
|||
"Filter": [Function],
|
||||
"Header": "Is published",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "is_published",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Filter": [Function],
|
||||
"Header": "Is realtime",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "is_realtime",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Filter": [Function],
|
||||
"Header": "Is available",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "is_available",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Filter": [Function],
|
||||
"Header": "Is overshadowed",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"id": "is_overshadowed",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
|
|
|
@ -33,16 +33,24 @@ import {
|
|||
MoreButton,
|
||||
RefreshButton,
|
||||
SegmentTimeline,
|
||||
TableClickableCell,
|
||||
TableColumnSelector,
|
||||
TableFilterableCell,
|
||||
ViewControlBar,
|
||||
} from '../../components';
|
||||
import { AsyncActionDialog } from '../../dialogs';
|
||||
import { SegmentTableActionDialog } from '../../dialogs/segments-table-action-dialog/segment-table-action-dialog';
|
||||
import { ShowValueDialog } from '../../dialogs/show-value-dialog/show-value-dialog';
|
||||
import {
|
||||
booleanCustomTableFilter,
|
||||
BooleanFilterInput,
|
||||
parseFilterModeAndNeedle,
|
||||
sqlQueryCustomTableFilter,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../react-table';
|
||||
import { Api } from '../../singletons';
|
||||
import {
|
||||
addFilter,
|
||||
booleanCustomTableFilter,
|
||||
Capabilities,
|
||||
CapabilitiesMode,
|
||||
compact,
|
||||
|
@ -50,19 +58,14 @@ import {
|
|||
filterMap,
|
||||
formatBytes,
|
||||
formatInteger,
|
||||
getNeedleAndMode,
|
||||
hasPopoverOpen,
|
||||
isNumberLikeNaN,
|
||||
LocalStorageBackedVisibility,
|
||||
LocalStorageKeys,
|
||||
makeBooleanFilter,
|
||||
NumberLike,
|
||||
queryDruidSql,
|
||||
QueryManager,
|
||||
QueryState,
|
||||
sqlQueryCustomTableFilter,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
twoLines,
|
||||
} from '../../utils';
|
||||
import { BasicAction } from '../../utils/basic-action';
|
||||
|
@ -275,12 +278,19 @@ END AS "time_span"`,
|
|||
if (f.id === 'shard_type') {
|
||||
// Special handling for shard_type that needs to be search in the shard_spec
|
||||
// Creates filters like `shard_spec LIKE '%"type":"numbered"%'`
|
||||
const needleAndMode = getNeedleAndMode(f);
|
||||
const closingQuote = needleAndMode.mode === 'exact' ? '"' : '';
|
||||
return SqlComparison.like(
|
||||
SqlRef.column('shard_spec'),
|
||||
`%"type":"${needleAndMode.needle}${closingQuote}%`,
|
||||
);
|
||||
const modeAndNeedle = parseFilterModeAndNeedle(f);
|
||||
if (!modeAndNeedle) return;
|
||||
const shardSpecRef = SqlRef.column('shard_spec');
|
||||
switch (modeAndNeedle.mode) {
|
||||
case '=':
|
||||
return SqlComparison.like(shardSpecRef, `%"type":"${modeAndNeedle.needle}"%`);
|
||||
|
||||
case '!=':
|
||||
return SqlComparison.notLike(shardSpecRef, `%"type":"${modeAndNeedle.needle}"%`);
|
||||
|
||||
default:
|
||||
return SqlComparison.like(shardSpecRef, `%"type":"${modeAndNeedle.needle}%`);
|
||||
}
|
||||
} else if (f.id.startsWith('is_')) {
|
||||
if (f.value === 'all') return;
|
||||
return SqlRef.columnWithQuotes(f.id).equal(f.value === 'true' ? 1 : 0);
|
||||
|
@ -466,6 +476,30 @@ END AS "time_span"`,
|
|||
return actions;
|
||||
}
|
||||
|
||||
private onDetail(segmentId: string, datasource: string): void {
|
||||
this.setState({
|
||||
segmentTableActionDialogId: segmentId,
|
||||
datasourceTableActionDialogId: datasource,
|
||||
actions: this.getSegmentActions(segmentId, datasource),
|
||||
});
|
||||
}
|
||||
|
||||
private renderFilterableCell(field: string, disableComparisons = false) {
|
||||
const { segmentFilter } = this.state;
|
||||
|
||||
return (row: { value: any }) => (
|
||||
<TableFilterableCell
|
||||
field={field}
|
||||
value={row.value}
|
||||
filters={segmentFilter}
|
||||
onFiltersChange={filters => this.setState({ segmentFilter: filters })}
|
||||
disableComparisons={disableComparisons}
|
||||
>
|
||||
{row.value}
|
||||
</TableFilterableCell>
|
||||
);
|
||||
}
|
||||
|
||||
renderSegmentsTable() {
|
||||
const { segmentsState, segmentFilter, visibleColumns, groupByInterval } = this.state;
|
||||
const { capabilities } = this.props;
|
||||
|
@ -478,30 +512,13 @@ END AS "time_span"`,
|
|||
|
||||
const avgRowSizeValues = segments.map(d => formatInteger(d.avg_row_size));
|
||||
|
||||
const renderFilterableCell = (field: string) => {
|
||||
return (row: { value: any }) => {
|
||||
const value = row.value;
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
segmentFilter: addFilter(segmentFilter, field, value),
|
||||
});
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const hasSql = capabilities.hasSql();
|
||||
|
||||
// Only allow filtering of columns other than datasource if in SQL mode or we are filtering on an exact datasource
|
||||
// Only allow filtering of columns other than datasource if in SQL mode, or if we are filtering on an exact datasource
|
||||
const allowGeneralFilter =
|
||||
hasSql ||
|
||||
segmentFilter.some(
|
||||
filter => filter.id === 'datasource' && getNeedleAndMode(filter).mode === 'exact',
|
||||
filter => filter.id === 'datasource' && parseFilterModeAndNeedle(filter)?.mode === '=',
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -513,10 +530,10 @@ END AS "time_span"`,
|
|||
manual
|
||||
filterable
|
||||
filtered={segmentFilter}
|
||||
defaultSorted={[hasSql ? { id: 'start', desc: true } : { id: 'datasource', desc: false }]}
|
||||
onFilteredChange={filtered => {
|
||||
this.setState({ segmentFilter: filtered });
|
||||
}}
|
||||
defaultSorted={[hasSql ? { id: 'start', desc: true } : { id: 'datasource', desc: false }]}
|
||||
onFetchData={tableState => {
|
||||
this.fetchData(groupByInterval, tableState);
|
||||
}}
|
||||
|
@ -531,15 +548,24 @@ END AS "time_span"`,
|
|||
Header: 'Segment ID',
|
||||
show: visibleColumns.shown('Segment ID'),
|
||||
accessor: 'segment_id',
|
||||
width: 300,
|
||||
width: 280,
|
||||
sortable: hasSql,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: row => (
|
||||
<TableClickableCell
|
||||
onClick={() => this.onDetail(row.value, row.row.datasource)}
|
||||
hoverIcon={IconNames.SEARCH_TEMPLATE}
|
||||
>
|
||||
{row.value}
|
||||
</TableClickableCell>
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: 'Datasource',
|
||||
show: visibleColumns.shown('Datasource'),
|
||||
accessor: 'datasource',
|
||||
Cell: renderFilterableCell('datasource'),
|
||||
width: 140,
|
||||
Cell: this.renderFilterableCell('datasource'),
|
||||
},
|
||||
{
|
||||
Header: 'Interval',
|
||||
|
@ -549,36 +575,37 @@ END AS "time_span"`,
|
|||
sortable: hasSql,
|
||||
defaultSortDesc: true,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: renderFilterableCell('interval'),
|
||||
Cell: this.renderFilterableCell('interval'),
|
||||
},
|
||||
{
|
||||
Header: 'Start',
|
||||
show: visibleColumns.shown('Start'),
|
||||
accessor: 'start',
|
||||
width: 120,
|
||||
width: 160,
|
||||
sortable: hasSql,
|
||||
defaultSortDesc: true,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: renderFilterableCell('start'),
|
||||
Cell: this.renderFilterableCell('start'),
|
||||
},
|
||||
{
|
||||
Header: 'End',
|
||||
show: visibleColumns.shown('End'),
|
||||
accessor: 'end',
|
||||
width: 120,
|
||||
width: 160,
|
||||
sortable: hasSql,
|
||||
defaultSortDesc: true,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: renderFilterableCell('end'),
|
||||
Cell: this.renderFilterableCell('end'),
|
||||
},
|
||||
{
|
||||
Header: 'Version',
|
||||
show: visibleColumns.shown('Version'),
|
||||
accessor: 'version',
|
||||
width: 120,
|
||||
width: 160,
|
||||
sortable: hasSql,
|
||||
defaultSortDesc: true,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: this.renderFilterableCell('version'),
|
||||
},
|
||||
{
|
||||
Header: 'Time span',
|
||||
|
@ -587,7 +614,7 @@ END AS "time_span"`,
|
|||
width: 100,
|
||||
sortable: hasSql,
|
||||
filterable: allowGeneralFilter,
|
||||
Cell: renderFilterableCell('time_span'),
|
||||
Cell: this.renderFilterableCell('time_span'),
|
||||
},
|
||||
{
|
||||
Header: 'Shard type',
|
||||
|
@ -595,6 +622,7 @@ END AS "time_span"`,
|
|||
id: 'shard_type',
|
||||
width: 100,
|
||||
sortable: false,
|
||||
headerClassName: 'disable-comparisons',
|
||||
accessor: d => {
|
||||
let v: any;
|
||||
try {
|
||||
|
@ -604,7 +632,7 @@ END AS "time_span"`,
|
|||
if (typeof v?.type !== 'string') return '-';
|
||||
return v?.type;
|
||||
},
|
||||
Cell: renderFilterableCell('shard_type'),
|
||||
Cell: this.renderFilterableCell('shard_type', true),
|
||||
},
|
||||
{
|
||||
Header: 'Shard spec',
|
||||
|
@ -638,14 +666,16 @@ END AS "time_span"`,
|
|||
values.map((x, i) => formatRangeDimensionValue(dimensions[i], x)).join('; ');
|
||||
|
||||
return (
|
||||
<div className="spec-detail range-detail" onClick={onShowFullShardSpec}>
|
||||
<TableClickableCell
|
||||
onClick={onShowFullShardSpec}
|
||||
hoverIcon={IconNames.EYE_OPEN}
|
||||
>
|
||||
<span className="range-label">Start:</span>
|
||||
{Array.isArray(v.start) ? formatEdge(v.start) : '-∞'}
|
||||
<br />
|
||||
<span className="range-label">End:</span>
|
||||
{Array.isArray(v.end) ? formatEdge(v.end) : '∞'}
|
||||
{fullShardIcon}
|
||||
</div>
|
||||
</TableClickableCell>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -703,6 +733,7 @@ END AS "time_span"`,
|
|||
width: 60,
|
||||
filterable: false,
|
||||
sortable: hasSql,
|
||||
className: 'padded',
|
||||
},
|
||||
{
|
||||
Header: 'Size',
|
||||
|
@ -711,6 +742,8 @@ END AS "time_span"`,
|
|||
filterable: false,
|
||||
sortable: hasSql,
|
||||
defaultSortDesc: true,
|
||||
width: 120,
|
||||
className: 'padded',
|
||||
Cell: row => (
|
||||
<BracedText
|
||||
text={
|
||||
|
@ -728,6 +761,8 @@ END AS "time_span"`,
|
|||
accessor: 'num_rows',
|
||||
filterable: false,
|
||||
defaultSortDesc: true,
|
||||
width: 120,
|
||||
className: 'padded',
|
||||
Cell: row => (
|
||||
<BracedText
|
||||
text={row.original.is_available ? formatInteger(row.value) : '(unknown)'}
|
||||
|
@ -742,6 +777,7 @@ END AS "time_span"`,
|
|||
accessor: 'avg_row_size',
|
||||
filterable: false,
|
||||
width: 100,
|
||||
className: 'padded',
|
||||
Cell: ({ value }) => {
|
||||
if (isNumberLikeNaN(value)) return '-';
|
||||
return (
|
||||
|
@ -760,34 +796,43 @@ END AS "time_span"`,
|
|||
width: 60,
|
||||
filterable: false,
|
||||
defaultSortDesc: true,
|
||||
className: 'padded',
|
||||
},
|
||||
{
|
||||
Header: 'Is published',
|
||||
show: hasSql && visibleColumns.shown('Is published'),
|
||||
id: 'is_published',
|
||||
accessor: row => String(Boolean(row.is_published)),
|
||||
Filter: makeBooleanFilter(),
|
||||
Filter: BooleanFilterInput,
|
||||
className: 'padded',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: 'Is realtime',
|
||||
show: hasSql && visibleColumns.shown('Is realtime'),
|
||||
id: 'is_realtime',
|
||||
accessor: row => String(Boolean(row.is_realtime)),
|
||||
Filter: makeBooleanFilter(),
|
||||
Filter: BooleanFilterInput,
|
||||
className: 'padded',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: 'Is available',
|
||||
show: hasSql && visibleColumns.shown('Is available'),
|
||||
id: 'is_available',
|
||||
accessor: row => String(Boolean(row.is_available)),
|
||||
Filter: makeBooleanFilter(),
|
||||
Filter: BooleanFilterInput,
|
||||
className: 'padded',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: 'Is overshadowed',
|
||||
show: hasSql && visibleColumns.shown('Is overshadowed'),
|
||||
id: 'is_overshadowed',
|
||||
accessor: row => String(Boolean(row.is_overshadowed)),
|
||||
Filter: makeBooleanFilter(),
|
||||
Filter: BooleanFilterInput,
|
||||
className: 'padded',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
Header: ACTION_COLUMN_LABEL,
|
||||
|
@ -803,11 +848,7 @@ END AS "time_span"`,
|
|||
return (
|
||||
<ActionCell
|
||||
onDetail={() => {
|
||||
this.setState({
|
||||
segmentTableActionDialogId: id,
|
||||
datasourceTableActionDialogId: datasource,
|
||||
actions: this.getSegmentActions(id, datasource),
|
||||
});
|
||||
this.onDetail(id, datasource);
|
||||
}}
|
||||
actions={this.getSegmentActions(id, datasource)}
|
||||
/>
|
||||
|
|
|
@ -55,7 +55,7 @@ exports[`ServicesView renders data 1`] = `
|
|||
"Tier",
|
||||
"Host",
|
||||
"Port",
|
||||
"Curr size",
|
||||
"Current size",
|
||||
"Max size",
|
||||
"Usage",
|
||||
"Detail",
|
||||
|
@ -125,6 +125,7 @@ exports[`ServicesView renders data 1`] = `
|
|||
Array [
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Service",
|
||||
"accessor": "service",
|
||||
"show": true,
|
||||
|
@ -143,25 +144,31 @@ exports[`ServicesView renders data 1`] = `
|
|||
"accessor": [Function],
|
||||
"id": "tier",
|
||||
"show": true,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Header": "Host",
|
||||
"accessor": "host",
|
||||
"show": true,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Header": "Port",
|
||||
"accessor": [Function],
|
||||
"id": "port",
|
||||
"show": true,
|
||||
"width": 180,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Curr size",
|
||||
"Header": "Host",
|
||||
"accessor": "host",
|
||||
"show": true,
|
||||
"width": 200,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Port",
|
||||
"accessor": [Function],
|
||||
"id": "port",
|
||||
"show": true,
|
||||
"width": 100,
|
||||
},
|
||||
Object {
|
||||
"Aggregated": [Function],
|
||||
"Cell": [Function],
|
||||
"Header": "Current size",
|
||||
"accessor": "curr_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "curr_size",
|
||||
"show": true,
|
||||
|
@ -172,6 +179,7 @@ exports[`ServicesView renders data 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Max size",
|
||||
"accessor": "max_size",
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "max_size",
|
||||
"show": true,
|
||||
|
@ -182,6 +190,7 @@ exports[`ServicesView renders data 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Usage",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "usage",
|
||||
"show": true,
|
||||
|
@ -192,6 +201,7 @@ exports[`ServicesView renders data 1`] = `
|
|||
"Cell": [Function],
|
||||
"Header": "Detail",
|
||||
"accessor": [Function],
|
||||
"className": "padded",
|
||||
"filterable": false,
|
||||
"id": "queue",
|
||||
"show": true,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
.fill-indicator {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
height: 18px;
|
||||
background-color: #dadada;
|
||||
border-radius: 2px;
|
||||
|
||||
|
|
|
@ -30,12 +30,13 @@ import {
|
|||
MoreButton,
|
||||
RefreshButton,
|
||||
TableColumnSelector,
|
||||
TableFilterableCell,
|
||||
ViewControlBar,
|
||||
} from '../../components';
|
||||
import { AsyncActionDialog } from '../../dialogs';
|
||||
import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from '../../react-table';
|
||||
import { Api } from '../../singletons';
|
||||
import {
|
||||
addFilter,
|
||||
Capabilities,
|
||||
CapabilitiesMode,
|
||||
deepGet,
|
||||
|
@ -51,8 +52,6 @@ import {
|
|||
queryDruidSql,
|
||||
QueryManager,
|
||||
QueryState,
|
||||
STANDARD_TABLE_PAGE_SIZE,
|
||||
STANDARD_TABLE_PAGE_SIZE_OPTIONS,
|
||||
} from '../../utils';
|
||||
import { BasicAction } from '../../utils/basic-action';
|
||||
|
||||
|
@ -64,7 +63,7 @@ const allColumns: string[] = [
|
|||
'Tier',
|
||||
'Host',
|
||||
'Port',
|
||||
'Curr size',
|
||||
'Current size',
|
||||
'Max size',
|
||||
'Usage',
|
||||
'Detail',
|
||||
|
@ -74,7 +73,7 @@ const allColumns: string[] = [
|
|||
const tableColumns: Record<CapabilitiesMode, string[]> = {
|
||||
'full': allColumns,
|
||||
'no-sql': allColumns,
|
||||
'no-proxy': ['Service', 'Type', 'Tier', 'Host', 'Port', 'Curr size', 'Max size', 'Usage'],
|
||||
'no-proxy': ['Service', 'Type', 'Tier', 'Host', 'Port', 'Current size', 'Max size', 'Usage'],
|
||||
};
|
||||
|
||||
function formatQueues(
|
||||
|
@ -304,6 +303,21 @@ ORDER BY
|
|||
this.serviceQueryManager.terminate();
|
||||
}
|
||||
|
||||
private renderFilterableCell(field: string) {
|
||||
const { serviceFilter } = this.state;
|
||||
|
||||
return (row: { value: any }) => (
|
||||
<TableFilterableCell
|
||||
field={field}
|
||||
value={row.value}
|
||||
filters={serviceFilter}
|
||||
onFiltersChange={filters => this.setState({ serviceFilter: filters })}
|
||||
>
|
||||
{row.value}
|
||||
</TableFilterableCell>
|
||||
);
|
||||
}
|
||||
|
||||
renderServicesTable() {
|
||||
const { capabilities } = this.props;
|
||||
const { servicesState, serviceFilter, groupServicesBy, visibleColumns } = this.state;
|
||||
|
@ -342,6 +356,7 @@ ORDER BY
|
|||
show: visibleColumns.shown('Service'),
|
||||
accessor: 'service',
|
||||
width: 300,
|
||||
Cell: this.renderFilterableCell('service'),
|
||||
Aggregated: () => '',
|
||||
},
|
||||
{
|
||||
|
@ -349,49 +364,31 @@ ORDER BY
|
|||
show: visibleColumns.shown('Type'),
|
||||
accessor: 'service_type',
|
||||
width: 150,
|
||||
Cell: ({ value }) => {
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({
|
||||
serviceFilter: addFilter(serviceFilter, 'service_type', value),
|
||||
});
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
Cell: this.renderFilterableCell('service_type'),
|
||||
},
|
||||
{
|
||||
Header: 'Tier',
|
||||
show: visibleColumns.shown('Tier'),
|
||||
id: 'tier',
|
||||
width: 180,
|
||||
accessor: row => {
|
||||
return row.tier ? row.tier : row.worker ? row.worker.category : null;
|
||||
},
|
||||
Cell: ({ value }) => {
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
this.setState({ serviceFilter: addFilter(serviceFilter, 'tier', value) });
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
Cell: this.renderFilterableCell('tier'),
|
||||
},
|
||||
{
|
||||
Header: 'Host',
|
||||
show: visibleColumns.shown('Host'),
|
||||
accessor: 'host',
|
||||
width: 200,
|
||||
Cell: this.renderFilterableCell('host'),
|
||||
Aggregated: () => '',
|
||||
},
|
||||
{
|
||||
Header: 'Port',
|
||||
show: visibleColumns.shown('Port'),
|
||||
id: 'port',
|
||||
width: 100,
|
||||
accessor: row => {
|
||||
const ports: string[] = [];
|
||||
if (row.plaintext_port !== -1) {
|
||||
|
@ -402,15 +399,17 @@ ORDER BY
|
|||
}
|
||||
return ports.join(', ') || 'No port';
|
||||
},
|
||||
Cell: this.renderFilterableCell('port'),
|
||||
Aggregated: () => '',
|
||||
},
|
||||
{
|
||||
Header: 'Curr size',
|
||||
show: visibleColumns.shown('Curr size'),
|
||||
Header: 'Current size',
|
||||
show: visibleColumns.shown('Current size'),
|
||||
id: 'curr_size',
|
||||
width: 100,
|
||||
filterable: false,
|
||||
accessor: 'curr_size',
|
||||
className: 'padded',
|
||||
Aggregated: row => {
|
||||
if (row.row._pivotVal !== 'historical') return '';
|
||||
const originals = row.subRows.map(r => r._original);
|
||||
|
@ -430,6 +429,7 @@ ORDER BY
|
|||
width: 100,
|
||||
filterable: false,
|
||||
accessor: 'max_size',
|
||||
className: 'padded',
|
||||
Aggregated: row => {
|
||||
if (row.row._pivotVal !== 'historical') return '';
|
||||
const originals = row.subRows.map(r => r._original);
|
||||
|
@ -448,6 +448,7 @@ ORDER BY
|
|||
id: 'usage',
|
||||
width: 140,
|
||||
filterable: false,
|
||||
className: 'padded',
|
||||
accessor: row => {
|
||||
if (oneOf(row.service_type, 'middle_manager', 'indexer')) {
|
||||
return row.worker
|
||||
|
@ -515,6 +516,7 @@ ORDER BY
|
|||
id: 'queue',
|
||||
width: 400,
|
||||
filterable: false,
|
||||
className: 'padded',
|
||||
accessor: row => {
|
||||
if (oneOf(row.service_type, 'middle_manager', 'indexer')) {
|
||||
if (deepGet(row, 'worker.version') === '') return 'Disabled';
|
||||
|
@ -550,8 +552,6 @@ ORDER BY
|
|||
|
||||
case 'indexer':
|
||||
case 'middle_manager':
|
||||
return row.value;
|
||||
|
||||
case 'coordinator':
|
||||
case 'overlord':
|
||||
return row.value;
|
||||
|
|
Loading…
Reference in New Issue