├── .gitignore ├── client ├── assets │ ├── images │ │ ├── joalk.png │ │ ├── aws-logo.png │ │ ├── tysong24.png │ │ ├── aws-modal.gif │ │ ├── info-modal.gif │ │ ├── morgan562.png │ │ ├── sophiapak.png │ │ ├── stratosdb.gif │ │ ├── upload-modal.gif │ │ ├── stratosdb-latestui.jpg │ │ ├── StratosDB-twitter-pp.png │ │ ├── stratosdb_logo_black.png │ │ ├── stratosdb_logo_white.png │ │ ├── info-modal-code-editor.jpg │ │ ├── info-modal-line-graph.jpg │ │ ├── stratosdb_footer_banner.jpg │ │ ├── stratosdb_logo_visual.png │ │ ├── info-modal-returned-table.jpg │ │ └── info-modal-query-text-area.jpg │ └── stylesheets │ │ └── scss │ │ ├── application.scss │ │ ├── table.scss │ │ ├── sidebar.scss │ │ ├── codeEditor.scss │ │ ├── queryResults.scss │ │ ├── global.scss │ │ ├── _variables.scss │ │ ├── awsModal.scss │ │ ├── uploadModal.scss │ │ ├── container.scss │ │ └── infoModal.scss ├── App.tsx ├── components │ ├── Announcement.tsx │ ├── UploadModal.tsx │ ├── Table.tsx │ ├── LineGraph.tsx │ ├── AwsModal.tsx │ ├── CodeEditor.tsx │ ├── Sidebar.tsx │ └── InfoModal.tsx └── Container.tsx ├── uploads ├── uploadsample.txt ├── 1603340566741-sd_postgres_create.sql └── 1603340663035-sd_postgres_create.sql ├── __tests__ ├── serverTest.ts └── enzyme.tsx ├── index.html ├── tsconfig.json ├── LICENSE ├── demo └── sd_postgres_create.sql ├── webpack.config.js ├── server ├── controllers.ts └── server.ts ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | .DS_Store 4 | .vscode 5 | dist 6 | .env 7 | -------------------------------------------------------------------------------- /client/assets/images/joalk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/joalk.png -------------------------------------------------------------------------------- /client/assets/images/aws-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/aws-logo.png -------------------------------------------------------------------------------- /client/assets/images/tysong24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/tysong24.png -------------------------------------------------------------------------------- /client/assets/images/aws-modal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/aws-modal.gif -------------------------------------------------------------------------------- /client/assets/images/info-modal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/info-modal.gif -------------------------------------------------------------------------------- /client/assets/images/morgan562.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/morgan562.png -------------------------------------------------------------------------------- /client/assets/images/sophiapak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/sophiapak.png -------------------------------------------------------------------------------- /client/assets/images/stratosdb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb.gif -------------------------------------------------------------------------------- /client/assets/images/upload-modal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/upload-modal.gif -------------------------------------------------------------------------------- /client/assets/images/stratosdb-latestui.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb-latestui.jpg -------------------------------------------------------------------------------- /client/assets/images/StratosDB-twitter-pp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/StratosDB-twitter-pp.png -------------------------------------------------------------------------------- /client/assets/images/stratosdb_logo_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb_logo_black.png -------------------------------------------------------------------------------- /client/assets/images/stratosdb_logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb_logo_white.png -------------------------------------------------------------------------------- /client/assets/images/info-modal-code-editor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/info-modal-code-editor.jpg -------------------------------------------------------------------------------- /client/assets/images/info-modal-line-graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/info-modal-line-graph.jpg -------------------------------------------------------------------------------- /client/assets/images/stratosdb_footer_banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb_footer_banner.jpg -------------------------------------------------------------------------------- /client/assets/images/stratosdb_logo_visual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/stratosdb_logo_visual.png -------------------------------------------------------------------------------- /client/assets/images/info-modal-returned-table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/info-modal-returned-table.jpg -------------------------------------------------------------------------------- /client/assets/images/info-modal-query-text-area.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oslabs-beta/StratosDB/HEAD/client/assets/images/info-modal-query-text-area.jpg -------------------------------------------------------------------------------- /uploads/uploadsample.txt: -------------------------------------------------------------------------------- 1 | Imported files will be uploaded here. 2 | 3 | Files will be named with in the format: 4 | " - " -------------------------------------------------------------------------------- /__tests__/serverTest.ts: -------------------------------------------------------------------------------- 1 | // import server from '../server/server'; 2 | // import * as request from 'supertest'; 3 | 4 | // describe('server router integration', () => { 5 | // describe('/refresh', () => {}); 6 | // describe('/connect', () => {}); 7 | // describe('/newSchema', () => {}); 8 | // describe('/results', () => {}); 9 | // }); 10 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | StratosDB 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/application.scss: -------------------------------------------------------------------------------- 1 | // IMPORTING ALL SCSS FILES INTO APP.SCSS FOR MODULARITY 2 | @import './global.scss'; 3 | @import './container.scss'; 4 | @import './sidebar.scss'; 5 | @import './codeEditor.scss'; 6 | @import './queryResults.scss'; 7 | @import './awsModal.scss'; 8 | @import './infoModal.scss'; 9 | @import './table.scss'; 10 | @import './uploadModal.scss'; 11 | -------------------------------------------------------------------------------- /client/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { render } from 'react-dom'; 3 | import Container from './Container'; 4 | import 'codemirror/lib/codemirror.css'; 5 | import './assets/stylesheets/scss/application.scss'; 6 | 7 | class App extends Component<{}, { name: string }> { 8 | render() { 9 | return ( 10 |
11 | 12 |
13 | ); 14 | } 15 | } 16 | 17 | render(, document.querySelector('#root')); 18 | -------------------------------------------------------------------------------- /client/components/Announcement.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // initial Announcement State with Type string 4 | interface AnnouncementState { 5 | announcement: string; 6 | } 7 | 8 | // Functional Component, Announcement 9 | const Announcement: React.FC = ( 10 | props: AnnouncementState 11 | ) => { 12 | return ( 13 |
14 |

{`${props.announcement}`}

15 |
16 | ); 17 | }; 18 | 19 | export default Announcement; 20 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/table.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #table-container { 4 | max-height: 80%; 5 | margin: 0 0 10px 0; 6 | overflow-y: scroll; 7 | 8 | &::-webkit-scrollbar { 9 | display: none; 10 | } 11 | 12 | #result-table { 13 | width: 100%; 14 | color: #ffffff; 15 | 16 | th { 17 | background-color: $stratos-blue; 18 | padding: 5px; 19 | } 20 | 21 | td { 22 | background-color: #0d1122; 23 | text-align: center; 24 | padding: 5px; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/sidebar.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #sidebar { 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: space-between; 7 | 8 | #main-sidebar { 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: space-between; 12 | 13 | img { 14 | margin: 25px auto; 15 | } 16 | 17 | svg { 18 | margin: 20px auto; 19 | fill: #ffffff; 20 | 21 | &:hover { 22 | fill: $stratos-blue; 23 | } 24 | } 25 | } 26 | 27 | #bottom-sidebar { 28 | height: 41.53px; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node12/tsconfig.json", 3 | "$schema": "https://json.schemastore.org/tsconfig", 4 | "display": "Node 12", 5 | 6 | "compilerOptions": { 7 | "target": "esnext", 8 | "jsx": "react", 9 | "lib": [ 10 | "dom", 11 | "es2019", 12 | "es2020.promise", 13 | "es2020.bigint", 14 | "es2020.string" 15 | ], 16 | "module": "commonjs", 17 | "watch": true, 18 | "outDir": "./dist", 19 | 20 | "strict": true, 21 | "esModuleInterop": true, 22 | "forceConsistentCasingInFileNames": true 23 | }, 24 | "exclude": ["node_modules", "dist"] 25 | } 26 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/codeEditor.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #code-editor { 4 | height: 100%; 5 | width: 40%; 6 | display: flex; 7 | flex-direction: column; 8 | 9 | .code-mirror-container { 10 | height: 94%; 11 | } 12 | 13 | .react-codemirror2 { 14 | height: 94%; 15 | } 16 | 17 | .CodeMirror { 18 | height: 94%; 19 | z-index: 0; 20 | } 21 | 22 | #buttons-section { 23 | display: flex; 24 | justify-content: space-around; 25 | margin: -50px 0 -100px 0; 26 | } 27 | 28 | #cancel-button { 29 | fill: $stratos-yellow; 30 | } 31 | 32 | #submit-button { 33 | fill: $stratos-green; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/queryResults.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #queries-results-panel { 4 | display: flex; 5 | flex-direction: column; 6 | margin: 20px; 7 | 8 | #query-request { 9 | display: flex; 10 | flex-direction: column; 11 | margin: 0 0 15px 0; 12 | 13 | #query-input { 14 | height: 100px; 15 | background-color: #0d1122; 16 | color: #ffffff; 17 | resize: none; 18 | border: none; 19 | padding: 10px; 20 | 21 | &:focus { 22 | outline: none; 23 | } 24 | } 25 | 26 | #query-submit { 27 | height: 50px; 28 | background-color: $stratos-yellow; 29 | border: none; 30 | 31 | &:hover { 32 | background-color: $stratos-green; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/global.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | /* 4 | GLOBAL DEFAULTS: 5 | - Box-Sizing: Margin & Padding is included within the height/width adjustments 6 | - Margin & Padding: override the pre-built margin & padding to absolute zero 7 | - Font: change default font to selected variable 8 | */ 9 | 10 | html, 11 | body { 12 | box-sizing: border-box; 13 | margin: 0px; 14 | padding: 0px; 15 | font-family: $font-inter; 16 | font-weight: 700; 17 | } 18 | 19 | /* 20 | GLOBAL INHERITANCE: 21 | - Box-Sizing: Making sure that all elements will inherit the Border-Box Global Default 22 | - Font: Making sure that all elements will inherit the selected font variable 23 | */ 24 | 25 | *, 26 | *::before, 27 | *::after { 28 | box-sizing: inherit; 29 | font-family: $font-inter; 30 | font-weight: 700; 31 | } 32 | -------------------------------------------------------------------------------- /__tests__/enzyme.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { configure, shallow } from 'enzyme'; 3 | import Adapter from 'enzyme-adapter-react-16'; 4 | import Container from '../client/Container'; 5 | import LineGraph from '../client/components/LineGraph'; 6 | import Sidebar from '../client/components/Sidebar'; 7 | import { propTypes } from 'react-codemirror'; 8 | // import toJson from 'enzyme-to-json'; 9 | 10 | configure({ adapter: new Adapter() }); 11 | 12 | describe('renders without crashing', () => { 13 | beforeEach(() => { 14 | queryHistory: ['SELECT * FROM address;']; 15 | }); 16 | 17 | xit('renders Container', () => { 18 | shallow(); 19 | }); 20 | it('renders LineGraph', () => { 21 | shallow(); 22 | }); 23 | }); 24 | 25 | // describe('math', () => { 26 | // it('test', () => { 27 | // expect(2).toEqual(2); 28 | // }); 29 | // }); 30 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); 2 | 3 | /************************************************************ 4 | ************************ TYPOGRAPHY ************************ 5 | ************************************************************/ 6 | 7 | // FONT 8 | $font-inter: 'Inter', sans-serif; 9 | 10 | /************************************************************ 11 | ************************** COLORS ************************** 12 | ************************************************************/ 13 | 14 | // SIGNATURE BRAND COLORS 15 | $stratos-red: #ff0086; 16 | $stratos-yellow: #ffb600; 17 | $stratos-green: #3fe078; 18 | $stratos-blue: #399cff; 19 | 20 | // BACKGROUND COLOR(S) 21 | $background-darkmode-dark: #2a2b47; 22 | $background-darkmode-darker: #1b1b2c; 23 | $background-darkmode-darkest: #0c0c11; 24 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/awsModal.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #aws-modal { 4 | display: flex; 5 | flex-direction: column; 6 | 7 | p { 8 | color: $stratos-red; 9 | margin: 0 auto 10px auto; 10 | } 11 | 12 | .primary-button { 13 | margin: 10px 0 0 0; 14 | height: 30px; 15 | background-color: $stratos-red; 16 | border: none; 17 | } 18 | 19 | .secondary-button { 20 | margin: 10px 0 0 0; 21 | height: 30px; 22 | background-color: rgba(0, 0, 0, 0); 23 | border: 1px solid $stratos-red; 24 | color: $stratos-red; 25 | } 26 | 27 | #aws-modal-form { 28 | display: flex; 29 | flex-direction: column; 30 | 31 | input { 32 | text-align: center; 33 | border: none; 34 | margin: 10px 0; 35 | height: 30px; 36 | width: 100%; 37 | background-color: $background-darkmode-darker; 38 | color: $stratos-yellow; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 OSLabs Beta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/uploadModal.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #upload-modal { 4 | display: flex; 5 | flex-direction: column; 6 | height: auto; 7 | 8 | h1 { 9 | font-family: $font-inter; 10 | font-weight: 800; 11 | font-size: 52pt; 12 | color: $stratos-blue; 13 | line-height: 2rem; 14 | margin: 20px auto 0 auto; 15 | } 16 | 17 | p { 18 | color: #ffffff; 19 | margin: 20px auto 30px auto; 20 | } 21 | 22 | #upload-form { 23 | margin: 0 auto 20px auto; 24 | 25 | .choose-file-button { 26 | color: $stratos-yellow; 27 | } 28 | 29 | .choose-file-button::-webkit-file-upload-button { 30 | background: $stratos-yellow; 31 | border: none; 32 | padding: 5px 10px; 33 | margin: 0 10px 0 0; 34 | } 35 | } 36 | 37 | .primary-button { 38 | margin: 10px 0 0; 39 | height: 30px; 40 | background-color: $stratos-green; 41 | border: none; 42 | } 43 | 44 | .secondary-button { 45 | margin: 10px 0 0 0; 46 | height: 30px; 47 | background-color: rgba(0, 0, 0, 0); 48 | border: 1px solid $stratos-green; 49 | color: $stratos-green; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/container.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | /************************************************************ 4 | ********************** MAIN CONTAINER ********************** 5 | ************************************************************/ 6 | 7 | #main-container { 8 | display: flex; 9 | height: 100vh; 10 | } 11 | 12 | /************************************************************ 13 | ************************ LEFT PANEL ************************ 14 | ************************************************************/ 15 | 16 | #left-panel { 17 | display: flex; 18 | background-color: $background-darkmode-dark; 19 | } 20 | 21 | /************************************************************ 22 | ************************ RIGHT PANEL *********************** 23 | ************************************************************/ 24 | 25 | #right-panel { 26 | display: flex; 27 | flex-direction: column; 28 | height: 100%; 29 | width: 100%; 30 | background-color: $background-darkmode-darker; 31 | 32 | #announcement-bar { 33 | display: flex; 34 | width: 100%; 35 | height: 25px; 36 | background-color: $stratos-red; 37 | 38 | h1 { 39 | display: flex; 40 | color: white; 41 | font-size: 15px; 42 | margin: auto; 43 | } 44 | } 45 | 46 | #main-feature { 47 | display: flex; 48 | flex-direction: row; 49 | height: 95%; 50 | 51 | #queries-results-panel { 52 | width: 60%; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/assets/stylesheets/scss/infoModal.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | 3 | #info-modal { 4 | font-family: $font-inter; 5 | height: 80%; 6 | width: 60%; 7 | text-align: center; 8 | 9 | img { 10 | margin: 0 auto; 11 | } 12 | 13 | span { 14 | color: $stratos-blue; 15 | } 16 | 17 | a { 18 | color: $stratos-blue; 19 | text-decoration: none; 20 | } 21 | 22 | h1 { 23 | color: $stratos-yellow; 24 | font-family: $font-inter; 25 | font-size: 32pt; 26 | font-weight: 700; 27 | } 28 | 29 | h2 { 30 | color: $stratos-blue; 31 | font-family: $font-inter; 32 | font-size: 18pt; 33 | font-weight: 700; 34 | } 35 | 36 | h3 { 37 | color: $stratos-blue; 38 | font-family: $font-inter; 39 | font-size: 18pt; 40 | font-weight: 700; 41 | } 42 | 43 | p { 44 | color: #ffffff; 45 | } 46 | 47 | strong { 48 | color: $stratos-red; 49 | } 50 | 51 | em { 52 | color: $stratos-green; 53 | } 54 | 55 | &::-webkit-scrollbar { 56 | display: none; 57 | } 58 | 59 | #info-composition { 60 | display: flex; 61 | flex-direction: column; 62 | margin: 0 10px; 63 | } 64 | 65 | .secondary-button { 66 | margin: 10px 0 0 0; 67 | height: 30px; 68 | background-color: rgba(0, 0, 0, 0); 69 | border: none; 70 | color: $stratos-red; 71 | text-align: right; 72 | font-size: 25px; 73 | font-family: $font-inter; 74 | 75 | &:focus { 76 | outline: none; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /client/components/UploadModal.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modal from 'react-modal'; 3 | 4 | // uploadModalState state types 5 | interface uploadModalState { 6 | modalIsOpen: boolean; 7 | closeModal: any; 8 | fileUpdate: any; 9 | fileUpload: any; 10 | selectedFile: any; 11 | } 12 | 13 | //uploadModal styling 14 | const customStyles = { 15 | content: { 16 | top: '50%', 17 | left: '50%', 18 | right: 'auto', 19 | bottom: 'auto', 20 | marginRight: '-50%', 21 | transform: 'translate(-50%, -50%)', 22 | backgroundColor: '#2a2b47', 23 | border: 'none', 24 | }, 25 | overlay: { 26 | backgroundColor: 'rgba(12, 12, 17, 0.75)', 27 | }, 28 | }; 29 | 30 | Modal.setAppElement('#root'); 31 | 32 | // Functional Component, UploadModal 33 | const UploadModal: React.FC = (props: uploadModalState) => { 34 | return ( 35 |
36 | {/* Modal prop drilled and rendered in sidebar */} 37 | 44 |

IMPORT

45 |

.sql amd .txt Format Only

46 |
52 | 58 |
59 | 66 | 69 |
70 |
71 | ); 72 | }; 73 | 74 | export default UploadModal; 75 | -------------------------------------------------------------------------------- /client/components/Table.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface TableProps { 4 | queryTable: []; 5 | } 6 | 7 | const Table: React.FC = (props: TableProps) => { 8 | // QUERYTABLE: ARRAY OF OBJECTS (OUR RETURNED QUERY) 9 | const queryTable: any = props.queryTable; 10 | 11 | // TABLE HEADER: ARRAY OF COLUMN NAMES 12 | const tableHeader: any = 13 | queryTable.length === 0 ? null : Object.keys(queryTable[0]); 14 | 15 | // FUNCTION THAT WILL RETURN OUR TABLE HEADER WITH OUR COLUMN NAMES 16 | const tableHeaderCreator = () => { 17 | // IF TABLEHEADER HAS ONE ELEMENT OR MORE 18 | if (tableHeader) { 19 | return tableHeader.map((el: any, index: number) => { 20 | return {el}; 21 | }); 22 | } 23 | }; 24 | 25 | // FUNCTION THAT WILL RETURN OUR TABLE BODY ROWS 26 | const tableBodyCreator = () => { 27 | // FUNCTION THAT WILL RETURN OUR TABLE BODY DATA CELLS 28 | const iteratorFunc = (array: any) => { 29 | return array.map((values: any, index: number) => { 30 | return {values}; 31 | }); 32 | }; 33 | // IF TABLEHEADER HAS ONE ELEMENT OR MORE 34 | if (tableHeader) { 35 | return queryTable.map((obj: any, index: number) => { 36 | const target = Object.values(obj); 37 | // INVOKES OUR ITERATORFUNC FUNCTION THAT WILL GENERATE OUR TABLE DATA CELLS 38 | return ( 39 | 40 | {iteratorFunc(target)} 41 | 42 | ); 43 | }); 44 | } 45 | }; 46 | 47 | if (queryTable.length === 0) { 48 | return
; 49 | } else { 50 | return ( 51 |
52 | 53 | 54 | {tableHeaderCreator()} 55 | {tableBodyCreator()} 56 | 57 |
58 |
59 | ); 60 | } 61 | }; 62 | 63 | export default Table; 64 | -------------------------------------------------------------------------------- /client/components/LineGraph.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Line, defaults } from 'react-chartjs-2'; 3 | 4 | // Line graph props (prop drilled from Container component) 5 | interface LineGraphProps { 6 | queries: {}[]; 7 | queryStatistics: number[]; 8 | queryHistory: any; 9 | } 10 | 11 | // Linegraph class component 12 | class LineGraph extends Component { 13 | constructor(props: LineGraphProps) { 14 | super(props); 15 | } 16 | 17 | render() { 18 | // destructured queries, queryStatistics, and queryHistory from props 19 | const { queries, queryStatistics, queryHistory } = this.props; 20 | // function to create array of labels for X axis of Line graph 21 | const labelData = () => { 22 | let newArr = []; 23 | for (let i = 0; i < queryHistory.length; i++) { 24 | newArr.push(queryHistory[i]); 25 | } 26 | return newArr; 27 | }; 28 | 29 | const data = { 30 | labels: labelData(), 31 | datasets: [ 32 | { 33 | label: 'Run Time', 34 | fill: true, 35 | lineTension: 0.5, 36 | backgroundColor: '#399cff', 37 | borderColor: 'rgba(247,247,247,247)', 38 | borderWidth: 2, 39 | data: queryStatistics, 40 | }, 41 | ], 42 | }; 43 | 44 | return ( 45 |
46 | 69 |
70 | ); 71 | } 72 | } 73 | 74 | export default LineGraph; 75 | -------------------------------------------------------------------------------- /client/components/AwsModal.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modal from 'react-modal'; 3 | 4 | // initial AWS Modal State types 5 | interface awsModalState { 6 | connect: any; 7 | modalIsOpen: boolean; 8 | closeModal: any; 9 | awsInfo: any; 10 | awsInfoChange: any; 11 | } 12 | 13 | // Modal custom styles 14 | const customStyles = { 15 | content: { 16 | top: '50%', 17 | left: '50%', 18 | right: 'auto', 19 | bottom: 'auto', 20 | marginRight: '-50%', 21 | transform: 'translate(-50%, -50%)', 22 | backgroundColor: '#151524', 23 | border: 'none', 24 | }, 25 | overlay: { 26 | backgroundColor: 'rgba(12, 12, 17, 0.75)', 27 | }, 28 | }; 29 | 30 | Modal.setAppElement('#root'); 31 | 32 | // Functional Component, AWS Modal 33 | // Modal toggles on when Cloud Icon is clicked 34 | const AwsModal: React.FC = (props: awsModalState) => { 35 | return ( 36 |
37 | 44 | 49 |
50 | 57 | 64 | 71 | 78 | 85 | 88 |
89 | 92 |
93 |
94 | ); 95 | }; 96 | 97 | export default AwsModal; 98 | -------------------------------------------------------------------------------- /client/components/CodeEditor.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { UnControlled as CodeMirror } from 'react-codemirror2'; 3 | import 'codemirror/lib/codemirror.css'; 4 | import 'codemirror/mode/sql/sql'; 5 | import 'codemirror/theme/blackboard.css'; 6 | 7 | // initial Code Editor State types 8 | interface CodeEditorState { 9 | schemaEntry: string; 10 | data: object; 11 | schemaName: string; 12 | schemaChange: any; 13 | schemaSubmit: any; 14 | injectedCode: string; 15 | emptyInject: any; 16 | } 17 | 18 | // Functional component, Code Editor 19 | const CodeEditor: React.FC = (props: CodeEditorState) => { 20 | // Codemirror module configuration options 21 | const options = { 22 | lineNumbers: true, // DIV "CODEMIRROR-GUTTERS CODEMIRROR-LINENUMBERS" 23 | mode: 'sql', 24 | theme: 'blackboard', 25 | lineWrapping: true, 26 | scrollbarStyle: 'null', 27 | viewportMargin: Infinity, 28 | tabSize: 2, 29 | }; 30 | 31 | // check if injectedCode in state is not empty 32 | // if user imports file, injectedCode will not be empty 33 | const injectCheck = () => { 34 | if (props.injectedCode) { 35 | return ( 36 |
37 | props.schemaChange(e)} 40 | options={options} 41 | /> 42 |
43 | ); 44 | } else { 45 | return ( 46 |
47 | props.schemaChange(e)} 49 | options={options} 50 | /> 51 |
52 | ); 53 | } 54 | }; 55 | 56 | return ( 57 |
58 | {injectCheck()} 59 |
60 | 68 | 69 | 70 | 78 | 79 | 80 |
81 |
82 | ); 83 | }; 84 | 85 | export default CodeEditor; 86 | -------------------------------------------------------------------------------- /demo/sd_postgres_create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.owners ( 2 | "_id" serial NOT NULL, 3 | "email" varchar UNIQUE NOT NULL, 4 | "firstName" varchar (50) NOT NULL, 5 | "lastName" varchar (50) NOT NULL, 6 | "password" varchar NOT NULL, 7 | "address_id" bigint NOT NULL, 8 | CONSTRAINT "owners_pk" PRIMARY KEY ("_id") 9 | ) WITH ( 10 | OIDS=FALSE 11 | ); 12 | 13 | CREATE TABLE public.address ( 14 | "_id" serial NOT NULL, 15 | "zipcode" integer NOT NULL, 16 | "street" varchar NOT NULL, 17 | "city" varchar NOT NULL, 18 | "state" varchar NOT NULL, 19 | CONSTRAINT "address_pk" PRIMARY KEY ("_id") 20 | ) WITH ( 21 | OIDS=FALSE 22 | ); 23 | 24 | CREATE TABLE public.dogs ( 25 | "_id" serial NOT NULL, 26 | "name" varchar NOT NULL, 27 | "breed" varchar NOT NULL, 28 | "age" int NOT NULL, 29 | "owner_id" int NOT NULL, 30 | CONSTRAINT "dogs_pk" PRIMARY KEY ("_id") 31 | ) WITH ( 32 | OIDS=FALSE 33 | ); 34 | 35 | CREATE TABLE public.cats ( 36 | "_id" serial NOT NULL, 37 | "name" varchar NOT NULL, 38 | "breed" varchar NOT NULL, 39 | "age" int NOT NULL, 40 | "owner_id" bigint NOT NULL, 41 | CONSTRAINT "cats_pk" PRIMARY KEY ("_id") 42 | ) WITH ( 43 | OIDS=FALSE 44 | ); 45 | 46 | ALTER TABLE public.owners ADD FOREIGN KEY ("address_id") REFERENCES public.address("_id"); 47 | ALTER TABLE public.cats ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 48 | ALTER TABLE public.dogs ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 49 | 50 | INSERT INTO public.address VALUES (1, 92663, '123 daisy lane', 'oc', 'california'); 51 | INSERT INTO public.address VALUES (2, 92663, '123 orchid lane', 'los angeles', 'california'); 52 | INSERT INTO public.address VALUES (3, 92663, '123 lily lane', 'sb', 'california'); 53 | INSERT INTO public.address VALUES (4, 92663, '123 basil lane', 'nyc', 'ny'); 54 | INSERT INTO public.address VALUES (5, 92663, '123 rose avenue', 'san diego', 'california'); 55 | 56 | INSERT INTO public.owners VALUES (1, 'sp@gmail.cocm', 'Sophia', 'Pak', 'helloworld123', 1); 57 | INSERT INTO public.owners VALUES (2, 'jk@gmail.com', 'Joal', 'Kim', 'helloworld456', 2); 58 | INSERT INTO public.owners VALUES (3, 'ts@gmail.com', 'Tommy', 'Song', 'helloworld789', 3); 59 | INSERT INTO public.owners VALUES (4, 'tm@gmail.com', 'Tyler', 'Morgan', 'helloworld0-=', 4); 60 | INSERT INTO public.owners VALUES (5, 'ns@gmail.com', 'Nicholas', 'Shay', 'helloworld321', 5); 61 | 62 | INSERT INTO public.dogs VALUES (1, 'Pancake', 'Pembroke Welsh Corgi', 6, 1); 63 | INSERT INTO public.dogs VALUES (2, 'Honey', 'Pembroke Welsh Corgi', 1, 1); 64 | INSERT INTO public.dogs VALUES (3, 'Oreo', 'Dalmatian', 17, 2); 65 | INSERT INTO public.dogs VALUES (4, 'Rex', 'Belgian Malinois', 5, 1); 66 | INSERT INTO public.dogs VALUES (5, 'Duke', 'Pembroke Welsh Corgi', 7, 5); 67 | 68 | INSERT INTO public.cats VALUES (1, 'Mr. Flufflers', 'Ragdoll', 1, 3); 69 | INSERT INTO public.cats VALUES (2, 'Mr. Pickles', 'British Short Hair', 2, 5); 70 | 71 | SELECT setval('public.owners__id_seq', 6, false); 72 | SELECT setval('public.address__id_seq', 6, false); 73 | SELECT setval('public.dogs__id_seq', 6, false); 74 | SELECT setval('public.cats__id_seq', 3, false); -------------------------------------------------------------------------------- /uploads/1603340566741-sd_postgres_create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.owners ( 2 | "_id" serial NOT NULL, 3 | "email" varchar UNIQUE NOT NULL, 4 | "firstName" varchar (50) NOT NULL, 5 | "lastName" varchar (50) NOT NULL, 6 | "password" varchar NOT NULL, 7 | "address_id" bigint NOT NULL, 8 | CONSTRAINT "owners_pk" PRIMARY KEY ("_id") 9 | ) WITH ( 10 | OIDS=FALSE 11 | ); 12 | 13 | CREATE TABLE public.address ( 14 | "_id" serial NOT NULL, 15 | "zipcode" integer NOT NULL, 16 | "street" varchar NOT NULL, 17 | "city" varchar NOT NULL, 18 | "state" varchar NOT NULL, 19 | CONSTRAINT "address_pk" PRIMARY KEY ("_id") 20 | ) WITH ( 21 | OIDS=FALSE 22 | ); 23 | 24 | CREATE TABLE public.dogs ( 25 | "_id" serial NOT NULL, 26 | "name" varchar NOT NULL, 27 | "breed" varchar NOT NULL, 28 | "age" int NOT NULL, 29 | "owner_id" int NOT NULL, 30 | CONSTRAINT "dogs_pk" PRIMARY KEY ("_id") 31 | ) WITH ( 32 | OIDS=FALSE 33 | ); 34 | 35 | CREATE TABLE public.cats ( 36 | "_id" serial NOT NULL, 37 | "name" varchar NOT NULL, 38 | "breed" varchar NOT NULL, 39 | "age" int NOT NULL, 40 | "owner_id" bigint NOT NULL, 41 | CONSTRAINT "cats_pk" PRIMARY KEY ("_id") 42 | ) WITH ( 43 | OIDS=FALSE 44 | ); 45 | 46 | ALTER TABLE public.owners ADD FOREIGN KEY ("address_id") REFERENCES public.address("_id"); 47 | ALTER TABLE public.cats ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 48 | ALTER TABLE public.dogs ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 49 | 50 | INSERT INTO public.address VALUES (1, 92663, '123 daisy lane', 'oc', 'california'); 51 | INSERT INTO public.address VALUES (2, 92663, '123 orchid lane', 'los angeles', 'california'); 52 | INSERT INTO public.address VALUES (3, 92663, '123 lily lane', 'sb', 'california'); 53 | INSERT INTO public.address VALUES (4, 92663, '123 basil lane', 'nyc', 'ny'); 54 | INSERT INTO public.address VALUES (5, 92663, '123 rose avenue', 'san diego', 'california'); 55 | 56 | INSERT INTO public.owners VALUES (1, 'sp@gmail.cocm', 'Sophia', 'Pak', 'helloworld123', 1); 57 | INSERT INTO public.owners VALUES (2, 'jk@gmail.com', 'Joal', 'Kim', 'helloworld456', 2); 58 | INSERT INTO public.owners VALUES (3, 'ts@gmail.com', 'Tommy', 'Song', 'helloworld789', 3); 59 | INSERT INTO public.owners VALUES (4, 'tm@gmail.com', 'Tyler', 'Morgan', 'helloworld0-=', 4); 60 | INSERT INTO public.owners VALUES (5, 'ns@gmail.com', 'Nicholas', 'Shay', 'helloworld321', 5); 61 | 62 | INSERT INTO public.dogs VALUES (1, 'Pancake', 'Pembroke Welsh Corgi', 6, 1); 63 | INSERT INTO public.dogs VALUES (2, 'Honey', 'Pembroke Welsh Corgi', 1, 1); 64 | INSERT INTO public.dogs VALUES (3, 'Oreo', 'Dalmatian', 17, 2); 65 | INSERT INTO public.dogs VALUES (4, 'Rex', 'Belgian Malinois', 5, 1); 66 | INSERT INTO public.dogs VALUES (5, 'Duke', 'Pembroke Welsh Corgi', 7, 5); 67 | 68 | INSERT INTO public.cats VALUES (1, 'Mr. Flufflers', 'Ragdoll', 1, 3); 69 | INSERT INTO public.cats VALUES (2, 'Mr. Pickles', 'British Short Hair', 2, 5); 70 | 71 | SELECT setval('public.owners__id_seq', 6, false); 72 | SELECT setval('public.address__id_seq', 6, false); 73 | SELECT setval('public.dogs__id_seq', 6, false); 74 | SELECT setval('public.cats__id_seq', 3, false); -------------------------------------------------------------------------------- /uploads/1603340663035-sd_postgres_create.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.owners ( 2 | "_id" serial NOT NULL, 3 | "email" varchar UNIQUE NOT NULL, 4 | "firstName" varchar (50) NOT NULL, 5 | "lastName" varchar (50) NOT NULL, 6 | "password" varchar NOT NULL, 7 | "address_id" bigint NOT NULL, 8 | CONSTRAINT "owners_pk" PRIMARY KEY ("_id") 9 | ) WITH ( 10 | OIDS=FALSE 11 | ); 12 | 13 | CREATE TABLE public.address ( 14 | "_id" serial NOT NULL, 15 | "zipcode" integer NOT NULL, 16 | "street" varchar NOT NULL, 17 | "city" varchar NOT NULL, 18 | "state" varchar NOT NULL, 19 | CONSTRAINT "address_pk" PRIMARY KEY ("_id") 20 | ) WITH ( 21 | OIDS=FALSE 22 | ); 23 | 24 | CREATE TABLE public.dogs ( 25 | "_id" serial NOT NULL, 26 | "name" varchar NOT NULL, 27 | "breed" varchar NOT NULL, 28 | "age" int NOT NULL, 29 | "owner_id" int NOT NULL, 30 | CONSTRAINT "dogs_pk" PRIMARY KEY ("_id") 31 | ) WITH ( 32 | OIDS=FALSE 33 | ); 34 | 35 | CREATE TABLE public.cats ( 36 | "_id" serial NOT NULL, 37 | "name" varchar NOT NULL, 38 | "breed" varchar NOT NULL, 39 | "age" int NOT NULL, 40 | "owner_id" bigint NOT NULL, 41 | CONSTRAINT "cats_pk" PRIMARY KEY ("_id") 42 | ) WITH ( 43 | OIDS=FALSE 44 | ); 45 | 46 | ALTER TABLE public.owners ADD FOREIGN KEY ("address_id") REFERENCES public.address("_id"); 47 | ALTER TABLE public.cats ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 48 | ALTER TABLE public.dogs ADD FOREIGN KEY ("owner_id") REFERENCES public.owners("_id"); 49 | 50 | INSERT INTO public.address VALUES (1, 92663, '123 daisy lane', 'oc', 'california'); 51 | INSERT INTO public.address VALUES (2, 92663, '123 orchid lane', 'los angeles', 'california'); 52 | INSERT INTO public.address VALUES (3, 92663, '123 lily lane', 'sb', 'california'); 53 | INSERT INTO public.address VALUES (4, 92663, '123 basil lane', 'nyc', 'ny'); 54 | INSERT INTO public.address VALUES (5, 92663, '123 rose avenue', 'san diego', 'california'); 55 | 56 | INSERT INTO public.owners VALUES (1, 'sp@gmail.cocm', 'Sophia', 'Pak', 'helloworld123', 1); 57 | INSERT INTO public.owners VALUES (2, 'jk@gmail.com', 'Joal', 'Kim', 'helloworld456', 2); 58 | INSERT INTO public.owners VALUES (3, 'ts@gmail.com', 'Tommy', 'Song', 'helloworld789', 3); 59 | INSERT INTO public.owners VALUES (4, 'tm@gmail.com', 'Tyler', 'Morgan', 'helloworld0-=', 4); 60 | INSERT INTO public.owners VALUES (5, 'ns@gmail.com', 'Nicholas', 'Shay', 'helloworld321', 5); 61 | 62 | INSERT INTO public.dogs VALUES (1, 'Pancake', 'Pembroke Welsh Corgi', 6, 1); 63 | INSERT INTO public.dogs VALUES (2, 'Honey', 'Pembroke Welsh Corgi', 1, 1); 64 | INSERT INTO public.dogs VALUES (3, 'Oreo', 'Dalmatian', 17, 2); 65 | INSERT INTO public.dogs VALUES (4, 'Rex', 'Belgian Malinois', 5, 1); 66 | INSERT INTO public.dogs VALUES (5, 'Duke', 'Pembroke Welsh Corgi', 7, 5); 67 | 68 | INSERT INTO public.cats VALUES (1, 'Mr. Flufflers', 'Ragdoll', 1, 3); 69 | INSERT INTO public.cats VALUES (2, 'Mr. Pickles', 'British Short Hair', 2, 5); 70 | 71 | SELECT setval('public.owners__id_seq', 6, false); 72 | SELECT setval('public.address__id_seq', 6, false); 73 | SELECT setval('public.dogs__id_seq', 6, false); 74 | SELECT setval('public.cats__id_seq', 3, false); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | entry: './client/App.tsx', 6 | mode: process.env.NODE_ENV, 7 | output: { 8 | filename: 'bundle.js', 9 | path: path.resolve(__dirname, 'dist'), 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.s?css$/, 15 | use: [ 16 | { 17 | loader: 'style-loader', 18 | }, 19 | { 20 | loader: 'css-loader', 21 | }, 22 | { 23 | loader: 'postcss-loader', 24 | options: { 25 | postcssOptions: { 26 | plugins: ['autoprefixer'], 27 | }, 28 | }, 29 | }, 30 | { 31 | loader: 'sass-loader', 32 | }, 33 | ], 34 | }, 35 | { 36 | test: /\.jsx?/, 37 | exclude: /node_modules/, 38 | use: { 39 | loader: 'babel-loader', 40 | options: { 41 | presets: ['@babel/preset-env', '@babel/preset-react'], 42 | }, 43 | }, 44 | }, 45 | { 46 | test: /\.ts(x)?$/, 47 | exclude: /node_modules/, 48 | loader: 'ts-loader', 49 | }, 50 | { 51 | test: /\.(jpg|jpeg|png|ttf|svg)$/, 52 | use: [ 53 | 'file-loader', 54 | { 55 | loader: 'image-webpack-loader', 56 | options: { 57 | mozjpeg: { 58 | quality: 10, 59 | }, 60 | }, 61 | }, 62 | ], 63 | exclude: /node_modules/, 64 | }, 65 | ], 66 | }, 67 | resolve: { 68 | modules: [path.resolve(__dirname, 'node_modules')], 69 | extensions: [ 70 | '.js', 71 | '.jsx', 72 | '.json', 73 | '.scss', 74 | '.less', 75 | '.css', 76 | '.tsx', 77 | '.ts', 78 | ], 79 | }, 80 | devServer: { 81 | publicPath: '/dist/', 82 | contentBase: path.resolve(__dirname, '../StratosDB'), 83 | host: 'localhost', 84 | port: '8080', 85 | hot: true, 86 | compress: true, 87 | watchContentBase: true, 88 | watchOptions: { 89 | ignored: /node_modules/, 90 | }, 91 | proxy: { 92 | '/refresh': 'http://localhost:3000', 93 | '/results': 'http://localhost:3000', 94 | '/newSchema': 'http://localhost:3000', 95 | '/connect': 'http://localhost:3000', 96 | '/upload': 'http://localhost:3000', 97 | }, 98 | }, 99 | plugins: [ 100 | new HtmlWebpackPlugin({ 101 | filename: 'index.html', 102 | title: 'StratosDB', 103 | cspPlugin: { 104 | enabled: true, 105 | policy: { 106 | 'base-uri': "'self'", 107 | 'object-src': "'none'", 108 | 'script-src': ["'self'"], 109 | 'style-src': ["'self'"], 110 | }, 111 | hashEnable: { 112 | 'script-src': true, 113 | 'style-src': true, 114 | }, 115 | nonceEnabled: { 116 | 'script-src': true, 117 | 'style-src': true, 118 | }, 119 | }, 120 | }), 121 | ], 122 | }; 123 | -------------------------------------------------------------------------------- /server/controllers.ts: -------------------------------------------------------------------------------- 1 | import express, { query } from 'express'; 2 | import db from './server'; 3 | 4 | /** 5 | * NOTE TO TEAM: PSQL CLI TO RESET/WIPE/DROP ALL TABLES FROM DB (FOR TESTING/DEMO PURPOSES) 6 | * DROP SCHEMA public CASCADE; 7 | * CREATE SCHEMA public; 8 | */ 9 | 10 | /** 11 | * TYPESCRTIPT INTERFACE DECLARACTIONS 12 | * NOTE TO DEVS: WILL NEED TO ADD TO INTERFACE CONTROLLERSS 13 | * IF YOU ARE ADDING A NEW CONTROLLER 14 | */ 15 | interface controllers { 16 | createSchema: any; 17 | runTest: any; 18 | queryTable: any; 19 | } 20 | 21 | interface dataType { 22 | queryData: string; 23 | queryStatistics: string; 24 | } 25 | 26 | export const stratosController: controllers = { 27 | /** 28 | * CONTROLLER: CREATESCHEMA 29 | * WILL ENTER THE SCHEMA INTO THE CONNECTED DATABASE THAT WAS 30 | * INPUTTED BY THE USER FROM THE FRONTEND 31 | */ 32 | createSchema: ( 33 | req: express.Request, 34 | res: express.Response, 35 | next: express.NextFunction 36 | ) => { 37 | // DESTRUCTURING SCHEMAENTRY FROM REQ.BODY 38 | const { schemaEntry } = req.body; 39 | db.query(schemaEntry) 40 | .then(() => { 41 | return next(); 42 | }) 43 | .catch((error: string) => { 44 | console.log( 45 | 'Error in Controllers > createSchema > db.query > SCHEMA: ', 46 | error 47 | ); 48 | }); 49 | }, 50 | 51 | /** 52 | * CONTROLLER: QUERYTABLE 53 | * WILL RETURN THE DATA REQUESTED BY THE USER 54 | * INPUTTED QUERY STRING FROM FRONTEND 55 | */ 56 | queryTable: ( 57 | req: express.Request, 58 | res: express.Response, 59 | next: express.NextFunction 60 | ) => { 61 | // DESTRUCTURING QUERYENTRY FROM REQ.BODY 62 | const { queryEntry } = req.body; 63 | db.query(queryEntry) 64 | .then((results: any) => { 65 | res.locals.queryResult = results.rows; 66 | return next(); 67 | }) 68 | .catch((error: string) => { 69 | console.log( 70 | 'Error in Controller > queryTable > db.query > QUERY RESULT: ', 71 | error 72 | ); 73 | }); 74 | }, 75 | 76 | /** 77 | * CONTROLLER: RUNTEST 78 | * WILL RETURN THE DATA STATISTICS FROM THE RAN QUERY STRING 79 | */ 80 | runTest: ( 81 | req: express.Request, 82 | res: express.Response, 83 | next: express.NextFunction 84 | ) => { 85 | // DESTRUCTURING QUERYENTRY FROM REQ.BODY 86 | const { queryEntry } = req.body; 87 | // OBJECT DECLARATION THAT WILL HOLD OUR RESULTS FROM OUR DB.QUERY 88 | const newData: dataType = { 89 | queryData: '', 90 | queryStatistics: '', 91 | }; 92 | // VARIABLE STORING THE NEW.DATA.QUERYSTATISTICS[0] (WHICH IS AN OBJECT) PROPERTY NAME BECAUSE OF TS COMPILE ERROR 93 | const queryPlan: any = 'QUERY PLAN'; 94 | // RUNNING EXPLAIN BY PASSING IN A CONCANTENATED STRING OF EXPLAIN... AND THE SCHEMAENTRY QUERY STRING 95 | db.query('EXPLAIN (FORMAT JSON, ANALYZE) ' + queryEntry) 96 | .then((queryStatistics: any) => { 97 | // RE-ASSIGNING OUR NEWDATA.QUERYSTATISTICS TO OUR RETURNED DATA ANALYTICS 98 | newData.queryStatistics = queryStatistics.rows[0][queryPlan]; 99 | res.locals.explain = newData.queryStatistics; 100 | return next(); 101 | }) 102 | .catch((error: string) => { 103 | console.log( 104 | 'Error in Controllers > runTest > db.query > EXPLAIN: ', 105 | error 106 | ); 107 | }); 108 | }, 109 | }; 110 | -------------------------------------------------------------------------------- /client/components/Sidebar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import AwsModal from './AwsModal'; 3 | import InfoModal from './InfoModal'; 4 | import UploadModal from './UploadModal'; 5 | 6 | // initial Sidebar state types 7 | interface SidebarState { 8 | refresh: any; 9 | connect: any; 10 | awsOpenModal: any; 11 | awsCloseModal: any; 12 | awsModalIsOpen: boolean; 13 | awsInfo: any; 14 | awsInfoChange: any; 15 | infoOpenModal: any; 16 | infoCloseModal: any; 17 | infoModalIsOpen: boolean; 18 | fileUpload: any; 19 | fileUpdate: any; 20 | selectedFile: any; 21 | uploadModalIsOpen: boolean; 22 | uploadOpenModal: any; 23 | uploadCloseModal: any; 24 | } 25 | 26 | // Functional Component, Sidebar 27 | const Sidebar: React.FC = (props: SidebarState) => { 28 | return ( 29 | 105 | ); 106 | }; 107 | 108 | export default Sidebar; 109 | -------------------------------------------------------------------------------- /server/server.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import bodyParser from 'body-parser'; 3 | import { stratosController } from './controllers'; 4 | const { Pool } = require('pg'); 5 | const app: express.Application = express(); 6 | const multer = require('multer'); 7 | const fs = require('fs'); 8 | 9 | /** 10 | * TYPESCRTIPT INTERFACE DECLARACTIONS 11 | */ 12 | interface queryResultObjType { 13 | queryStatistics: any; 14 | queryTable: any; 15 | } 16 | 17 | interface awsTypes { 18 | user: string; 19 | host: string; 20 | database: string; 21 | password: string; 22 | port: string; 23 | } 24 | 25 | const PORT = 3000; 26 | 27 | // OBJECT CONTAINING AWS INFO FROM THE FRONT END 28 | let awsInfo: awsTypes = { 29 | user: '', 30 | host: '', 31 | database: '', 32 | password: '', 33 | port: '', 34 | }; 35 | 36 | // DECLARING INITIAL POOL VARIABLE THAT WILL BE UPDATED ONCE APPLICATION REFRESHES 37 | let pool: any; 38 | 39 | // DECLARING INITIAL DB VARIABLE THAT WILL BE UPDATED ONCE APPLICATION REFRESHES 40 | const db: any = {}; 41 | 42 | app.use(bodyParser.json()); 43 | 44 | // SET STORAGE FOR NEW FILE IN LOCATION UPLOADS 45 | let storage = multer.diskStorage({ 46 | destination: (req: any, file: any, cb: any) => { 47 | cb(null, './uploads'); 48 | }, 49 | filename: (req: any, file: any, cb: any) => { 50 | cb(null, Date.now() + '-' + file.originalname); 51 | }, 52 | }); 53 | 54 | // DECLARING FILE UPLOAD 55 | let upload = multer({ storage: storage }); 56 | let type = upload.single('myFile'); 57 | 58 | // SERVER SIDE HANDLING OF FILE UPLOAD 59 | // NOT SURE IF THIS PART ACTUALLY WORKS 60 | app.post('/upload', type, (req, res, next) => { 61 | const file = req.body.file; 62 | // CHECKING IF FILE HAS ERRORS 63 | if (!file) { 64 | const error = new Error('Please upload a file'); 65 | res.status(400); 66 | return next(); 67 | } 68 | res.send(file); 69 | }); 70 | 71 | /** 72 | * APP.GET REQUEST (/REFRESH): WHEN REFRESHED, THE APP WILL RESET AWS CONNECTION INFO TO EMPTY VALUES 73 | */ 74 | app.get('/refresh', (req, res) => { 75 | awsInfo = { 76 | user: '', 77 | host: '', 78 | database: '', 79 | password: '', 80 | port: '', 81 | }; 82 | res.status(200).send('DATABASE CONNECTION HAS BEEN RESET'); 83 | }); 84 | 85 | /** 86 | * APP.POST REQUEST (/CONNECT): USER WILL CONNECT TO DB BASED ON THEIR INPUTTED AWS RDS INFORMATION 87 | */ 88 | app.post('/connect', (req, res) => { 89 | // REASSIGNING AWSINFO PROPERTY VALUES TO THE USER INPUTTED VALUES FROM THE FRONT END SIDEBAR CLOUD BUTTON MODAL 90 | awsInfo = { 91 | user: req.body.user, 92 | host: req.body.host, 93 | database: req.body.database, 94 | password: req.body.password, 95 | port: req.body.port, 96 | }; 97 | // ESTABLISHING A POOL CONNECTION BASED ON OUR NEWLY INPUTTED DB CONNECTION INFORMATION 98 | pool = new Pool(awsInfo); 99 | // ADDING A NEW PROPERTY TO OUR DB VARIABLE WITH OUR POOL METHOD THAT WILL ALLOW US TO QUERY OUR DB 100 | db['query'] = (text: string, params?: any, callback?: any) => { 101 | return pool.query(text, params, callback); 102 | }; 103 | res.status(200); 104 | }); 105 | 106 | /** 107 | * APP.POST REQUEST (/NEWSCHEMA): SEND IMPORTED/INPUTTED SCHEMAS TO CLOUD DB 108 | */ 109 | app.post('/newSchema', stratosController.createSchema, (req, res) => { 110 | // SENDING CLIENT STATUS FOR SCHEMA CREATION 111 | res.status(200).send('success'); 112 | }); 113 | 114 | /** 115 | * APP.POST REQUEST (/RESULTS): RUNNING QUERY REQUEST & TESTS ON THE SCHEMAS IN THE CLOUD 116 | */ 117 | app.post( 118 | '/results', 119 | stratosController.queryTable, 120 | stratosController.runTest, 121 | (req, res) => { 122 | // CONDENSING OUR RES.LOCALS VARIABLES INTO AN OBJECT TO SEND BACK TO THE FRONTEND TO BE PARSED 123 | const queryResultObj: queryResultObjType = { 124 | queryStatistics: res.locals.explain, 125 | queryTable: res.locals.queryResult, 126 | }; 127 | // SENDING CLIENT THE RESULTS FROM THE PERFORMANCE TEST 128 | res.status(200).send(queryResultObj); 129 | } 130 | ); 131 | 132 | /** 133 | * APP.LISTEN: PORT 3000 134 | */ 135 | app.listen(PORT, () => { 136 | console.log(`stratosDB server is running on port ${PORT}`); 137 | }); 138 | 139 | // EXPORTING OUR DB SO THAT WE CAN UTILIZE THE QUERY METHOD IN OUR CONTROLLERS.TS 140 | export default db; 141 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "StratosDB", 3 | "version": "0.5.0", 4 | "description": "StratosDB", 5 | "main": "App.tsx", 6 | "scripts": { 7 | "start": "NODE_ENV=production node server/server.ts", 8 | "build": "NODE_ENV=production webpack", 9 | "dev": "cross-env NODE_ENV=development concurrently \"nodemon server/server.ts\" \"webpack-dev-server --open --hot\"", 10 | "beta": "cross-env NODE_ENV=development concurrently \"nodemon server/server.ts\" \"webpack-dev-server --open --hot\"", 11 | "compile": "tsc", 12 | "test": "jest" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/morgan562/StratosDB.git" 17 | }, 18 | "nodemonConfig": { 19 | "ignore": [ 20 | "dist", 21 | "client", 22 | "node_modules", 23 | "assets", 24 | "stylesheets", 25 | ".env" 26 | ] 27 | }, 28 | "jest": { 29 | "moduleFileExtensions": [ 30 | "ts", 31 | "tsx", 32 | "js" 33 | ], 34 | "transform": { 35 | "^.+\\.(ts|tsx)$": "ts-jest" 36 | }, 37 | "setupFiles": [ 38 | "raf/polyfill" 39 | ], 40 | "globals": { 41 | "ts-jest": { 42 | "tsConfigFile": "tsconfig.json" 43 | } 44 | }, 45 | "testMatch": [ 46 | "**/__tests__/*.+(ts|tsx|js)" 47 | ] 48 | }, 49 | "keywords": [], 50 | "author": { 51 | "name": "stratosDB", 52 | "url": "http://www.stratosDB.io" 53 | }, 54 | "contributors": [ 55 | { 56 | "name": "Joal Kim", 57 | "email": "joalkims@gmail.com", 58 | "url": "https://github.com/joalk" 59 | }, 60 | { 61 | "name": "Sophia Pak", 62 | "email": "sophiakpak@gmail.com", 63 | "url": "https://github.com/sophiapak" 64 | }, 65 | { 66 | "name": "Tommy Song", 67 | "email": "tommysong123@gmail.com", 68 | "url": "https://github.com/tysong24" 69 | }, 70 | { 71 | "name": "Tyler Morgan", 72 | "email": "tylermor562@gmail.com", 73 | "url": "https://github.com/morgan562" 74 | } 75 | ], 76 | "license": "MIT", 77 | "bugs": { 78 | "url": "https://github.com/morgan562/StratosDB/issues" 79 | }, 80 | "homepage": "https://github.com/morgan562/StratosDB#readme", 81 | "dependencies": { 82 | "@reduxjs/toolkit": "^1.4.0", 83 | "@skidding/react-codemirror": "^1.0.2", 84 | "@types/enzyme": "^3.10.7", 85 | "@types/enzyme-adapter-react-16": "^1.0.6", 86 | "@types/jest": "^26.0.14", 87 | "@types/mocha": "^8.0.3", 88 | "@types/react-codemirror": "^1.0.3", 89 | "@types/react-modal": "^3.10.6", 90 | "@types/react-redux": "^7.1.9", 91 | "autoprefixer": "^10.0.1", 92 | "axios": "^0.20.0", 93 | "body-parser": "^1.19.0", 94 | "chart.js": "^2.9.3", 95 | "codemirror": "^5.58.1", 96 | "cors": "^2.8.5", 97 | "express": "^4.17.1", 98 | "multer": "^1.4.2", 99 | "node": "^14.13.0", 100 | "pg": "^8.3.3", 101 | "postcss": "^8.1.1", 102 | "raf": "^3.4.1", 103 | "react": "^16.13.1", 104 | "react-chartjs-2": "^2.10.0", 105 | "react-codemirror": "^1.0.0", 106 | "react-codemirror2": "^7.2.1", 107 | "react-dom": "^16.13.1", 108 | "react-modal": "^3.11.2", 109 | "react-redux": "^7.2.1", 110 | "sass": "^1.26.11", 111 | "ts-jest": "^26.4.1", 112 | "typescript": "^4.0.3" 113 | }, 114 | "devDependencies": { 115 | "@babel/core": "^7.11.6", 116 | "@babel/preset-env": "^7.11.5", 117 | "@babel/preset-react": "^7.10.4", 118 | "@tsconfig/node12": "^1.0.7", 119 | "@types/express": "^4.17.8", 120 | "@types/node": "^14.11.2", 121 | "@types/react": "^16.9.49", 122 | "@types/react-dom": "^16.9.8", 123 | "babel-loader": "^8.1.0", 124 | "babel-plugin-transform-class-properties": "^6.24.1", 125 | "concurrently": "^5.3.0", 126 | "cross-env": "^7.0.2", 127 | "css-loader": "^4.3.0", 128 | "enzyme": "^3.11.0", 129 | "enzyme-adapter-react-16": "^1.15.5", 130 | "file-loader": "^6.1.0", 131 | "html-webpack-plugin": "^4.5.0", 132 | "jest": "^26.6.0", 133 | "nodemon": "^2.0.4", 134 | "postcss-loader": "^4.0.3", 135 | "react-hot-loader": "^4.13.0", 136 | "sass-loader": "^10.0.2", 137 | "style-loader": "^1.2.1", 138 | "supertest": "^5.0.0", 139 | "ts-loader": "^8.0.4", 140 | "ts-node": "^9.0.0", 141 | "url-loader": "^4.1.0", 142 | "webpack": "^4.44.2", 143 | "webpack-cli": "^3.3.12", 144 | "webpack-dev-server": "^3.11.0" 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /client/components/InfoModal.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Modal from 'react-modal'; 3 | 4 | // initial Info Modal State types 5 | interface infoModalState { 6 | modalIsOpen: boolean; 7 | closeModal: any; 8 | } 9 | 10 | // Modal custom styles 11 | const customStyles = { 12 | content: { 13 | top: '50%', 14 | left: '50%', 15 | right: 'auto', 16 | bottom: 'auto', 17 | marginRight: '-50%', 18 | transform: 'translate(-50%, -50%)', 19 | backgroundColor: '#151524', 20 | border: 'none', 21 | }, 22 | overlay: { 23 | backgroundColor: 'rgba(12, 12, 17, 0.75)', 24 | }, 25 | }; 26 | 27 | Modal.setAppElement('#root'); 28 | 29 | // Functional Component, Info Modal 30 | // Modal toggles on when i Icon is clicked 31 | const InfoModal: React.FC = (props: infoModalState) => { 32 | return ( 33 |
34 | 41 |
42 | 45 | 50 |
51 |
52 |

Setup

53 |

54 | Click on the Cloud Icon (located on the Left Sidebar) and enter your 55 | AWS RDS Information and press Connect 56 |

57 |

58 | User: Database Username 59 |
60 | Host: AWS RDS Endpoint Link * 61 |
62 | Database: Database name ** 63 |
64 | Password: Database Password 65 |

66 |
67 | 68 |
69 |

70 | * Sourced from AWS RDS Database Instance Dashboard 71 |
72 | ** If Database name was left blank when the AWS RDS Datbase Instance 73 | was created, use postgres 74 |

75 |

Overview

76 |

Importing .sql and .txt Files

77 |

78 | 1. Click on the Import Icon (located on the Left Sidebar) 79 |
80 |
81 | 2. Choose the .SQL or .TXT file you would like to import 82 |
83 |
84 | 3. Select Import to populate your file's code base 85 | into the application's built-in code editor. 86 |

87 |
88 | 89 |
90 |

Schema Code Editor

91 |

92 | Use the Schema Code Editor to input any psql command queries (EG.{' '} 93 | CREATE TABLE, INSERT INTO) to 94 | create/read tables and/or data entries from your tethered AWS RDS 95 | database 96 |

97 |
98 | 103 |
104 |

Query Text Editor

105 |

106 | Enter your SELECT psql commands into the provided 107 | text editor and press Submit Query to initiate the 108 | performance analysis on your existing schema design 109 |

110 |

111 | EG. SELECT * FROM TABLE_NAME; 112 |

113 |
114 | 119 |
120 |

Return Table

121 |

122 | A scrollable table will render based on the SELECT{' '} 123 | query you have entered in the Query Text Editor 124 |

125 |
126 | 131 |
132 |

Visual Line Graph

133 |

134 | A visual line graph representation will render the performance time 135 | (milliseconds) for each successfully performed{' '} 136 | SELECT query *** 137 |

138 |
139 | 144 |
145 |

146 | *** You can hover each point in the line graph to view the query 147 | that was ran and its corresponding performance time (ms) 148 |

149 |
150 |

Beta

151 |

152 | StratosDB is currently still in Beta and our team will strive to 153 | continuously release updates and additional features. 154 |

155 |

1. If you would like to contribute to this open source project:

156 | 157 | Please feel free to submit a PR 158 | 159 |

160 | 2. If you happen to come across any issues while tinkering with the 161 | application: 162 |

163 | 164 | Please report the bug/issue by submitting a ticket on our Github 165 | Repository 166 | 167 |
168 |

Thank You

169 | 174 |
175 | 176 | Website |{' '} 177 | Github |{' '} 178 | Twitter 179 | 180 |
181 |
182 |
183 |
184 |
185 | ); 186 | }; 187 | 188 | export default InfoModal; 189 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 |
8 | 9 | StratosDB.io 10 | 11 |
12 | 13 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/oslabs-beta/StratosDB) 14 | ![License: MIT](https://img.shields.io/badge/License-MIT-orange.svg) 15 | ![Contributions Welcome](https://img.shields.io/badge/Contributions-welcome-blue.svg) 16 | [![Github stars](https://img.shields.io/github/stars/oslabs-beta/StratosDB?style=social)](https://github.com/oslabs-beta/StratosDB) 17 | [![Twitter](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fteamstratosdb)](https://twitter.com/TeamStratosDB) 18 | 19 |
20 | 21 |

StratosDB: An all-in-one tool for Cloud SQL

22 | 23 |
24 | 25 |
26 | 27 | ## Table of Contents 28 | 29 | - Beta Stage 30 | - Overview 31 | - Getting Started 32 | - Main Features 33 | - Built With 34 | - Core Team 35 | - License 36 | 37 |
38 | 39 | ## Beta Stage 40 | 41 | Team StratosDB will strive to continuously release updates and additional features. 42 | 43 | 1. If you would like to contribute to this project: 44 | 45 | - Please feel free to submit a PR 46 | 47 | 2. If you happen to come across any issues while tinkering with the application: 48 | - Please report the bug/issue by submitting a ticket located in the Issues Tab within this repository 49 | 50 |
51 | 52 | ## Overview 53 | 54 | With the current trajectory of technological improvements, businesses and applications are moving towards a “serverless” architecture. With cloud computing becoming more reliable, it just makes more sense for businesses to take the “pay as you go and avoid upfront costs” approach. 55 | 56 | Although cloud computing and serverless architecture has all these great qualities, not everything is rainbows and sunshine! Cloud services are still pretty new and user interfaces for these services are not very intuitive. Amazon’s AWS, itself, does not offer a platform that is intuitive for the users. The platform itself can be extremely confusing when using services such as AWS RDS. As such, third party applications are often used to alleviate these problems one at a time. 57 | 58 | In response, our team decided that we wanted to tackle this issue by creating a tool that can be used for all AWS RDS database instances. We would like to introduce StratosDB, a one stop shop for users of AWS RDS to create, test, and deploy their RDS database instances! StratosDB offers a platform built on NodeJS that connects to your specific AWS RDS instance with a streamlined GUI that makes using AWS RDS much more simple and efficient. 59 | 60 |
61 | 62 |
63 | 64 |
65 | 66 |
67 | 68 | ## Getting Started 69 | 70 | 1. Clone StratosDB to your local machine and point to the StratosDB directory: 71 | 72 | git clone https://github.com/oslabs-beta/StratosDB.git 73 | 74 | cd StratosDB 75 | 76 | 2. Install all required dependencies with the following script: 77 | 78 | npm install 79 | 80 | 3. Run the following script to open StratosDB on http://localhost:8080: 81 | 82 | npm run beta 83 | 84 | 4. Once StratosDB is opened on http://localhost:8080, click on the Cloud Icon (located on the Left Sidebar) and enter your AWS RDS Information and press Connect: 85 | 86 | User: Database Username 87 |
88 | Host: AWS RDS Endpoint Link \* 89 |
90 | Database: Database name \*\* 91 |
92 | Password: Database Password 93 | 94 |
95 | 98 |
99 | 100 | \* Sourced from AWS RDS Database Instance Dashboard 101 | 102 | \*\* If Database name was left blank when the AWS RDS Datbase Instance was created, use postgres 103 | 104 |
105 | 106 | ## Main Features 107 | 108 | ### Importing .sql & .txt Files 109 | 110 | 1. Click on the Import Icon (located on the Left Sidebar) 111 | 2. Choose the .SQL or .TXT file you would like to import 112 | 3. Select Import to populate your file's code base into the application's built-in code editor. 113 | 114 |
115 | 116 |
117 | 118 | ### Schema Code Editor 119 | 120 | Use the Schema Code Editor to input any psql command queries (EG. CREATE TABLE, INSERT INTO) to create/read tables 121 | and/or data entries from your tethered AWS RDS database 122 | 123 |
124 | 127 |
128 | 129 | ### Query Text Editor 130 | 131 | Enter your SELECT psql commands into the provided 132 | text editor and press Submit Query to initiate the 133 | performance analysis on your existing schema design 134 | 135 | EG. SELECT \* FROM TABLE_NAME; 136 | 137 |
138 | 141 |
142 | 143 | ### Return Table 144 | 145 | A scrollable table will render based on the SELECT query you have entered in the Query Text Editor 146 | 147 |
148 | 151 |
152 | 153 | ### Visual Line Graph 154 | 155 | A visual line graph representation will render the performance time 156 | (milliseconds) for each successfully performed SELECT query \*\* 157 | 158 |
159 | 162 |
163 | 164 | \*\* You can hover over each point in the line graph to view the query 165 | that was ran and its corresponding the performance time (ms) 166 | 167 | ### Information Modal 168 | 169 | A dedicated modal (located on the Left Sidebar) guides first time users through the application's features in detail and provides more information about StratosDB 170 | 171 |
172 | 175 |
176 | 177 |
178 | 179 | ## Built With 180 | 181 | - React 182 | - TypeScript 183 | - CodeMirror 184 | - React-ChartJS 185 | - Node.JS 186 | - Express 187 | - Multer 188 | - AWS RDS 189 | - PostgreSQL 190 | 191 |
192 | 193 | ## Core Team 194 | 195 |
196 | 197 | 198 | 203 | 208 | 213 | 218 | 219 |
199 | 200 |
201 | Joal Kim 202 |
204 | 205 |
206 | Sophia Pak 207 |
209 | 210 |
211 | Tommy Song 212 |
214 | 215 |
216 | Tyler Morgan 217 |
220 |
221 | 222 |
223 | 224 | ## License 225 | 226 | This project is licensed under the MIT License 227 | -------------------------------------------------------------------------------- /client/Container.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Announcement from './components/Announcement'; 3 | import CodeEditor from './components/CodeEditor'; 4 | import Sidebar from './components/Sidebar'; 5 | import LineGraph from './components/LineGraph'; 6 | import axios from 'axios'; 7 | import Table from './components/Table'; 8 | 9 | interface ContainerState { 10 | queries: any; 11 | queryStatistics: any; 12 | queryHistory: any; 13 | queryEntry: any; 14 | queryTable: any; 15 | //Announcement 16 | announcement: string; 17 | //codeEditorState 18 | schemaEntry: string; 19 | schemaName: string; 20 | //Sidebar 21 | awsModalIsOpen: boolean; 22 | awsInfo: { 23 | user: string; 24 | host: string; 25 | database: string; 26 | password: string; 27 | port: string; 28 | }; 29 | infoModalIsOpen: boolean; 30 | selectedFile: any; 31 | uploadModalIsOpen: boolean; 32 | injectedCode: string; 33 | } 34 | 35 | interface HTMLInputEvent extends Event { 36 | target: HTMLInputElement & EventTarget; 37 | } 38 | 39 | // class Componenet, Container 40 | class Container extends Component<{}, ContainerState> { 41 | constructor(props: {}) { 42 | super(props); 43 | } 44 | 45 | // ContainerState types 46 | state: ContainerState = { 47 | queries: [], 48 | queryStatistics: [], 49 | queryHistory: [], 50 | queryEntry: '', 51 | queryTable: [], 52 | announcement: 'Welcome to StratosDB Beta', 53 | schemaEntry: '', 54 | schemaName: '', 55 | awsModalIsOpen: false, 56 | awsInfo: { 57 | user: '', 58 | host: '', 59 | database: '', 60 | password: '', 61 | port: '', 62 | }, 63 | infoModalIsOpen: false, 64 | selectedFile: 'hello', 65 | uploadModalIsOpen: false, 66 | injectedCode: '', 67 | }; 68 | 69 | // componentDidMount sends an axios request with result data once componenet is mounted 70 | componentDidMount() { 71 | axios.get('/refresh').catch((err) => console.error(err)); 72 | } 73 | 74 | // UPDATING SCHEMA STATE DURING TYPING 75 | schemaChange = (event: string) => { 76 | this.setState({ 77 | schemaEntry: event, 78 | }); 79 | }; 80 | 81 | // SUBMITTING SCHEMA CODE TO BACKEND 82 | schemaSubmit = (event: React.MouseEvent) => { 83 | event.preventDefault(); 84 | 85 | const schemaObj: any = { 86 | schemaEntry: this.state.injectedCode, 87 | }; 88 | axios.post('/newSchema', schemaObj).then((data) => { 89 | this.setState({ queries: data.data[0] }); 90 | }); 91 | }; 92 | 93 | // UPDATING QUERY STATE WHILE TYPING 94 | queryChange = (event: React.ChangeEvent) => { 95 | this.setState({ 96 | queryEntry: event.target.value, 97 | }); 98 | }; 99 | 100 | // SUBMITTING QUERY SEARCH TO BACKEND 101 | querySubmit = (event: React.MouseEvent) => { 102 | event.preventDefault(); 103 | let historyArr: any = this.state.queryHistory; 104 | historyArr.push(this.state.queryEntry); 105 | this.setState({ 106 | queryHistory: historyArr, 107 | }); 108 | 109 | // DIFFERENT OBJECT FOR QUERY ENTRY 110 | const queryObj: any = { 111 | queryEntry: this.state.queryEntry, 112 | }; 113 | let newArr: any = this.state.queryStatistics; 114 | axios.post('/results', queryObj).then((data) => { 115 | newArr = newArr.concat(data.data.queryStatistics[0]['Execution Time']); 116 | this.setState({ 117 | queryStatistics: newArr, 118 | queryTable: data.data.queryTable, 119 | }); 120 | }); 121 | }; 122 | 123 | // ESTABLISH CLOUD CONNECTION FUNCTION 124 | connect = (event: React.MouseEvent) => { 125 | event.preventDefault(); 126 | // ADD THE PROPERTIES IN THE FORM INTO STATE BY USING SETSTATE 127 | let info = this.state.awsInfo; 128 | // REMEMBER TO CHANGE THIS INTO A POST REQUEST ONCE WE GET THE ROUTE WORKING 129 | axios 130 | .post('/connect', info) 131 | .catch((err) => console.log('There has been an error: ', err)); 132 | 133 | // CLOSING MODAL 134 | this.setState({ awsModalIsOpen: false }); 135 | }; 136 | 137 | // SHOW POPUP CLOUD MODAL 138 | awsOpenModal = () => { 139 | this.setState({ awsModalIsOpen: true }); 140 | }; 141 | 142 | awsCloseModal = () => { 143 | this.setState({ awsModalIsOpen: false }); 144 | }; 145 | 146 | // SHOW POPUP INFO MODAL 147 | infoOpenModal = () => { 148 | this.setState({ infoModalIsOpen: true }); 149 | }; 150 | 151 | infoCloseModal = () => { 152 | this.setState({ infoModalIsOpen: false }); 153 | }; 154 | 155 | uploadOpenModal = () => { 156 | this.setState({ uploadModalIsOpen: true }); 157 | }; 158 | 159 | uploadCloseModal = () => { 160 | this.setState({ uploadModalIsOpen: false }); 161 | }; 162 | 163 | // UPDATING STATE TO LOCATION OF FILE 164 | fileUpdate = (event: any) => { 165 | this.setState({ 166 | injectedCode: '', 167 | }); 168 | // PULL NEW FILE TARGET 169 | const newFile = event.target.files[0]; 170 | // SET NEW FILE TO STATE 171 | this.setState({ selectedFile: newFile }); 172 | // READ FILE 173 | const reader = new FileReader(); 174 | reader.onload = (event: any) => { 175 | // PULL TEXT FROM EVENT.TARGET 176 | const newText = event.target.result; 177 | // PARSE THROUGH ANY REGEX ISSUES 178 | const lines = newText.split(/\r\n|\n/); 179 | // SETTING STATE TO PERSIST INJECTED CODE 180 | this.setState({ 181 | injectedCode: lines.join('\n'), 182 | }); 183 | }; 184 | 185 | // ERROR HANDLER FOR FILEREADER 186 | reader.onerror = (event: any) => { 187 | console.log(event.target.error.name); 188 | }; 189 | 190 | // FILEREADER FUNCTION ON NEWFILE 191 | reader.readAsText(newFile); 192 | }; 193 | 194 | // SENDING FILE TO BACKEND 195 | fileUpload = () => { 196 | // SETTING UPDATING SCHEMAENTRY STATE WITH NEW INJECTED CODE 197 | 198 | this.setState({ 199 | uploadModalIsOpen: false, 200 | }); 201 | 202 | // SETTING FILE META DATA AS FORM DATA TO SEND TO SERVER 203 | const data = new FormData(); 204 | // APPENDING FILE TO DATA 205 | data.append('myFile', this.state.selectedFile); 206 | // SENDING FILE TO SERVER FOR PROCESSING AND UPLOADING 207 | axios 208 | .post('/upload', data) 209 | .catch((err) => console.log('Error in file upload: ', err)); 210 | }; 211 | 212 | // EMPTY CODE EDITOR TEXT ON X BUTTON CLICK 213 | emptyInject = () => { 214 | this.setState({ 215 | injectedCode: '', 216 | }); 217 | }; 218 | 219 | // CHANGING AWSINFO STATE 220 | awsInfoChange = (e: React.ChangeEvent) => { 221 | const { id, value } = e.target; 222 | let newAWS: any = { ...this.state.awsInfo }; 223 | newAWS[id] = value; 224 | this.setState({ awsInfo: newAWS }); 225 | }; 226 | 227 | // possibly needs component did update 228 | refresh = (event: React.ChangeEvent) => { 229 | event.preventDefault(); 230 | window.location.reload(false); 231 | }; 232 | 233 | render() { 234 | return ( 235 |
236 |
237 | 255 |
256 |
257 | 258 |
259 | 268 |
269 |
270 | 274 | 277 |
278 | 279 | 284 | 285 | 286 | 287 | 288 | ); 289 | } 290 | } 291 | 292 | export default Container; 293 | --------------------------------------------------------------------------------