diff --git a/package-lock.json b/package-lock.json
index 8e6597c..21fcd11 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -54,8 +54,8 @@
"react-notification-system-redux": "1.2.0",
"react-redux": "5.0.6",
"react-resize-detector": "1.1.0",
- "react-svg-inline": "2.0.1",
- "redux-form": "7.2.0",
+ "react-svg-inline": "2.1.0",
+ "redux-form": "7.2.1",
"redux-undo": "1.0.0-beta9-9-7",
"reselect": "3.0.1",
"semver": "5.4.1",
@@ -6942,9 +6942,9 @@
}
},
"react-svg-inline": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/react-svg-inline/-/react-svg-inline-2.0.1.tgz",
- "integrity": "sha512-9YVqJ80g1gPWAvD9CS/z4cKPD45ZSMjjzwxFAmQJiMEoAo1Ajhz92WirXag3ftltDN5lPNkVWx/KOnEWB/PaMQ==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-svg-inline/-/react-svg-inline-2.1.0.tgz",
+ "integrity": "sha512-GzRID5IcEQ8dnnaUtTb9MDTAbhuaOiVKKAVLgrCNuehHsg3DuZbe82bjc9JhmPv0zsDWhDrJwzADNgzEvE6VeQ==",
"requires": {
"classnames": "2.2.5",
"prop-types": "15.6.0"
@@ -7058,9 +7058,9 @@
}
},
"redux-form": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-7.2.0.tgz",
- "integrity": "sha512-qbgeI19drwnm9FeGAotDA1vsZO8q94XF7IxPDuJmSXxDYX2rqzhND6NROahCBJfBK5xM1cchvmgscO2rry1EEw==",
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-7.2.1.tgz",
+ "integrity": "sha512-KWV+rq+L1QGoRSKoJXbGS8Mw2q4ta5FVyGxW5ZYnAEjXZAukvUCkqDUzobBmOqiRHvrZ3/ssEA7kJFdu7rV8+w==",
"requires": {
"deep-equal": "1.0.1",
"es6-error": "4.1.1",
@@ -8271,6 +8271,11 @@
"resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
"integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA="
},
+ "validate-ip": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/validate-ip/-/validate-ip-1.0.1.tgz",
+ "integrity": "sha1-615PY+HRq8buRuGK4gaXv1vtBto="
+ },
"validate-npm-package-license": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
diff --git a/package.json b/package.json
index 8b655e4..473f113 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"react-resize-detector": "^1.1.0",
"shortid": "^2.2.8",
"three": "^0.88.0",
+ "validate-ip": "^1.0.1",
"webpack-bundle-analyzer": "^2.9.2"
},
"devDependencies": {
diff --git a/src/interface/Settings.js b/src/interface/Settings.js
index ec94401..d28b5ee 100644
--- a/src/interface/Settings.js
+++ b/src/interface/Settings.js
@@ -18,6 +18,7 @@ import materialSettings from '../settings/material.yml';
import qualitySettings from '../settings/quality.yml';
import update from 'react-addons-update';
import SettingsIcon from 'material-ui-icons/Settings';
+import validateIp from 'validate-ip';
const styles = {
textFieldRow: {
@@ -79,6 +80,7 @@ class Settings extends React.Component {
open: false,
name: '',
printer: '',
+ ip: '',
error: null
},
managePrinter: {
@@ -102,25 +104,22 @@ class Settings extends React.Component {
let state = _.cloneDeep(this.state);
- const removeAddPrinterError = () => {
- state = update(state, { addPrinter: { error: { $set: null } } });
- };
-
switch (fieldName) {
case 'managePrinter.printer':
case 'managePrinter.name':
+ case 'managePrinter.ip':
state = _.set(state, fieldName, value);
+ state = update(state, { managePrinter: { error: { $set: null } } });
break;
case 'addPrinter.printer':
- state = update(state, { addPrinter: { printer: { $set: value } } });
- state = update(state, { addPrinter: { name: { $set: printerSettings[value].title } } });
- removeAddPrinterError();
- break;
-
case 'addPrinter.name':
- state = update(state, { addPrinter: { name: { $set: value } } });
- removeAddPrinterError();
+ case 'addPrinter.ip':
+ state = _.set(state, fieldName, value);
+ if (fieldName === 'addPrinter.printer') {
+ state = update(state, { addPrinter: { name: { $set: printerSettings[value].title } } });
+ }
+ state = update(state, { addPrinter: { error: { $set: null } } });
break;
case 'activePrinter':
@@ -204,12 +203,13 @@ class Settings extends React.Component {
constructSettings(localStorage) {
if (!localStorage.active) return defaultSettings;
- const { printer, material, quality, advanced } = localStorage.printers[localStorage.active].settings;
+ const { ip, settings: { printer, material, quality, advanced } } = localStorage.printers[localStorage.active];
let settings = {
...defaultSettings,
printer,
material,
quality
+ ip
};
settings = _.merge({}, settings, printerSettings[printer]);
@@ -225,10 +225,14 @@ class Settings extends React.Component {
}
addPrinter = () => {
- const { name, printer } = this.state.addPrinter;
+ const { name, printer, ip } = this.state.addPrinter;
if (!name || !printer) {
- this.setState({ addPrinter: { ...this.state.addPrinter, error: 'Please enter a name and printer' } });
+ this.setState(update(this.state, { addPrinter: { error: { $set: 'Please enter a name and printer' } } }));
+ return;
+ }
+ if (printer === 'doodle3d_printer' && !validateIp(ip)) {
+ this.setState(update(this.state, { addPrinter: { error: { $set: 'Please enter a valid IP adress' } } }));
return;
}
@@ -237,7 +241,7 @@ class Settings extends React.Component {
active: id,
printers: {
...this.state.localStorage.printers,
- [id]: { name, settings: { printer, material: 'pla', quality: 'medium', advanced: {} } }
+ [id]: { name, ip, settings: { printer, material: 'pla', quality: 'medium', advanced: {} } }
}
};
this.setState({ localStorage });
@@ -250,11 +254,22 @@ class Settings extends React.Component {
};
editPrinter = () => {
- const { localStorage: { active, printers }, managePrinter: { printer, name } } = this.state;
+ const { localStorage: { active, printers }, managePrinter: { printer, name, ip } } = this.state;
+
+ if (!name) {
+ this.setState(update(this.state, { managePrinter: { error: { $set: 'Please enter a name' } } }));
+ return;
+ }
+ if (printer === 'doodle3d_printer' && !validateIp(ip)) {
+ this.setState(update(this.state, { managePrinter: { error: { $set: 'Please enter a valid IP adress' } } }));
+ return;
+ }
+
const localStorage = update(this.state.localStorage, {
printers: {
[active]: {
name: { $set: name },
+ ip: { $set: ip },
settings: {
printer: { $set: printer }
}
@@ -288,7 +303,7 @@ class Settings extends React.Component {
closeAddPrinterDialog = () => this.setAddPrinterDialog(false);
openAddPrinterDialog = () => this.setAddPrinterDialog(true);
- setAddPrinterDialog = (open) => this.setState({ addPrinter: { name: '', printer: '', error: null, open } });
+ setAddPrinterDialog = (open) => this.setState({ addPrinter: { ip: '', name: '', printer: '', error: null, open } });
closeManagePrinterDialog = () => this.setManagePrinterDialog(false);
openManagePrinterDialog = () => this.setManagePrinterDialog(true);
@@ -299,7 +314,9 @@ class Settings extends React.Component {
managePrinter: {
open,
name: printers[active].name,
- printer: printers[active].settings.printer
+ ip: printers[active].ip,
+ printer: printers[active].settings.printer,
+ error: null
}
});
}
@@ -415,6 +432,7 @@ class Settings extends React.Component {
))}
{addPrinter.error}
} ); diff --git a/test.js b/test.js new file mode 100644 index 0000000..d448d41 --- /dev/null +++ b/test.js @@ -0,0 +1,122 @@ +import 'babel-polyfill' +import React from 'react'; +import { render } from 'react-dom'; +import injectTapEventPlugin from 'react-tap-event-plugin'; +// import './fetch.js'; + +injectTapEventPlugin(); + +const IP = 'http://10.0.0.109'; +const DEFAULT_GCODE = `; Generated with Doodle3D Slicer V0.0.18 +G28 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +; test +`; + +const CIRCLE = `; Generated with Doodle3D Slicer V0.0.18 +G28 +G1 X50 Y70 +G1 X56.180339887498945 Y69.02113032590307 +G1 X61.75570504584947 Y66.18033988749895 +G1 X66.18033988749895 Y61.75570504584947 +G1 X69.02113032590307 Y56.180339887498945 +G1 X70 Y50 +G1 X69.02113032590307 Y43.819660112501055 +G1 X66.18033988749895 Y38.24429495415054 +G1 X61.75570504584947 Y33.819660112501055 +G1 X56.18033988749895 Y30.97886967409693 +G1 X50 Y30 +G1 X43.819660112501055 Y30.978869674096927 +G1 X38.24429495415054 Y33.819660112501055 +G1 X33.819660112501055 Y38.24429495415053 +G1 X30.97886967409693 Y43.81966011250105 +G1 X30 Y49.99999999999999 +G1 X30.978869674096927 Y56.180339887498945 +G1 X33.81966011250105 Y61.75570504584946 +G1 X38.24429495415053 Y66.18033988749895 +G1 X43.81966011250105 Y69.02113032590307 +; test +`; + +// export function fetch(url, data = {}, onProgress) { +// return new Promise((resolve, reject) => { +// const request = new Request(url, data); +// const xhr = new XMLHttpRequest(); +// +// xhr.onload = () => { +// const { status, statusText, responseURL: url } = xhr; +// resolve(new Response(xhr.response, { status, statusText, url })); +// } +// xhr.onerror = () => reject(new TypeError('Network request failed')); +// xhr.ontimeout = () => reject(new TypeError('Network request failed')); +// +// xhr.open(request.method, url); +// +// if (request.credentials === 'include') { +// xhr.withCredentials = true +// } else if (request.credentials === 'omit') { +// xhr.withCredentials = false +// } +// if (xhr.upload && onProgress) xhr.upload.onprogress = onProgress; +// if (xhr.responseType) xhr.responseType = 'blob'; +// +// request.headers.forEach((value, name) => { +// xhr.setRequestHeader(name, value) +// }); +// +// xhr.send(data.body); +// }); +// } + +class Print extends React.Component { + home = () => fetch(`${IP}/set?code=G28`, { method: 'GET', mode: 'no-cors' }); + status = () => fetch(`${IP}/inquiry`, { method: 'GET', mode: 'no-cors' }) + .then(response => response.text()) + .then(result => console.log('result: ', result)); + start = () => fetch(`${IP}/set?code=M565`, { method: 'GET', mode: 'no-cors' }); + stop = () => fetch(`${IP}/set?cmd={P:X}`, { method: 'GET', mode: 'no-cors' }); + upload = async () => { + const gcode = this.refs.gcode.value; + + const headers = new Headers(); + headers.append('Content-Disposition', 'form-data; name="file"; filename="doodle.gcode"'); + headers.append('Content-Type', 'application/octet-stream'); + headers.append('Accept', 'application/json'); + + const body = new FormData(); + const file = new File([gcode], 'doodle.gcode', { type: 'application/octet-stream' }); + body.append('file', file); + + const result = await fetch(`${IP}/upload`, { method: 'POST', mode: 'no-cors', headers, body }); + }; + + render() { + return ( + + + + + +