This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.2 KiB
115 lines
3.2 KiB
'use strict'; |
|
var _ = require('lodash'); |
|
var rx = require('rx-lite-aggregates'); |
|
var util = require('util'); |
|
var runAsync = require('run-async'); |
|
var utils = require('../utils/utils'); |
|
var Base = require('./baseUI'); |
|
|
|
/** |
|
* Base interface class other can inherits from |
|
*/ |
|
|
|
var PromptUI = module.exports = function (prompts, opt) { |
|
Base.call(this, opt); |
|
this.prompts = prompts; |
|
}; |
|
util.inherits(PromptUI, Base); |
|
|
|
PromptUI.prototype.run = function (questions) { |
|
// Keep global reference to the answers |
|
this.answers = {}; |
|
|
|
// Make sure questions is an array. |
|
if (_.isPlainObject(questions)) { |
|
questions = [questions]; |
|
} |
|
|
|
// Create an observable, unless we received one as parameter. |
|
// Note: As this is a public interface, we cannot do an instanceof check as we won't |
|
// be using the exact same object in memory. |
|
var obs = _.isArray(questions) ? rx.Observable.from(questions) : questions; |
|
|
|
this.process = obs |
|
.concatMap(this.processQuestion.bind(this)) |
|
// `publish` creates a hot Observable. It prevents duplicating prompts. |
|
.publish(); |
|
|
|
this.process.connect(); |
|
|
|
return this.process |
|
.reduce(function (answers, answer) { |
|
_.set(this.answers, answer.name, answer.answer); |
|
return this.answers; |
|
}.bind(this), {}) |
|
.toPromise(Promise) |
|
.then(this.onCompletion.bind(this)); |
|
}; |
|
|
|
/** |
|
* Once all prompt are over |
|
*/ |
|
|
|
PromptUI.prototype.onCompletion = function (answers) { |
|
this.close(); |
|
|
|
return answers; |
|
}; |
|
|
|
PromptUI.prototype.processQuestion = function (question) { |
|
question = _.clone(question); |
|
return rx.Observable.defer(function () { |
|
var obs = rx.Observable.of(question); |
|
|
|
return obs |
|
.concatMap(this.setDefaultType.bind(this)) |
|
.concatMap(this.filterIfRunnable.bind(this)) |
|
.concatMap(utils.fetchAsyncQuestionProperty.bind(null, question, 'message', this.answers)) |
|
.concatMap(utils.fetchAsyncQuestionProperty.bind(null, question, 'default', this.answers)) |
|
.concatMap(utils.fetchAsyncQuestionProperty.bind(null, question, 'choices', this.answers)) |
|
.concatMap(this.fetchAnswer.bind(this)); |
|
}.bind(this)); |
|
}; |
|
|
|
PromptUI.prototype.fetchAnswer = function (question) { |
|
var Prompt = this.prompts[question.type]; |
|
this.activePrompt = new Prompt(question, this.rl, this.answers); |
|
return rx.Observable.defer(function () { |
|
return rx.Observable.fromPromise(this.activePrompt.run().then(function (answer) { |
|
return {name: question.name, answer: answer}; |
|
})); |
|
}.bind(this)); |
|
}; |
|
|
|
PromptUI.prototype.setDefaultType = function (question) { |
|
// Default type to input |
|
if (!this.prompts[question.type]) { |
|
question.type = 'input'; |
|
} |
|
return rx.Observable.defer(function () { |
|
return rx.Observable.return(question); |
|
}); |
|
}; |
|
|
|
PromptUI.prototype.filterIfRunnable = function (question) { |
|
if (question.when === false) { |
|
return rx.Observable.empty(); |
|
} |
|
|
|
if (!_.isFunction(question.when)) { |
|
return rx.Observable.return(question); |
|
} |
|
|
|
var answers = this.answers; |
|
return rx.Observable.defer(function () { |
|
return rx.Observable.fromPromise( |
|
runAsync(question.when)(answers).then(function (shouldRun) { |
|
if (shouldRun) { |
|
return question; |
|
} |
|
}) |
|
).filter(function (val) { |
|
return val != null; |
|
}); |
|
}); |
|
};
|
|
|