diff --git a/web-console/package-lock.json b/web-console/package-lock.json index fdac73370ad..5c25e00ce13 100644 --- a/web-console/package-lock.json +++ b/web-console/package-lock.json @@ -4395,9 +4395,9 @@ "integrity": "sha512-0sYnfUHHMoajaud/i5BHKA12bUxiWEHJ9rxGqVEppFxsEcxef0TZQ5J59lU+UniEBcz/sG5fTESRyS7cOm3tSQ==" }, "druid-query-toolkit": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.3.15.tgz", - "integrity": "sha512-q7uKfUdBItjOyNF1PlWF/rAhOim1uAjI085fsoKIBDZ2o5O4XRjaCKqXtW49Ovv92ks/22zLoYWNdU51i4PB/w==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.3.20.tgz", + "integrity": "sha512-jrGNu+o/nD+uhbxAMLXEQrSWNEylCRmkiuFDJSPCMz7cjMNArsdIgyBQHPezNAeTDpReelAt59xJ7pvqXwPIvw==", "requires": { "tslib": "^1.10.0" } diff --git a/web-console/package.json b/web-console/package.json index 14ef194d07b..8f3b214cea8 100644 --- a/web-console/package.json +++ b/web-console/package.json @@ -61,7 +61,7 @@ "d3": "^5.9.7", "d3-array": "^2.2.0", "druid-console": "^0.0.2", - "druid-query-toolkit": "^0.3.15", + "druid-query-toolkit": "^0.3.20", "file-saver": "^2.0.2", "has-own-prop": "^2.0.0", "hjson": "^3.1.2", diff --git a/web-console/src/components/deferred/__snapshots__/deferred.spec.tsx.snap b/web-console/src/components/deferred/__snapshots__/deferred.spec.tsx.snap new file mode 100644 index 00000000000..60bc7894080 --- /dev/null +++ b/web-console/src/components/deferred/__snapshots__/deferred.spec.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`deferred matches snapshot 1`] = `
`; diff --git a/web-console/src/components/deferred/deferred.spec.tsx b/web-console/src/components/deferred/deferred.spec.tsx new file mode 100644 index 00000000000..8125fafbcfc --- /dev/null +++ b/web-console/src/components/deferred/deferred.spec.tsx @@ -0,0 +1,31 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; + +import { Deferred } from './deferred'; + +describe('deferred', () => { + it('matches snapshot', () => { + const deferred =
} />; + + const { container } = render(deferred); + expect(container.firstChild).toMatchSnapshot(); + }); +}); diff --git a/web-console/src/components/deferred/deferred.tsx b/web-console/src/components/deferred/deferred.tsx new file mode 100644 index 00000000000..6194979193d --- /dev/null +++ b/web-console/src/components/deferred/deferred.tsx @@ -0,0 +1,36 @@ +/* + * 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 React from 'react'; + +export interface DeferredProps { + content: () => JSX.Element; +} + +export interface DeferredState {} + +export class Deferred extends React.PureComponent { + constructor(props: DeferredProps, context: any) { + super(props, context); + } + + render(): JSX.Element { + const { content } = this.props; + return content(); + } +} diff --git a/web-console/src/dialogs/query-history-dialog/__snapshots__/query-plan-history.spec.tsx.snap b/web-console/src/dialogs/query-history-dialog/__snapshots__/query-plan-history.spec.tsx.snap new file mode 100644 index 00000000000..d7efc740e7f --- /dev/null +++ b/web-console/src/dialogs/query-history-dialog/__snapshots__/query-plan-history.spec.tsx.snap @@ -0,0 +1,111 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`query plan dialog matches snapshot 1`] = ` +
+
+
+
+
+
+

+ Query history +

+ +
+
+
+
+ +
+ +
+
+
+
+`; diff --git a/web-console/src/dialogs/query-history-dialog/query-history-dialog.scss b/web-console/src/dialogs/query-history-dialog/query-history-dialog.scss new file mode 100644 index 00000000000..34bf4b79b01 --- /dev/null +++ b/web-console/src/dialogs/query-history-dialog/query-history-dialog.scss @@ -0,0 +1,33 @@ +/* + * 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. + */ + +.query-history-dialog { + &.bp3-dialog { + width: 900px; + } + + .panel { + width: 100%; + } + + .text-area { + width: 100%; + height: 500px; + resize: none; + } +} diff --git a/web-console/src/dialogs/query-history-dialog/query-history-dialog.tsx b/web-console/src/dialogs/query-history-dialog/query-history-dialog.tsx new file mode 100644 index 00000000000..c17dbc60486 --- /dev/null +++ b/web-console/src/dialogs/query-history-dialog/query-history-dialog.tsx @@ -0,0 +1,91 @@ +/* + * 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, Intent, Tab, Tabs, TextArea } from '@blueprintjs/core'; +import React from 'react'; + +import './query-history-dialog.scss'; + +export interface QueryRecord { + version: string; + queryString: string; +} +export interface QueryHistoryDialogProps { + setQueryString: (queryString: string) => void; + onClose: () => void; + queryRecords: QueryRecord[]; +} + +export interface QueryHistoryDialogState { + activeTab: number; +} + +export class QueryHistoryDialog extends React.PureComponent< + QueryHistoryDialogProps, + QueryHistoryDialogState +> { + constructor(props: QueryHistoryDialogProps) { + super(props); + this.state = { + activeTab: 0, + }; + } + + render(): JSX.Element { + const { onClose, queryRecords, setQueryString } = this.props; + const { activeTab } = this.state; + + const versions = queryRecords.map((record, index) => ( + } + panelClassName={'panel'} + /> + )); + + return ( + +
+ this.setState({ activeTab: tab })} + > + {versions} + + +
+
+
+
+
+
+ ); + } +} diff --git a/web-console/src/dialogs/query-history-dialog/query-plan-history.spec.tsx b/web-console/src/dialogs/query-history-dialog/query-plan-history.spec.tsx new file mode 100644 index 00000000000..d164c3e0171 --- /dev/null +++ b/web-console/src/dialogs/query-history-dialog/query-plan-history.spec.tsx @@ -0,0 +1,32 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; + +import { QueryHistoryDialog } from './query-history-dialog'; + +describe('query plan dialog', () => { + it('matches snapshot', () => { + const queryPlanDialog = ( + null} queryRecords={[]} onClose={() => {}} /> + ); + render(queryPlanDialog); + expect(document.body.lastChild).toMatchSnapshot(); + }); +}); diff --git a/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap b/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap index abd814e44b1..e91d4b8c7ca 100644 --- a/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap +++ b/web-console/src/dialogs/query-plan-dialog/__snapshots__/query-plan-dialog.spec.tsx.snap @@ -75,6 +75,16 @@ exports[`query plan dialog matches snapshot 1`] = ` Close +
diff --git a/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx index 465436d5a04..de7bc91a204 100644 --- a/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx +++ b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.spec.tsx @@ -24,7 +24,12 @@ import { QueryPlanDialog } from './query-plan-dialog'; describe('query plan dialog', () => { it('matches snapshot', () => { const queryPlanDialog = ( - {}} /> + null} + explainResult={'test'} + explainError={undefined} + onClose={() => {}} + /> ); render(queryPlanDialog); expect(document.body.lastChild).toMatchSnapshot(); diff --git a/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx index 94bcdf3caa5..000cb9a2d8e 100644 --- a/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx +++ b/web-console/src/dialogs/query-plan-dialog/query-plan-dialog.tsx @@ -16,7 +16,15 @@ * limitations under the License. */ -import { Button, Classes, Dialog, FormGroup, InputGroup, TextArea } from '@blueprintjs/core'; +import { + Button, + Classes, + Dialog, + FormGroup, + InputGroup, + Intent, + TextArea, +} from '@blueprintjs/core'; import React from 'react'; import { BasicQueryExplanation, SemiJoinQueryExplanation } from '../../utils'; @@ -27,6 +35,7 @@ export interface QueryPlanDialogProps { explainResult?: BasicQueryExplanation | SemiJoinQueryExplanation | string; explainError?: string; onClose: () => void; + setQueryString: (queryString: string) => void; } export interface QueryPlanDialogState {} @@ -40,8 +49,10 @@ export class QueryPlanDialog extends React.PureComponent< this.state = {}; } + private queryString: string = ''; + render(): JSX.Element { - const { explainResult, explainError, onClose } = this.props; + const { explainResult, explainError, onClose, setQueryString } = this.props; let content: JSX.Element; @@ -60,17 +71,15 @@ export class QueryPlanDialog extends React.PureComponent< ); } + this.queryString = JSON.stringify( + (explainResult as BasicQueryExplanation).query[0], + undefined, + 2, + ); content = (
-