Conditional Prompt rendering in Inquirer? - javascript

I am building a command line interface in node.js using library: inquirer.
based on my need I want to render prompt, confirmation text etc when user input's. example.
inquirer usage
var _questions = [{
'type': 'list',
'name': 'databasetype',
'message': 'Choose database :',
'choices': ['mongoDB', 'mysql [alpha]', 'firebase [alpha]', 'url [alpha]'],
'default': 'mongoDB'
}, {
'type': 'input',
'name': 'xfactor',
'message': 'X Factor [email, username etc..] :'
}]
// show question's.
Inquirer.prompt(_questions).then(async (__answers) => {
console.log(__answers)
})
what i want
if user chooses mongoDB than it should render another prompt asking
mongodb url

You can use the when question property, its value should be a function that returns a boolean; true for show question, false for don't show question
so using your example:
_questions = [{
type: 'list',
name: 'databasetype',
message: 'Choose database :',
choices: ['mongoDB', 'mysql [alpha]', 'firebase [alpha]', 'url [alpha]'],
default: 'mongoDB'
}, {
type: 'input',
name: 'url',
message: 'Enter the URL',
when: (answers) => answers.databasetype === 'mongoDB'
}]
see more examples here when usage examples

Related

MapBox JS having issues connecting the data csv/google sheets files in our config.js code

We are working on a map with multiple points and trying to add a filter to it. Similar to this documentation: https://labs.mapbox.com/education/impact-tools/finder-with-filters/. Where we use a csv data file to add/update the location information.
We originally tried using the CSV: './Sample_Data.csv', line in our config.js file, but we were getting an error that said "XMLHttpRequest cannot load Sample_Data.csv due to access control checks.", and we are not sure what that error is or how to fix it.
config.js file with CSV code to link:
'use strict';
// eslint-disable-next-line no-unused-vars
const config = {
style: 'mapbox://styles/mapbox/light-v10',
accessToken:
'pk.eyJ1IjoicmItZmlkZWxpdHkiLCJhIjoiY2wyNjdjeTlkMXd3dTNjanIzb2h2bDN1cCJ9.diGkmbkrJJRQegleKOHhhA',
CSV: './Sample_Data.csv',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-120.234, 47.398],
zoom: 5,
title: 'Replace with your title',
description:
'Replace with information about your application. Ex. You can search by address to sort the list below by distance. You can also filter the list by language support options, which days a location is open, and whether they have devices to use to complete the survey by phone or online.',
sideBarInfo: ['Location_Name', 'Address', 'Phone'],
popupInfo: ['Location_Name'],
filters: [
{
type: 'dropdown',
title: 'Languages supported: ',
columnHeader: 'Languages',
listItems: [
'Amharic',
'ASL',
'Cambodian',
'Chinese',
'Danish',
'English',
'French',
'German',
'Greek',
'Hindi',
'Italian',
'Japanese',
'Korean',
'Language Line Services',
'Norwegian',
'Oriya',
'Portuguese',
'Punjabi',
'Russian',
'Somali',
'Spanish',
'Swedish',
'Tagalog',
'Thai',
'Tigrinya',
'Tongan',
'Vietnamese',
'Ukranian',
'TEST'
],
},
{
type: 'checkbox',
title: 'Devices available: ',
columnHeader: 'Devices_available', // Case sensitive - must match spreadsheet entry
listItems: ['Computer', 'Wi-Fi', 'Adaptive Laptops'], // Case sensitive - must match spreadsheet entry; This will take up to six inputs but is best used with a maximum of three;
},
{
type: 'dropdown',
title: 'Clients: ',
columnHeader: 'Clients',
listItems: [
'Adults',
'Disabled',
'Homeless',
'Immigrants/Refugees',
'Low Income',
'Seniors',
'Youth: Pre-teen',
'Youth: Teen',
],
},
],
};
We also tried making a Google Sheet of the csv data, that we can use and update, but are not sure where we can place the code correctly, in our config.js file for it to connect to the sheet and use its data.
From the documentation that we read on Sheet Mapper: https://labs.mapbox.com/education/impact-tools/sheet-mapper/, we got this code:
$(document).ready(function () {
$.ajax({
type: "GET",
//YOUR TURN: Replace with csv export link
url: 'https://docs.google.com/spreadsheets/d/1DbFiU7vOnFFBI57HHjOOSZcRxoH7hbErn7kTlm3kwiw/gviz/tq?tqx=out:csv&sheet=FIDELITY-MAPBOX-DATA',
dataType: "text",
success: function (csvData) { makeGeoJSON(csvData); }
});
Either method we can't get to work and are stuck how to proceed.
Thank you for any help.

Dynamically return config value (node.js)

I'm building a content middleware which gather contents from our external publishers. The publishers will share their contents either in rss or json and the key/value field would be different from each other. To make thing easier, I created a config file where I can pre-defined the key/value and the feed type. The problem is, how can I dynamically return this config value based on publishers name.
Example: To get Publisher #1 feed type, I just can use config.articles.rojak_daily.url_feed
my config file /config/index.js
module.exports = {
batch:100,
mysql: {
database: process.env.database,
host: process.env.host,
username: process.env.username,
password: process.env.password
},
articles:{
rojak_daily:{ // Publisher 1
url: 'xxx',
url_feed: 'rss',
id: null,
Name: 'title',
Description: 'description',
Link: 'link',
DatePublishFrom: 'pubDate',
LandscapeImage: 's3image',
SiteName: 'Rojak Daily',
SiteLogo: null
},
rojak_weekly:{ // publisher 2
url: 'xxx',
url_feed: 'json',
id: null,
Name: 'Name',
Description: 'Desc',
Link: 'link',
DatePublishFrom: 'pubDate',
LandscapeImage: 's3image',
SiteName: 'Rojak Weekly',
SiteLogo: null
}
}
}
my main application script
const config = require('#config'); // export from config file
class Main {
constructor(){
this.publishers = ['rojak_daily','rojak_weekly'];
}
// Main process
async startExport(){
try{
for(let publisher of this.publishers){
const feedType = await this.getFeedType(publisher)
const result = (feedType == 'rss')? await this.rss.start(publisher): await this.json.start(publisher)
return result
}
}catch(err){
console.log("Error occured: ", err)
}
}
// Get feed type from config
async getFeedType(publisher){
return await config.articles.rojak_daily.url_feed;
// this only return publisher 1 url feed.
// my concern is to dynamically passing variable
// into this config file (example: config.articles.<publisher>.url_feed)
}
}
module.exports = Main
async getFeedType(publisher){
return await config.articles[publisher].url_feed;
}
You can access properties of objects by variable
You could either loop over the articles by using Object.entries(articles) or Object.values(articles) in conjunction with Array.prototype.forEach(), or since you already have the name of the publisher you could access that entry with config.articles[publisher].url_feed, like so:
const config = {
articles: {
rojak_daily: { // Publisher 1
url: 'xxx',
url_feed: 'rss',
id: null,
Name: 'title',
Description: 'description',
Link: 'link',
DatePublishFrom: 'pubDate',
LandscapeImage: 's3image',
SiteName: 'Rojak Daily',
SiteLogo: null
},
rojak_weekly: { // publisher 2
url: 'xxx',
url_feed: 'json',
id: null,
Name: 'Name',
Description: 'Desc',
Link: 'link',
DatePublishFrom: 'pubDate',
LandscapeImage: 's3image',
SiteName: 'Rojak Weekly',
SiteLogo: null
}
}
}
const publishers = ['rojak_daily', 'rojak_weekly']
function getFeedType(publisher) {
return config.articles[publisher].url_feed;
}
publishers.forEach(publisher => console.log(getFeedType(publisher)));

Pass data between prompts

Can i pass data between two prompts in yeoman?
Eg i've got two prompts like
{
type: 'input',
name: 'Name',
message: 'Name?'
},{
type: 'input',
name: 'package',
message: 'Package?',
default: 'org.my.app.'+<prompt.name>
}
I want to show name property as default value for package? One way i can think of is:
Show a template in default (like in example)
Change the value later when creating the final template for user.
Another way that i tried is using when
{
type: 'input',
name: 'Name',
message: 'Name?'
},{
when: (response) => {
this.testValue = response.Name
return true
},
type: 'input',
name: 'package',
message: 'Package?',
default: 'org.my.app.'+this.testValue
}
but it gives undefined even though inside the function value has been stored for in this.testValue
Is there any better way?
i finally found the answer. The way to achieve it is using two prompt variables and running the second one after first's promise returns
const prompt1 = [{
type: 'input',
name: 'Name',
message: 'Name?'
}];
return this.prompt(prompt1).then(props => {
const prompt2 = [{
type: 'input',
name: 'package',
message: 'Package?',
default: 'org.my.app.'+props.name
}];
return this.prompt(prompt2).then(props => {
//code goes here
});
});

Broadcast message only for the owner of the models

I am building an application where users can create event and other users can "join" and add comments to events, also they can open a chat between them, I have a model named "Notification" where I want to store all the notifications in the system and I want to warn to the owner of the event whenever a user comment on his events, write a new message to him, etc.
This is the part of code for comments that I have wrote:
Notification Model:
/* Notification.js */
module.exports = {
attributes: {
title: {
type: 'string',
required: true
},
text: {
type: 'string'
},
type:{
type: 'string',
enum: ['new_assistant', 'cancel_assistant', 'new_message', 'new_comment'],
required: 'true'
},
read: {
type: 'boolean',
defaultsTo: false
},
user: {
model: 'user'
}
}
};
This is where I subscribe the socket to his notification model:
Notification.find({
user: owner_id
}).then(function(notifications) {
return Notification.watch(req.socket);
});
And whenever a user comment in an event I create a new Notification record:
Notification.create({
title: 'A new user has comment',
text: "Hola",
type: 'new_comment',
read: false,
user: event.owner
}).then(function(comment) {
return Notification.publishCreate({
id: notification.id,
title: 'A new user has comment'
});
});
That code run but this sent a socket message to all users and I just want to warn to the owner of the event (And in the future to the users who going to this event).
Thank you so much.
watch sends the model instance creation message to all of the sockets that are watching the model, the same registration could have been performed without finding the notification as it's not instance dependent, i.e. just call: Notification.watch(req.socket);
To send the notification to a single subscriber use sails.sockets
Create a room for the owner when you want to subscribe:
sails.sockets.join(req.socket, owner_id);
And when you want to publish broadcast to this room:
Notification.create({
title: 'A new user has comment',
text: "Hola",
type: 'new_comment',
read: false,
user: event.owner
}).then(function(comment) {
sails.sockets.broadcast(event.owner, {
id: notification.id,
title: 'A new user has comment'
});
});

Facebook stream.share returns undefined

Why does Facebook stream.share return undefined when a user publish a status or click "Skip"?
I'm currently trying to use this, so if the user doesn't publish the content, no action should happen, but if the user publish the content an action should happen.
How do I do this?
You can use the graph API feed dialog to publish a post and know if it was published or not by the user:
FB.ui(
{
method: 'feed',
message: '',
name: 'name here',
caption: 'caption here',
description: 'description here',
picture: 'picture url here',
link: 'http://yourlinkurlhere.com',
actions : [{name : 'action name', link : 'action link'}]
},
function(response) {
if (response && response.post_id) {
// Post was published
} else {
// Post did get published
}
});

Categories