Skip to content

Commit a9d7771

Browse files
authored
Merge pull request #247 from open-source-labs/sam/collections
import export collections, small httpController fix
2 parents 9f39fc0 + 70f26ec commit a9d7771

File tree

7 files changed

+237
-6
lines changed

7 files changed

+237
-6
lines changed

main.js

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
44
// Import parts of electron to use
55
// app - Control your application's event lifecycle
66
// ipcMain - Communicate asynchronously from the main process to renderer processes
7-
const { app, BrowserWindow, TouchBar, ipcMain } = require('electron');
7+
const { app, BrowserWindow, TouchBar, ipcMain, dialog } = require('electron');
88
const path = require('path');
99
const url = require('url');
10+
const fs = require('fs');
1011

1112
// Import Auto-Updater- Swell will update itself
1213
const { autoUpdater } = require('electron-updater');
1314
const log = require('electron-log');
1415
// TouchBarButtons are our nav buttons(ex: Select All, Deselect All, Open Selected, Close Selected, Clear All)
1516
const { TouchBarButton, TouchBarSpacer } = TouchBar;
1617

18+
1719
// basic http cookie parser
1820
const cookie = require('cookie');
1921
// node-fetch for the fetch request
@@ -25,7 +27,6 @@ const gql = require('graphql-tag');
2527
const { InMemoryCache } = require('apollo-cache-inmemory');
2628
const { createHttpLink } = require('apollo-link-http');
2729
const { ApolloLink } = require('apollo-link');
28-
const { onError } = require("apollo-link-error");
2930

3031
// configure logging
3132
autoUpdater.logger = log;
@@ -276,6 +277,94 @@ app.on('activate', () => {
276277
}
277278
});
278279

280+
// export collection ipc
281+
ipcMain.on('export-collection', (event, args) => {
282+
let content = JSON.stringify(args.collection);
283+
284+
dialog.showSaveDialog((fileName) => {
285+
if (fileName === undefined){
286+
console.log("You didn't save the file");
287+
return;
288+
}
289+
290+
// fileName is a string that contains the path and filename created in the save file dialog.
291+
fs.writeFile(fileName, content, (err) => {
292+
if(err){
293+
console.log("An error ocurred creating the file "+ err.message)
294+
}
295+
});
296+
});
297+
})
298+
299+
ipcMain.on('import-collection', (event, args) => {
300+
dialog.showOpenDialog((fileNames) => {
301+
// reusable error message options object
302+
const options = {
303+
type: 'error',
304+
buttons: ['Okay'],
305+
defaultId: 2,
306+
title: 'Error',
307+
message: '',
308+
detail: '',
309+
};
310+
311+
// fileNames is an array that contains all the selected
312+
if(fileNames === undefined){
313+
console.log("No file selected");
314+
return;
315+
}
316+
317+
// get first file path - not dynamic for multiple files
318+
let filepath = fileNames[0];
319+
320+
// get file extension
321+
const ext = path.extname(filepath);
322+
323+
// make sure if there is an extension that it is .txt
324+
if (ext && ext !== '.txt') {
325+
options.message = 'Invalid File Type';
326+
options.detail = 'Please use a .txt file';
327+
dialog.showMessageBox(null, options);
328+
return;
329+
}
330+
331+
fs.readFile(filepath, 'utf-8', (err, data) => {
332+
if(err){
333+
alert("An error ocurred reading the file :" + err.message);
334+
return;
335+
}
336+
337+
// parse data, will throw error if not parsable
338+
let parsed;
339+
try {
340+
parsed = JSON.parse(data);
341+
} catch {
342+
options.message = 'Invalid File Structure';
343+
options.detail = 'Please use a JSON object';
344+
dialog.showMessageBox(null, options);
345+
return;
346+
}
347+
348+
if (parsed) {
349+
// validate parsed data type and properties
350+
if (typeof parsed !== 'object' ||
351+
!parsed['id'] ||
352+
!parsed['name'] ||
353+
!parsed['reqResArray'] ||
354+
!parsed['created_at']) {
355+
options.message = 'Invalid File';
356+
options.detail = 'Please try again.';
357+
dialog.showMessageBox(null, options);
358+
return;
359+
}
360+
}
361+
362+
// send data to chromium for state update
363+
event.sender.send('add-collection', {data});
364+
});
365+
});
366+
})
367+
279368

280369
// ipcMain listener that
281370
ipcMain.on('http1-fetch-message', (event, arg) => {

package-lock.json

Lines changed: 74 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assets/style/sidebar.scss

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@
365365
&:hover .collection-delete-image {
366366
opacity: 1;
367367
}
368+
&:hover .collection-export-container {
369+
display: flex;
370+
}
368371
}
369372
.history-text-container, .collection-text-container {
370373
align-items: center;
@@ -429,6 +432,40 @@
429432
opacity: 0;
430433
width: 16px;
431434
}
435+
.collection-export-container {
436+
display: none;
437+
float: right;
438+
height: 26px;
439+
position: relative;
440+
right: 0px;
441+
top: -28px;
442+
z-index: 0;
443+
padding-left: 10px;
444+
}
445+
.collection-export-container button {
446+
background: transparent;
447+
color: rgb(216, 216, 216);
448+
border: 0;
449+
cursor: pointer;
450+
outline: none;
451+
}
452+
.collection-import-container {
453+
display: flex;
454+
float: right;
455+
height: 26px;
456+
position: relative;
457+
right: 0px;
458+
top: -28px;
459+
z-index: 0;
460+
padding-right: 10px;
461+
}
462+
.collection-import-container button {
463+
background: transparent;
464+
color: rgb(216, 216, 216);
465+
border: 0;
466+
cursor: pointer;
467+
outline: none;
468+
}
432469
.collections-container {
433470
min-height: 150px;
434471
max-height: 400px;

src/client/components/containers/CollectionsContainer.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
22
import { connect } from 'react-redux';
33
import * as actions from '../../actions/actions';
44
import Collection from '../display/Collection.jsx'
5+
import collectionsController from '../../controllers/collectionsController';
56

67
const mapStateToProps = store => ({
78
collections: store.business.collections,
@@ -30,6 +31,9 @@ class CollectionsContainer extends Component {
3031
return (
3132
<div className={'collections-container'}>
3233
<h1>Collections</h1>
34+
<div className="collection-import-container">
35+
<button className="import-collections" onClick={collectionsController.importCollection}>Import Collection</button>
36+
</div>
3337
{collectionComponents}
3438
</div>
3539
)

src/client/components/display/Collection.jsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ class Collection extends Component {
2323
return (
2424
<div className={'collection-container'}>
2525
<div className={'collection-text-container'} onClick={this.addCollectionToReqResContainer}>
26-
<div className={'collection-name'}> {this.props.content.name}
27-
</div>
26+
<div className={'collection-name'}> {this.props.content.name}</div>
27+
</div>
28+
<div className="collection-export-container">
29+
<button onClick={() => collectionsController.exportCollection(this.props.content.id)}>Export</button>
2830
</div>
2931
<div className='collection-delete-container'>
3032
<div className='collection-delete-fade'>

src/client/controllers/collectionsController.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import * as store from '../store';
22
import * as actions from '../actions/actions';
33
import db from '../db';
4-
// import uuid from 'uuid/v4';
4+
import { ipcRenderer } from 'electron';
5+
import uuid from 'uuid/v4';
6+
7+
ipcRenderer.on('add-collection', (event, args) => {
8+
console.log('here');
9+
collectionsController.addCollectionToIndexedDb(JSON.parse(args.data));
10+
collectionsController.getCollections();
11+
});
512

613
const collectionsController = {
714

@@ -36,6 +43,24 @@ const collectionsController = {
3643
});
3744
});
3845
},
46+
47+
exportCollection(id) {
48+
db.collections.where('id').equals(id).first(foundCollection => {
49+
// change name and id of collection to satisfy uniqueness requirements of db
50+
foundCollection.name = foundCollection.name + " import";
51+
foundCollection.id = uuid();
52+
53+
ipcRenderer.send('export-collection', {collection: foundCollection});
54+
})
55+
.catch((error) => {
56+
console.error(error.stack || error);
57+
reject(error);
58+
});
59+
},
60+
61+
importCollection() {
62+
ipcRenderer.send('import-collection');
63+
},
3964
};
4065

4166
export default collectionsController;

src/client/controllers/httpController.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ const httpController = {
310310
const heads = response.headers;
311311
reqResObj.response.headers = heads;
312312

313-
reqResObj.timeSent = Date.now();
313+
reqResObj.timeReceived = Date.now();
314314
store.default.dispatch(actions.reqResUpdate(reqResObj));
315315

316316
const theResponseHeaders = response.headers;

0 commit comments

Comments
 (0)