diff --git a/.kibana-plugin-helpers.json b/.kibana-plugin-helpers.json new file mode 100644 index 0000000..91012ec --- /dev/null +++ b/.kibana-plugin-helpers.json @@ -0,0 +1,12 @@ +{ + "styleSheetToCompile": "public/app.scss", + "buildSourcePatterns": [ + "package.json", + "tsconfig.json", + "yarn.lock", + ".yarnrc", + "index.js", + "{lib,public,server,test}/**/*", + "!__tests__" + ] +} diff --git a/README.md b/README.md index cdf6b2e..609ff7b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,65 @@ -## Open Distro for Elasticsearch SQL Kibana Plugin +# Open Distro for Elasticsearch SQL Kibana + +The Open Distro for Elasticsearch SQL Kibana plugin lets you query your Elasticsearch data using SQL syntax from a dedicated Kibana UI. You can then download data in JSON, JDBC, or CSV format. + + +## Documentation + +Please see our [documentation](https://opendistro.github.io/for-elasticsearch-docs/). + + +## Setup + +1. Download Elasticsearch for the version that matches the [Kibana version specified in package.json](./package.json#L8). +1. Download and install the appropriate [Open Distro for Elasticsearch Sql plugin](https://github.com/opendistro-for-elasticsearch/sql). +1. Download the Kibana source code for the [version specified in package.json](./package.json#L8) you want to set up. + + See the [Kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#setting-up-your-development-environment) for more instructions on setting up your development environment. + +1. Change your node version to the version specified in `.node-version` inside the Kibana root directory. +1. Create a `kibana-extra` directory as a sibling directory to the Kibana source code directory. +1. Check out this package from version control into the `kibana-extra` directory. +1. Run `yarn kbn bootstrap` inside `kibana-extra/opendistro-elasticsearch-sql-kibana`. + +Ultimately, your directory structure should look like this: + +```md +. +├── kibana +├── kibana-extra +│ └── opendistro-elasticsearch-sql-kibana +``` + + +## Build + +To build the plugin's distributable zip simply run `yarn build`. + +Example output: `./build/opendistro-kibana-sql-1.0.0.0.zip` + + +## Run + +- `yarn start` + + Starts Kibana and includes this plugin. Kibana will be available on `localhost:5601`. + +- `NODE_PATH=../../kibana/node_modules yarn test:jest` + + Runs the plugin tests. + + +## Contributing to Open Distro for Elasticsearch SQL Kibana + +- Refer to [CONTRIBUTING.md](./CONTRIBUTING.md). +- Since this is a Kibana plugin, it can be useful to review the [Kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) alongside the documentation around [Kibana plugins](https://www.elastic.co/guide/en/kibana/master/kibana-plugins.html) and [plugin development](https://www.elastic.co/guide/en/kibana/master/plugin-development.html). + ## License -This library is licensed under the Apache 2.0 License. +This code is licensed under the Apache 2.0 License. + +## Copyright + +Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file diff --git a/THIRD-PARTY b/THIRD-PARTY new file mode 100644 index 0000000..274c6df --- /dev/null +++ b/THIRD-PARTY @@ -0,0 +1,397 @@ +** @elastic/eui; version 6.5.1 -- https://elastic.github.io/eui/#/ +Copyright 2017 Elasticsearch BV +** TSLint; version 5.11.0 -- https://github.com/palantir/tslint +Copyright 2017 Palantir Technologies, Inc. +** typescript; version 3.0.3 -- https://github.com/Microsoft/TypeScript +/*! +***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** +*/ + +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND +DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and + distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the + copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other + entities that control, are controlled by, or are under common control + with that entity. For the purposes of this definition, "control" means + (i) the power, direct or indirect, to cause the direction or management + of such entity, whether by contract or otherwise, or (ii) ownership of + fifty percent (50%) or more of the outstanding shares, or (iii) + beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising + permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation source, + and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but not limited + to compiled object code, generated documentation, and conversions to + other media types. + + "Work" shall mean the work of authorship, whether in Source or Object + form, made available under the License, as indicated by a copyright + notice that is included in or attached to the work (an example is + provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, + that is based on (or derived from) the Work and for which the editorial + revisions, annotations, elaborations, or other modifications represent, + as a whole, an original work of authorship. For the purposes of this + License, Derivative Works shall not include works that remain separable + from, or merely link (or bind by name) to the interfaces of, the Work and + Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original + version of the Work and any modifications or additions to that Work or + Derivative Works thereof, that is intentionally submitted to Licensor for + inclusion in the Work by the copyright owner or by an individual or Legal + Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, "submitted" means any form of electronic, + verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic + mailing lists, source code control systems, and issue tracking systems + that are managed by, or on behalf of, the Licensor for the purpose of + discussing and improving the Work, but excluding communication that is + conspicuously marked or otherwise designated in writing by the copyright + owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on + behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this + License, each Contributor hereby grants to You a perpetual, worldwide, + non-exclusive, no-charge, royalty-free, irrevocable (except as stated in + this section) patent license to make, have made, use, offer to sell, sell, + import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily + infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. + If You institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory + patent infringement, then any patent licenses granted to You under this + License for that Work shall terminate as of the date such litigation is + filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or + Derivative Works thereof in any medium, with or without modifications, and + in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a + copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating + that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You + distribute, all copyright, patent, trademark, and attribution notices + from the Source form of the Work, excluding those notices that do not + pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must include + a readable copy of the attribution notices contained within such NOTICE + file, excluding those notices that do not pertain to any part of the + Derivative Works, in at least one of the following places: within a + NOTICE text file distributed as part of the Derivative Works; within the + Source form or documentation, if provided along with the Derivative + Works; or, within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents of the + NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative Works + that You distribute, alongside or as an addendum to the NOTICE text from + the Work, provided that such additional attribution notices cannot be + construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may + provide additional or different license terms and conditions for use, + reproduction, or distribution of Your modifications, or for any such + Derivative Works as a whole, provided Your use, reproduction, and + distribution of the Work otherwise complies with the conditions stated in + this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to the + Licensor shall be under the terms and conditions of this License, without + any additional terms or conditions. Notwithstanding the above, nothing + herein shall supersede or modify the terms of any separate license agreement + you may have executed with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, except + as required for reasonable and customary use in describing the origin of the + Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in + writing, Licensor provides the Work (and each Contributor provides its + Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied, including, without limitation, any + warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or + FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining + the appropriateness of using or redistributing the Work and assume any risks + associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether + in tort (including negligence), contract, or otherwise, unless required by + applicable law (such as deliberate and grossly negligent acts) or agreed to + in writing, shall any Contributor be liable to You for damages, including + any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability + to use the Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all other + commercial damages or losses), even if such Contributor has been advised of + the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work + or Derivative Works thereof, You may choose to offer, and charge a fee for, + acceptance of support, warranty, indemnity, or other liability obligations + and/or rights consistent with this License. However, in accepting such + obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You + agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by + reason of your accepting any such warranty or additional liability. END OF + TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification +within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +* For @elastic/eui see also this required NOTICE: + Copyright 2017 Elasticsearch BV +* For TSLint see also this required NOTICE: + Copyright 2017 Palantir Technologies, Inc. +* For typescript see also this required NOTICE: + /*! + ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not + use + this file except in compliance with the License. You may obtain a copy of + the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing + permissions + and limitations under the License. + ***************************************************************************** + */ + +------ + +** enzyme; version 3.1.0 -- http://airbnb.io/enzyme/ +Copyright (c) 2015 Airbnb, Inc. + +The MIT License (MIT) + +Copyright (c) 2015 Airbnb, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------ + +** react; version 16.3.0 -- https://reactjs.org/ +Copyright (c) Facebook, Inc. and its affiliates. + +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------ + +** expect.js; version 0.3.1 -- https://github.com/Automattic/expect.js/ +Copyright (c) 2011 Guillermo Rauch +Heavily borrows from should.js by TJ Holowaychuck - MIT. + +(The MIT License) + +Copyright (c) 2011 Guillermo Rauch + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------ + +** jest; version 23.6.0 -- https://jestjs.io/ +Copyright (c) 2014-present, Facebook, Inc. + +MIT License + +For Jest software + +Copyright (c) 2014-present, Facebook, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------ + +** @types/react; version 16.3.14 -- https://www.npmjs.com/package/@types/react +These definitions were written by Asana https://asana.com, AssureSign +http://www.assuresign.com, Microsoft https://microsoft.com, John Reilly +https://github.com/johnnyreilly, Benoit Benezech https://github.com/bbenezech, +Patricio Zavolinsky https://github.com/pzavolinsky, Digiguru +https://github.com/digiguru, Eric Anderson https://github.com/ericanderson, +Tanguy Krotoff https://github.com/tkrotoff, Dovydas Navickas +https://github.com/DovydasNavickas, Stéphane Goetz https://github.com/onigoetz, +Josh Rutherford https://github.com/theruther4d, Guilherme Hübner +https://github.com/guilhermehubner, Ferdy Budhidharma +https://github.com/ferdaber, Johann Rakotoharisoa +https://github.com/jrakotoharisoa, Olivier Pascal +https://github.com/pascaloliv, Martin Hochel https://github.com/hotell, Frank +Li https://github.com/franklixuefei, Jessica Franco +https://github.com/Kovensky, Paul Sherman https://github.com/pshrmn. + +This project is licensed under the MIT license. +Copyrights are respective of each contributor listed at the beginning of each +definition file. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..af4b2b9 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,22 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +// babelrc doesn't respect NODE_PATH anymore but using require does. +// Alternative to install them locally in node_modules +module.exports = { + presets: [require("@babel/preset-env"), require("@babel/preset-react"), require("@babel/preset-typescript")], + plugins: [require("@babel/plugin-proposal-class-properties"), require("@babel/plugin-proposal-object-rest-spread")], +}; + \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..13953ef --- /dev/null +++ b/index.js @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 query from './server/routes/query'; +import translate from './server/routes/translate'; +import QueryService from './server/services/QueryService'; +import TranslateService from './server/services/TranslateService'; +import { createSqlCluster } from './server/clusters'; + +export const PLUGIN_NAME = 'opendistro-sql-kibana'; + +export default function (kibana) { + return new kibana.Plugin({ + require: ['elasticsearch'], + name: PLUGIN_NAME, + uiExports: { + app: { + title: 'SQL Console', + description: 'SQL Console', + main: 'plugins/' + PLUGIN_NAME + '/app', + icon:'plugins/' + PLUGIN_NAME + '/icons/sql.svg', + }, + styleSheetPaths: require('path').resolve(__dirname, 'public/app.scss'), + }, + + config(Joi) { + return Joi.object({ + enabled: Joi.boolean().default(true), + }).default(); + }, + + init(server, options) { // eslint-disable-line no-unused-vars + // Create Clusters + createSqlCluster(server); + const client = server.plugins.elasticsearch; + + // Add server routes and initialize the plugin here + query(server, new QueryService(client)); + translate(server, new TranslateService(client)); + } + }); +} diff --git a/main.tsx b/main.tsx new file mode 100644 index 0000000..2cc5d03 --- /dev/null +++ b/main.tsx @@ -0,0 +1,392 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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'; +import { EuiSpacer } from '@elastic/eui'; +import Header from '../Header/Header'; +import QueryEditor from '../QueryEditor/QueryEditor'; +import QueryResults from '../QueryResults/QueryResults'; +import { getQueries, getQueryIndex } from '../../utils/utils'; + +export type QueryResultCSV = string; +export type QueryResultJDBC = string; +export type QueryResultRaw = string; + +interface ResponseData { + data: { + ok: boolean; + resp: any; + }; +} + +export interface Tab { + id: string; + name: string; + disabled: boolean; +} + +export interface ResponseDetail { + fulfilled: boolean; + errorMessage?: string; + data?: T; +} + +export interface TranslateResult { + translation: string; +} + +export interface QueryMessage { + text: any; + className: string; +} + +export interface QueryResult { + fields: string[]; + records: { [key: string]: any }[]; + message: string; +} + +interface MainProps { + httpClient: any; +} + +interface MainState { + queries: string[]; + queryTranslations: Array>; + queryResultsCSV: Array>; + queryResultsTable: Array>; + queryResultsJDBC: Array>; + queryResults: Array>; + selectedTabName: string; + selectedTabId: string; + searchQuery: string; + itemIdToExpandedRowMap: object; + message: Array; +} + +export function getQueryResultsForTable( + queryResultsRaw: ResponseDetail[] +): ResponseDetail[] { + return queryResultsRaw.map( + (queryResultResponseDetail: ResponseDetail): ResponseDetail => { + if (!queryResultResponseDetail.fulfilled) { + return { + fulfilled: queryResultResponseDetail.fulfilled, + errorMessage: queryResultResponseDetail.errorMessage, + }; + } else { + let databaseRecords: { [key: string]: any }[] = []; + let databaseFields: string[]; + let hits = []; + const obj = JSON.parse(queryResultResponseDetail.data); + + if (obj.hasOwnProperty('hits')) { + hits = obj['hits']['hits']; + databaseFields = hits != null && hits.length > 0 ? Object.keys(hits[0]['_source']) : []; + } + + for (let i = 0; i < hits.length; i += 1) { + const values = hits[i] != null ? Object.values(hits[i]['_source']) : ''; + const databaseRecord: { [key: string]: any } = {}; + + //Add row id + databaseRecord['id'] = i.toString(); + for (let j = 0; j < values.length; j += 1) { + const field: string = databaseFields[j]; + databaseRecord[field] = values[j]; + } + databaseRecords.push(databaseRecord); + } + + return { + fulfilled: queryResultResponseDetail.fulfilled, + data: { + fields: databaseFields, + records: databaseRecords, + message: 'Successfull', + }, + }; + } + } + ); +} + +export class Main extends React.Component { + private httpClient: any; + + constructor(props: MainProps) { + super(props); + + this.state = { + queries: [], + queryTranslations: [], + queryResultsCSV: [], + selectedTabName: 'messages', + selectedTabId: 'messages', + searchQuery: ' ', + itemIdToExpandedRowMap: { id: { nodes: {}, expandedRow: {}, selectedNodes: {} } }, + queryResultsTable: [], + queryResultsJDBC: [], + queryResults: [], + message: [], + }; + + this.httpClient = this.props.httpClient; + } + + processTranslateResponse(response: ResponseData): ResponseDetail { + if (!response.data.ok) { + return { + fulfilled: false, + errorMessage: response.data.resp, + data: null, + }; + } + return { + fulfilled: true, + data: response.data.resp, + }; + } + + processQueryResponse(response: ResponseData): ResponseDetail { + if (!response.data.ok) { + return { + fulfilled: false, + errorMessage: response.data.resp, + data: null, + }; + } + + return { + fulfilled: true, + data: response.data.resp, + }; + } + + onSelectedTabIdChange = (tab: Tab): void => { + this.setState({ + selectedTabId: tab.id, + selectedTabName: tab.name, + searchQuery: ' ', + itemIdToExpandedRowMap: {}, + }); + }; + + onQueryChange = ({ query }) => { + // Reset pagination state. + this.setState({ + searchQuery: query, + itemIdToExpandedRowMap: {}, + }); + }; + + updateExpandedMap = map => { + this.setState({ itemIdToExpandedRowMap: map }); + }; + + onRun = (queriesString: string): void => { + const queries: string[] = getQueries(queriesString); + + if (queries.length > 0) { + const queryTranslationsPromise = Promise.all( + queries.map((query: string) => + this.httpClient.post('../api/sql_console/translate', { query }).catch((error: any) => { + this.setState({ + message: [ + { + text: error.message, + className: 'error-message', + }, + ], + }); + }) + ) + ); + + const queryResultsPromise = Promise.all( + queries.map((query: string) => + this.httpClient.post('../api/sql_console/query', { query }).catch((error: any) => { + this.setState({ + message: [ + { + text: error.message, + className: 'error-message', + }, + ], + }); + }) + ) + ); + + const queryResultsJDBCPromise = Promise.all( + queries.map((query: string) => + this.httpClient.post('../api/sql_console/queryjdbc', { query }).catch((error: any) => { + this.setState({ message: error.message }); + }) + ) + ); + + const queryResultsCSVPromise = Promise.all( + queries.map((query: string) => + this.httpClient.post('../api/sql_console/querycsv', { query }).catch((error: any) => { + this.setState({ message: error.message }); + }) + ) + ); + + Promise.all([ + queryTranslationsPromise, + queryResultsPromise, + queryResultsJDBCPromise, + queryResultsCSVPromise, + ]).then( + ([ + queryTranslationsResponse, + queryResultsResponse, + queryResultsJDBCResponse, + queryResultsCSVResponse, + ]) => { + const queryResults = queryResultsResponse.map(queryResultResponse => + this.processQueryResponse(queryResultResponse) + ); + const queryResultsForTable = getQueryResultsForTable(queryResults); + const queryResultsJDBC = queryResultsJDBCResponse.map(queryJDBCResultResponse => + this.processQueryResponse(queryJDBCResultResponse) + ); + const queryResultsCSV = queryResultsCSVResponse.map(queryCSVResultResponse => + this.processQueryResponse(queryCSVResultResponse) + ); + + this.setState({ + queries, + queryTranslations: queryTranslationsResponse.map(translatedQueryResponse => + this.processTranslateResponse(translatedQueryResponse) + ), + queryResultsTable: queryResultsForTable, + queryResults: queryResults, + queryResultsJDBC: queryResultsJDBC, + queryResultsCSV: queryResultsCSV, + selectedTabId: + queryResults && queryResults.length > 0 && queryResults[0].fulfilled + ? '0' + : 'messages', + selectedTabName: + queryResults && + queryResults.length > 0 && + queryResults[0].fulfilled && + queries.length > 0 + ? getQueryIndex(queries[0]) + : 'messages', + message: this.getMessage(queryResultsForTable), + itemIdToExpandedRowMap: {}, + searchQuery: ' ', + }); + } + ); + } + }; + + getMessage(queryResultsForTable) { + const messages = queryResultsForTable.map(queryResult => { + return { + text: !queryResult.fulfilled ? queryResult.errorMessage : queryResult.data.message, + className: !queryResult.fulfilled ? 'error-message' : 'successful-message', + }; + }); + return messages; + } + + onTranslate = (queriesString: string): void => { + const queries: string[] = getQueries(queriesString); + if (queries.length > 0) { + Promise.all( + queries.map((query: string) => + this.httpClient + .post('../api/sql_console/translate', { query }) + .catch((error: any) => ({ ok: false, resp: error.message })) + ) + ).then(queryTranslationsResponse => { + this.setState({ + queries, + queryResultsCSV: [], + queryResultsJDBC: [], + queryResults: [], + queryResultsTable: [], + message: [{ text: '', className: '' }], + selectedTabId: 'messages', + selectedTabName: 'messages', + itemIdToExpandedRowMap: {}, + queryTranslations: queryTranslationsResponse.map(translatedQueryResponse => + this.processTranslateResponse(translatedQueryResponse) + ), + }); + }); + } + }; + + onClear = (): void => { + this.setState({ + queryTranslations: [], + queryResultsCSV: [], + queryResultsJDBC: [], + queryResults: [], + queryResultsTable: [], + message: [{ text: '', className: '' }], + selectedTabId: 'messages', + selectedTabName: 'messages', + itemIdToExpandedRowMap: {}, + }); + }; + + // TODO + resize() {} + + render() { + return ( +
+
+
+
+ +
+ + +
+ +
+
+
+ ); + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..eb13fbd --- /dev/null +++ b/package.json @@ -0,0 +1,93 @@ +{ + "name": "opendistro-sql-kibana", + "version": "1.1.0.0", + "description": "SQL Console", + "main": "index.js", + "license": "Apache-2.0", + "homepage": "https://github.com/opendistro-for-elasticsearch/sql-kibana-plugin", + "kibana": { + "version": "7.1.1", + "templateVersion": "6.3.3" + }, + "repository": { + "type": "git", + "url": "https://github.com/opendistro-for-elasticsearch/sql-kibana-plugin" + }, + "scripts": { + "preinstall": "node ../../kibana/preinstall_check", + "kbn": "node ../../kibana/scripts/kbn", + "lint": "tslint .", + "start": "plugin-helpers start", + "test:server": "plugin-helpers test:server", + "test:browser": "testcafe chrome public/__tests__", + "test:jest": "NODE_PATH=../../kibana/node_modules ./node_modules/.bin/jest --config ./test/jest.config.js", + "build": "plugin-helpers build" + }, + "dependencies": { + "@elastic/eui": "^14.4.0", + "@kbn/i18n": "link:../../kibana/packages/kbn-i18n", + "@kbn/ui-framework": "link:../../kibana/packages/kbn-ui-framework", + "react-dom": "^16.3.0", + "react-double-scrollbar": "^0.0.15" + }, + "devDependencies": { + "@babel/plugin-proposal-class-properties": "^7.5.5", + "@babel/plugin-proposal-object-rest-spread": "^7.5.5", + "@babel/preset-env": "^7.5.5", + "@babel/preset-react": "^7.0.0", + "@babel/preset-typescript": "^7.3.3", + "@elastic/elasticsearch": "^7.2.0", + "@elastic/eslint-config-kibana": "link:../../kibana/packages/eslint-config-kibana", + "@elastic/eslint-import-resolver-kibana": "link:../../kibana/packages/kbn-eslint-import-resolver-kibana", + "@kbn/expect": "link:../../kibana/packages/kbn-expect", + "@kbn/plugin-helpers": "link:../../kibana/packages/kbn-plugin-helpers", + "@testing-library/jest-dom": "^4.0.0", + "@testing-library/react": "^8.0.5", + "@testing-library/user-event": "^4.1.0", + "@types/angular": "1.6.50", + "@types/hapi-latest": "npm:@types/hapi@17.0.12", + "@types/jest": "^24.0.9", + "@types/lodash": "^3.10.1", + "@types/node": "^10.12.27", + "@types/react": "^16.3.14", + "@types/react-dom": "^16.0.5", + "@types/react-router-dom": "^4.3.1", + "babel-eslint": "^9.0.0", + "eslint": "^5.6.0", + "eslint-plugin-babel": "^5.2.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-jest": "^21.26.2", + "eslint-plugin-jsx-a11y": "^6.1.2", + "eslint-plugin-mocha": "^5.2.0", + "eslint-plugin-no-unsanitized": "^3.0.2", + "eslint-plugin-prefer-object-spread": "^1.2.1", + "eslint-plugin-react": "^7.11.1", + "husky": "^3.0.0", + "jest": "^23.5.0", + "jest-cli": "24.9.0", + "jest-raw-loader": "^1.0.1", + "lint-staged": "^9.2.0", + "prettier": "1.18.2", + "ts-jest": "^23.1.4", + "ts-loader": "^3.5.0", + "ts-node": "^7.0.1", + "tslint": "^5.11.0", + "tslint-config-prettier": "^1.18.0", + "tslint-plugin-prettier": "^2.0.1", + "typescript": "3.0.3" + }, + "engines": { + "node": "10.15.2", + "yarn": "^1.10.1" + }, + "resolutions": { + "**/@types/node": "10.12.27", + "@types/react": "16.3.14", + "**/@types/angular": "1.6.50", + "**/@types/jest": "^24.0.9", + "**/@types/react-dom": "^16.0.5", + "**/@types/react-router-dom": "^4.3.1", + "eslint-utils": "^1.4.2", + "**/@types/react": "16.3.14" + } +} diff --git a/public/ace-themes/sql_console.css b/public/ace-themes/sql_console.css new file mode 100644 index 0000000..bbcb2cc --- /dev/null +++ b/public/ace-themes/sql_console.css @@ -0,0 +1,179 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +.ace-sql-console .ace_gutter { + background: rgb(245, 247, 250); /* $euiColorLightestShade */ + color: rgb(105, 112, 125); /* $$euiColorDarkShade */ +} + +.ace-sql-console .ace_print-margin { + width: 1px; + background: #e8e8e8; +} + +.ace-sql-console .ace_fold { + background-color: #6B72E6; +} + +.ace-sql-console { + background-color: rgb(245, 247, 250); /* $euiColorLightestShade */ + color: black; +} + +.ace-sql-console .ace_marker-layer .ace_active-line.ace_active-line { + background-color: rgb(211, 218, 230); /* $euiColorLightShade */; +} + +.ace-sql-console .ace_cursor { + color: black; +} + +.ace-sql-console .ace_invisible { + color: rgb(191, 191, 191); +} + +.ace-sql-console .ace_storage, +.ace-sql-console .ace_keyword { + color: blue; +} + +.ace-sql-console .ace_constant { + color: rgb(197, 6, 11); +} + +.ace-sql-console .ace_constant.ace_buildin { + color: rgb(88, 72, 246); +} + +.ace-sql-console .ace_constant.ace_language { + color: rgb(88, 92, 246); +} + +.ace-sql-console .ace_constant.ace_library { + color: rgb(6, 150, 14); +} + +.ace-sql-console .ace_invalid { + background-color: rgba(255, 0, 0, 0.1); + color: red; +} + +.ace-sql-console .ace_support.ace_function { + color: rgb(60, 76, 114); +} + +.ace-sql-console .ace_support.ace_constant { + color: rgb(6, 150, 14); +} + +.ace-sql-console .ace_support.ace_type, +.ace-sql-console .ace_support.ace_class { + color: rgb(109, 121, 222); +} + +.ace-sql-console .ace_keyword.ace_operator { + color: rgb(104, 118, 135); +} + +.ace-sql-console .ace_string { + color: rgb(3, 106, 7); +} + +.ace-sql-console .ace_comment { + color: rgb(76, 136, 107); +} + +.ace-sql-console .ace_comment.ace_doc { + color: rgb(0, 102, 255); +} + +.ace-sql-console .ace_comment.ace_doc.ace_tag { + color: rgb(128, 159, 191); +} + +.ace-sql-console .ace_constant.ace_numeric { + color: rgb(0, 0, 205); +} + +.ace-sql-console .ace_variable { + color: rgb(49, 132, 149); +} + +.ace-sql-console .ace_xml-pe { + color: rgb(104, 104, 91); +} + +.ace-sql-console .ace_entity.ace_name.ace_function { + color: #0000A2; +} + + +.ace-sql-console .ace_heading { + color: rgb(12, 7, 255); +} + +.ace-sql-console .ace_list { + color:rgb(185, 6, 144); +} + +.ace-sql-console .ace_meta.ace_tag { + color:rgb(0, 22, 142); +} + +.ace-sql-console .ace_string.ace_regex { + color: rgb(255, 0, 0) +} + +.ace-sql-console .ace_marker-layer .ace_selection { + background: rgb(181, 213, 255); +} + +.ace-sql-console.ace_multiselect .ace_selection.ace_start { + box-shadow: 0 0 3px 0px white; +} + +.ace-sql-console .ace_marker-layer .ace_step { + background: rgb(252, 255, 0); +} + +.ace-sql-console .ace_marker-layer .ace_stack { + background: rgb(164, 229, 101); +} + +.ace-sql-console .ace_marker-layer .ace_bracket { + margin: -1px 0 0 -1px; + border: 1px solid rgb(192, 192, 192); +} + +.ace-sql-console .ace_marker-layer .ace_active-line { + background: rgba(0, 0, 0, 0.07); +} + +.ace-sql-console .ace_gutter-active-line { + background-color : rgb(211, 218, 230); /* $euiColorLightShade */ +} + +.ace-sql-console .ace_marker-layer .ace_selected-word { + background: rgb(250, 250, 255); + border: 1px solid rgb(200, 200, 250); +} + +.ace-sql-console .ace_indent-guide { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y; +} + +.ace_editor .ace-sql-console { + height: 200px; +} diff --git a/public/ace-themes/sql_console.js b/public/ace-themes/sql_console.js new file mode 100644 index 0000000..e9be8cd --- /dev/null +++ b/public/ace-themes/sql_console.js @@ -0,0 +1,25 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 * as ace from 'brace'; + +ace.define('ace/theme/sql_console', ['require', 'exports', 'module', 'ace/lib/dom'], function (acequire, exports, module) { + exports.isDark = false; + exports.cssClass = 'ace-sql-console'; + exports.cssText = require('./sql_console.css'); + + const dom = acequire('../lib/dom'); + dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/public/app.js b/public/app.js new file mode 100644 index 0000000..a81b5b0 --- /dev/null +++ b/public/app.js @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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'; +import { uiModules } from 'ui/modules'; +import chrome from 'ui/chrome'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import 'ui/autoload/styles'; +import './less/main.less'; +import { Main } from './components/main'; + +const app = uiModules.get('apps/sqlConsole'); + +app.config($locationProvider => { + $locationProvider.html5Mode({ + enabled: false, + requireBase: false, + rewriteLinks: false, + }); +}); +app.config(stateManagementConfigProvider => + stateManagementConfigProvider.disable() +); + +function RootController($scope, $element, $http) { + const domNode = $element[0]; + + // render react to DOM + render(
, domNode); + + // unmount react on controller destroy + $scope.$on('$destroy', () => { + unmountComponentAtNode(domNode); + }); +} + +chrome.setRootController('sqlConsole', RootController); diff --git a/public/app.scss b/public/app.scss new file mode 100644 index 0000000..5444a7e --- /dev/null +++ b/public/app.scss @@ -0,0 +1,272 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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 '../node_modules/@elastic/eui/src/global_styling/variables/colors'; +@import '../node_modules/@elastic/eui/src/global_styling/variables/size'; + +.sql-console-page-header { + padding: $euiSizeS $euiSizeL; + font-weight: 600; +} + +.sql-console-query-container { + padding: $euiSizeL; + height: 1142px; +} + +.sql-console-query-editor { + height: 500px; + max-height: 500px; + + .container-panel { + border-radius: 0px; + box-shadow: none; + } + .container-panel-header { + font-weight: 450px; + padding: $euiSize $euiSize; + } + .sql-query-panel { + border-radius: 0px; + border-width: 1px; + border-right-width: 0.5px; + box-shadow: none; + } + .sql-query-panel-header { + padding: $euiSizeS; + background-color: $euiColorLightestShade; + } + .translated-query-panel { + border-radius: 0px; + border-width: 1px; + border-left-width: 0.5px; + box-shadow: none; + } + .translated-query-panel-header { + padding: $euiSizeS; + background-color: $euiColorLightestShade; + } + .action-container { + padding: $euiSizeM; + } + .resize-panel { + resize: vertical; + overflow: auto; + cursor: row-resize; + } + .sql-editor-link:visited { + background-color: rgb(255,255,255); + } + .sql-editor-button { + margin:10px; + } +} +.sql-console-query-result{ + height: 577px; + scroll-behavior: smooth; + .sql-console-results-container { + overflow: auto; + } + .query-result-container { + border: solid 1.5px #d9d9d9; + border-radius: 0px; + border-bottom-width: 0; + } + .tabs-container { + overflow: hidden; + margin: 3px; + } + .table-name { + font-size: 20px; + padding: 20px; + } + .table-header { + /*border-top: solid 1px #d9d9d9;*/ + background-color: #d9d9d9; + } + .sideNav-table { + border: solid 1px rgb(217, 217, 217); + border-collapse: separate; + } + .search-panel { + display: inline-flex; + width:100%; + padding:20px; + } + .search-bar { + width:80%; + } + .pagination-container { + margin-top: 10px; + margin-bottom: 10px; + } + + .tab-arrow-down-container { + padding: 25px; + height: 56px; + vertical-align: middle; + color: rgb(0, 121, 165); + } + + .download-container { + padding: $euiSizeM; + height: 56px; + vertical-align: middle; + border-width: 1px; + margin-bottom: 20px; + } + + .download-button-container { + float:right; + } + + .toggleContainer { + margin: 20px; + } +} + +.expanded-row { + /*background-color: rgb(232,243,246); + /*background-color: rgb(245,247,250);*/ + border-collapse: separate; +} + +.expanded-row:hover { + background-color: rgb(232,243,246); +} + +.no-background { + background-color: rgba(0, 0, 0, 0); +} + +/* Message Tab */ +.code-editor { + color: #006BB4; +} + +.error-message { + color: red; +} + +.successful-message{ + color: #006BB4; +} + +/********* EuiTable overrides ***********/ +.euiTableCellContent { + display: inline-block; + width: 100%; +} + +.euiTableRow.euiTableRow-isExpandedRow .euiTableRowCell { + background-color: unset; +} + +.sideNav-table .euiTableRowCell { + border-top: 0; +} + +.euiTableRow:hover{ + background-color: unset; +} + +/********* EuiSideNav overrides *********/ + +/* Add the vertical line to connect the side Nav to the parent row */ +.sideNavItem__items { + position: relative; + &:after { /* 1 */ + position: absolute; + content: ''; + top: -10px; + bottom: 32px; + width: 1px; + background: rgb(217, 217, 217); + left: 0; + } +} + +/* Add the vertical line to connect the side nav item to its parent item */ +.euiSideNavItem__items:after { + bottom: 50%; +} + +/* Add the tick line to each item */ +.euiSideNavItem { + /** + * 1. Absolutely position the horizontal tick connecting the item to the vertical line. + */ + > .euiSideNavItemButton { + position: relative; /* 1 */ + padding-left: 13px; + padding-right: 8px; /* 1 */ + + &:after { + position: absolute; + content: ""; + top: 50%; + left: 0; + width: 10px; + height: 2px; + background: rgb(217, 217, 217); + } + } + +/* Remove the horizontal tick from the root of the sideNav */ + &.euiSideNavItem--root > .euiSideNavItemButton { + &:after { + background: none; + } + } + + & > .sideNavItem__items { + margin-left: 16px; + } +} + +/* To remove caret icon from sideNavItems */ +.euiIcon--small { + width: 0px; + height: 0px; +} + +/* To remove bold and underline inside nested tables */ +.euiSideNavItemButton.euiSideNavItemButton-isSelected .euiSideNavItemButton__label .euiTableRowCell { + font-weight: normal; + text-decoration: none; +} + +.euiSideNavItemButton__content { + float: left; +} + +/* To Fix Word-wrap not working for table cells inside SideNav component */ +.euiSideNavItemButton__label { + white-space: normal; +} + +/* To center vertical line from sideNav item to its children*/ +.euiSideNavItem--trunk > .euiSideNavItem__items { + margin-left: 15px; +} + +/* +.euiSideNavItem .euiSideNavItem--trunk .euiSideNavItem--hasChildItems:after { + bottom:100%; +}*/ + +.euiSideNavItem--branch > .euiSideNavItemButton { + padding-left: 10px; +} \ No newline at end of file diff --git a/public/components/Header/Header.test.tsx b/public/components/Header/Header.test.tsx new file mode 100644 index 0000000..6439758 --- /dev/null +++ b/public/components/Header/Header.test.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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"; +import "@testing-library/jest-dom/extend-expect"; +import { render } from "@testing-library/react"; +import Header from "./Header"; + + +describe("
spec", () => { + it("renders the component", () => { + render(
); + expect(document.body.children[0]).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/public/components/Header/Header.tsx b/public/components/Header/Header.tsx new file mode 100644 index 0000000..9a656b5 --- /dev/null +++ b/public/components/Header/Header.tsx @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file 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'; +import { EuiHorizontalRule } from '@elastic/eui'; + +const Header = () => { + return ( +
+
+ SQL console +
+ +
+ ); +}; + +export default Header; diff --git a/public/components/Header/__snapshots__/Header.test.tsx.snap b/public/components/Header/__snapshots__/Header.test.tsx.snap new file mode 100644 index 0000000..fef9868 --- /dev/null +++ b/public/components/Header/__snapshots__/Header.test.tsx.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`
spec renders the component 1`] = ` +
+
+
+ SQL console +
+
+
+
+`; diff --git a/public/components/Main/__snapshots__/main.test.tsx.snap b/public/components/Main/__snapshots__/main.test.tsx.snap new file mode 100644 index 0000000..f34fabc --- /dev/null +++ b/public/components/Main/__snapshots__/main.test.tsx.snap @@ -0,0 +1,2041 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`
spec click run button, and response causes an error 1`] = ` +
+
+
+
+ SQL console +
+
+
+
+
+
+

+ SQL console +

+
+
+
+ SQL +
+
+
+

+ Press Enter to start editing. +

+

+ When you're done, press Escape to stop editing. +

+
+
+