<commit_before>// ***********************************************
// WINE LIFE
// DISCOVER WINDOW - DiscoverWindow.js
//
// MEN+1
// Programmer: Matthew Johnson
// ***********************************************

function DiscoverWindow(title) {

	var global = require('ui/common/globals');
	var dropdown = require('ui/common/elements/dropdown');
	var self = global.createWindow(title);
	self.barImage='images/iPhone_Nav_Bar_Bkgrd_With_Black.png';
	var TU = require ('/TitanUp/TitanUp');

	// This view holds the wine list
	var view = Ti.UI.createView({
		top:'35%',
		left:0,
		width:'100%',
		height:'70%',
		layout: 'vertical',
	});

	var label_title = Ti.UI.createLabel({
		color: global.colors.dark,
		top: '5%',
		text:"Today's Featured Wines",
		font:{
            fontFamily:'Helvetica Neue',
            fontSize:18,
            fontWeight:'Bold'
           }
	});
//***********************************************************************************
//  This original list in the future will display advertised wines / picks of the day
//***********************************************************************************
	self.addEventListener('open', function(e){
		global.api.search_with_filter("Zinfandel", '124', function(search_results){
            table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
			});
		   view.add(label_title);
           view.add(table);
      });
	});

	self.add(view);

//************************************************************************
// Arrays with wines for picker menu's
//************************************************************************

 var allwines = ['Type', 'Albarino', 'Barbera', 'Carmenere', 'Cabernet Sauvignon',
 'Cabernet Franc', 'Chardonnay', 'Chenin Blanc', 'Dessert Wines', 'Dolcetto', 'Gamay', 'Grenache', 'Grigio',
 'Gris', 'Madeira', 'Merlot', 'Mourvedre', 'Muscat', 'Nebbiolo', 'Petite Sirah', 'Pinot Blanc', 'Pinot Noir', 'Port', 'Primitivo', 'Riesling',
  'Sangiovese', 'Sauvignon Blanc', 'Semillon', 'Sherry', 'Shiraz', 'Syrah', 'Tempranillo', 'Torrontes', 'Viognier', 'Zinfandel', 'Non-Vintage'];

 var redwines =  ['Type', 'Barbera',  'Cabernet Sauvignon', 'Cabernet Franc', 'Carmenere',
   'Dolcetto', 'Gamay', 'Grenache', 'Merlot', 'Mourvedre', 'Nebbiolo', 'Petite Sirah', 'Pinot Noir',
  'Primitivo', 'Sangiovese', 'Shiraz', 'Syrah', 'Tempranillo', 'Zinfandel'];

 var whitewines = ['Type','Albarino', 'Chardonnay', 'Chenin Blanc',
  'Grigio', 'Gris', 'Muscat', 'Pinot Blanc', 'Riesling',
  'Sauvignon Blanc', 'Semillon', 'Torrontes', 'Viognier' ];

// wines with filters not working
//  'Barolo', 'Carmenere', 'Chianti', 'Bordeaux',

// Drop down view
	var view_discover = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			layout: 'vertical',
			left: 10,
			right: 10,
		});

	var wine_review = null;
	var table = null;

	// Dropdown menu components
	var search_bar = Ti.UI.createTextField({
		top:0,
		width:'90%',
		left:'5%',
		hintText:' Discover a wine...',
		borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	});

	var picker_color = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Color",
		values: ['Color','Red', 'White']
	});

	var picker_allwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: allwines
	});

	var picker_redwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: redwines
	});

	var picker_whitewines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: whitewines
	});

	// These variables store picker selected values
	var winecolor = null; // this is for color id to refine search
	var wineColor = null;  // this is for actual wine color
	var winetype = null;

//*****************************************************************
//  Associative array used for server query filtering
//*****************************************************************

	var wines = new Object;
	wines['Albarino'] = '136';
    wines['Barbera'] = '172';
	wines['Bordeaux'] = '-2147483648'; // Filter doesnt work
	wines['Cabernet Sauvignon'] = '139';
    wines['Cabernet Franc']	= '197';
	wines['Carmenere'] = '10081';
	wines['Chenin Blanc'] = '165';
	wines['Chardonnay'] = '140';
	wines['Dessert Wines'] = '160';
    wines['Dolcetto'] = '183';
	wines['Gamay'] = '150';
	wines['Grenache'] = '10080';
	wines['Grigio'] = '194';
	wines['Gris'] = '194';
	wines['Madeira'] = '154';
//  wines['Malbec'] = '';
	wines['Merlot'] = '138';
	//wines['Murray'] = '162'; -bad filter
	wines['Muscat'] = '173';
    wines['Mourvedre'] = '10083';
    wines['Nebbiolo'] = '170';
    wines['Non-Vintage'] = '182';
	wines['Petite Sirah'] = '176';
	wines['Pinot Noir'] = '143';
	wines['Pinot Blanc'] = '168';
    wines['Port'] = '155';
    wines['Primitivo'] = '10084';
//  wines['Rhone Blends'] = '';
	wines['Riesling'] = '153';
	wines['Rose'] = '147';
	wines['Sangiovese'] = '163';
	wines['Sauvignon Blanc'] = '151';
	wines['Semillon'] = '177';
	wines['Shiraz'] = '146';
	wines['Sherry'] = '157';
	wines['Syrah'] = '146';
	wines['Tempranillo'] = '169';
    wines['Torrontes'] = '209';
	wines['Viognier'] = '162';
	wines['Zinfandel'] = '141';

//******************************************************************************
// Event listener for wine color picker.  This function adds and removes views
// based off of what is selected in the picker.
//******************************************************************************
	picker_color.addEventListener ('TUchange', function (e) {
		if(e.value == 'Red'){
			winecolor = '124';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_whitewines);
			view_discover.add(picker_redwines);

		picker_redwines.addEventListener ('TUchange', function (e) {
		winetype =  e.value;
		});

		}
		else if(e.value == "White"){
			winecolor = '125';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_whitewines);

			picker_whitewines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}
		else{
			winecolor = null;
			wineColor = null;
			view_discover.remove(picker_whitewines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_allwines);

			picker_allwines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}

	});

	picker_allwines.addEventListener ('TUchange', function (e) {
	winetype =  e.value;
	});

	view_discover.add(search_bar);
	view_discover.add(picker_color);
	view_discover.add(picker_allwines);

//***********************************************************************************
// Dropdown menu area
// This function controls the dropdown menu and the logic for the pickers and
// search bar.
//***********************************************************************************
	dropdown(view_discover, self, "Find", "Browse", "down", function(){

		view.setTop('4%');
		view.setHeight('100%');
		view.remove(table);
		view.setBottom('5%');
		view.remove(label_title);
		self.remove(view);
		label_title.setText("Search Results");
		view.add(label_title);

		if(search_bar.value != null && search_bar.value != ""){

		if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(search_bar.value, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else
			{
				global.api.search(search_bar.value, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}

        self.add(view);

     }
     else{
     //	if nothing entered in textfield do these
     	if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(winetype, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(winetype, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(wineColor, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else if(winecolor == null && winetype == null)
			{
				//alert('Please Enter a Wine or Select a Filter to Search');
			}

     	self.add(view);
     }
	});

global.outputHook(self);
return self;
};

module.exports = DiscoverWindow;<commit_msg>fixed where featured wines display's<commit_after>// ***********************************************
// WINE LIFE
// DISCOVER WINDOW - DiscoverWindow.js
//
// MEN+1
// Programmer: Matthew Johnson
// ***********************************************

function DiscoverWindow(title) {

	var global = require('ui/common/globals');
	var dropdown = require('ui/common/elements/dropdown');
	var self = global.createWindow(title);
	self.barImage='images/iPhone_Nav_Bar_Bkgrd_With_Black.png';
	var TU = require ('/TitanUp/TitanUp');

	// This view holds the wine list
	var view = Ti.UI.createView({
		top:'35%',
		left:0,
		width:'100%',
		height:'70%',
		layout: 'vertical',
	});

	var label_title = Ti.UI.createLabel({
		color: global.colors.dark,
		top: '5%',
		text:"Today's Featured Wines",
		font:{
            fontFamily:'Helvetica Neue',
            fontSize:18,
            fontWeight:'Bold'
           }
	});
//***********************************************************************************
//  This original list in the future will display advertised wines / picks of the day
//***********************************************************************************
	self.addEventListener('open', function(e){

		label_title.setTop(view_discover.getBottom() + 5);

		global.api.search_with_filter("Zinfandel", '124', function(search_results){
            table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
			});
		   view.add(label_title);
           view.add(table);
      });
	});

	self.add(view);

//************************************************************************
// Arrays with wines for picker menu's
//************************************************************************

 var allwines = ['Type', 'Albarino', 'Barbera', 'Carmenere', 'Cabernet Sauvignon',
 'Cabernet Franc', 'Chardonnay', 'Chenin Blanc', 'Dessert Wines', 'Dolcetto', 'Gamay', 'Grenache', 'Grigio',
 'Gris', 'Madeira', 'Merlot', 'Mourvedre', 'Muscat', 'Nebbiolo', 'Petite Sirah', 'Pinot Blanc', 'Pinot Noir', 'Port', 'Primitivo', 'Riesling',
  'Sangiovese', 'Sauvignon Blanc', 'Semillon', 'Sherry', 'Shiraz', 'Syrah', 'Tempranillo', 'Torrontes', 'Viognier', 'Zinfandel', 'Non-Vintage'];

 var redwines =  ['Type', 'Barbera',  'Cabernet Sauvignon', 'Cabernet Franc', 'Carmenere',
   'Dolcetto', 'Gamay', 'Grenache', 'Merlot', 'Mourvedre', 'Nebbiolo', 'Petite Sirah', 'Pinot Noir',
  'Primitivo', 'Sangiovese', 'Shiraz', 'Syrah', 'Tempranillo', 'Zinfandel'];

 var whitewines = ['Type','Albarino', 'Chardonnay', 'Chenin Blanc',
  'Grigio', 'Gris', 'Muscat', 'Pinot Blanc', 'Riesling',
  'Sauvignon Blanc', 'Semillon', 'Torrontes', 'Viognier' ];

// wines with filters not working
//  'Barolo', 'Carmenere', 'Chianti', 'Bordeaux',

// Drop down view
	var view_discover = Ti.UI.createView({
			width: Ti.UI.FILL,
			height: Ti.UI.SIZE,
			layout: 'vertical',
			left: 10,
			right: 10,
		});

	var wine_review = null;
	var table = null;

	// Dropdown menu components
	var search_bar = Ti.UI.createTextField({
		top:0,
		width:'90%',
		left:'5%',
		hintText:' Discover a wine...',
		borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	});

	var picker_color = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Color",
		values: ['Color','Red', 'White']
	});

	var picker_allwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: allwines
	});

	var picker_redwines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: redwines
	});

	var picker_whitewines = TU.UI.createSimplePicker ({
		left: '5%',
		right: '5%',
		title: "Type",
		values: whitewines
	});

	// These variables store picker selected values
	var winecolor = null; // this is for color id to refine search
	var wineColor = null;  // this is for actual wine color
	var winetype = null;

//*****************************************************************
//  Associative array used for server query filtering
//*****************************************************************

	var wines = new Object;
	wines['Albarino'] = '136';
    wines['Barbera'] = '172';
	wines['Bordeaux'] = '-2147483648'; // Filter doesnt work
	wines['Cabernet Sauvignon'] = '139';
    wines['Cabernet Franc']	= '197';
	wines['Carmenere'] = '10081';
	wines['Chenin Blanc'] = '165';
	wines['Chardonnay'] = '140';
	wines['Dessert Wines'] = '160';
    wines['Dolcetto'] = '183';
	wines['Gamay'] = '150';
	wines['Grenache'] = '10080';
	wines['Grigio'] = '194';
	wines['Gris'] = '194';
	wines['Madeira'] = '154';
//  wines['Malbec'] = '';
	wines['Merlot'] = '138';
	//wines['Murray'] = '162'; -bad filter
	wines['Muscat'] = '173';
    wines['Mourvedre'] = '10083';
    wines['Nebbiolo'] = '170';
    wines['Non-Vintage'] = '182';
	wines['Petite Sirah'] = '176';
	wines['Pinot Noir'] = '143';
	wines['Pinot Blanc'] = '168';
    wines['Port'] = '155';
    wines['Primitivo'] = '10084';
//  wines['Rhone Blends'] = '';
	wines['Riesling'] = '153';
	wines['Rose'] = '147';
	wines['Sangiovese'] = '163';
	wines['Sauvignon Blanc'] = '151';
	wines['Semillon'] = '177';
	wines['Shiraz'] = '146';
	wines['Sherry'] = '157';
	wines['Syrah'] = '146';
	wines['Tempranillo'] = '169';
    wines['Torrontes'] = '209';
	wines['Viognier'] = '162';
	wines['Zinfandel'] = '141';

//******************************************************************************
// Event listener for wine color picker.  This function adds and removes views
// based off of what is selected in the picker.
//******************************************************************************
	picker_color.addEventListener ('TUchange', function (e) {
		if(e.value == 'Red'){
			winecolor = '124';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_whitewines);
			view_discover.add(picker_redwines);

		picker_redwines.addEventListener ('TUchange', function (e) {
		winetype =  e.value;
		});

		}
		else if(e.value == "White"){
			winecolor = '125';
			wineColor = e.value;
			view_discover.remove(picker_allwines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_whitewines);

			picker_whitewines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}
		else{
			winecolor = null;
			wineColor = null;
			view_discover.remove(picker_whitewines);
			view_discover.remove(picker_redwines);
			view_discover.add(picker_allwines);

			picker_allwines.addEventListener ('TUchange', function (e) {
			winetype =  e.value;
			});
		}

	});

	picker_allwines.addEventListener ('TUchange', function (e) {
	winetype =  e.value;
	});

	view_discover.add(search_bar);
	view_discover.add(picker_color);
	view_discover.add(picker_allwines);

//***********************************************************************************
// Dropdown menu area
// This function controls the dropdown menu and the logic for the pickers and
// search bar.
//***********************************************************************************
	dropdown(view_discover, self, "Find", "Browse", "down", function(){

		view.setTop('4%');
		view.setHeight('100%');
		view.remove(table);
		view.setBottom('5%');
		view.remove(label_title);
		self.remove(view);
		label_title.setText("Search Results");
		view.add(label_title);

		if(search_bar.value != null && search_bar.value != ""){

		if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(search_bar.value, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(search_bar.value, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else
			{
				global.api.search(search_bar.value, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}

        self.add(view);

     }
     else{
     //	if nothing entered in textfield do these
     	if(winetype == 'Type'){winetype = null;}

			if(winecolor != null && winetype != null)
			{
				global.api.search_with_filter(winetype, winecolor + '+' + wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor == null && winetype != null)
			{
				global.api.search_with_filter(winetype, wines[winetype], function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			  });
			}
			else if(winecolor != null && winetype == null)
			{
				global.api.search_with_filter(wineColor, winecolor, function(search_results){
         		table = global.api.search_results(search_results, function(wine){
				wine_review = require('ui/handheld/WineReview');
				self.containingTab.open(wine_review(wine));
				});
				view.add(table);
			 });
			}
			else if(winecolor == null && winetype == null)
			{
				//alert('Please Enter a Wine or Select a Filter to Search');
			}

     	self.add(view);
     }
	});

global.outputHook(self);
return self;
};

module.exports = DiscoverWindow;<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Bookmark component
 * @author Meine Toonen
 */
Ext.define ("viewer.components.Bookmark",{
    extend: "viewer.components.Component",
    form: null,
    url: "",
    compUrl: "",
    baseUrl: "",
    shareUrls: null,
    imagePath: null,
    config:{
        title: null,
        titlebarIcon: null,
        tooltip: null,
        label: "",
        shareEmail: false,
        shareTwitter: false,
        shareLinkedIn: false,
        shareGooglePlus: false,
        shareFacebook: false,
        shareText: "I'd like to share this with #FlamingoMC: ",
        shareTitle: "Sharing",
        showShortUrl: true,
        showFullUrl: true
    },
    constructor: function (conf){
        if(!Ext.isDefined(conf.details.height)) conf.details.height = 200;
        viewer.components.Bookmark.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        imagePath=contextPath+"/viewer-html/components/resources/images/bookmark/"
        this.shareUrls ={
            email: "mailto:%20?subject=[title]&body=[text]%20[url]",
            twitter: "http://twitter.com/share?url=[url]&text=[text]",
            linkedin: "http://www.linkedin.com/shareArticle?mini=true&url=[url]&summary=[text]&title=[title]",
            googleplus: "https://plus.google.com/share?url=[url]&text=[text]",
            facebook: "https://www.facebook.com/sharer.php?u=[url]&text=[text]"
        }

        this.renderButton();
        this.loadWindow();

        return this;
    },
    renderButton: function() {
        var me = this;
        this.superclass.renderButton.call(this,{
            text: me.title,
            icon: me.titlebarIcon,
            tooltip: me.tooltip,
            label: me.label,
            handler: function() {
                me.showWindow();
            }
        });
    },
    loadWindow : function(){
        var socialButtons=[];
        if(this.shareEmail){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Email',
                icon: imagePath + 'email-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["email"]);
                        }
                    }
                }
            });
        }if (this.shareTwitter){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Twitter',
                icon: imagePath + 'twitter-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["twitter"]);
                        }
                    }
                }
            });
        }if (this.shareLinkedIn){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'LinkedIn',
                icon: imagePath+"in-16.png",
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["linkedin"]);
                        }
                    }
                }
            });
        }if (this.shareGooglePlus){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Google+',
                icon: imagePath + 'gplus-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["googleplus"]);
                        }
                    }
                }
            });
        }if (this.shareFacebook){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Facebook',
                icon: imagePath + 'fb-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["facebook"]);
                        }
                    }
                }
            });
        }
        var formItems=[];

        if (this.showFullUrl){
            formItems.push({
                xtype: 'textfield',
                fieldLabel: 'Bookmark',
                name: 'bookmark',
                anchor: '100%',
                id: 'bookmark',
                value: this.url
            });
        }
        if (this.showShortUrl){
            formItems.push({
                xtype: 'textfield',
                fieldLabel: 'Compact link',
                name: 'compactlink',
                anchor: '100%',
                id: 'compactlink'
            });
        }
        formItems.push({
            xtype: 'container',
            layout: {
                type: 'hbox'
            },
            items: socialButtons
        });
        formItems.push({
            xtype: 'button',
            componentCls: 'mobileLarge',
            margin: '10px 0px 0px 0px',
            text: 'Toevoegen aan favorieten',
            listeners: {
                click:{
                    scope: this,
                    fn: this.addToFavorites
                }
            }
        });
        formItems.push({
            xtype: 'button',
            componentCls: 'mobileLarge',
            margin: '10px 0px 0px 10px',
            text: 'Sluiten',
            listeners: {
                click:{
                    scope: this,
                    fn: this.hideWindow
                }
            }
        });
        this.form = new Ext.form.FormPanel({
            frame: false,
            border: 0,
            width: '95%',
            margin: '0px 0px 0px 10px',
            padding: '5px',
            items: formItems,
            renderTo: this.getContentDiv()
        });
    },
    showWindow : function(){
        var paramJSON = this.viewerController.getBookmarkUrl();
        var parameters = "";

        for ( var i = 0 ; i < paramJSON["params"].length ; i ++){
            var param = paramJSON["params"][i];
            if(param.name == 'url'){
                this.url = param.value;
                this.baseUrl = param.value;
            }else if(param.name == 'extent'){
                parameters += param.name +"=";
                var extent = param.value;
                parameters += extent.minx+","+extent.miny+","+extent.maxx+","+extent.maxy+"&";
            }else if(param.name == 'layers'){
                parameters += param.name +"=";
                var layers = param.value;
                for( var x = 0 ; x < layers.length ; x++){
                     parameters += layers[x];
                     if(x != (layers.length - 1)){
                         parameters += ",";
                     }
                }
                parameters +="&";
            }else if (param.name == 'levelOrder' && param.value.length > 0){
                parameters += param.name +"=";
                parameters += param.value.join(",");
                parameters +="&";
            }else if(param.name != 'selectedContent' && param.name != 'services' && param.name != 'appLayers' && param.name != "" && param.value != ""){
                parameters += param.name +"="+ param.value +"&";
            }
        }

        var componentParams="";
        //get all the params from components that need to be added to the bookmark
        var components = this.viewerController.getComponents();
        for (var i=0; i < components.length; i++){
            var state = components[i].getBookmarkState(false);
            if (!Ext.isEmpty(state)){
                componentParams+=encodeURIComponent(components[i].getName());
                componentParams+="=";
                componentParams+=encodeURIComponent(Ext.encode(state));
                componentParams+="&";
            }
        }
        this.url += parameters;
        if (componentParams.length!=0){
            this.url+=componentParams;
        }
        if (this.showShortUrl){
            //get all the states of the components for the short url
            for (var i=0; i < components.length; i++){
                var state = components[i].getBookmarkState(true);
                if (!Ext.isEmpty(state)){
                    var param = {name: components[i].getName(),
                            value: Ext.JSON.encode(state)};
                    paramJSON.params.push(param);
                }
            }

            var me = this;
            Ext.create("viewer.Bookmark").createBookmark(
                Ext.JSON.encode(paramJSON),
                function(code){me.succesCompactUrl(code);},
                function(code){me.failureCompactUrl(code);}
            );
        }else if (this.showFullUrl){
            this.form.getChildByElement("bookmark").setValue(this.url);
            this.popup.show();
        }
    },
    succesCompactUrl : function(code){
        this.compUrl = this.baseUrl+"bookmark="+code;
        if(this.showShortUrl){
            this.form.getChildByElement("compactlink").setValue(this.compUrl);
        }
        if(this.showFullUrl){
            this.form.getChildByElement("bookmark").setValue(this.url);
        }
        this.popup.show();
    },
    failureCompactUrl : function(code){
        // TODO: error message?
        this.viewerController.logger.error(code);
    },
    hideWindow : function(){
        this.popup.hide();
    },
    addToFavorites : function(){
        if(Ext.firefoxVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.ieVersion != 0){
            window.external.AddFavorite(this.compUrl, this.title);
        }else if(Ext.chromeVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.operaVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.safariVersion != 0){
            alert("This browser doesn't support this function.");
        }
    },
    share: function (shareUrl){
        var url = ""+shareUrl;
        var bookmarkUrl = this.compUrl;
        if (!bookmarkUrl || bookmarkUrl == ""){
            bookmarkUrl=this.url;
        }
        if (url.indexOf("[url]")!=-1){
            url=url.replace("[url]",encodeURIComponent(bookmarkUrl));
        }
        if (url.indexOf("[text]")!=-1){
            url = url.replace("[text]",encodeURIComponent(this.shareText));
        }
        if (url.indexOf("[title]")!=-1){
            url = url.replace("[title]",encodeURIComponent(this.shareTitle));
        }
        console.log(url);
        window.open(url);
    },
    getExtComponents: function() {
        return [ this.form.getId() ];
    }
});<commit_msg>Check if browser is IE before displaying the 'add to favorites' button<commit_after>/*
 * Copyright (C) 2012-2013 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Bookmark component
 * @author Meine Toonen
 */
Ext.define ("viewer.components.Bookmark",{
    extend: "viewer.components.Component",
    form: null,
    url: "",
    compUrl: "",
    baseUrl: "",
    shareUrls: null,
    imagePath: null,
    config:{
        title: null,
        titlebarIcon: null,
        tooltip: null,
        label: "",
        shareEmail: false,
        shareTwitter: false,
        shareLinkedIn: false,
        shareGooglePlus: false,
        shareFacebook: false,
        shareText: "I'd like to share this with #FlamingoMC: ",
        shareTitle: "Sharing",
        showShortUrl: true,
        showFullUrl: true
    },
    constructor: function (conf){
        if(!Ext.isDefined(conf.details.height)) conf.details.height = 200;
        viewer.components.Bookmark.superclass.constructor.call(this, conf);
        this.initConfig(conf);

        imagePath=contextPath+"/viewer-html/components/resources/images/bookmark/"
        this.shareUrls ={
            email: "mailto:%20?subject=[title]&body=[text]%20[url]",
            twitter: "http://twitter.com/share?url=[url]&text=[text]",
            linkedin: "http://www.linkedin.com/shareArticle?mini=true&url=[url]&summary=[text]&title=[title]",
            googleplus: "https://plus.google.com/share?url=[url]&text=[text]",
            facebook: "https://www.facebook.com/sharer.php?u=[url]&text=[text]"
        }

        this.renderButton();
        this.loadWindow();

        return this;
    },
    renderButton: function() {
        var me = this;
        this.superclass.renderButton.call(this,{
            text: me.title,
            icon: me.titlebarIcon,
            tooltip: me.tooltip,
            label: me.label,
            handler: function() {
                me.showWindow();
            }
        });
    },
    loadWindow : function(){
        var socialButtons=[];
        if(this.shareEmail){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Email',
                icon: imagePath + 'email-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["email"]);
                        }
                    }
                }
            });
        }if (this.shareTwitter){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Twitter',
                icon: imagePath + 'twitter-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["twitter"]);
                        }
                    }
                }
            });
        }if (this.shareLinkedIn){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'LinkedIn',
                icon: imagePath+"in-16.png",
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["linkedin"]);
                        }
                    }
                }
            });
        }if (this.shareGooglePlus){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Google+',
                icon: imagePath + 'gplus-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["googleplus"]);
                        }
                    }
                }
            });
        }if (this.shareFacebook){
            socialButtons.push({
                xtype: 'button',
                margin: '10px 0px 0px 10px',
                //text: 'Facebook',
                icon: imagePath + 'fb-16.png',
                listeners: {
                    click:{
                        scope: this,
                        fn: function(){
                            this.share(this.shareUrls["facebook"]);
                        }
                    }
                }
            });
        }
        var formItems=[];

        if (this.showFullUrl){
            formItems.push({
                xtype: 'textfield',
                fieldLabel: 'Bookmark',
                name: 'bookmark',
                anchor: '100%',
                id: 'bookmark',
                value: this.url
            });
        }
        if (this.showShortUrl){
            formItems.push({
                xtype: 'textfield',
                fieldLabel: 'Compact link',
                name: 'compactlink',
                anchor: '100%',
                id: 'compactlink'
            });
        }
        formItems.push({
            xtype: 'container',
            layout: {
                type: 'hbox'
            },
            items: socialButtons
        });
        if(Ext.ieVersion != 0){
            formItems.push({
                xtype: 'button',
                componentCls: 'mobileLarge',
                margin: '10px 0px 0px 0px',
                text: 'Toevoegen aan favorieten',
                listeners: {
                    click:{
                        scope: this,
                        fn: this.addToFavorites
                    }
                }
            });
        }
        formItems.push({
            xtype: 'button',
            componentCls: 'mobileLarge',
            margin: '10px 0px 0px 10px',
            text: 'Sluiten',
            listeners: {
                click:{
                    scope: this,
                    fn: this.hideWindow
                }
            }
        });
        this.form = new Ext.form.FormPanel({
            frame: false,
            border: 0,
            width: '95%',
            margin: '0px 0px 0px 10px',
            padding: '5px',
            items: formItems,
            renderTo: this.getContentDiv()
        });
    },
    showWindow : function(){
        var paramJSON = this.viewerController.getBookmarkUrl();
        var parameters = "";

        for ( var i = 0 ; i < paramJSON["params"].length ; i ++){
            var param = paramJSON["params"][i];
            if(param.name == 'url'){
                this.url = param.value;
                this.baseUrl = param.value;
            }else if(param.name == 'extent'){
                parameters += param.name +"=";
                var extent = param.value;
                parameters += extent.minx+","+extent.miny+","+extent.maxx+","+extent.maxy+"&";
            }else if(param.name == 'layers'){
                parameters += param.name +"=";
                var layers = param.value;
                for( var x = 0 ; x < layers.length ; x++){
                     parameters += layers[x];
                     if(x != (layers.length - 1)){
                         parameters += ",";
                     }
                }
                parameters +="&";
            }else if (param.name == 'levelOrder' && param.value.length > 0){
                parameters += param.name +"=";
                parameters += param.value.join(",");
                parameters +="&";
            }else if(param.name != 'selectedContent' && param.name != 'services' && param.name != 'appLayers' && param.name != "" && param.value != ""){
                parameters += param.name +"="+ param.value +"&";
            }
        }

        var componentParams="";
        //get all the params from components that need to be added to the bookmark
        var components = this.viewerController.getComponents();
        for (var i=0; i < components.length; i++){
            var state = components[i].getBookmarkState(false);
            if (!Ext.isEmpty(state)){
                componentParams+=encodeURIComponent(components[i].getName());
                componentParams+="=";
                componentParams+=encodeURIComponent(Ext.encode(state));
                componentParams+="&";
            }
        }
        this.url += parameters;
        if (componentParams.length!=0){
            this.url+=componentParams;
        }
        if (this.showShortUrl){
            //get all the states of the components for the short url
            for (var i=0; i < components.length; i++){
                var state = components[i].getBookmarkState(true);
                if (!Ext.isEmpty(state)){
                    var param = {name: components[i].getName(),
                            value: Ext.JSON.encode(state)};
                    paramJSON.params.push(param);
                }
            }

            var me = this;
            Ext.create("viewer.Bookmark").createBookmark(
                Ext.JSON.encode(paramJSON),
                function(code){me.succesCompactUrl(code);},
                function(code){me.failureCompactUrl(code);}
            );
        }else if (this.showFullUrl){
            this.form.getChildByElement("bookmark").setValue(this.url);
            this.popup.show();
        }
    },
    succesCompactUrl : function(code){
        this.compUrl = this.baseUrl+"bookmark="+code;
        if(this.showShortUrl){
            this.form.getChildByElement("compactlink").setValue(this.compUrl);
        }
        if(this.showFullUrl){
            this.form.getChildByElement("bookmark").setValue(this.url);
        }
        this.popup.show();
    },
    failureCompactUrl : function(code){
        // TODO: error message?
        this.viewerController.logger.error(code);
    },
    hideWindow : function(){
        this.popup.hide();
    },
    addToFavorites : function(){
        if(Ext.firefoxVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.ieVersion != 0){
            window.external.AddFavorite(this.compUrl, this.title);
        }else if(Ext.chromeVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.operaVersion != 0){
            alert("This browser doesn't support this function.");
        }else if(Ext.safariVersion != 0){
            alert("This browser doesn't support this function.");
        }
    },
    share: function (shareUrl){
        var url = ""+shareUrl;
        var bookmarkUrl = this.compUrl;
        if (!bookmarkUrl || bookmarkUrl == ""){
            bookmarkUrl=this.url;
        }
        if (url.indexOf("[url]")!=-1){
            url=url.replace("[url]",encodeURIComponent(bookmarkUrl));
        }
        if (url.indexOf("[text]")!=-1){
            url = url.replace("[text]",encodeURIComponent(this.shareText));
        }
        if (url.indexOf("[title]")!=-1){
            url = url.replace("[title]",encodeURIComponent(this.shareTitle));
        }
        console.log(url);
        window.open(url);
    },
    getExtComponents: function() {
        return [ this.form.getId() ];
    }
});<|endoftext|>


<commit_before>'use strict';

/**
 * Add frame to a picture
 */

const gravityValue = 'Center';
const frameWidthArr = [10, 30];
const colorArr = [
    // yellow
    ['#D89C07','#FCD31D'],
    // red
    ['#B6707E', '#FFA3B5'],
    // blue
    ['#079DAF', '#1DE4FC'],
    // purple
    ['#9E47F1', '#CDB4F8']
];

const gm = require('gm').subClass({
    imageMagick: true
});

const getColor = () => {
    return colorArr[Math.floor(Math.random() * 4)];
};

const addOneFrame = (imageFilename, image, width, height, colorObj, round, cb) => {
    const color = colorObj[round];
    let borderWidth = (round === 0) ? frameWidthArr[0] : frameWidthArr[0] + frameWidthArr[1];
    image
        .gravity(gravityValue)
        .background(color)
        .extent(width + borderWidth, height + borderWidth)
        .quality(100)
        .write(imageFilename, function (err) {
            if (!err) {
                console.log(imageFilename, '===> done with round ' + round);
            }
            if (cb) {
                cb();
            }
        });
};

const addFrame = (img) => {
    const image = gm(img);
    const color = getColor();
    image.size(function (err, value) {
        // TODO: handle err
        const width = value.width;
        const height = value.height;
        image
            addOneFrame(img, image, width, height, color, 0, function() {
                addOneFrame(img, image, width, height, color, 1);
            });
    });
};

module.exports = addFrame;
<commit_msg>moved get size inside addOneFrame to simplify logic<commit_after>'use strict';

/**
 * Add color frames to an image
 */

const gm = require('gm').subClass({
    imageMagick: true
});

const colorArr = [
    // yellow
    ['#D89C07','#FCD31D'],
    // red
    ['#B6707E', '#FFA3B5'],
    // blue
    ['#079DAF', '#1DE4FC'],
    // purple
    ['#9E47F1', '#CDB4F8']
];

const frameWidthArr = [10, 30];
const gravityValue = 'Center';

const getColor = () => {
    return colorArr[Math.floor(Math.random() * 4)];
};

const addOneFrame = (imageFilename, image, colorObj, round, cb) => {
    const color = colorObj[round];
    const borderWidth = frameWidthArr[round];
    image.size(function (err, value) {
        // TODO: handle err
        const width = value.width;
        const height = value.height;
        image
            .gravity(gravityValue)
            .background(color)
            .extent(width + borderWidth, height + borderWidth)
            .quality(100)
            .write(imageFilename, function (err) {
                if (!err) {
                    console.log(imageFilename, '===> done with round ' + round);
                }
                if (cb) {
                    cb();
                }
            });
    });
};

const addFrame = (img) => {
    const image = gm(img);
    // We want to use the same color theme for each image
    const color = getColor();
    addOneFrame(img, image, color, 0, function() {
        addOneFrame(img, image, color, 1);
    });
};

module.exports = addFrame;
<|endoftext|>


<commit_before>// Copyright 2014-2015, Renasar Technologies Inc.
/* jshint node: true */
'use strict';

var di = require('di'),
    express = require('express'),
    parser = require('body-parser'),
    _ = require('lodash'),
    router = express.Router();

router.use(parser.json());

module.exports = nodesRouterFactory;

di.annotate(nodesRouterFactory, new di.Inject(
        'Services.Waterline',
        'Protocol.TaskGraphRunner',
        'common-api-presenter',
        'Services.Configuration',
        'gridfs',
        'Task.Services.OBM',
        'Logger',
        'Tracer'
    )
);

function nodesRouterFactory (
    waterline,
    taskGraphProtocol,
    presenter,
    configuration,
    gridfsService,
    obmService,
    logger
) {

    /**
     * @api {get} /api/common/nodes/ GET /
     * @apiDescription get list of nodes
     * @apiName nodes-get
     * @apiGroup nodes
     */

    router.get('/nodes', presenter.middleware(function (req) {
        return waterline.nodes.find(req.query);
    }));

    /**
     * @api {post} /api/common/nodes/?identifiers= POST /
     * @apiDescription create a node
     * @apiName nodes-post
     * @apiParam {String} identifiers Mac addresses and unique aliases to
     *                                         identify the node by
     * @apiParam {String[]} identifiers Mac addresses and unique aliases to
     *                                         identify the node by
     * @apiParam {String} profile Default profile to set for the node
     * @apiGroup nodes
     */

    router.post('/nodes', presenter.middleware(function (req) {
        return waterline.nodes.create(req.body);
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier GET /:id
     * @apiDescription get specific node details
     * @apiName node-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'));
    }));

    /**
     * @api {patch} /api/common/nodes/:identifier PATCH /:id
     * @apiDescription patch specific node details
     * @apiName node-patch
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.patch('/nodes/:identifier', presenter.middleware(function (req) {
       return waterline.nodes.updateByIdentifier(
            req.param('identifier'),
            req.body
        );
    }));

    /**
     * @api {delete} /api/common/nodes/:identifier DELETE /:id
     * @apiDescription Delete specific node details.
     * @apiName node-delete
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.delete('/nodes/:identifier', presenter.middleware(function (req) {
        return waterline.nodes.destroyByIdentifier(
            req.param('identifier')
        );
    }, { success: 204}));

    /**
     * @api {get} /api/common/nodes/:identifier/obm GET /:id/obm
     * @apiDescription Get obm settings for specified node.
     * @apiName node-obm-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/obm', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return node.obmSettings;
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:identifier/obm POST /:id/obm
     * @apiDescription Set obm settings for specified node.
     * @apiName node-obm-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.post('/nodes/:identifier/obm', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return node.addObmSettings(req.body);
            }
        });
    }, { success: 201 }));

    /**
     * @api {post} /api/common/nodes/:identifier/obm/identify POST /:id/obm/identify
     * @apiDescription Enable or disable identify light on node through OBM (if supported)
     * @apiName node-obm-identify-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     * @aprParam {} posted object containing "value: true" or "value: false".
     * If not included, defaults to "false", which disables identify.
     */

    router.post('/nodes/:identifier/obm/identify', presenter.middleware(function (req) {
        // TODO: Make this a taskGraph instead once we improve multiple task
        // graph handling per node.
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (req.body && req.body.value) {
                return obmService.identifyOn(node.id);
            } else {
                return obmService.identifyOff(node.id);
            }
        });
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier/pollerdata GET /:id/pollerdata
     * @apiDescription Retrieve latest values from pollers associated with
     * this node
     * @apiName node-poller-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/pollerdata', presenter.middleware(function(req) {
        req;
        /*
        return pollerCache.getLatestForId(req.param('identifier'));
        */
    }));

    /**
     * @api {get} /api/common/nodes/:identifier/catalogs GET /:id/catalogs
     * @apiDescription Get catalogs for specified node.
     * @apiName node-catalogs-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/catalogs', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return waterline.catalogs.find(
                    _.merge(
                        { where: req.query || {}},
                        { where: { node: node.id }}
                    )
                );
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:macaddress/dhcp/whitelist POST /:mac/dhcp/whitelist
     * @apiDescription Post whitelist.
     * @apiName node-dhcp-whitelist-post
     * @apiGroup nodes
     * @apiParam {String} macaddress macaddress of node
     */

    router.post('/nodes/:macaddress/dhcp/whitelist', function(req, res) {
        // TODO: add this to DHCP protocol and send over that exchange
        var whitelist = configuration.get('whitelist') || [];
        whitelist.push(req.param('macaddress').replace(/:/g, '-'));
        configuration.set('whitelist', whitelist);
        res.status(201).end();
    });

    /**
     * @api {delete} /api/common/nodes/:macaddress/dhcp/whitelist DELETE /:mac/dhcp/whitelist
     * @apiDescription Remove a whitelist of specified mac address
     * @apiName node-dhcp-whitelist-delete
     * @apiGroup nodes
     * @apiParam {String} macaddress macaddress of node
     */

    router.delete('/nodes/:macaddress/dhcp/whitelist', function(req, res) {
        // TODO: add this to DHCP protocol and send over that exchange
        var whitelist = configuration.get('whitelist');
        if (!whitelist || _.isEmpty(whitelist)) {
            res.status(204).end();
        } else {
            _.remove(whitelist, function(mac) {
                return mac === req.param('macaddress').replace(/:/g, '-');
            });
            configuration.set('whitelist', whitelist);
            res.status(204).end();
        }
    });

    /**
     * @api {get} /api/common/nodes/:identifier/files GET /:identifier/files
     * @apiDescription get a file associated with a node :identifier
     * @apiName nodes-files-get
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "Node identifier does not exist."
     *     }
     */

    router.get('/nodes/:identifier/files', function(req, res) {
        logger.debug("Received request for file ", {
            filename: req.param('filename'),
            identifier: req.param('identifier')
        });

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }
            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            return gridfsService.apiDownloadFile(res, query);
        })
        .fail(function(err) {
            logger.error("Error creating gridfs read stream: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: err.stack
            });

            res.status(500).json({
                error: "Error retrieving file from the database."
            });
        });
    });

    /**
     * @api {put} /api/common/nodes/:identifier/files PUT /:identifier/files
     * @apiDescription put a file associated with a node :identifier
     * @apiName nodes-files-put
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiSuccessExample Completed-Response:
     *     HTTP/1.1 201 Created
     * @apiError Error Any problem was encountered, file was not written.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 500 Error
     *     {
     *       "error": "File upload failed."
     *     }
     */

    router.put('/nodes/:identifier/files', function(req, res) {
        logger.debug("Receiving file " +
            req.param('filename') + " from " + req.param('identifier'));

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }

            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            gridfsService.apiUploadFile(req, res, query);
        })
        .fail(function(error) {
            logger.error("Error creating gridfs write stream: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: error.stack
            });
            res.status(500).json({
                error: "Error saving file to the database."
            });
        });
    });

    /**
     * @api {delete} /api/common/nodes/:identifier/files DELETE /:identifier/files
     * @apiDescription delete a file associated with a node :identifier
     * @apiName nodes-files-delete
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiSuccessExample Completed-Response:
     *     HTTP/1.1 204 Deleted
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Error
     *     {
     *       "error": "Node identifier does not exist."
     *     }
     */

    router.delete('/nodes/:identifier/files', function(req, res) {
        logger.debug("Receiving file " + req.param('filename') + " from " +
            req.param('identifier'));

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }
            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            return gridfsService.apiDeleteFile(res, query);
        })
        .fail(function(error) {
            logger.error("Error removing file from gridfs: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: error.stack
            });
            res.status(500).json({
                error: "Error deleting file from the database."
            });
        });
    });

    /**
     * @api {get} /api/common/nodes/:identifier/workflows GET /:id/workflows
     * @apiDescription Get workflows of node.
     * @apiName node-workflows-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node
     */

    router.get('/nodes/:identifier/workflows', presenter.middleware(function (req) {
        //TODO(heckj) this is intended to show past workflows - not sure how
        // to do that with taskGraph Service
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraphs( { target: node.id });
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:identifier/workflows  POST /:id/workflows
     * @apiDescription Create workflow for node.
     * @apiName node-workflows-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.post('/nodes/:identifier/workflows', presenter.middleware(function(req) {
        //TODO(heckj): how are we assigning a nodes to a workflow - through
        // options? Merge in req.param('identifier')?
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.runTaskGraph(req.param('name'),
                    req.param('options'), node.id);
            }
        });
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier/workflows/active GET /:id/workflows/active
     * @apiDescription Fetch the  active workflow for the specified node
     * @apiName node-workflows-active-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/workflows/active', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraph( { target: node.id });
            }
        });
    }));

    /**
     * @api {delete} /api/common/nodes/:identifier/workflows/active DELETE /:id/workflows/active
     * @apiDescription delete the current active workflow for the specified node
     * @apiName node-workflows-active-delete
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.delete('/nodes/:identifier/workflows/active', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraphs( { target: node.id })
                    .then(function(taskGraphInstance) {
                        return taskGraphProtocol.cancelTaskGraph(taskGraphInstance);
                });
            }
        });
    }));

    /**
     * @api {get} /api/common/nodes/:identifier/workflows/current GET /:id/workflows/current
     * @apiDescription Fetch the active or most recent workflow for the specified node. Active
     * workflows are stored in memory, so in the case of a server restart, we still want
     * to be able to retrieve the most recently ran workflow.
     * @apiName node-workflows-current-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */
    // NOTE(heckj): commenting out until I know how to get historical workflows
    //
    //router.get('/nodes/:identifier/workflows/current', presenter.middleware(function (req) {
    //    return waterline.nodes.findByIdentifier(req.param('identifier')).then(function (node) {
    //        if (node) {
    //            return workflowService.getWorkflow(node.id).then(function (workflow) {
    //                if (workflow) {
    //                    return waterline.workflows.findByInstance(
    //                        workflow.instance
    //                    ).populate('workflows').then(firstWorkflowOrBlank);
    //                } else {
    //                    return waterline.workflows.findMostRecent(
    //                        { node: req.param('identifier'), type: 'parentWorkflow' }
    //                    ).populate('workflows').then(firstWorkflowOrBlank);
    //                }
    //            });
    //        }
    //    });
    //
    //    function firstWorkflowOrBlank(workflows) {
    //        if (workflows.length) {
    //            return workflows[0];
    //        } else {
    //            return {};
    //        }
    //    }
    //}));

    return router;
}
<commit_msg>fixing POST /nodes/:identifier/obm<commit_after>// Copyright 2014-2015, Renasar Technologies Inc.
/* jshint node: true */
'use strict';

var di = require('di'),
    express = require('express'),
    parser = require('body-parser'),
    _ = require('lodash'),
    router = express.Router();

router.use(parser.json());

module.exports = nodesRouterFactory;

di.annotate(nodesRouterFactory, new di.Inject(
        'Services.Waterline',
        'Protocol.TaskGraphRunner',
        'common-api-presenter',
        'Services.Configuration',
        'gridfs',
        'Task.Services.OBM',
        'Logger',
        'Tracer'
    )
);

function nodesRouterFactory (
    waterline,
    taskGraphProtocol,
    presenter,
    configuration,
    gridfsService,
    obmService,
    logger
) {

    /**
     * @api {get} /api/common/nodes/ GET /
     * @apiDescription get list of nodes
     * @apiName nodes-get
     * @apiGroup nodes
     */

    router.get('/nodes', presenter.middleware(function (req) {
        return waterline.nodes.find(req.query);
    }));

    /**
     * @api {post} /api/common/nodes/?identifiers= POST /
     * @apiDescription create a node
     * @apiName nodes-post
     * @apiParam {String} identifiers Mac addresses and unique aliases to
     *                                         identify the node by
     * @apiParam {String[]} identifiers Mac addresses and unique aliases to
     *                                         identify the node by
     * @apiParam {String} profile Default profile to set for the node
     * @apiGroup nodes
     */

    router.post('/nodes', presenter.middleware(function (req) {
        return waterline.nodes.create(req.body);
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier GET /:id
     * @apiDescription get specific node details
     * @apiName node-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'));
    }));

    /**
     * @api {patch} /api/common/nodes/:identifier PATCH /:id
     * @apiDescription patch specific node details
     * @apiName node-patch
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.patch('/nodes/:identifier', presenter.middleware(function (req) {
       return waterline.nodes.updateByIdentifier(
            req.param('identifier'),
            req.body
        );
    }));

    /**
     * @api {delete} /api/common/nodes/:identifier DELETE /:id
     * @apiDescription Delete specific node details.
     * @apiName node-delete
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.delete('/nodes/:identifier', presenter.middleware(function (req) {
        return waterline.nodes.destroyByIdentifier(
            req.param('identifier')
        );
    }, { success: 204}));

    /**
     * @api {get} /api/common/nodes/:identifier/obm GET /:id/obm
     * @apiDescription Get obm settings for specified node.
     * @apiName node-obm-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/obm', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return node.obmSettings;
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:identifier/obm POST /:id/obm
     * @apiDescription Set obm settings for specified node.
     * @apiName node-obm-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.post('/nodes/:identifier/obm', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                var obmSettings = node.obmSettings || [];
                obmSettings.push(req.body);
                return waterline.nodes.updateByIdentifier(
                    req.param('identifier'),
                    { obmSettings: obmSettings }
                );
            }
        });
    }, { success: 201 }));

    /**
     * @api {post} /api/common/nodes/:identifier/obm/identify POST /:id/obm/identify
     * @apiDescription Enable or disable identify light on node through OBM (if supported)
     * @apiName node-obm-identify-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     * @aprParam {} posted object containing "value: true" or "value: false".
     * If not included, defaults to "false", which disables identify.
     */

    router.post('/nodes/:identifier/obm/identify', presenter.middleware(function (req) {
        // TODO: Make this a taskGraph instead once we improve multiple task
        // graph handling per node.
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (req.body && req.body.value) {
                return obmService.identifyOn(node.id);
            } else {
                return obmService.identifyOff(node.id);
            }
        });
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier/pollerdata GET /:id/pollerdata
     * @apiDescription Retrieve latest values from pollers associated with
     * this node
     * @apiName node-poller-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/pollerdata', presenter.middleware(function(req) {
        req;
        /*
        return pollerCache.getLatestForId(req.param('identifier'));
        */
    }));

    /**
     * @api {get} /api/common/nodes/:identifier/catalogs GET /:id/catalogs
     * @apiDescription Get catalogs for specified node.
     * @apiName node-catalogs-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/catalogs', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return waterline.catalogs.find(
                    _.merge(
                        { where: req.query || {}},
                        { where: { node: node.id }}
                    )
                );
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:macaddress/dhcp/whitelist POST /:mac/dhcp/whitelist
     * @apiDescription Post whitelist.
     * @apiName node-dhcp-whitelist-post
     * @apiGroup nodes
     * @apiParam {String} macaddress macaddress of node
     */

    router.post('/nodes/:macaddress/dhcp/whitelist', function(req, res) {
        // TODO: add this to DHCP protocol and send over that exchange
        var whitelist = configuration.get('whitelist') || [];
        whitelist.push(req.param('macaddress').replace(/:/g, '-'));
        configuration.set('whitelist', whitelist);
        res.status(201).end();
    });

    /**
     * @api {delete} /api/common/nodes/:macaddress/dhcp/whitelist DELETE /:mac/dhcp/whitelist
     * @apiDescription Remove a whitelist of specified mac address
     * @apiName node-dhcp-whitelist-delete
     * @apiGroup nodes
     * @apiParam {String} macaddress macaddress of node
     */

    router.delete('/nodes/:macaddress/dhcp/whitelist', function(req, res) {
        // TODO: add this to DHCP protocol and send over that exchange
        var whitelist = configuration.get('whitelist');
        if (!whitelist || _.isEmpty(whitelist)) {
            res.status(204).end();
        } else {
            _.remove(whitelist, function(mac) {
                return mac === req.param('macaddress').replace(/:/g, '-');
            });
            configuration.set('whitelist', whitelist);
            res.status(204).end();
        }
    });

    /**
     * @api {get} /api/common/nodes/:identifier/files GET /:identifier/files
     * @apiDescription get a file associated with a node :identifier
     * @apiName nodes-files-get
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Not Found
     *     {
     *       "error": "Node identifier does not exist."
     *     }
     */

    router.get('/nodes/:identifier/files', function(req, res) {
        logger.debug("Received request for file ", {
            filename: req.param('filename'),
            identifier: req.param('identifier')
        });

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }
            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            return gridfsService.apiDownloadFile(res, query);
        })
        .fail(function(err) {
            logger.error("Error creating gridfs read stream: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: err.stack
            });

            res.status(500).json({
                error: "Error retrieving file from the database."
            });
        });
    });

    /**
     * @api {put} /api/common/nodes/:identifier/files PUT /:identifier/files
     * @apiDescription put a file associated with a node :identifier
     * @apiName nodes-files-put
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiSuccessExample Completed-Response:
     *     HTTP/1.1 201 Created
     * @apiError Error Any problem was encountered, file was not written.
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 500 Error
     *     {
     *       "error": "File upload failed."
     *     }
     */

    router.put('/nodes/:identifier/files', function(req, res) {
        logger.debug("Receiving file " +
            req.param('filename') + " from " + req.param('identifier'));

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }

            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            gridfsService.apiUploadFile(req, res, query);
        })
        .fail(function(error) {
            logger.error("Error creating gridfs write stream: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: error.stack
            });
            res.status(500).json({
                error: "Error saving file to the database."
            });
        });
    });

    /**
     * @api {delete} /api/common/nodes/:identifier/files DELETE /:identifier/files
     * @apiDescription delete a file associated with a node :identifier
     * @apiName nodes-files-delete
     * @apiGroup nodes
     * @apiParam {String} filename - identifier Name of file.
     * @apiSuccessExample Completed-Response:
     *     HTTP/1.1 204 Deleted
     * @apiErrorExample Error-Response:
     *     HTTP/1.1 404 Error
     *     {
     *       "error": "Node identifier does not exist."
     *     }
     */

    router.delete('/nodes/:identifier/files', function(req, res) {
        logger.debug("Receiving file " + req.param('filename') + " from " +
            req.param('identifier'));

        waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function(node) {
            if (!node) {
                res.status(404).json({
                    error: 'Node identifier does not exist.'
                });
                return;
            }
            var query = {
                nodeId: node.id,
                filename: req.param('filename')
            };

            return gridfsService.apiDeleteFile(res, query);
        })
        .fail(function(error) {
            logger.error("Error removing file from gridfs: ", {
                identifier: req.param('identifier'),
                filename: req.param('filename'),
                error: error.stack
            });
            res.status(500).json({
                error: "Error deleting file from the database."
            });
        });
    });

    /**
     * @api {get} /api/common/nodes/:identifier/workflows GET /:id/workflows
     * @apiDescription Get workflows of node.
     * @apiName node-workflows-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node
     */

    router.get('/nodes/:identifier/workflows', presenter.middleware(function (req) {
        //TODO(heckj) this is intended to show past workflows - not sure how
        // to do that with taskGraph Service
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraphs( { target: node.id });
            }
        });
    }));

    /**
     * @api {post} /api/common/nodes/:identifier/workflows  POST /:id/workflows
     * @apiDescription Create workflow for node.
     * @apiName node-workflows-post
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.post('/nodes/:identifier/workflows', presenter.middleware(function(req) {
        //TODO(heckj): how are we assigning a nodes to a workflow - through
        // options? Merge in req.param('identifier')?
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.runTaskGraph(req.param('name'),
                    req.param('options'), node.id);
            }
        });
    }, { success: 201 }));

    /**
     * @api {get} /api/common/nodes/:identifier/workflows/active GET /:id/workflows/active
     * @apiDescription Fetch the  active workflow for the specified node
     * @apiName node-workflows-active-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.get('/nodes/:identifier/workflows/active', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraph( { target: node.id });
            }
        });
    }));

    /**
     * @api {delete} /api/common/nodes/:identifier/workflows/active DELETE /:id/workflows/active
     * @apiDescription delete the current active workflow for the specified node
     * @apiName node-workflows-active-delete
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */

    router.delete('/nodes/:identifier/workflows/active', presenter.middleware(function (req) {
        return waterline.nodes.findByIdentifier(req.param('identifier'))
        .then(function (node) {
            if (node) {
                return taskGraphProtocol.getActiveTaskGraphs( { target: node.id })
                    .then(function(taskGraphInstance) {
                        return taskGraphProtocol.cancelTaskGraph(taskGraphInstance);
                });
            }
        });
    }));

    /**
     * @api {get} /api/common/nodes/:identifier/workflows/current GET /:id/workflows/current
     * @apiDescription Fetch the active or most recent workflow for the specified node. Active
     * workflows are stored in memory, so in the case of a server restart, we still want
     * to be able to retrieve the most recently ran workflow.
     * @apiName node-workflows-current-get
     * @apiGroup nodes
     * @apiParam {String} identifier of node, must cast to ObjectId
     */
    // NOTE(heckj): commenting out until I know how to get historical workflows
    //
    //router.get('/nodes/:identifier/workflows/current', presenter.middleware(function (req) {
    //    return waterline.nodes.findByIdentifier(req.param('identifier')).then(function (node) {
    //        if (node) {
    //            return workflowService.getWorkflow(node.id).then(function (workflow) {
    //                if (workflow) {
    //                    return waterline.workflows.findByInstance(
    //                        workflow.instance
    //                    ).populate('workflows').then(firstWorkflowOrBlank);
    //                } else {
    //                    return waterline.workflows.findMostRecent(
    //                        { node: req.param('identifier'), type: 'parentWorkflow' }
    //                    ).populate('workflows').then(firstWorkflowOrBlank);
    //                }
    //            });
    //        }
    //    });
    //
    //    function firstWorkflowOrBlank(workflows) {
    //        if (workflows.length) {
    //            return workflows[0];
    //        } else {
    //            return {};
    //        }
    //    }
    //}));

    return router;
}
<|endoftext|>


<commit_before>import {promisify} from 'util';
import path from 'path';
import {execSync} from 'child_process';
import {EventEmitter} from 'events';

import tryCatch from 'try-catch';
import versionio from 'version-io';
import changelog from 'changelog-io';
import rendy from 'rendy';
import series from 'async/series.js';
import minor from 'minor';
import jessy from 'jessy';
import {readPackageUp} from 'read-pkg-up';
import fullstore from 'fullstore';
import currify from 'currify';

import {validatePackage} from './validate-package.js';
import {parseCommitType} from './parse-commit-type.js';
import {release} from './release.js';

import _prepend from 'prepend';

const prepend = promisify(_prepend);

import runWisdom from './run-wisdom.js';
import getEnv from './get-env.js';

const isUndefined = (a) => typeof a === 'undefined';

const Cmd = [
    'git add --all',
    'git commit -m "chore{{ commitType }} v{{ version }}"',
    'git pull --rebase',
    'git push origin {{ branch }}',
].join('&&');

const CmdTag = [
    'git tag v{{ version }}',
    'git push origin v{{ version }}',
].join('&&');

const chlogStore = fullstore();
const InfoDirStore = fullstore();

const setInfoDir = (data) => {
    const dir = path.dirname(data.path);

    InfoDirStore(dir);

    return data;
};

const getPkg = (data) => data.packageJson;

export default (version) => {
    const emitter = new EventEmitter();

    const onError = (e) => {
        const error = Error(`Error reading package.json: ${e.message}`);
        emitter.emit('error', error);
    };

    const start = currify((version, emitter, info) => {
        if (validatePackage({version, emitter, info}))
            return;

        publish(version, info, emitter);
    });

    readPackageUp()
        .then(setInfoDir)
        .then(getPkg)
        .then(start(version, emitter))
        .catch(onError);

    return emitter;
};

function publish(version, info, emitter) {
    let type = '--';

    if (!version.indexOf('v')) {
        version = version.slice(1);
        type += 'v' + version;
    } else if (/major|minor|patch/.test(version)) {
        type += version;
        version = minor(version, info.version);
    }

    const cmd = rendy(Cmd, {
        version,
        commitType: parseCommitType(info.commitType),
        branch: info.branch || 'master',
    });

    const cmdTag = rendy(CmdTag, {
        version,
    });

    series([
        async function beforePublish() {
            const cmd = jessy('scripts.wisdom', info);

            if (!cmd)
                return;

            await runWisdom('wisdom', '', version, info, emitter);
        },

        async function beforePublishType() {
            const cmd = jessy('scripts.wisdom:type', info);

            if (!cmd)
                return;

            await runWisdom('wisdom:type', type, version, info, emitter);
        },

        async () => {
            if (!isUndefined(info.changelog) && !info.changelog) {
                emitter.emit('data', 'changelog: false\n');
                return;
            }

            const [error, data] = tryCatch(changelog, version);

            if (error) {
                error.message += '\n';
                throw error;
            }

            const name = path.join(InfoDirStore(), 'ChangeLog');

            await prepend(name, data);

            const value = rmLines(data, 2);
            chlogStore(value);
        },

        async () => {
            await versionio(version);
        },

        (callback) => {
            execute(cmd, version, emitter, callback);
        },

        function tag(callback) {
            const isNoTag = !info.tag && !isUndefined(info.tag);

            if (isNoTag) {
                emitter.emit('data', 'tag: false\n');
                return callback();
            }

            execute(cmdTag, version, emitter, callback);
        },

        async function releaseToGitHub() {
            await release({
                version,
                info,
                chlog: chlogStore,
                emitter,
                count: info.releaseTriesCount || 10,
            });
        },

        function npmPublish(callback) {
            if (info.private)
                return callback();

            execute(`npm publish`, version, emitter, callback);
        },

        async function afterPublish() {
            const cmd = jessy('scripts.wisdom:done', info);

            if (!cmd)
                return;

            await runWisdom('wisdom:done', '', version, info, emitter);
        },
    ], (error) => {
        if (error)
            emitter.emit('error', error);

        emitter.emit('exit');
    });

    return emitter;
}

function execute(cmd, version, emitter, callback) {
    const stdio = [0, 1, 2, 'pipe'];

    const [e] = tryCatch(execSync, cmd, {
        env: getEnv(version),
        cwd: InfoDirStore(),
        stdio,
    });

    callback(e);
}

function rmLines(str, count) {
    return str
        .split('\n')
        .slice(count)
        .join('\n');
}

<commit_msg>fix: wisdom: prepend<commit_after>import {promisify} from 'util';
import path from 'path';
import {execSync} from 'child_process';
import {EventEmitter} from 'events';

import tryCatch from 'try-catch';
import versionio from 'version-io';
import changelog from 'changelog-io';
import rendy from 'rendy';
import series from 'async/series.js';
import minor from 'minor';
import jessy from 'jessy';
import {readPackageUp} from 'read-pkg-up';
import fullstore from 'fullstore';
import currify from 'currify';
import _prepend from 'prepend';

import {validatePackage} from './validate-package.js';
import {parseCommitType} from './parse-commit-type.js';
import {release} from './release.js';

const prepend = promisify(_prepend);

import runWisdom from './run-wisdom.js';
import getEnv from './get-env.js';

const isUndefined = (a) => typeof a === 'undefined';

const Cmd = [
    'git add --all',
    'git commit -m "chore{{ commitType }} v{{ version }}"',
    'git pull --rebase',
    'git push origin {{ branch }}',
].join('&&');

const CmdTag = [
    'git tag v{{ version }}',
    'git push origin v{{ version }}',
].join('&&');

const chlogStore = fullstore();
const InfoDirStore = fullstore();

const setInfoDir = (data) => {
    const dir = path.dirname(data.path);

    InfoDirStore(dir);

    return data;
};

const getPkg = (data) => data.packageJson;

export default (version) => {
    const emitter = new EventEmitter();

    const onError = (e) => {
        const error = Error(`Error reading package.json: ${e.message}`);
        emitter.emit('error', error);
    };

    const start = currify((version, emitter, info) => {
        if (validatePackage({version, emitter, info}))
            return;

        publish(version, info, emitter);
    });

    readPackageUp()
        .then(setInfoDir)
        .then(getPkg)
        .then(start(version, emitter))
        .catch(onError);

    return emitter;
};

function publish(version, info, emitter) {
    let type = '--';

    if (!version.indexOf('v')) {
        version = version.slice(1);
        type += 'v' + version;
    } else if (/major|minor|patch/.test(version)) {
        type += version;
        version = minor(version, info.version);
    }

    const cmd = rendy(Cmd, {
        version,
        commitType: parseCommitType(info.commitType),
        branch: info.branch || 'master',
    });

    const cmdTag = rendy(CmdTag, {
        version,
    });

    series([
        async function beforePublish() {
            const cmd = jessy('scripts.wisdom', info);

            if (!cmd)
                return;

            await runWisdom('wisdom', '', version, info, emitter);
        },

        async function beforePublishType() {
            const cmd = jessy('scripts.wisdom:type', info);

            if (!cmd)
                return;

            await runWisdom('wisdom:type', type, version, info, emitter);
        },

        async () => {
            if (!isUndefined(info.changelog) && !info.changelog) {
                emitter.emit('data', 'changelog: false\n');
                return;
            }

            const [error, data] = tryCatch(changelog, version);

            if (error) {
                error.message += '\n';
                throw error;
            }

            const name = path.join(InfoDirStore(), 'ChangeLog');

            await prepend(name, data);

            const value = rmLines(data, 2);
            chlogStore(value);
        },

        async () => {
            await versionio(version);
        },

        (callback) => {
            execute(cmd, version, emitter, callback);
        },

        function tag(callback) {
            const isNoTag = !info.tag && !isUndefined(info.tag);

            if (isNoTag) {
                emitter.emit('data', 'tag: false\n');
                return callback();
            }

            execute(cmdTag, version, emitter, callback);
        },

        async function releaseToGitHub() {
            await release({
                version,
                info,
                chlog: chlogStore,
                emitter,
                count: info.releaseTriesCount || 10,
            });
        },

        function npmPublish(callback) {
            if (info.private)
                return callback();

            execute(`npm publish`, version, emitter, callback);
        },

        async function afterPublish() {
            const cmd = jessy('scripts.wisdom:done', info);

            if (!cmd)
                return;

            await runWisdom('wisdom:done', '', version, info, emitter);
        },
    ], (error) => {
        if (error)
            emitter.emit('error', error);

        emitter.emit('exit');
    });

    return emitter;
}

function execute(cmd, version, emitter, callback) {
    const stdio = [0, 1, 2, 'pipe'];

    const [e] = tryCatch(execSync, cmd, {
        env: getEnv(version),
        cwd: InfoDirStore(),
        stdio,
    });

    callback(e);
}

function rmLines(str, count) {
    return str
        .split('\n')
        .slice(count)
        .join('\n');
}

<|endoftext|>