@domoinc/multiline
Version:
MultiLine - Domo Widget
458 lines (434 loc) • 15.4 kB
JavaScript
var blue = '\x1B[0;36m';
var yellow = '\x1B[1;33m';
var noColor = '\x1B[0m';
var request = require('request');
var fs = require('fs');
var shell = require('shelljs');
var apiUrl = 'http://domoapps.dev.domo.com/devapi/';
var sandbox = true;
module.exports = function(grunt) {
'use strict';
//var _ = require('lodash');
var svgs = grunt.file.expand('media/*.svg');
var videos = grunt.file.expand('media/*.mp4');
videos.unshift('None');
var widget;
var categories = [
{name: 'Vertical Bar Charts'},
{name: 'Horizontal Bar Charts'},
{name: 'Line & Area Charts'},
{name: 'Pie & Funnel Charts'},
{name: 'Maps'},
{name: 'Gauges'},
{name: 'Bubble & Scatter Charts'},
{name: 'Controls'},
{name: 'Other Charts'}
];
// Project configuration
grunt.initConfig({
// Metadata
bower: grunt.file.readJSON('bower.json'),
banner: '/*! <%= bower.name %> - v<%= bower.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> Domo */\n',
// Task configuration
jshint: {
dev: {
options: {
force: true,
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
src: ['*.js', '!Gruntfile.js']
},
dep: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
src: ['*.js', '!Gruntfile.js']
}
},
init: {
dist: {
title: "<%= bower.name %>"
}
},
prompt: {
config: {
options: {
questions: [{
config: 'publishConfig.name',
type: 'input',
message: 'Widget name',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').name) {
return grunt.config('publishConfig').name;
}
return grunt.config('bower').name;
}
},
{
config: 'publishConfig.version',
type: 'input',
message: 'Widget version',
default: function() { return grunt.config('bower').version; }
},
{
config: 'publishConfig.github',
type: 'input',
message: 'Github repo name',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').github) {
return grunt.config('publishConfig').github;
}
var dir = __dirname.split('/');
var folder = dir[dir.length - 1];
return folder;
}
},
{
config: 'publishConfig.description',
type: 'input',
message: 'Enter a description',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').description) {
return grunt.config('publishConfig').description;
}
return '';
}
},
{
config: 'publishConfig.tags',
type: 'input',
message: 'Enter a comma-seperated list of tags',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').tags) {
return grunt.config('publishConfig').tags.join(',');
}
return '';
}
},
{
config: 'publishConfig.categories',
type: 'checkbox',
message: 'Select all categories that apply',
choices: categories
},
{
config: 'publishConfig.customers',
type: 'input',
message: 'Enter a comma-seperated list of customers',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').customers) {
return grunt.config('publishConfig').customers.join(',');
}
return '';
}
},
{
config: 'publishConfig.builderVersion',
type: 'input',
message: 'Enter the minimum version of the app builder required for this widget',
default: function() {
if (grunt.config('publishConfig') && grunt.config('publishConfig').builderVersion) {
return grunt.config('publishConfig').builderVersion;
}
return '';
}
},
{
config: 'publishConfig.file',
type: 'list',
message: 'Choose the widget svg',
default: function () {
if (grunt.config('publishConfig') && grunt.config('publishConfig').file) {
return grunt.config('publishConfig').file;
}
return '';
},
choices: svgs
},
{
config: 'publishConfig.video',
type: 'list',
message: 'Choose the widget video',
default: function () {
if (grunt.config('publishConfig') && grunt.config('publishConfig').video) {
return grunt.config('publishConfig').video;
}
return '';
},
choices: videos
}]
}
},
chooseWidget: {
options: {
questions: [{
config: 'publishConfigFile',
type: 'list',
message: 'Choose the widget to publish'
}]
}
}
}
});
// These plugins provide necessary tasks
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-bower-install');
grunt.loadNpmTasks('grunt-release');
grunt.loadNpmTasks('grunt-notify');
grunt.loadNpmTasks('grunt-prompt');
grunt.registerTask('saveWidget', function(){
var publishConfig = grunt.config('publishConfig');
var configFile = grunt.config('publishConfigFile');
if(!configFile){
configFile = 'publishConfig-' + publishConfig.name.replace(/\s/g, '') + '.json';
grunt.config('publishConfigFile', configFile);
}
if(typeof publishConfig.tags === 'string'){
publishConfig.tags = publishConfig.tags.split(/\s*,\s*/);
}
if(typeof publishConfig.customers === 'string'){
if (publishConfig.customers.length > 0) {
publishConfig.customers = publishConfig.customers.split(/\s*,\s*/);
} else {
delete publishConfig.customers;
}
}
grunt.config('publishConfig', publishConfig);
var fileName = publishConfig.file;
var videoName = publishConfig.video;
var builderVersion = publishConfig.builderVersion;
var done = this.async();
var id = publishConfig._id;
var prodId = id;
var devId = publishConfig._devid;
if (sandbox) {
id = devId;
}
if (id) {
request({
method: 'GET',
url: apiUrl + '/widgets/' + id,
}, function(error, response, body) {
if (!error && response.statusCode === 200) {
updateWidget(publishConfig, id);
} else {
postWidget(publishConfig);
}
})
} else {
postWidget(publishConfig);
}
function postWidget(widget) {
var id = widget._id;
request({
method: 'POST',
url: apiUrl + '/widgets',
json: publishConfig
}, function(error, response, body) {
if (!error && response.statusCode === 200) {
console.log('Widget saved');
uploadFile(body, function(){
done();
delete body.updated;
if (sandbox) {
body._devid = body._id;
body._id = prodId;
} else {
body._devid = devId;
}
body.video = videoName;
body.file = fileName;
body.builderVersion = builderVersion;
grunt.file.write(configFile, JSON.stringify(body));
});
} else {
console.log('Error while saving');
done();
}
});
}
function updateWidget(widget, id) {
request({
method: 'PUT',
url: apiUrl + '/widgets/' + id,
json: widget
}, function(error, response, body) {
if (!error && response.statusCode === 200) {
console.log('Widget updated');
uploadFile(body, function(){
done();
delete body.updated;
body._id = prodId;
body._devid = devId;
body.video = videoName;
body.file = fileName;
body.builderVersion = builderVersion;
grunt.file.write(configFile, JSON.stringify(body));
});
} else {
console.log('Error while updating');
done();
}
});
}
function uploadFile(widget, callback) {
if (fileName && grunt.file.exists(fileName)) {
var r = request.post(apiUrl + 'widgets/' + widget._id + '/image', function optionalCallback(err, httpResponse, body) {
if (err) {
uploadVideo(widget, callback);
return console.error('upload failed:', err);
}
uploadVideo(widget, callback);
console.log('Svg upload successful!');
});
var form = r.form();
form.append('image', fs.createReadStream(fileName));
} else {
console.log('No svg found')
uploadVideo(widget, callback);
}
}
function uploadVideo(widget, callback) {
if (videoName && grunt.file.exists(videoName)) {
var r = request.post(apiUrl + 'widgets/' + widget._id + '/video', function optionalCallback(err, httpResponse, body) {
if (err) {
callback();
return console.error('upload failed:', err);
}
callback();
console.log('Video upload successful!');
});
var form = r.form();
form.append('video', fs.createReadStream(videoName));
} else {
console.log('No video found')
callback();
}
}
});
grunt.registerTask('readConfig', function(){
var configFile = grunt.config('publishConfigFile');
if (grunt.file.exists(configFile)) {
grunt.config('publishConfig', grunt.file.readJSON(configFile));
categories.map(function(category){
var index = grunt.config('publishConfig').categories.indexOf(category.name);
category.checked = index >= 0;
});
}
});
grunt.registerTask('pushPublishConfig', function () {
var done = this.async();
var configFileText = grunt.config('publishConfigFile');
var instanceText = sandbox ? 'sandbox' : 'prod';
console.log(yellow + 'Warning this will push any staged changes.\n' + noColor);
console.log("Adding && Committing " + blue + "publishConfig*" + noColor + " files...");
shell.exec('git add publishConfig-*.json');
shell.exec('git commit publishConfig-*.json -m "chore(): updated config: '+ configFileText + ' to ' + instanceText + '"');
console.log("\nPushing " + blue + "publishConfig*" + noColor + " files...");
shell.exec('git push', {async: false} , function (code, output) {
if (code !== 0)
{
grunt.fail.warn('\'git push\' failed. Please push this commit.', code);
}
console.log('Done.');
done();
});
});
grunt.registerTask('publish', function(env, widgetName) {
var configFile;
if(env && env.toLowerCase() === 'prod'){
apiUrl = 'http://domoapps.dev.domo.com/api/';
sandbox = false;
} else if (env && !widgetName) {
// If the keyword 'prod' is not used, assume the first argument was the widget name
widgetName = env;
}
if(widgetName){
configFile = 'publishConfig-' + widgetName + '.json';
grunt.config('publishConfigFile', configFile);
grunt.task.run(['readConfig', 'prompt:config', 'saveWidget', 'pushPublishConfig']);
} else {
var configs = grunt.file.expand('publishConfig-*.json');
if(configs.length === 0){
grunt.task.run(['prompt:config', 'saveWidget', 'pushPublishConfig']);
} else if(configs.length === 1) {
configFile = configs[0];
grunt.config('publishConfigFile', configFile)
grunt.task.run(['readConfig', 'prompt:config', 'saveWidget', 'pushPublishConfig']);
} else {
var questions = grunt.config('prompt.chooseWidget.options.questions');
questions[0].choices = configs;
grunt.config('prompt.chooseWidget.options.questions', questions);
grunt.task.run(['prompt:chooseWidget', 'readConfig', 'prompt:config', 'saveWidget', 'pushPublishConfig']);
}
}
});
grunt.registerTask('unpublish', function(env, widgetName) {
var configFile;
if(env && env.toLowerCase() === 'prod'){
apiUrl = 'http://domoapps.dev.domo.com/api/';
sandbox = false;
} else if (env && !widgetName) {
// If the keyword 'prod' is not used, assume the first argument was the widget name
widgetName = env;
}
if(widgetName){
configFile = 'publishConfig-' + widgetName + '.json';
grunt.config('publishConfigFile', configFile);
grunt.task.run(['deleteWidget']);
} else {
var configs = grunt.file.expand('publishConfig-*.json');
if(configs.length === 0){
console.log('There are no widgets to unpublish');
} else if(configs.length === 1) {
configFile = configs[0];
grunt.config('publishConfigFile', configFile)
grunt.task.run(['deleteWidget']);
} else {
var questions = grunt.config('prompt.chooseWidget.options.questions');
questions[0].choices = configs;
grunt.config('prompt.chooseWidget.options.questions', questions);
grunt.task.run(['prompt:chooseWidget', 'deleteWidget']);
}
}
});
grunt.registerTask('deleteWidget', function(){
var configFile = grunt.config('publishConfigFile');
if (grunt.file.exists(configFile)) {
var publishConfig = grunt.file.readJSON(configFile);
var id = sandbox ? publishConfig._devid : publishConfig._id;
if(id){
var done = this.async();
request({
method: 'delete',
url: apiUrl + '/widgets/' + id
}, function(error, response, body) {
if (!error) {
if (response.statusCode === 200) {
console.log('Widget unpublished');
} else if (response.statusCode === 404) {
console.log('Widget already unpublished');
}
if (sandbox) {
delete publishConfig._devid;
} else {
delete publishConfig._id;
}
grunt.file.write(configFile, JSON.stringify(publishConfig));
} else {
console.log('Error removing widget. Success unknown.');
}
done();
});
} else {
console.log('This widget has not been published');
}
} else {
console.log('This widget has not been published');
}
});
};