I'm building a Yeoman generator, and have some prompts for the user, I use a prompt queue like this:
var prompts = [{
name: 'name',
message: 'What is the name of this module?'
},{
name: 'desc',
message: 'Describe your module:'
}];
this.prompt(prompts, function (props) {
this.name = props.name;
this.desc = props.desc;
done();
}.bind(this));
But how can I add a recursive question to this prompt? I want to ask the user for dependencies, and let them fill in a name, press enter, fill in another name, until they press enter with a blank answer.
After some attempts i found a solution that works:
var dependencies = [];
var dependency = function(self) {
var dep_quest = {
name: "dependency",
message: "Need any dependencies? (Leave blank to continue)"
};
self.prompt([dep_quest], function(props)
if (props.dependency !== '') {
dependencies.push(props.dependency);
dependency(self);
}
else {
self.dependencies = dependencies;
done();
}
});
}
this.prompt(prompts, function (props) {
this.name = props.name;
this. desc = props.desc;
dependency(self);
}.bind(this));
After the regular questions i call the dependency function that asks one question again and again until a blank answer is provided. Then it calls the done() function.
Related
I developed a meteor app in which while registering I am fetching the user location at the client side, to do so I have added the packages listed below:
meteor add mdg:geolocation
meteor add jeremy:geocomplete
meteor aldeed:geocoder
meteor add jaymc:google-reverse-geocode
The code written at client side is as follows:
if (Meteor.isClient) {
Meteor.startup(() => {
GoogleMaps.load({
v: '3.26',
key: '',
libraries: 'geometry,places'
});
console.log("is GoogleMaps.loaded",GooglMaps.loaded());
});
Template.Registration.onRendered(function () {
Tracker.autorun(() => {
if (GoogleMaps.loaded()) {
$('#txt_address').geocomplete({country: "AU", type:
['()']});
}
});
var date = new Date();
$('#div_dob').datetimepicker({
format: 'DD/MM/YYYY',
maxDate : date,
ignoreReadonly: true
});
date=null;
});
Template.Registration.helpers({
location:function(){
$('input[name="txt_address"]').val(Session.get('location'));
}
});
Template.Registration.events({
'click #btn_findlocation':function(event){
alert('Find Location')
event.preventDefault();
function success(position) {
var crd = position.coords;
console.log(`Latitude0 : ${crd.latitude}`);
console.log(`Longitude0: ${crd.longitude}`);
var lat = crd.latitude;
var long = crd.longitude;
reverseGeocode.getLocation(lat, long, function(location)
{
console.log("Address",JSON.stringify(reverseGeocode.getAddrStr()));
Session.set('location', reverseGeocode.getAddrStr());
});
};// end of function success(position)
function error(err) {
console.warn('ERROR(' + err.code + '): ' + err.message);
};//end of function error(err)
// geolocation options
var options = {
enableHighAccuracy: true,
maximumAge: 0
};// end of var options
navigator.geolocation.getCurrentPosition(success, error,
options);
},
})
}
But I am getting false value for GoogleMaps.loaded() function and the following below error when I click a button to fetch the location.
Can't able to read formatted address of undefined.
Results are inconsistent as sometimes I was able to fetch the location other times not.
Please give any suggestions...
I'm not sure if it's because I'm testing in the alexa developer console but it appears the session is restarted after every intent.
In the below code, if I invoke SetMyVarA it will write out the correct value to cloudwatch (or the terminal when using serverless), but if I then invoke SetMyVarB immediately after then I'll get "Hmm, I don't know that one" (running locally will just give me undefined for the value).
I've also tried following the advice in this question but it didn't seem to have an effect: adding alexa skill session attributes from nodejs
/*jslint es6 */
"use strict";
const Alexa = require(`alexa-sdk`);
module.exports.handler = (event, context, callback) => {
console.log(`handler: ${JSON.stringify(event.request)}`);
const alexa = Alexa.handler(event, context, callback);
alexa.appId = process.env.APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
};
const handlers = {
"LaunchRequest": function() {
console.log(`LaunchRequest`);
this.emit(`AMAZON.HelpIntent`);
},
"SetMyVarA": function() {
console.log(`Set MyVarA`);
var myVarA = this.event.session.attributes.myVarA = this.event.request.intent.slots.myVarA.value;
console.log(`MyVarA is ${myVarA}.`);
var speechOutput = `MyVarA has been set to ` + myVarA + `.`;
this.response.speak(speechOutput);
this.emit(`:responseReady`);
},
"SetMyVarB": function() {
console.log(`Set MyVarB`);
var myVarB = this.event.session.attributes.myVarB = this.event.request.intent.slots.myVarB.value;
console.log(`MyVarB is ${myVarB}.`);
var myVarA = this.event.session.attributes.myVarA
console.log(`MyVarA is ${myVarA}.`);
var speechOutput = {
"type": `SSML`,
"ssml": `<speak>MyVarB is ` + myVarB + `.</speak>`,
};
this.response.speak(speechOutput);
this.emit(`:responseReady`);
},
"AMAZON.HelpIntent": function() {
var speechOutput = `This is a skill.`;
var reprompt = `Help here.`;
speechOutput = speechOutput + reprompt;
this.response.speak(speechOutput)
.listen(reprompt);
this.emit(`:responseReady`);
},
"AMAZON.CancelIntent": function() {
},
"AMAZON.StopIntent": function() {
},
"AMAZON.RepeatIntent": function() {
console.log(`RepeatIntent`);
this.emit(`LaunchRequest`);
},
"Unhandled": function() {
// handle any intent in interaction model with no handler code
console.log(`Unhandled`);
this.emit(`LaunchRequest`);
},
"SessionEndedRequest": function() {
// "exit", timeout or error. Cannot send back a response
console.log(`Session ended: ${this.event.request.reason}`);
},
};
In SetMyVar if you use speak() and then emit a responseReady the session gets closed by default, so you're already out of it when you try to call your 2nd intent.
If you want to do exactly the same thing you're doing in SetMyVarA but not close the session immediately you need to set this.response.shouldEndSession to false. The Alexa Dev Console can handle skill sessions with no problems, so don't worry about that.
By the way, you're using ASK v1 which is outdated. Please switch to v2 code like this:
https://developer.amazon.com/blogs/alexa/post/decb3931-2c81-497d-85e4-8fbb5ffb1114/now-available-version-2-of-the-ask-software-development-kit-for-node-js
https://ask-sdk-for-nodejs.readthedocs.io/en/latest/ASK-SDK-Migration-Guide.html
Yesterday my app was launched, Ionic v1, and a few users entered the wrong password and can't log into the app.
The app uses firebase authentication. I have a __refs file that points to the database and have tried numerous things trying to get the reset to work.
I've tried referencing $firebaseAuth, of course my __refs, $firebase then use $firebase.auth()...
I didn't write the authentication of this app so I'm not real sure how it works. I'm hoping that someone can help me.
My reset controller
angular.module('formulaWizard').controller('ResetPasswordCtrl',
function($scope, $ionicLoading, $firebaseAuth, __Refs) {
$scope.user = {
email: ''
};
$scope.errorMessage = null;
var fbAuth = $firebaseAuth(__Refs.rootRef);
$scope.resetPassword = function() {
$scope.errorMessage = null;
$ionicLoading.show({
template: 'Please wait...'
});
fbAuth.sendPasswordResetEmail($scope.user.email)
.then(showConfirmation)
.catch(handleError);
};
function showConfirmation() {
$scope.emailSent = true;
$ionicLoading.hide();
}
function handleError(error) {
switch (error.code) {
case 'INVALID_EMAIL':
case 'INVALID_USER':
$scope.errorMessage = 'Invalid email';
break;
default:
$scope.errorMessage = 'Error: [' + error.code + ']';
}
$ionicLoading.hide();
}
});
My Refs file
angular.module('formulaWizard')
.factory('__Refs', function ($firebaseArray, $firebaseObject) {
// Might use a resource here that returns a JSON arrayf
var ref = new Firebase('https://firebasedatabase.com/');
return {
rootRef: ref,
customers: ref.child('customers'),
}
});
I can't take credit for the answer it was provide by Abimbola Idowu on HackHands.
Since I paid for the answer I thought I would share it with anyone else that might also be stumped by this.
$scope.resetPassword = function() {
$scope.errorMessage = null;
$ionicLoading.show({
template: 'Please wait...'
});
__Refs.rootRef.resetPassword({ email: $scope.user.email }, function(error) {
if (error === null) {
showConfirmation();
} else {
handleError()
}
});
};
This is the __refs service
angular.module('formulaWizard')
.factory('__Refs', function ($firebaseArray, $firebaseObject) {
// Might use a resource here that returns a JSON arrayf
var ref = new Firebase('https://firebasedatabase.com/');
return {
rootRef: ref,
}
});
I've created an UI action using various guides (include Jeff Potts really great ones) successfully and it function exactly as expected - but I want to add that action to the multi-select tool as well. It has been really difficult finding much documentation.
Some things I've tried:
Tried to find out if there was an applicable actionGroup - which there doesn't seem to be.
Tried adding the multi-select tags to my share-config-custom.xml to define the item - it shows up, but I obviously can't seem to use the action ID to reference that action.
My next step was to try and create a js file with a registerAction function in it, which I am able to do and have it run (I can see the console.log dump) but I don't really have any idea how I would go about invoking my repo action from there).
How can I complete this task?
There is already function exist for invoking the repository custom action.This function is defined inside below file.
share-war\components\documentlibrary\actions.js
You can take reference of below code for invoking the repository action.
onActionSimpleRepoAction: function dlA_onActionSimpleRepoAction(record, owner)
{
//ACE-2470 : Clone: Clicking multiple times the simple Workflow approval menu item gives unexpected results.
if (owner.title.indexOf("_deactivated") == -1)
{
// Get action params
var params = this.getAction(record, owner).params,
displayName = record.displayName,
namedParams = ["function", "action", "success", "successMessage", "failure", "failureMessage", "async"],
repoActionParams = {};
for (var name in params)
{
if (params.hasOwnProperty(name) && !Alfresco.util.arrayContains(namedParams, name))
{
repoActionParams[name] = params[name];
}
}
//Deactivate action
var ownerTitle = owner.title;
owner.title = owner.title + "_deactivated";
var async = params.async ? "async=" + params.async : null;
// Prepare genericAction config
var config =
{
success:
{
event:
{
name: "metadataRefresh",
obj: record
}
},
failure:
{
message: this.msg(params.failureMessage, displayName),
fn: function showAction()
{
owner.title = ownerTitle;
},
scope: this
},
webscript:
{
method: Alfresco.util.Ajax.POST,
stem: Alfresco.constants.PROXY_URI + "api/",
name: "actionQueue",
queryString: async
},
config:
{
requestContentType: Alfresco.util.Ajax.JSON,
dataObj:
{
actionedUponNode: record.nodeRef,
actionDefinitionName: params.action,
parameterValues: repoActionParams
}
}
};
// Add configured success callbacks and messages if provided
if (YAHOO.lang.isFunction(this[params.success]))
{
config.success.callback =
{
fn: this[params.success],
obj: record,
scope: this
};
}
if (params.successMessage)
{
config.success.message = this.msg(params.successMessage, displayName);
}
// Acd configured failure callback and message if provided
if (YAHOO.lang.isFunction(this[params.failure]))
{
config.failure.callback =
{
fn: this[params.failure],
obj: record,
scope: this
};
}
if (params.failureMessage)
{
config.failure.message = this.msg(params.failureMessage, displayName);
}
// Execute the repo action
this.modules.actions.genericAction(config);
}
},
I probably misunderstood something but here is my problem on plunker.
I put the relevant code here anyway:
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
var cellNameEditable =
'<cell-template model=COL_FIELD input=COL_FIELD entity=row.entity></cell-template>';
var cellNameDisplay =
'<div class="ngCellText" ng-class="col.colIndex()">{{row.getProperty(col.field)}}</div>';
$scope.myData= [{"id":1,"code":"1","name":"Ain"},{"id":2,"code":"2","name":"Aisne"},{"id":3,"code":"3","name":"Allier"},{"id":4,"code":"5","name":"Hautes-Alpes"},{"id":5,"code":"4","name":"Alpes-de-Haute-Provence"},{"id":6,"code":"6","name":"Alpes-Maritimes"},{"id":7,"code":"7","name":"Ardèche"},{"id":8,"code":"8","name":"Ardennes"},{"id":9,"code":"9","name":"Ariège"},{"id":10,"code":"10","name":"Aube"}];
$scope.gridOptions = {
data: 'myData',
multiSelect: false,
enableCellSelection: true,
enableRowSelection: false,
enableCellEditOnFocus: false,
rowHeight: 100,
columnDefs: [
{field:'id', displayName:'Id', visible: false},
{field:'code', displayName:'Code', enableCellEdit:true},
{
field:'name', displayName:'Name', enableCellEdit:true,
cellTemplate: cellNameDisplay,
editableCellTemplate: cellNameEditable
}
]
};
});
app.directive('cellTemplate', function () {
var cellTemplate =
'<div><form name="myForm" class="simple-form" novalidate>' +
'<input type="text" name="myField" ng-input="localInput" ng-model="localModel" entity="entity" required/>' +
'<span ng-show="myForm.myField.$error.required"> REQUIRED</span>' +
'localModel = {{localModel}} localInput = {{localInput}} entity = {{entity}}' +
'</form></div>';
return {
template: cellTemplate,
restrict: 'E',
scope: {
localModel:'=model',
localInput:'=input',
entity:'=entity'
},
controller: function ($scope) {
$scope.$on('ngGridEventStartCellEdit', function (event) {
console.log('cellTemplate controller - ngGridEventStartCellEdit fired');
$scope.oldEntity = angular.copy(event.currentScope.entity);
$scope.oldValue = angular.copy(event.currentScope.localModel);
});
$scope.$on('ngGridEventEndCellEdit', function(event) {
console.log('ngGridEventEndCellEdit fired');
if(event.currentScope.myForm.$valid) {
if(!angular.equals($scope.oldEntity, event.currentScope.entity)) {
alert('data saved !');
}
} else {
$scope.localModel = angular.copy($scope.oldValue);
$scope.localInput = angular.copy($scope.oldValue);
$scope.entity = angular.copy($scope.oldEntity);
}
});
}
};
});
Then explanations:
I have a ng-grid and based on the official example named "Excel-like Editing
Example" but with enableCellEditOnFocus option turned to false.
The cell "name" is defined in a directive containing a form to handle
data validation before updating the model.
I want to implement this behavior: When a user put invalid data, the
directive display error message and when the user leave the field, the
directive rollback data. If everything ok then I let the data updated.
The rollback part does not work. On the given plunker line 67 to 72 (last block on the code given here) it
fails to retore data. But my binding is with "=" so it should. Or maybe
because I am on the ngGridEventEndCellEdit event it breaks the links ?
I really don't understand why it fail.
So to reproduce my issue: enter in modification on a name cell, delete
all the data, REQUIRED is shown, then go out from the cell -> model is
not rolled back.
If you use a custom template, you should emit ngGridEventEndCellEdit event.