diff --git a/backend/components/alexa.js b/backend/components/alexa.js index b06c44f..2fc124d 100644 --- a/backend/components/alexa.js +++ b/backend/components/alexa.js @@ -33,7 +33,7 @@ module.exports = { updateIntentsJSON: function () { databaseHelper - .loadSkill (config.SKILL_DB_ID) + .getSkill (config.SKILL_DB_ID) .then (skill => { skill.intents.map (intent => { alexaApp.intent ( diff --git a/backend/config/config.js b/backend/config/config.js index 3edee7d..67573de 100644 --- a/backend/config/config.js +++ b/backend/config/config.js @@ -1,6 +1,6 @@ var config = {}; -config.dbURL = 'mongodb://localhost:27017/tellall'; +config.DB_URL = 'mongodb://localhost:27017/tellall'; config.PORT = 5000; config.TOKEN = 'Atza|IwEBIBe6gDqrrowEEav6N-_6s4NztYeP3oG8PGWmu8ZiZw6lbOh3wNla3TK6pY-VEpT1d8an-dVf_n3kXJzVFsNo_4xBfZyFHGoCTDTFjs3yBRul4PVdBOhwwiH3-sgRLcUofZbe2oE06GmTcbfYtaStfXpQI5dfpldfnsJg_CvhSA6AHb_snJT3F6lyXzbV076d_3cYUMJxFldJGnYcviNHHxjjmuQTD06hhGzCbAxxe9eBmkuopRsNfyedLT2UlKP_ublah9CUGA3AdIX_3Iuke82jMwGnNl9gv7pbaDNEjAbj7IQSl3B08uuREtJq-oTBOjALNXRvFxTJmQjZwXNf9eHC7fSHJDdEPdZQU0AcffRQObAyAkUuL6Jv39OHzhb3Q64-zzoyODqnJyLP5SQZ2JVF53Kc_cTBqjIc9pXljqe7yEVk6JDs7q1zKbBibx_AQm57TO79IzWyLBzBMlYL5HdTsqEfRzLeDw2tws-hGMgkx2HWfdbYnmf5Qb4SyIhzvmmdfPLg3MVKTxjIBu1rx0xf3n0PLZP1EO6jsJPoMRPg77Gm4oit5Zp6s37ek3A3Vxh-ntoASpkrkxGTG9kVtRNt'; diff --git a/backend/config/constants.js b/backend/config/constants.js index 39913a3..0fe470f 100644 --- a/backend/config/constants.js +++ b/backend/config/constants.js @@ -1,24 +1,30 @@ const constants = {}; constants.amazonResultCodes = { - ok:200, - accepted:202, - badRequest:400, - unauthorized:401, - notFound:404, - conflict:409, - payloadTooLarge:413 + OK:200, + ACCEPTED:202, + BAD_REQUEST:400, + UNAUTHORIZED:401, + NOT_FOUND:404, + CONFLICT:409, + PAYLOAD_TOO_LARGE:413 } constants.apiResultCodes = { - genericError : -1, - ok:0, - amazonError:1, - databaseError:2, - IDLengthError:3, + GENERIC_ERROR : -1, + OK:0, + AMAZON_ERROR:1, //amazon api works, but error is some of the amazonResultCodes + AMAZON_FAIL:2, //amazon api doesn't work + DATABASE_ERROR:3, + NO_SKILL:4, + INCONSISTEN_STATE:5, } -constants.skillIDLength = 24; +constants.HTTPResultCodes = { + INTERNAL_SERVER_ERROR : 500, +} + +constants.SKILL_ID_LENGTH = 24; diff --git a/backend/controllers/skill.js b/backend/controllers/skill.js index b292f8d..1d8cd44 100644 --- a/backend/controllers/skill.js +++ b/backend/controllers/skill.js @@ -8,7 +8,7 @@ var alexa = require ('../components/alexa'); router.get ('/:id', async (req, res, next) => { const id = req.params.id; - if (id.length !== constants.skillIDLength) { + if (id.length !== constants.SKILL_ID_LENGTH) { res.json ([]); } else { databaseHelper @@ -31,63 +31,66 @@ router.put ('/:id', bodyParser.json (), async (req, res, next) => { delete skill.updateOnAmazon; delete skill._id; - console.log ('id = ' + id); - - //TODO : Fix inconsistency ! If skill is sent to amazon and accepted, but - //fails in database (ID doesn't exist) - if (id.length === constants.skillIDLength) { - if (updateOnAmazon) { - amazonHelper - .updateSkill (skill) - .then (amazonResult => { - console.log ('Amazon : ' + amazonResult); - if ( - amazonResult === constants.amazonResultCodes.ok || - amazonResult === constants.amazonResultCodes.accepted - ) { - //Skill uploaded, it's ok to update databaseI - databaseHelper - .updateSkill (id, skill) - .then (result => { - res.json ({result: constants.apiResultCodes.ok, message: ''}); - alexa.updateIntentsJSON (); - }) - .catch (e => { - res.json ({ - result: constants.apiResultCodes.databaseError, - message: '', - }); - }); - } else { - res.json ({ - result: constants.apiResultCodes.amazonError, - message: amazonResult, - }); - } - }) - .catch (e => { - res.json ({ - result: constants.apiResultCodes.amazonError, - message: 'unknown', - }); - }); - } else { + //First get current skill from DB + databaseHelper + .getSkill (id) + .then (currentSkillState => { + //Now let's update skill in DB databaseHelper .updateSkill (id, skill) - .then (result => { - res.json ({result: constants.apiResultCodes.ok, message: ''}); - alexa.updateIntentsJSON (); + .then (() => { + //Ok, done, now update skill on Amazon (if needed) + if (updateOnAmazon) { + amazonHelper + .updateSkill (skill) + .then (amazonResult => { + if ( + amazonResult === constants.amazonResultCodes.OK || + amazonResult === constants.amazonResultCodes.ACCEPTED + ) { + res.json ({result: constants.apiResultCodes.OK, message: ''}); + alexa.updateIntentsJSON (); + } else { + res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({ + result: constants.apiResultCodes.AMAZON_ERROR, + message: amazonResult, + }); + } + }) + .catch (e => { + res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({ + result: constants.apiResultCodes.AMAZON_FAIL, + message: e, + }); + }); + }else{ + res.json ({result: constants.apiResultCodes.OK, message: ''}); + alexa.updateIntentsJSON (); + } }) - .catch (e => { - res.json ({ - result: constants.apiResultCodes.databaseError, - message: '', - }); + .catch (() => { + //Update in database didn't go well, revert changes + databaseHelper + .updateSkill (id, currentSkillState) + .then (() => { + res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({ + result: constants.apiResultCodes.DATABASE_ERROR, + message: '', + }); + }) + .catch (() => { + //This should never happen, something is seriously wrong, like no database connection + res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({ + result: constants.apiResultCodes.INCONSISTEN_STATE, + message: '', + }); + }); }); - } - } else { - res.json ({result: constants.IDLengthError, message: ''}); - } + }) + .catch (e => { + //I don't know why, but something went wrong, possibly ID of skill is wrong, doesn't exist in DB + res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({result: constants.apiResultCodes.NO_SKILL, message: ''}); + }); }); module.exports = router; diff --git a/backend/helpers/amazon.js b/backend/helpers/amazon.js index 3a66cbf..1fd9410 100644 --- a/backend/helpers/amazon.js +++ b/backend/helpers/amazon.js @@ -35,17 +35,20 @@ var refreshTokens = function () { }; request (options, function (error, response, body) { - if (error) reject (error); - parsedResponse = JSON.parse (body); - if (parsedResponse.refresh_token) - return databaseHelper.updateTokens ( - parsedResponse.refresh_token, - parsedResponse.access_token, - parsedResponse.expires_in - ); - console.log ('Token refresh failed'); - console.log (body); - reject (body); + if (error) { + reject (error); + }else{ + parsedResponse = JSON.parse (body); + if (parsedResponse.refresh_token){ + databaseHelper.updateTokens(parsedResponse.refresh_token, parsedResponse.access_token, parsedResponse.expires_in).then(()=>{ + resolve(); + }).catch(e=>{ + reject(e); + }); + }else{ + reject (body); + } + } }); }); }; diff --git a/backend/helpers/database.js b/backend/helpers/database.js index bd662a2..6934339 100644 --- a/backend/helpers/database.js +++ b/backend/helpers/database.js @@ -43,16 +43,19 @@ module.exports = { db .collection ('token_list') .update ({id: 1}, newTokenDocument, {upsert: true}, (err, result) => { - if (err) reject (err); - config.REFRESH_TOKEN = refresh_token; - config.TOKEN = access_token; - config.TOKEN_EXPIRES_IN = newTokenDocument.expires_in; - resolve (); + if (err) { + reject (err) + }else{ + config.REFRESH_TOKEN = refresh_token; + config.TOKEN = access_token; + config.TOKEN_EXPIRES_IN = newTokenDocument.expires_in; + resolve (); + } }); }); }, - loadSkill: function (skillDbID) { + getSkill: function (skillDbID) { return new Promise ((resolve, reject) => { db .collection ('skill_list') @@ -92,20 +95,5 @@ module.exports = { } }); }); - }, - - getSkill: function (id) { - return new Promise ((resolve, reject) => { - db - .collection ('skill_list') - .find ({_id: ObjectID (id)}) - .toArray ((err, result) => { - if (err) { - reject (err); - }else{ - resolve (result); - } - }); - }); - }, + } }; diff --git a/backend/middleware/index.js b/backend/middleware/index.js index 0b842fa..9543c0a 100644 --- a/backend/middleware/index.js +++ b/backend/middleware/index.js @@ -1,7 +1,7 @@ module.exports = function (req, res, next) { res.header ('Access-Control-Allow-Origin', '*'); res.header ('Access-Control-Allow-Headers', 'Origin, Content-Type'); - res.header ('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.header ('Access-Control-Allow-Methods', 'GET, POST, PUT'); res.header ('Access-Control-Allow-Credentials', 'true'); next (); }; diff --git a/backend/server.js b/backend/server.js index cbed3c5..859389c 100644 --- a/backend/server.js +++ b/backend/server.js @@ -20,7 +20,7 @@ app.set ('view engine', 'ejs'); app.use (require ('./middleware')); //common middleware for all requests app.use (require ('./controllers')); //all routes -MongoClient.connect (config.dbURL) +MongoClient.connect (config.DB_URL) .then (database => { databaseHelper.initModule (database); diff --git a/web/package.json b/web/package.json index 217a9a8..e4474aa 100644 --- a/web/package.json +++ b/web/package.json @@ -17,7 +17,8 @@ "watch-css": "nodemon -e scss -x \"npm run watch-css-mine\"", "start-js": "react-scripts start", "start": "npm-run-all -p watch-css start-js", - "build": "react-scripts build", + "react-build" : "react-scripts build", + "build": "npm-run-all -p build-css react-build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, diff --git a/web/src/App.js b/web/src/App.js index b3bd1fe..663d0ec 100644 --- a/web/src/App.js +++ b/web/src/App.js @@ -31,11 +31,10 @@ class App extends Component { }; getSkill(this.state._id).then(l=>l.json()).then(result=>{ - let jResult = result[0]; - if (jResult===undefined) return; - this.setState({ skillID:jResult.skillID,skillName:jResult.skillName, invocationName: jResult.invocationName, - invocationAnswer: jResult.invocationAnswer, - allIntents: jResult.intents, contactEmail: jResult.contactEmail}) + if (result===undefined) return; + this.setState({ skillID:result.skillID,skillName:result.skillName, invocationName: result.invocationName, + invocationAnswer: result.invocationAnswer, + allIntents: result.intents, contactEmail: result.contactEmail}) }) this.handleIntentClick = this.handleIntentClick.bind(this); diff --git a/web/src/components/IntentDetails.js b/web/src/components/IntentDetails.js index 5af5471..e5c6066 100644 --- a/web/src/components/IntentDetails.js +++ b/web/src/components/IntentDetails.js @@ -28,13 +28,13 @@ class IntentDetails extends Component { id="intent name" lineDirection="center" placeholder="Intent name" - label="Intent name" + label="Question name" className="md-cell md-cell--bottom IntentDetailsInputBoxes" onChange={this.handleIntentNameEdit} maxLength={INTENT_NAME_MAX_LENGTH} value={this.state.intent.intentName} /> -
Questions
+
Question variants
{ this.state.intent.questions.map((question, index)=>{ return ( @@ -68,8 +68,8 @@ class IntentDetails extends Component { }



- - + + diff --git a/web/src/components/IntentList.js b/web/src/components/IntentList.js index 96a86d1..00596fc 100644 --- a/web/src/components/IntentList.js +++ b/web/src/components/IntentList.js @@ -30,7 +30,7 @@ class IntentList extends Component {
-

Intents

+

Questions

{ this.state.intents.map((intent,index)=>{ @@ -45,7 +45,7 @@ class IntentList extends Component {

+ disabled={this.props.waiting}>Add question ); }