diff --git a/app/backend.js b/app/backend.js
index 2c740022..cdaeb00e 100644
--- a/app/backend.js
+++ b/app/backend.js
@@ -1,5 +1,6 @@
/* globals __BUILD__ */
-import { app } from 'electron'
+// import {chunksToLinesAsync, chomp} from '@rauschma/stringio'
+import { app, dialog } from 'electron'
import { spawn } from 'child_process'
import { EventEmitter } from 'events'
import path from 'path'
@@ -151,9 +152,15 @@ export default class Backend extends EventEmitter {
}
this.backend.on('close', (code) => {
+ if (process.env.NODE_ENV !== 'development') {
+ dialog.showErrorBox("Qri Backend Closed", "For some unexpected reason the Qri backend process has closed. Things aren't going to work well. Mind restarting?")
+ }
this.log('closed backend process')
})
this.backend.on('error', (err) => {
+ if (process.env.NODE_ENV !== 'development') {
+ dialog.showErrorBox("Qri Backend Error", err)
+ }
this.log(`backend error: ${err}`)
})
}
diff --git a/app/main.dev.js b/app/main.dev.js
index 237f2177..16c6486f 100644
--- a/app/main.dev.js
+++ b/app/main.dev.js
@@ -17,7 +17,7 @@ import touchbar from './touchbar'
const isDevelopment = (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD !== 'false')
-let mainWindow = null
+// let mainWindow = null
let backend = null
if (process.env.NODE_ENV === 'production') {
@@ -97,7 +97,6 @@ app.on('quit', () => {
})
function createMainWindow () {
- console.log('booting app...')
let mainWindow = new BrowserWindow({
show: false,
width: 1500,
@@ -140,31 +139,6 @@ function createMainWindow () {
})
}
- const menuBuilder = new MenuBuilder(mainWindow)
+ const menuBuilder = new MenuBuilder(mainWindow, createMainWindow)
menuBuilder.buildMenu()
-
- // mainWindow.webContents.session.on('will-download', (event, item, webContents) => {
- // console.log(event)
- // // Set the save path, making Electron not to prompt a save dialog.
- // item.setSavePath('/tmp/save.pdf')
-
- // item.on('updated', (event, state) => {
- // if (state === 'interrupted') {
- // console.log('Download is interrupted but can be resumed')
- // } else if (state === 'progressing') {
- // if (item.isPaused()) {
- // console.log('Download is paused')
- // } else {
- // console.log(`Received bytes: ${item.getReceivedBytes()}`)
- // }
- // }
- // })
- // item.once('done', (event, state) => {
- // if (state === 'completed') {
- // console.log('Download successfully')
- // } else {
- // console.log(`Download failed: ${state}`)
- // }
- // })
- // })
}
diff --git a/app/menu.js b/app/menu.js
index 06b1079a..81dcedbf 100644
--- a/app/menu.js
+++ b/app/menu.js
@@ -3,8 +3,9 @@ import { app, Menu, shell, BrowserWindow } from 'electron';
export default class MenuBuilder {
mainWindow: BrowserWindow;
- constructor(mainWindow: BrowserWindow) {
+ constructor(mainWindow: BrowserWindow, createWindow) {
this.mainWindow = mainWindow;
+ this.createWindow = createWindow;
}
buildMenu() {
@@ -44,19 +45,23 @@ export default class MenuBuilder {
buildDarwinTemplate() {
const subMenuAbout = {
- label: 'qri',
+ label: 'Qri',
submenu: [
- { label: 'About qri', selector: 'orderFrontStandardAboutPanel:' },
- // { type: 'separator' },
- // { label: 'Services', submenu: [] },
+ { label: 'About Qri', selector: 'orderFrontStandardAboutPanel:' },
{ type: 'separator' },
- { label: 'Hide qri', accelerator: 'Command+H', selector: 'hide:' },
+ { label: 'Hide Qri', accelerator: 'Command+H', selector: 'hide:' },
{ label: 'Hide Others', accelerator: 'Command+Shift+H', selector: 'hideOtherApplications:' },
{ label: 'Show All', selector: 'unhideAllApplications:' },
{ type: 'separator' },
{ label: 'Quit', accelerator: 'Command+Q', click: () => { app.quit(); } }
]
};
+ const subMenuFile = {
+ label: 'File',
+ submenu: [
+ { label: 'New Window', accelerator: 'Command+N', click: () => { this.createWindow() }}
+ ]
+ }
const subMenuEdit = {
label: 'Edit',
submenu: [
@@ -69,7 +74,7 @@ export default class MenuBuilder {
{ label: 'Select All', accelerator: 'Command+A', selector: 'selectAll:' }
]
};
- const subMenuViewDev = {
+ const subMenuView = {
label: 'View',
submenu: [
{ label: 'Reload', accelerator: 'Command+R', click: () => { this.mainWindow.webContents.reload(); } },
@@ -77,13 +82,6 @@ export default class MenuBuilder {
{ label: 'Toggle Developer Tools', accelerator: 'Command+Shift+C', click: () => { this.mainWindow.toggleDevTools(); } }
]
};
- const subMenuViewProd = {
- label: 'View',
- submenu: [
- { label: 'Toggle Full Screen', accelerator: 'Ctrl+Command+F', click: () => { this.mainWindow.setFullScreen(!this.mainWindow.isFullScreen()); } },
- { label: 'Toggle Developer Tools', accelerator: 'Command+Shift+C', click: () => { this.mainWindow.openDevTools(); } }
- ]
- };
const subMenuWindow = {
label: 'Window',
submenu: [
@@ -96,18 +94,17 @@ export default class MenuBuilder {
const subMenuHelp = {
label: 'Help',
submenu: [
- { label: 'Learn More', click() { shell.openExternal('http://qri.io'); } },
- { label: 'Documentation', click() { shell.openExternal('https://github.com/qri-io/frontend/blob/master/readme.md'); } },
- // { label: 'Community Discussions', click() { shell.openExternal('https://discuss.atom.io/c/electron'); } },
- { label: 'Search Issues', click() { shell.openExternal('https://github.com/qri-io/frontend/issues'); } }
+ { label: 'Qri Site', click() { shell.openExternal('http://qri.io'); } },
+ { label: 'Discord Chat', click() { shell.openExternal('https://discord.gg/etap8Gb'); } },
+ { label: 'Docs', click() { shell.openExternal('https://qri.io/docs'); } },
+ { label: 'App Github', click() { shell.openExternal('https://github.com/qri-io/frontend/blob/master/readme.md'); } },
+ { label: 'App Github Issues', click() { shell.openExternal('https://github.com/qri-io/frontend/issues'); } }
]
};
- const subMenuView = process.env.NODE_ENV === 'development'
- ? subMenuViewDev : subMenuViewProd;
-
return [
subMenuAbout,
+ subMenuFile,
subMenuEdit,
subMenuView,
subMenuWindow,
diff --git a/app/package.json b/app/package.json
index c2035e96..e6f3ce8f 100644
--- a/app/package.json
+++ b/app/package.json
@@ -1,7 +1,7 @@
{
"name": "qri-webapp",
"productName": "qri",
- "version": "0.5.1",
+ "version": "0.5.2",
"description": "qri (\"query\") frontend application",
"main": "./main.prod.js",
"author": {
diff --git a/lib/actions/dataset.js b/lib/actions/dataset.js
index be76ac30..4c94a8d2 100755
--- a/lib/actions/dataset.js
+++ b/lib/actions/dataset.js
@@ -245,7 +245,7 @@ export function downloadDataset (datasetRef) {
}
// prepFiles turns strings into File objects for submission via a form/multipart API request
-function prepFiles (dataset = {}, transformScript = '', vizScript = '', bodyData) {
+function prepFiles (dataset = {}, transformScript = '', vizScript = '', bodyData = '') {
let viz, transform, body
let file = new File([JSON.stringify(dataset)], 'dataset.json', {
@@ -264,7 +264,8 @@ function prepFiles (dataset = {}, transformScript = '', vizScript = '', bodyData
})
}
- if (bodyData) {
+ if (bodyData && bodyData.length) {
+ console.log(bodyData, bodyData.length)
body = new File([bodyData], 'body', {
type: 'text/plain'
})
diff --git a/lib/components/App.js b/lib/components/App.js
index 6d5ff361..0865ceef 100644
--- a/lib/components/App.js
+++ b/lib/components/App.js
@@ -60,9 +60,11 @@ export default class App extends Base {
this.props.layoutResize(window.innerWidth, window.innerHeight)
}, 250)
- window.onbeforeunload = () => {
+ window.onbeforeunload = (e) => {
if (this.props.editorDirty) {
- if (!confirm('the editor has unsaved changes. are you *sure* want to close this window?')) {
+ if (!confirm('the editor has unsaved changes. are you sure want to close this window?')) {
+ e.preventDefault()
+ e.returnValue = ''
return false
}
}
diff --git a/lib/components/ExternalLink.electron.js b/lib/components/ExternalLink.electron.js
new file mode 100644
index 00000000..7a54acd4
--- /dev/null
+++ b/lib/components/ExternalLink.electron.js
@@ -0,0 +1,11 @@
+import React from 'react'
+import { shell } from 'electron'
+
+export default class ExternalLink extends React.Component {
+ render () {
+ return ( {
+ e.preventDefault()
+ shell.openExternal(this.props.href)
+ }} {...this.props}>{this.props.children})
+ }
+}
diff --git a/lib/components/ExternalLink.web.js b/lib/components/ExternalLink.web.js
new file mode 100644
index 00000000..1013062e
--- /dev/null
+++ b/lib/components/ExternalLink.web.js
@@ -0,0 +1,7 @@
+import React from 'react'
+
+export default class ExternalLink extends React.Component {
+ render () {
+ return {this.props.children}
+ }
+}
diff --git a/lib/components/TopBar.js b/lib/components/TopBar.js
index c0514282..e407ca77 100644
--- a/lib/components/TopBar.js
+++ b/lib/components/TopBar.js
@@ -7,6 +7,7 @@ import { defaultPalette } from '../propTypes/palette'
import SearchBar from './form/SearchBar'
import Base from './Base'
+import ExternalLink from './ExternalLink.APP_TARGET'
export default class TopBar extends Base {
constructor (props) {
@@ -88,8 +89,8 @@ export default class TopBar extends Base {
{meta.description}
: undefined} - {meta && meta.downloadPath ? {meta.downloadPath} : undefined} + {meta && meta.keywords &&{meta.description}
} + {meta && meta.downloadPath &&