Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bba4489
Download and install nut
mimiwrp Feb 16, 2022
4ce6ef9
added save button using Material UI library.
Feb 19, 2022
d12fdfb
Add dropdown componant to sidebar
mimiwrp Feb 20, 2022
29392ff
implemented save functionality onto button
Feb 22, 2022
80350df
fixing drop-down componant with mui
mimiwrp Feb 23, 2022
98aa861
implemented load functionality
Feb 23, 2022
7a64bb5
beginning to fix save functionality where queries concated to save file
Feb 23, 2022
8d2f634
fixed saving functionality so that additional queries are added to th…
Feb 24, 2022
57f5bd2
updated upload icon
Feb 24, 2022
5d731aa
Merge
JuiceBawks Feb 24, 2022
51e7d19
Merge
JuiceBawks Feb 24, 2022
76ce921
Merge complete
JuiceBawks Feb 24, 2022
b96d5d7
Removed comments
JuiceBawks Feb 24, 2022
f4ebeb6
added accordion functionality
JuiceBawks Feb 25, 2022
7bbc607
Styling for dropdown
JuiceBawks Feb 26, 2022
86d2f64
Styling Feature
JuiceBawks Feb 28, 2022
307c84a
Removed unecessary files
JuiceBawks Feb 28, 2022
d22186e
Merge pull request #1 from oslabs-beta/Justin/Merge
JuiceBawks Feb 28, 2022
4bbb391
Merge branch 'VincentJohn/SaveButton' of https://github.com/oslabs-be…
jwagner988 Mar 4, 2022
eb9d58f
updated useState functions
jwagner988 Mar 7, 2022
c48498f
updated comparedQueries to satisfy isCompared prop on QueryEntry
jwagner988 Mar 7, 2022
6018318
updated charting algorithm to sort by group rather than label
jwagner988 Mar 7, 2022
846985e
updated compareTable to accept query groups
jwagner988 Mar 7, 2022
3ebe5b7
added feedback messages and restricted groups to allow for only a sin…
jwagner988 Mar 7, 2022
833c083
updated setCompare function to change executionPlan values rather tha…
jwagner988 Mar 7, 2022
bb2c03e
removed flag from QueryData interface
jwagner988 Mar 7, 2022
f9c0ad2
Merge pull request #2 from oslabs-beta/john/FinishChart
ericJH92 Mar 7, 2022
7407fb1
fixed comparison table bug when queries were unselected and showing 0
vincentt114 Mar 8, 2022
b590214
Merge pull request #4 from oslabs-beta/development
jwagner988 Mar 8, 2022
b3631c4
Merge pull request #69 from oslabs-beta/master
ericJH92 Mar 8, 2022
dbde626
Updating Quick Start View
mimiwrp Mar 9, 2022
c0a525e
Updating README and GIF
mimiwrp Mar 9, 2022
ec6349c
Update to version number
JuiceBawks Mar 9, 2022
a24fb62
Updated tests for new functionalities
JuiceBawks Mar 9, 2022
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@
"ignorePackages",
{ "js": "never", "jsx": "never", "ts": "never", "tsx": "never" }
],
// "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], **trying to resolve the electron issue
"jsx-a11y/label-has-associated-control": "off",
// prevent wrong warning with typescript overloads
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error"],
"no-dupe-class-members": "off",
"no-dupe-class-members": "off",
"@typescript-eslint/no-dupe-class-members": ["error"],
"lines-between-class-members": "off",
"@typescript-eslint/lines-between-class-members": [
Expand All @@ -52,5 +53,6 @@
"react/jsx-props-no-spreading": "off",
"camelcase": "off"
},
// "settings": "import/core-modules: [ electron ]", **trying to resolve the electron issue
"root": true
}
28 changes: 20 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

To get started on contributing to this project:

1. Download and install [Postgres.app](https://postgresapp.com/) and start it before opening up SeeQR
1. Download and install [Postgres.app](https://postgresapp.com/)(Mac)/[PGAdmin](https://www.pgadmin.org/download)(Windows) and start it before opening up SeeQR
2. Ensure that psql is available in the `$PATH`
3. Ensure that a 'postgres' role exists
4. Download the latest version of [SeeQR](https://github.com/open-source-labs/seeqr/releases/latest)
Expand Down Expand Up @@ -85,7 +85,7 @@ To get started on contributing to this project:
- Create/Edit Database <i>(currently in beta)</i>

- Users can create a new database from scratch by clicking the `Create New Database` button at the bottom of the sidebar
- Once a the database is given a name, htiting the `Initialize Database` button will create new database on the users PostgreSQL instance
- Once a the database is given a name, hitting the `Initialize Database` button will create new database on the users PostgreSQL instance
- Users can then input SQL commands and click `Update Database` to create and drop tables in the database
- Users have the option to alter any existing databases as well by selecting the database on the sidebar and running any SQL commands they would like.
- The `Export` button will write a .sql file on the user's desktop of the selected database
Expand All @@ -99,13 +99,24 @@ To get started on contributing to this project:

- In the 'QUERIES' view, the main panel is where the query input text field is located, utilizing CodeMirror. The paint button in the top right corner of the panel auto-formats the inputted query
- Users can select the database to use in the 'Database' dropdown above the main panel
- Users also have the option to execute a labelled or unlabelled query — simply provide a label in the 'Label' field above the main panel to identify the query in later comparisons against other queries
- Users also have the option to execute a labelled/grouped or unlabelled/ungrouped query — simply provide a label/group in the 'Label'/'Group' field above the main panel to identify the query in later comparisons against other queries
- Please note that only labelled queries will be saved in the current session for future references
- To execute the query, simply select the 'RUN QUERY' button at the bottom of the panel or press 'Ctrl-Enter' on the keyboard

<br />
<div align="center">
<img src="./assets/readmeImages/gifs/Query_Execution.gif" width=800/>
</div>

- Save/Load Queries

- In the 'QUERIES' view, the file upload icon will open a file explorer window to select a .JSON to import query data from
- The file icon to the right of the upload icon will designate the file path to save query data to if you press the save button on the queries
- To save individual query data press the save icon on the individual queries in the dropdowns

<br />
<div align="center">
<img src="./assets/readmeImages/gifs/query.gif" width=800/>
<img src="./assets/readmeImages/gifs/Save_Load_Queries.gif" width=800/>
</div>

- Data
Expand All @@ -121,21 +132,22 @@ To get started on contributing to this project:
- Clicking on a node will display additional details regarding that action as well
- To execute a new query, simply select the '+' button in the sidebar. To go back to a previously saved query, just select it in the sidebar


<br />
<div align="center">
<img src="./assets/readmeImages/gifs/execution_plan.gif" width=800/>
<img src="./assets/readmeImages/gifs/Query_Exec_Plan.gif" width=800/>
</div>

- Compare

- Click on the 'bar graph' icon at the top of the sidebar to get to the 'Compare Queries' view
- The comparison table is flexible to the user’s preferences as the user selects which queries to compare side by side
- Simply check or uncheck the box next to each saved query to add or remove the query from the graph
- Graph will be organized along the x-axis by label, and colored by schema
- Graph will be organized along the x-axis by group, and colored by schema
- Aside from the visualized performance comparison of the selected queries, a table will display information about each selected query, including its total run time and performance relative to other queries with the same label, with the most performant query highlighted

<div align="center">
<img src="./assets/readmeImages/gifs/compare_view.gif" width=800/>
<img src="./assets/readmeImages/gifs/Comparing_Queries.gif" width=800/>
</div>

## Application Architecture and Logic
Expand All @@ -152,7 +164,7 @@ We've released SeeQR because it's a useful tool to help optimize SQL databases.

## Core Team

[Allison Le](https://github.com/allisonle1) | [Brandon Lee](https://github.com/BrandonW-Lee) | [Casey Escovedo](https://github.com/caseyescovedo) | [Casey Walker](https://github.com/cwalker3011) | [Catherine Chiu](https://github.com/catherinechiu) | [Chris Akinrinade](https://github.com/chrisakinrinade) | [Cindy Chau](https://github.com/cindychau) | [Claudio Santos](https://github.com/Claudiohbsantos) | [Faraz Akhtar](https://github.com/faraza22) | [Frank Norton](https://github.com/FrankNorton32) | [Harrison Nam](https://github.com/harrynam07) | [James Kolotouros](https://github.com/dkolotouros) | [Jennifer Courtner](https://github.com/jcourtner) | [Justin Dury-Agri](https://github.com/justinD-A) | [Katie Klochan](https://github.com/kklochan) | [Mercer Stronck](https://github.com/mercerstronck) | [Muhammad Trad](https://github.com/muhammadtrad) | [Richard Guo](https://github.com/richardguoo) | [Richard Lam](https://github.com/rlam108) | [Sam Frakes](https://github.com/frakes413) | [Serena Kuo](https://github.com/serenackuo) | [Timothy Sin](https://github.com/timothysin)
[Allison Le](https://github.com/allisonle1) | [Brandon Lee](https://github.com/BrandonW-Lee) | [Casey Escovedo](https://github.com/caseyescovedo) | [Casey Walker](https://github.com/cwalker3011) | [Catherine Chiu](https://github.com/catherinechiu) | [Chris Akinrinade](https://github.com/chrisakinrinade) | [Cindy Chau](https://github.com/cindychau) | [Claudio Santos](https://github.com/Claudiohbsantos) | [Eric Han](https://github.com/ericJH92) | [Faraz Akhtar](https://github.com/faraza22) | [Frank Norton](https://github.com/FrankNorton32) | [Harrison Nam](https://github.com/harrynam07) | [James Kolotouros](https://github.com/dkolotouros) | [Jennifer Courtner](https://github.com/jcourtner) | [John Wagner](https://github.com/jwagner988) | [Justin Dury-Agri](https://github.com/justinD-A) | [Justin Hicks](https://github.com/JuiceBawks) | [Katie Klochan](https://github.com/kklochan) | [May Wirapa Boonyasurat](https://github.com/mimiwrp) | [Mercer Stronck](https://github.com/mercerstronck) | [Muhammad Trad](https://github.com/muhammadtrad) | [Richard Guo](https://github.com/richardguoo) | [Richard Lam](https://github.com/rlam108) | [Sam Frakes](https://github.com/frakes413) | [Serena Kuo](https://github.com/serenackuo) | [Timothy Sin](https://github.com/timothysin) | [Vincent Trang](https://github.com/vincentt114)


## License
Expand Down
43 changes: 34 additions & 9 deletions __tests__/frontend/lib/queries.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
window.require = ((str: string) => str) as any
import * as queries from '../../../frontend/lib/queries';
import type { QueryData } from '../../../frontend/types';
import type { QueryData, ExplainJson } from '../../../frontend/types';

const first: Partial<QueryData> = {
label: 'firstQuery',
db: 'firstDb',
group: 'group1',
sqlString: 'select * from tests',
executionPlan: {
Plan: {
'Node Type': 'Seq Scan',
'Relation Name': 'users',
Alias: 'users',
'Startup Cost': 0,
'Total Cost': 0,
'Plan Rows': 0,
'Plan Width': 0,
'Actual Startup Time': 0,
'Actual Total Time': 0,
'Actual Rows': 0,
'Actual Loops': 0,
},
'Planning Time': 1,
'Execution Time': 1,
},
};

const second: Partial<QueryData> = {
Expand All @@ -15,15 +34,16 @@ const second: Partial<QueryData> = {

describe('key generation', () => {
it('should create key from label and db given as params', () => {
expect(queries.keyFromData('LABEL', 'DB')).toEqual('label:LABEL db:DB');
expect(queries.keyFromData('LABEL', 'DB', 'GROUP')).toEqual('label:LABEL db:DB group:GROUP');
});

it('should create key from query object', () => {
const query = {
label: 'query1',
db: 'db1',
group: 'group1'
};
expect(queries.key(query as QueryData)).toEqual('label:query1 db:db1');
expect(queries.key(query as QueryData)).toEqual('label:query1 db:db1 group:group1');
});
});

Expand Down Expand Up @@ -137,23 +157,28 @@ describe('setCompare', () => {

it('should not mutate original collection', () => {
expect(Object.keys(collection).length).toBe(0);
const newCollection = queries.setCompare({}, first as QueryData, true);
const newCollection = queries.setCompare({}, {}, first as QueryData, true);
expect(Object.keys(collection).length).toBe(0);
expect(newCollection).not.toBe(collection);
});

it('should add query to new collection if given true for isCompared', () => {
expect(Object.keys(collection).length).toBe(0);
const newCollection = queries.setCompare({}, first as QueryData, true);
const newCollection = queries.setCompare({}, {}, first as QueryData, true);
expect(Object.keys(newCollection).length).toBe(1);
expect(newCollection[queries.key(first as QueryData)]).toEqual(first);
});

it('should remove query from new collection if given false for isCompared', () => {
it('should set execution time to 0 if given false for isCompared', () => {
let qs:any = { [`${queries.key(first as QueryData)}`]: first };
expect(Object.keys(collection).length).toBe(0);
const newCollection = queries.setCompare({}, first as QueryData, true);
const newCollection = queries.setCompare({}, qs, first as QueryData, true);
expect(Object.keys(newCollection).length).toBe(1);
const clearedCollection = queries.setCompare({}, first as QueryData, false);
expect(Object.keys(clearedCollection).length).toBe(0);
expect(newCollection[queries.key(first as QueryData)].executionPlan['Planning Time']).toBe(1);
expect(newCollection[queries.key(first as QueryData)].executionPlan['Execution Time']).toBe(1);
const newSetCollection = queries.setCompare(newCollection, qs, first as QueryData, false);
expect(Object.keys(newSetCollection).length).toBe(1);
expect(newSetCollection[queries.key(first as QueryData)].executionPlan['Planning Time']).toBe(0);
expect(newSetCollection[queries.key(first as QueryData)].executionPlan['Execution Time']).toBe(0);
});
});
Binary file added assets/readmeImages/gifs/Comparing_Queries.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Generate_Dummy_Data.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Import_DB_&_Copy_DB.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Manual_Create_DB.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Query_Exec_Plan.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Query_Execution.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/readmeImages/gifs/Save_Load_Queries.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/readmeImages/gifs/compare_view.gif
Binary file not shown.
Binary file removed assets/readmeImages/gifs/execution_plan.gif
Binary file not shown.
Binary file removed assets/readmeImages/gifs/query.gif
Binary file not shown.
2 changes: 1 addition & 1 deletion backend/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { FamilyRestroomRounded } from '@mui/icons-material';
import { app, BrowserWindow, Menu } from 'electron';

const dev: boolean = process.env.NODE_ENV === 'development';
Expand Down Expand Up @@ -71,7 +72,6 @@ if (dev) {
installExtension(REACT_DEVELOPER_TOOLS);
});
}

// Invoke createWindow to create browser windows after Electron has been initialized.
app.on('ready', createWindow);

Expand Down
1 change: 0 additions & 1 deletion backend/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const { Pool } = require('pg');
// Note: User must have a 'postgres' role set-up prior to initializing this connection. https://www.postgresql.org/docs/13/database-roles.html
const PG_URI: string = 'postgres://postgres:postgres@localhost:5432';
let pool = new Pool({ connectionString: PG_URI });
// console.log('Connected to: ', PG_URI);


// *********************************************************** HELPER FUNCTIONS ************************************************* //
Expand Down
6 changes: 5 additions & 1 deletion frontend/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ const App = () => {

const [selectedDb, setSelectedDb] = useState<AppState['selectedDb']>('');
const [sidebarIsHidden, setSidebarHidden] = useState(false);
const [newFilePath, setFilePath] = useState<AppState['newFilePath']>('');

/**
* Hook to create new Query from data
*/
const createNewQuery: CreateNewQuery = (query: QueryData) => {
// Only save query to saved queries if it contains all minimum information
if (query.label && query.db && query.sqlString) {
if (query.label && query.db && query.sqlString && query.group) {
const newQueries = createQuery(queries, query);
setQueries(newQueries);
}
Expand Down Expand Up @@ -115,6 +116,8 @@ const App = () => {
setWorkingQuery,
setSidebarHidden,
sidebarIsHidden,
setFilePath,
newFilePath
}}
/>
<Main $fullwidth={sidebarIsHidden}>
Expand All @@ -130,6 +133,7 @@ const App = () => {
setSelectedDb={setSelectedDb}
createNewQuery={createNewQuery}
show={shownView === 'queryView'}
queries={queries}
/>
<QuickStartView show={shownView === 'quickStartView'} />
<NewSchemaView
Expand Down
15 changes: 13 additions & 2 deletions frontend/components/sidebar/QueryEntry.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react';

import styled from 'styled-components';
import {
IconButton,
ListItemSecondaryAction,
Checkbox,
Tooltip,
Button
} from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';
import {
Expand All @@ -13,13 +15,13 @@ import {
textColor,
} from '../../style-variables';
import { QueryData } from '../../types';
import SaveIcon from '@material-ui/icons/Save';

const QueryText = styled(StyledListItemText)`
& .MuiListItemText-secondary {
color: ${textColor};
}
`;

const CompareCheck = styled(Checkbox)`
color: ${textColor};
`;
Expand All @@ -31,6 +33,7 @@ interface QueryEntryProps {
setComparison: (evt: React.ChangeEvent<HTMLInputElement>) => void;
isCompared: boolean;
deleteThisQuery: () => void;
saveThisQuery: () => void;
}

const QueryEntry = ({
Expand All @@ -40,13 +43,19 @@ const QueryEntry = ({
setComparison,
isCompared,
deleteThisQuery,
saveThisQuery,
}: QueryEntryProps) => (
<SidebarListItem button $customSelected={isSelected} onClick={select}>
<QueryText primary={query.label} secondary={query.db} />
<QueryText primary={`${query.label} - ${query.db}`} />
<ListItemSecondaryAction>
<Tooltip title="View in Comparison">
<CompareCheck onChange={setComparison} checked={isCompared} />
</Tooltip>
<Tooltip title="Save Query">
<IconButton onClick={saveThisQuery}>
<SaveIcon fontSize='default' />
</IconButton>
</Tooltip>
<Tooltip title="Forget Query">
<IconButton edge="end" onClick={deleteThisQuery}>
<CloseIcon />
Expand All @@ -56,4 +65,6 @@ const QueryEntry = ({
</SidebarListItem>
);



export default QueryEntry;
Loading