<commit_before>const Bot = require('./lib/Bot')
const SOFA = require('sofa-js')
const Fiat = require('./lib/Fiat')

let bot = new Bot()

// ROUTING

bot.onEvent = function (session, message) {

  console.log("The message is " + message.body)
  switch (message.type) {
    case 'Init':
      welcome(session)
      break
    case 'Message':
      onMessage(session, message)
      break
    case 'Command':
      onCommand(session, message)
      break
    case 'Payment':
      onPayment(session, message)
      break
    case 'PaymentRequest':
      paymentRequest(session, message)
      break
  }
}

function onMessage(session, message) {
  var username = session.user.username // logs username

  if (message.body == "12345") {
    plant(session)
  }
  else if (message.body == "undefined") {
    paymentRequest()
  }
  else {
    welcome(session, username)
  }
}

// takes command from the button

function onCommand(session, command) {
  switch (command.content.value) {
    case 'plant': // plant a tree
      plantMessage(session, `Please scan your seedling QR code to get information about where to plant it. You will be paid $1 upon verification that you have planted your seedling!`)
      //plant(session)
      break
    case 'verify': // verify a tree
      verifyMessage(session, 'For every image you verify, you will be compensated $0.1, i.e., 10 cents! Would you like to proceed?')
      break
    case 'fund': // fund a tree
      fundMessage(session, `For $3 you can fund the growth of one seedling! It only costs $150 to grow a small forest. Please select an amount below to fund.`)
      break
    case 'about': // Learn more about the Treebot
      about(session)
      break
    case 'scan': // Scan QR code (not functional)
      scan(session)
      break
    case 'help': // Get help
      help(session)
      break
  }
}

// takes care of payment

function sendRequest(session, message) {

  // session.reply(SOFA.PaymentRequest({
  //   "body": "Thanks for the great time! Can you send your share of the tab?",
  //   "value": "0xce0eb154f900000",
  //   "destinationAddress": "0x056db290f8ba3250ca64a45d16284d04bc6f5fbf"
  // }))
}

function paymentRequest(session) {

  // session.reply(SOFA.PaymentRequest({
  //   "body": "Thanks for the great time! Can you send your share of the tab?",
  //   "value": "0xce0eb154f900000",
  //   "destinationAddress": "0x056db290f8ba3250ca64a45d16284d04bc6f5fbf"
  // }))
}

function onPayment(session, message) {
  if (message.fromAddress == session.config.paymentAddress) {
    // handle payments sent by the bot
    if (message.status == 'confirmed') {
      // perform special action once the payment has been confirmed
      // on the network
    } else if (message.status == 'error') {
      // oops, something went wrong with a payment we tried to send!
    }
  } else {
    // handle payments sent to the bot
    if (message.status == 'unconfirmed') {
      // payment has been sent to the ethereum network, but is not yet confirmed
      sendMessage(session, `Thanks for the payment! 🙏`);
    } else if (message.status == 'confirmed') {
      // handle when the payment is actually confirmed!
    } else if (message.status == 'error') {
      sendMessage(session, `There was an error with your payment!🚫`);
    }
  }
}

// STATES

// Welcome message

function welcome(session, username) {
  sendMessage(session, `Hello ` + username + `, I am TreeBot, your reforestation friend. Tap “fund” to donate money towards planting a tree. Tap “plant” to earn money planting trees. Tap “verify” to help verify grown trees. To learn more about me and my mission, tap “about`)
}

// example of how to store state on each user

function verify(session) {

  sendMessage(session, `Our verification process is done using geolocation and QR codes! Geolocation is not yet available in the Token app, so stay tuned!`)

  /* Send a tree image to the user

  SOFA.Message({
    body: "Here you go...",
    attachments: [{
      "type": "image",
      "url": "farmer(1).jpg"
    }]
  }) */

  //   let verify = (session.get('verify') || 0) + 1
  //   session.set('verify', verify)
  //   sendMessage(session, `${verify}`)
}

function fund(session) {
  // request $1 USD at current exchange rates

  // NEEDS CODE - Request money from user with options
}

function plant(session) {
  //plantMessage(session, `Please scan your seedling QR code to get information about where to plant it. You will be paid $1 upon verification that you have planted your seedling!`)
  session.reply(`I will pay you $3 in 12 months for planting this Acacia Polyacantha`)
  session.reply(`It should be planted at this location *Geolocation*`)
  session.reply(`Ok, 12 months have not passed, but for the purpose of this hackathon please send us a photo of your tree for verification`)

}

function about(session) {
  sendMessage(session, `I am TreeBot and my mission is to restore land destroyed by deforestation. I’m starting in Africa, where I make it simple by mobilizing local communities to protect and nurture the land through planting trees. Restoring forests is not easy! But with TreeBot and the power of borderless payments, anybody can make the world a greener place.` + `\n` +`Made with ❤ by the Blockchain Education Network.`)
}

function scan(session, message) {
  session.reply('This feature is currently under development. Please enter the code 12345 instead (it\'s much easier 😉)')
  const foo = 12345

  // get the reply message and match it with foo

}

function help(session) {
  session.reply('We are currently out of seedlings to fund! Stay tuned for the next batch so you too can play a part in reforestation.')
}

// HELPERS

// Generic message with 4 options: Plant, Verify, Fund, and About

function sendMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Fund 💰', value: 'fund' },
    { type: 'button', label: 'Plant 🌲', value: 'plant' },
    { type: 'button', label: 'Verify ✔', value: 'verify' },
    { type: 'button', label: 'About', value: 'about' },
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

// Verify messsage shows three buttons - Yes, No and Help

function verifyMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Yes ✔', value: 'verify' },
    { type: 'button', label: 'No ❌', value: 'about' }
    //{ type: 'button', label: 'Help❓', value: 'help' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

// Plant message shows two options - Scan QR code and Help

function plantMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Scan QR code 📷', value: 'scan' },
    { type: 'button', label: 'Exit 🚪', value: 'about' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

function fundMessage(session, message) {
  let controls = [
    { type: 'button', label: '$3', value: 'help' },
    { type: 'button', label: '$150', value: 'help' },
    { type: 'button', label: 'Exit 🚪', value: 'about' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}
<commit_msg>product management<commit_after>const Bot = require('./lib/Bot')
const SOFA = require('sofa-js')
const Fiat = require('./lib/Fiat')

let bot = new Bot()

// ROUTING

bot.onEvent = function (session, message) {

  console.log("The message is " + message.body)
  switch (message.type) {
    case 'Init':
      welcome(session)
      break
    case 'Message':
      onMessage(session, message)
      break
    case 'Command':
      onCommand(session, message)
      break
    case 'Payment':
      onPayment(session, message)
      break
    case 'PaymentRequest':
      paymentRequest(session, message)
      break
  }
}

function onMessage(session, message) {
  var username = session.user.username // logs username

  if (message.body == "12345") {
    plant(session)
  }
  else if (message.body == "undefined") {
    paymentRequest()
  }
  else {
    welcome(session, username)
  }
}

// takes command from the button

function onCommand(session, command) {
  switch (command.content.value) {
    case 'plant': // plant a tree
      plantMessage(session, `Please scan your seedling QR code to get information about where to plant it. You will be paid $1 upon verification that you have planted your seedling!`)
      //plant(session)
      break
    case 'verify': // verify a tree
      verifyMessage(session, 'For every image you verify, you will be compensated $0.1, i.e., 10 cents! Would you like to proceed?')
      break
    case 'fund': // fund a tree
      fundMessage(session, `For $3 you can fund the growth of one seedling! It only costs $150 to grow a small forest. Please select an amount below to fund.`)
      break
    case 'about': // Learn more about the Treebot
      about(session)
      break
    case 'scan': // Scan QR code (not functional)
      scan(session)
      break
    case 'help': // Get help
      help(session)
      break
  }
}

// takes care of payment

function sendRequest(session, message) {

  // session.reply(SOFA.PaymentRequest({
  //   "body": "Thanks for the great time! Can you send your share of the tab?",
  //   "value": "0xce0eb154f900000",
  //   "destinationAddress": "0x056db290f8ba3250ca64a45d16284d04bc6f5fbf"
  // }))
}

function paymentRequest(session) {

  // session.reply(SOFA.PaymentRequest({
  //   "body": "Thanks for the great time! Can you send your share of the tab?",
  //   "value": "0xce0eb154f900000",
  //   "destinationAddress": "0x056db290f8ba3250ca64a45d16284d04bc6f5fbf"
  // }))
}

function onPayment(session, message) {
  if (message.fromAddress == session.config.paymentAddress) {
    // handle payments sent by the bot
    if (message.status == 'confirmed') {
      // perform special action once the payment has been confirmed
      // on the network
    } else if (message.status == 'error') {
      // oops, something went wrong with a payment we tried to send!
    }
  } else {
    // handle payments sent to the bot
    if (message.status == 'unconfirmed') {
      // payment has been sent to the ethereum network, but is not yet confirmed
      sendMessage(session, `Thanks for the payment! 🙏`);
    } else if (message.status == 'confirmed') {
      // handle when the payment is actually confirmed!
    } else if (message.status == 'error') {
      sendMessage(session, `There was an error with your payment!🚫`);
    }
  }
}

// STATES

// Welcome message

function welcome(session, username) {
  sendMessage(session, `Hello ` + username + `, I am TreeBot, your reforestation friend. Tap “fund” to donate money towards planting a tree. Tap “plant” to earn money planting trees. Tap “verify” to help verify grown trees. To learn more about me and my mission, tap “about`)
}

// example of how to store state on each user

function verifyexcuse(session) {

  sendMessage(session, `Our verification process is done using geolocation and QR codes! Geolocation is not yet available in the Token app, so stay tuned!`)

  /* Send a tree image to the user

  SOFA.Message({
    body: "Here you go...",
    attachments: [{
      "type": "image",
      "url": "farmer(1).jpg"
    }]
  }) */

  //   let verify = (session.get('verify') || 0) + 1
  //   session.set('verify', verify)
  //   sendMessage(session, `${verify}`)
}

function fund(session) {
  // request $1 USD at current exchange rates

  // NEEDS CODE - Request money from user with options
}

function plant(session) {
  //plantMessage(session, `Please scan your seedling QR code to get information about where to plant it. You will be paid $1 upon verification that you have planted your seedling!`)
  session.reply(`I will pay you $3 in 12 months for planting this Acacia Polyacantha`)
  session.reply(`It should be planted at this location *Geolocation*`)
  session.reply(`Ok, 12 months have not passed, but for the purpose of this hackathon please send us a photo of your tree for verification`)

}

function about(session) {
  sendMessage(session, `I am TreeBot and my mission is to restore land destroyed by deforestation. I’m starting in Africa, where I make it simple by mobilizing local communities to protect and nurture the land through planting trees. Restoring forests is not easy! But with TreeBot and the power of borderless payments, anybody can make the world a greener place.` + `\n` +`Made with ❤ by the Blockchain Education Network.`)
}

function scan(session, message) {
  session.reply('This feature is currently under development. Please enter the code 12345 instead (it\'s much easier 😉)')
  const foo = 12345

  // get the reply message and match it with foo

}

function help(session) {
  sendmessage(session, `We are currently out of seedlings to fund! Stay tuned for the next batch so you too can play a part in reforestation.`)
}

// HELPERS

// Generic message with 4 options: Plant, Verify, Fund, and About

function sendMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Fund 💰', value: 'fund' },
    { type: 'button', label: 'Plant 🌲', value: 'plant' },
    { type: 'button', label: 'Verify ✔', value: 'verify' },
    { type: 'button', label: 'About', value: 'about' },
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

// Verify messsage shows three buttons - Yes, No and Help

function verifyMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Yes ✔', value: 'verifyexcuse' },
    { type: 'button', label: 'No ❌', value: 'about' }
    //{ type: 'button', label: 'Help❓', value: 'help' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

// Plant message shows two options - Scan QR code and Help

function plantMessage(session, message) {
  let controls = [
    { type: 'button', label: 'Scan QR code 📷', value: 'scan' },
    { type: 'button', label: 'Exit 🚪', value: 'about' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}

function fundMessage(session, message) {
  let controls = [
    { type: 'button', label: '$3', value: 'help' },
    { type: 'button', label: '$150', value: 'help' },
    { type: 'button', label: 'Exit 🚪', value: 'about' }
  ]
  session.reply(SOFA.Message({
    body: message,
    controls: controls,
    showKeyboard: true,
  }))
}
<|endoftext|>


<commit_before>module.exports = function(grunt) {

	// Set UTF-8 Charset
	grunt.file.defaultEncoding = 'utf8';

	// Load grunt packages
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-compass');
	grunt.loadNpmTasks('grunt-text-replace');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Set our instructions
	grunt.initConfig({
		// Read package.json for instructions on what packages to use
		pkg : grunt.file.readJSON('package.json'),
		copy : {
			// WordPress
			wp : {
				files : [{
					expand : true,
					cwd : 'app/wordpress',
					src : 'wp-content/**',
					dest : 'app'
				}, {
					expand : true,
					cwd : 'app/wordpress',
					src : 'wp-config-sample.php',
					dest : 'app'
				}]
			}
		},
		clean : {
			// WordPress
			wp : ['app/wordpress/wp-config-sample.php', 'app/wp-content/plugins/hello.php', 'app/wp-content/themes/twentyten', 'app/wp-content/themes/twentyeleven', 'app/wp-content/themes/twentytwelve']
		},
		compass : {
			wp : {
				options : {
					environment : 'development',
					outputStyle : 'expanded',
					relativeAssets : true,
					basePath : 'app/wp-content/themes/gutsThemeStarter',
					cssDir : 'css',
					sassDir : 'sass',
					imagesDir : 'img',
					javascriptsDir : 'js',
					fontsDir : 'font',
					noLineComments : true,
					force : true
				}
			}
		},
		watch: {
			// Watch our sass files and auto compile them
			wp: {
				files: ['app/wp-content/themes/gutsThemeStarter/sass/**.*'],
				tasks: ['compass:wp']
			},
			// Watch our js files and auto compile them
			// js: {
				// files: ['assets/js/main.js', 'components/**/*.js'],
				// tasks: ['uglify']
			// },
			// Watch our files for any changes, then automatically reload the page
			// Requires livereload chrome extension, or equivalent
			livereload: {
				files: ['app/wp-content/themes/gutsThemeStarter/css/*.*'],
				options: {
					livereload: true
				}
			}
		},
		replace: {
			wpconfig: {
				src: ['app/wp-config.php'],
				overwrite: true,
				//dest: 'app/wp-config.php',
				replacements: [{
					from: '<?php',
					to: function (matchedWord) {   // callback replacement
						//return matchedWord;
						var phpTag = matchedWord + '\n\n\n';
						var prewrap1 = "/***** Dynamicaly generated from Gruntfile.js *****/ \n"
						var prewrap2 = "/***** You may need to update the path to your project *****/ \n"
					    var wp_home = "define('WP_HOME',    'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app'); \n";
					    var wp_siteurl = "define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app/wordpress'); \n";
					    var wp_content_dir = "define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/eikoncodex.com/app/wp-content'); \n";
					    var wp_content_url = "define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app/wp-content'); \n";
						var postwrap = "/***** End Gruntfile.js inserts *****/ \n\n\n"
					    return [phpTag + prewrap1 + prewrap2 + wp_home + wp_siteurl + wp_content_dir + wp_content_url + postwrap];
					}
				}]
			}
		}
	});

	/*
	 * Define Grunt Tasks
	 */
	// Set up wordpress, copy across wp-content and create index.php and wp-config-sample.php
	grunt.registerTask('wp', function() {
		grunt.file.write("app/index.php", '<?php define(\'WP_USE_THEMES\',true);require(dirname(__FILE__).\'/wordpress/wp-blog-header.php\');');
		grunt.task.run('copy:wp', 'clean:wp');
	});
	// Compile styles, and watch for changes
	grunt.registerTask('wpsass', ['compass:wp', 'watch:wp']);
	// Dynamically add necessary paths to wp-config.php. You will need to edit this.
	grunt.registerTask('wpconfig', function() {
		grunt.task.run('replace:wpconfig');
		grunt.log.write('Guts has dynamically added new lines to the top of your wp-config.php file in the app folder. You will need to edit these lines. Please do this now./');
	});

	// We want to disable default grunt for now, so provide a nice message
	grunt.registerTask('default', 'My "default" task description.', function() {
		grunt.log.writeln('');
		grunt.log.writeln('********************************************');
		grunt.log.writeln('There are no default tasks in this project.');
		grunt.log.writeln('Open Gruntfile.js to see how Grunt is built.');
		grunt.log.writeln('********************************************');
	});

};
<commit_msg>removed wp config sample when runnign wp config<commit_after>module.exports = function(grunt) {

	// Set UTF-8 Charset
	grunt.file.defaultEncoding = 'utf8';

	// Load grunt packages
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-compass');
	grunt.loadNpmTasks('grunt-text-replace');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Set our instructions
	grunt.initConfig({
		// Read package.json for instructions on what packages to use
		pkg : grunt.file.readJSON('package.json'),
		copy : {
			// WordPress
			wp : {
				files : [{
					expand : true,
					cwd : 'app/wordpress',
					src : 'wp-content/**',
					dest : 'app'
				}, {
					expand : true,
					cwd : 'app/wordpress',
					src : 'wp-config-sample.php',
					dest : 'app'
				}]
			}
		},
		clean : {
			// WordPress
			wp : ['app/wordpress/wp-config-sample.php', 'app/wp-content/plugins/hello.php', 'app/wp-content/themes/twentyten', 'app/wp-content/themes/twentyeleven', 'app/wp-content/themes/twentytwelve'],
			wpconfig: ['app/wp-config-sample.php']
		},
		compass : {
			wp : {
				options : {
					environment : 'development',
					outputStyle : 'expanded',
					relativeAssets : true,
					basePath : 'app/wp-content/themes/gutsThemeStarter',
					cssDir : 'css',
					sassDir : 'sass',
					imagesDir : 'img',
					javascriptsDir : 'js',
					fontsDir : 'font',
					noLineComments : true,
					force : true
				}
			}
		},
		watch: {
			// Watch our sass files and auto compile them
			wp: {
				files: ['app/wp-content/themes/gutsThemeStarter/sass/**.*'],
				tasks: ['compass:wp']
			},
			// Watch our js files and auto compile them
			// js: {
				// files: ['assets/js/main.js', 'components/**/*.js'],
				// tasks: ['uglify']
			// },
			// Watch our files for any changes, then automatically reload the page
			// Requires livereload chrome extension, or equivalent
			livereload: {
				files: ['app/wp-content/themes/gutsThemeStarter/css/*.*'],
				options: {
					livereload: true
				}
			}
		},
		replace: {
			wpconfig: {
				src: ['app/wp-config.php'],
				overwrite: true,
				//dest: 'app/wp-config.php',
				replacements: [{
					from: '<?php',
					to: function (matchedWord) {   // callback replacement
						//return matchedWord;
						var phpTag = matchedWord + '\n\n\n';
						var prewrap1 = "/***** Dynamicaly generated from Gruntfile.js *****/ \n"
						var prewrap2 = "/***** You may need to update the path to your project *****/ \n"
					    var wp_home = "define('WP_HOME',    'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app'); \n";
					    var wp_siteurl = "define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app/wordpress'); \n";
					    var wp_content_dir = "define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/eikoncodex.com/app/wp-content'); \n";
					    var wp_content_url = "define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/eikoncodex.com/app/wp-content'); \n";
						var postwrap = "/***** End Gruntfile.js inserts *****/ \n\n\n"
					    return [phpTag + prewrap1 + prewrap2 + wp_home + wp_siteurl + wp_content_dir + wp_content_url + postwrap];
					}
				}]
			}
		}
	});

	/*
	 * Define Grunt Tasks
	 */
	// Set up wordpress, copy across wp-content and create index.php and wp-config-sample.php
	grunt.registerTask('wp', function() {
		grunt.file.write("app/index.php", '<?php define(\'WP_USE_THEMES\',true);require(dirname(__FILE__).\'/wordpress/wp-blog-header.php\');');
		grunt.task.run('copy:wp', 'clean:wp');
	});
	// Compile styles, and watch for changes
	grunt.registerTask('wpsass', ['compass:wp', 'watch:wp']);
	// Dynamically add necessary paths to wp-config.php. You will need to edit this.
	grunt.registerTask('wpconfig', function() {
		grunt.task.run('replace:wpconfig', 'clean:wpconfig');
		grunt.log.write('Guts has dynamically added new lines to the top of your wp-config.php file in the app folder. You will need to edit these lines. Please do this now./');
	});

	// We want to disable default grunt for now, so provide a nice message
	grunt.registerTask('default', 'My "default" task description.', function() {
		grunt.log.writeln('');
		grunt.log.writeln('********************************************');
		grunt.log.writeln('There are no default tasks in this project.');
		grunt.log.writeln('Open Gruntfile.js to see how Grunt is built.');
		grunt.log.writeln('********************************************');
	});

};
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

"use strict";

// Include Gulp & Tools We"ll Use
var gulp = require("gulp");
var $ = require("gulp-load-plugins")();
var del = require("del");
var runSequence = require("run-sequence");
var browserSync = require("browser-sync");
var reload = browserSync.reload;
var merge = require("merge-stream");
var path = require("path");

var AUTOPREFIXER_BROWSERS = [
  "ie >= 10",
  "ie_mob >= 10",
  "ff >= 30",
  "chrome >= 34",
  "safari >= 7",
  "opera >= 23",
  "ios >= 7",
  "android >= 4.4",
  "bb >= 10"
];

var styleTask = function (stylesPath, srcs) {
  return gulp.src(srcs.map(function(src) {
      return path.join("app", stylesPath, src);
    }))
    .pipe($.changed(stylesPath, {extension: ".scss"}))
    .pipe($.if("*.scss", $.sass({
      outputStyle: "nested", // libsass doesn"t support expanded yet
      precision: 10,
      includePaths: ["."],
      onError: console.error.bind(console, "Sass error:")
    })))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest(".tmp/" + stylesPath))
    .pipe($.if("*.css", $.cssmin()))
    .pipe(gulp.dest("dist/" + stylesPath))
    .pipe($.size({title: stylesPath}));
};

// Compile and Automatically Prefix Stylesheets
gulp.task("styles", function () {
  return styleTask("styles", ["*.css", "*.scss"]);
});

gulp.task("elements", function () {
  return styleTask("elements", ["**/*.css", "**/*.scss"]);
});

// Lint JavaScript
gulp.task("jshint", function () {
  return gulp.src([
      "app/scripts/**/*.js",
      "app/elements/**/*.js",
      "app/elements/**/*.html"
    ])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint.extract()) // Extract JS from .html files
    .pipe($.jshint())
    .pipe($.jshint.reporter("jshint-stylish"))
    .pipe($.if(!browserSync.active, $.jshint.reporter("fail")));
});

// Optimize Images
gulp.task("images", function () {
  return gulp.src("app/images/**/*")
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest("dist/images"))
    .pipe($.size({title: "images"}));
});

// Copy All Files At The Root Level (app)
gulp.task("copy", function () {
  var app = gulp.src([
    "app/*",
    "!app/test"
  ], {
    dot: true
  }).pipe(gulp.dest("dist"));

  var bower = gulp.src([
    "bower_components/**/*"
  ]).pipe(gulp.dest("dist/bower_components"));

  var elements = gulp.src(["app/elements/**/*.{html,js}"])
    .pipe(gulp.dest("dist/elements"));

  var vulcanized = gulp.src(["app/elements/elements.html"])
    .pipe($.rename("elements.vulcanized.html"))
    .pipe(gulp.dest("dist/elements"));

  return merge(app, bower, elements, vulcanized)
    .pipe($.size({title: "copy"}));
});

// Copy Web Fonts To Dist
gulp.task("fonts", function () {
  return gulp.src(["app/fonts/**"])
    .pipe(gulp.dest("dist/fonts"))
    .pipe($.size({title: "fonts"}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task("html", function () {
  var assets = $.useref.assets({searchPath: [".tmp", "app", "dist"]});

  return gulp.src(["app/**/*.html", "!app/{elements,test}/**/*.html"])
    // Replace path for vulcanized assets
    .pipe($.if("*.html", $.replace("elements/elements.html", "elements/elements.vulcanized.html")))
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if("*.js", $.uglify({preserveComments: "some"})))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if("*.css", $.cssmin()))
    .pipe(assets.restore())
    .pipe($.useref())
    // Minify Any HTML
    .pipe($.if("*.html", $.minifyHtml({
      quotes: true,
      empty: true,
      spare: true
    })))
    // Output Files
    .pipe(gulp.dest("dist"))
    .pipe($.size({title: "html"}));
});

// Vulcanize imports
gulp.task("vulcanize", function () {
  var DEST_DIR = "dist/elements";

  return gulp.src("dist/elements/elements.vulcanized.html")
    .pipe($.vulcanize({
      dest: DEST_DIR,
      strip: true,
      inlineCss: true,
      inlineScripts: true
    }))
    .pipe(gulp.dest(DEST_DIR))
    .pipe($.size({title: "vulcanize"}));
});

// Clean Output Directory
gulp.task("clean", del.bind(null, [".tmp", "dist"]));

// Watch Files For Changes & Reload
gulp.task("serve", ["styles", "elements", "images"], function () {
  browserSync({
    notify: false,
    snippetOptions: {
      rule: {
        match: "",
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting "https: true"
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: {
      baseDir: [".tmp", "app"],
      routes: {
        "/bower_components": "bower_components"
      }
    }
  });

  gulp.watch(["app/**/*.html"], reload);
  gulp.watch(["app/styles/**/*.{css,scss}"], ["styles", reload]);
  gulp.watch(["app/elements/**/*.{css,scss}"], ["elements", reload]);
  gulp.watch(["app/{scripts,elements}/**/*.js"], ["jshint"]);
  gulp.watch(["app/images/**/*"], reload);
});

// Build and serve the output from the dist build
gulp.task("serve:dist", ["default"], function () {
  browserSync({
    notify: false,
    snippetOptions: {
      rule: {
        match: "",
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting "https: true"
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: "dist"
  });
});

// Build Production Files, the Default Task
gulp.task("default", ["clean"], function (cb) {
  runSequence(
    ["copy", "styles"],
    "elements",
    ["jshint", "images", "fonts", "html"],
    "vulcanize",
    cb);
});

// Load tasks for web-component-tester
// Adds tasks for `gulp test:local` and `gulp test:remote`
try { require("web-component-tester").gulp.init(gulp); } catch (err) {}

// Load custom tasks from the `tasks` directory
try { require("require-dir")("tasks"); } catch (err) {}

var gulpParam = require("gulp-param")(require("gulp"), process.argv);
gulpParam.task("el", function(name) {
  if (!name)
    return;

  function toClassName(s) {
      return s.replace(/\w[^-]*/g, function(txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
      }).replace("-", "");
  }

  var elemName = "lmv-" + name;
  var className = toClassName(name);

  var TEMPLATE_NAME = "lmv-template";
  var TEMPLATE_CLASS_NAME = "TemplateElement";

  return gulp.src(["app/elements/"+TEMPLATE_NAME+"/*.*"])
    .pipe($.rename({
      basename: elemName
    }))
    .pipe($.replace(TEMPLATE_NAME, elemName))
    .pipe($.if("*.js", $.replace(TEMPLATE_CLASS_NAME, className)))
    .pipe(gulp.dest("app/elements/"+elemName))
    .pipe($.size({title: "created " + elemName + " " + className}));
});<commit_msg>fix "gulp el" for names<commit_after>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

"use strict";

// Include Gulp & Tools We"ll Use
var gulp = require("gulp");
var $ = require("gulp-load-plugins")();
var del = require("del");
var runSequence = require("run-sequence");
var browserSync = require("browser-sync");
var reload = browserSync.reload;
var merge = require("merge-stream");
var path = require("path");

var AUTOPREFIXER_BROWSERS = [
  "ie >= 10",
  "ie_mob >= 10",
  "ff >= 30",
  "chrome >= 34",
  "safari >= 7",
  "opera >= 23",
  "ios >= 7",
  "android >= 4.4",
  "bb >= 10"
];

var styleTask = function (stylesPath, srcs) {
  return gulp.src(srcs.map(function(src) {
      return path.join("app", stylesPath, src);
    }))
    .pipe($.changed(stylesPath, {extension: ".scss"}))
    .pipe($.if("*.scss", $.sass({
      outputStyle: "nested", // libsass doesn"t support expanded yet
      precision: 10,
      includePaths: ["."],
      onError: console.error.bind(console, "Sass error:")
    })))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest(".tmp/" + stylesPath))
    .pipe($.if("*.css", $.cssmin()))
    .pipe(gulp.dest("dist/" + stylesPath))
    .pipe($.size({title: stylesPath}));
};

// Compile and Automatically Prefix Stylesheets
gulp.task("styles", function () {
  return styleTask("styles", ["*.css", "*.scss"]);
});

gulp.task("elements", function () {
  return styleTask("elements", ["**/*.css", "**/*.scss"]);
});

// Lint JavaScript
gulp.task("jshint", function () {
  return gulp.src([
      "app/scripts/**/*.js",
      "app/elements/**/*.js",
      "app/elements/**/*.html"
    ])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint.extract()) // Extract JS from .html files
    .pipe($.jshint())
    .pipe($.jshint.reporter("jshint-stylish"))
    .pipe($.if(!browserSync.active, $.jshint.reporter("fail")));
});

// Optimize Images
gulp.task("images", function () {
  return gulp.src("app/images/**/*")
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest("dist/images"))
    .pipe($.size({title: "images"}));
});

// Copy All Files At The Root Level (app)
gulp.task("copy", function () {
  var app = gulp.src([
    "app/*",
    "!app/test"
  ], {
    dot: true
  }).pipe(gulp.dest("dist"));

  var bower = gulp.src([
    "bower_components/**/*"
  ]).pipe(gulp.dest("dist/bower_components"));

  var elements = gulp.src(["app/elements/**/*.{html,js}"])
    .pipe(gulp.dest("dist/elements"));

  var vulcanized = gulp.src(["app/elements/elements.html"])
    .pipe($.rename("elements.vulcanized.html"))
    .pipe(gulp.dest("dist/elements"));

  return merge(app, bower, elements, vulcanized)
    .pipe($.size({title: "copy"}));
});

// Copy Web Fonts To Dist
gulp.task("fonts", function () {
  return gulp.src(["app/fonts/**"])
    .pipe(gulp.dest("dist/fonts"))
    .pipe($.size({title: "fonts"}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task("html", function () {
  var assets = $.useref.assets({searchPath: [".tmp", "app", "dist"]});

  return gulp.src(["app/**/*.html", "!app/{elements,test}/**/*.html"])
    // Replace path for vulcanized assets
    .pipe($.if("*.html", $.replace("elements/elements.html", "elements/elements.vulcanized.html")))
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if("*.js", $.uglify({preserveComments: "some"})))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if("*.css", $.cssmin()))
    .pipe(assets.restore())
    .pipe($.useref())
    // Minify Any HTML
    .pipe($.if("*.html", $.minifyHtml({
      quotes: true,
      empty: true,
      spare: true
    })))
    // Output Files
    .pipe(gulp.dest("dist"))
    .pipe($.size({title: "html"}));
});

// Vulcanize imports
gulp.task("vulcanize", function () {
  var DEST_DIR = "dist/elements";

  return gulp.src("dist/elements/elements.vulcanized.html")
    .pipe($.vulcanize({
      dest: DEST_DIR,
      strip: true,
      inlineCss: true,
      inlineScripts: true
    }))
    .pipe(gulp.dest(DEST_DIR))
    .pipe($.size({title: "vulcanize"}));
});

// Clean Output Directory
gulp.task("clean", del.bind(null, [".tmp", "dist"]));

// Watch Files For Changes & Reload
gulp.task("serve", ["styles", "elements", "images"], function () {
  browserSync({
    notify: false,
    snippetOptions: {
      rule: {
        match: "",
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting "https: true"
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: {
      baseDir: [".tmp", "app"],
      routes: {
        "/bower_components": "bower_components"
      }
    }
  });

  gulp.watch(["app/**/*.html"], reload);
  gulp.watch(["app/styles/**/*.{css,scss}"], ["styles", reload]);
  gulp.watch(["app/elements/**/*.{css,scss}"], ["elements", reload]);
  gulp.watch(["app/{scripts,elements}/**/*.js"], ["jshint"]);
  gulp.watch(["app/images/**/*"], reload);
});

// Build and serve the output from the dist build
gulp.task("serve:dist", ["default"], function () {
  browserSync({
    notify: false,
    snippetOptions: {
      rule: {
        match: "",
        fn: function (snippet) {
          return snippet;
        }
      }
    },
    // Run as an https by uncommenting "https: true"
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: "dist"
  });
});

// Build Production Files, the Default Task
gulp.task("default", ["clean"], function (cb) {
  runSequence(
    ["copy", "styles"],
    "elements",
    ["jshint", "images", "fonts", "html"],
    "vulcanize",
    cb);
});

// Load tasks for web-component-tester
// Adds tasks for `gulp test:local` and `gulp test:remote`
try { require("web-component-tester").gulp.init(gulp); } catch (err) {}

// Load custom tasks from the `tasks` directory
try { require("require-dir")("tasks"); } catch (err) {}

var gulpParam = require("gulp-param")(require("gulp"), process.argv);
gulpParam.task("el", function(name) {
  if (!name)
    return;

  function toClassName(s) {
      return s.replace(/\w[^-]*/g, function(txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
      }).replace(/-/g, "");
  }

  var elemName = "lmv-" + name;
  var className = toClassName(name);

  var TEMPLATE_NAME = "lmv-template";
  var TEMPLATE_CLASS_NAME = "TemplateElement";

  return gulp.src(["app/elements/"+TEMPLATE_NAME+"/*.*"])
    .pipe($.rename({
      basename: elemName
    }))
    .pipe($.replace(TEMPLATE_NAME, elemName))
    .pipe($.if("*.js", $.replace(TEMPLATE_CLASS_NAME, className)))
    .pipe(gulp.dest("app/elements/"+elemName))
    .pipe($.size({title: "created " + elemName + " " + className}));
});<|endoftext|>


<commit_before>// Generated on 2015-09-26 using generator-angular 0.12.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates:   'grunt-angular-templates',
    cdnify:        'grunt-google-cdn',
    express:       'grunt-express-server'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Express server
    express: {
      options: {
        port: 9000
      },
      dev: {
        options: {
          script: 'app/server.js'
        }
      },
      prod: {
        options: {
          script: 'app/prod_server.js',
          node_env: 'production'
        }
      },
      test: {
        options: {
          script: 'app/server.js'
        }
      }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {}
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer:server']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      express: {
        files: ['app/*.js'],
        tasks: ['express:dev'],
        options: {
          livereload: true,
          nospawn: true
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true,
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './app/bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          sourcemap: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'diddleplanApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'prod_server.js',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'views/*.html',
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'app/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
    this.async();
  });

  grunt.registerTask('serve', 'Compile then start an express web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'express:prod', 'express-keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'express:dev',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'express:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<commit_msg>Watch routes for express reload<commit_after>// Generated on 2015-09-26 using generator-angular 0.12.1
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates:   'grunt-angular-templates',
    cdnify:        'grunt-google-cdn',
    express:       'grunt-express-server'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Express server
    express: {
      options: {
        port: 9000
      },
      dev: {
        options: {
          script: 'app/server.js'
        }
      },
      prod: {
        options: {
          script: 'app/prod_server.js',
          node_env: 'production'
        }
      },
      test: {
        options: {
          script: 'app/server.js'
        }
      }
    },

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {}
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      compass: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        tasks: ['compass:server', 'autoprefixer:server']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      express: {
        files: ['app/*.js', 'app/routes/*.js'],
        tasks: ['express:dev'],
        options: {
          livereload: true,
          nospawn: true
        }
      }
    },

    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true,
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      },
      sass: {
        src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
        ignorePath: /(\.\.\/){1,2}bower_components\//
      }
    },

    // Compiles Sass to CSS and generates necessary files if requested
    compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './app/bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          sourcemap: true
        }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ],
        patterns: {
          js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'diddleplanApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'prod_server.js',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*',
            'views/*.html',
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: '.',
          src: 'app/bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'compass:server'
      ],
      test: [
        'compass'
      ],
      dist: [
        'compass:dist',
        'imagemin',
        'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('express-keepalive', 'Keep grunt running', function() {
    this.async();
  });

  grunt.registerTask('serve', 'Compile then start an express web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'express:prod', 'express-keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'express:dev',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'express:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		clean: {
			bootstrap: ['ui/app/static/css/bootstrap.css']
		},

		sass: {
			dev: {
				options: {
					compass: true,
					sourcemap: 'none',
					style: 'expanded'
				},
				files: {
					'../../ui/app/static/css/bootstrap.css': 'scss/bootstrap.scss'
				}
			},

			dist: {
				options: {
					compass: true,
					sourcemap: 'none',
					style: 'compressed'
				},
				files: {
					'../../ui/app/static/css/bootstrap.css': 'scss/bootstrap.scss'
				}
			},

			watch: {
				configFiles: {
					files: ['Gruntfile.js'],
					options: {
						reload: true
					}
				},

				css: {
					files: 'scss/*.scss',
					tasks: ['clean:bootstrap', 'sass:dev'],
					options: {
						livereload: true
					}
				}
			}
		}
	});

	// Distribution
	grunt.registerTask('dist', ['sass:dist']);

	// Development
	grunt.registerTask('dev', ['clean:bootstrap', 'sass:dev']);

	// Load NPM Tasks
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Default Task
	grunt.registerTask('default', ['watch:css']);
};<commit_msg>fixing scss file path error<commit_after>module.exports = function (grunt) {

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		clean: {
			bootstrap: ['ui/app/static/css/bootstrap.css']
		},

		sass: {
			dev: {
				options: {
					compass: true,
					sourcemap: 'none',
					style: 'expanded'
				},
				files: {
					'../../ui/app/static/css/bootstrap.css': 'scss/bootstrap.scss'
				}
			},

			dist: {
				options: {
					compass: true,
					sourcemap: 'none',
					style: 'compressed'
				},
				files: {
					'../../ui/app/static/css/bootstrap.css': 'scss/bootstrap.scss'
				}
			},

			watch: {
				configFiles: {
					files: ['Gruntfile.js'],
					options: {
						reload: true
					}
				},

				css: {
					files: ['scss/*.scss'],
					tasks: ['clean:bootstrap', 'sass:dev'],
					options: {
						livereload: true
					}
				}
			}
		}
	});

	// Distribution
	grunt.registerTask('dist', ['sass:dist']);

	// Development
	grunt.registerTask('dev', ['clean:bootstrap', 'sass:dev']);

	// Load NPM Tasks
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-sass');
	grunt.loadNpmTasks('grunt-contrib-watch');

	// Default Task
	grunt.registerTask('default', ['watch:css']);
};<|endoftext|>


<commit_before>var gulp = require('gulp')
var watch = require('gulp-watch')
var browser_sync = require('browser-sync').create()
var sass = require('gulp-sass')
var url = require('url')
var fs = require('fs')
var bulkSass = require('gulp-sass-bulk-import')
var kiska_logger = require('./libs/kiska_logger')
var scsslint = require('gulp-scss-lint')
var spritesmith = require('gulp.spritesmith')
var sourcemaps = require('gulp-sourcemaps')
var checkGem = require('gulp-check-gems')
var autoprefixer = require('gulp-autoprefixer')
var iconfont = require('gulp-iconfont')
var iconfontCss = require('gulp-iconfont-css')
var handlebars = require('gulp-handlebars')
var defineModule = require('gulp-define-module')
var flatten = require('gulp-flatten')
var concat = require('gulp-concat')
var filterBy = require('gulp-filter-by')
var wrap = require('gulp-wrap')
var path = require('path')

var enduro_helpers = require(ENDURO_FOLDER + '/libs/flat_utilities/enduro_helpers')

// Gulp tasks
var pagelist_generator = require(ENDURO_FOLDER + '/libs/build_tools/pagelist_generator').init(gulp)
var prettyfier = require(ENDURO_FOLDER + '/libs/build_tools/prettyfier').init(gulp)
var htmlvalidator = require(ENDURO_FOLDER + '/libs/build_tools/html_validator').init(gulp)

gulp.set_refresh = function (callback) {
	gulp.enduro_refresh = callback
}

gulp.enduro_refresh = function () {
	kiska_logger.err('refresh not defined')
}

// * ———————————————————————————————————————————————————————— * //
// * 	browser sync task
// * ———————————————————————————————————————————————————————— * //
gulp.task('browser_sync', ['sass'], function() {
	browsersync_start(false)
})

gulp.task('browser_sync_norefresh', ['sass'], function() {
	browsersync_start(true)
})

gulp.task('browser_sync_stop', [], function() {
	browser_sync.exit()
})

function browsersync_start(norefresh) {
	kiska_logger.timestamp('browsersync started', 'enduro_events')
	browser_sync.init({
		server: {
			baseDir: CMD_FOLDER + '/_src',
			middleware: function(req, res, next) {

				if(req.url.split('/')[1] && config.cultures.indexOf(req.url.split('/')[1]) + 1){
					return next()
				}

				// serve files without html
				if(!(req.url.indexOf('.') + 1) && req.url.length > 3) {
					req.url += '.html'
				}

				// patch to enable development of admin ui in enduro
				static_path_pattern = new RegExp(config.static_path_prefix + '\/(.*)')
				if(static_path_pattern.test(req.url)){
					req.url = '/' + req.url.match(static_path_pattern)[1]
				}

				// server admin/index file on /admin url
				if(req.url == '/admin/'){ req.url = '/admin/index.html' }

				return next()
			},
		},
		ui: false,
		logLevel: 'silent',
		notify: false,
		logPrefix: 'Enduro',
		startPath: START_PATH,
		open: !norefresh
	})
	watch([ CMD_FOLDER + '/assets/css/**/*', CMD_FOLDER + '/assets/fonticons/*', '!' + CMD_FOLDER + '/assets/css/sprites/*'],
				() => { gulp.start('sass') })									// Watch for scss

	if(!flags.nojswatch) {
		watch([CMD_FOLDER + '/assets/js/**/*'], () => { gulp.start('js'); browser_sync.reload() })							// Watch for js
	}

	watch([CMD_FOLDER + '/assets/img/**/*'], () => { gulp.start('img') })						// Watch for images
	watch([CMD_FOLDER + '/assets/vendor/**/*'], () => { gulp.start('vendor') })					// Watch for vendor files
	watch([CMD_FOLDER + '/assets/fonts/**/*'], () => { gulp.start('fonts') })					// Watch for fonts
	watch([CMD_FOLDER + '/assets/hbs_helpers/**/*'], () => { gulp.start('hbs_helpers') })		// Watch for local handlebars helpers
	watch([CMD_FOLDER + '/assets/spriteicons/*.png'], () => { gulp.start('sass') })				// Watch for png icons
	watch([CMD_FOLDER + '/assets/fonticons/*.svg'], () => {
		gulp.start('iconfont')
		gulp.enduro_refresh(() => {})
	})			// Watch for font icon
	watch([CMD_FOLDER + '/components/**/*.hbs'], () => { gulp.start('hbs_templates') })			// Watch for hbs templates

	// Watch for enduro changes
	if(!flags.nocmswatch) {
		watch([CMD_FOLDER + '/pages/**/*.hbs', CMD_FOLDER + '/components/**/*.hbs', CMD_FOLDER + '/cms/**/*.js'], function() {
			gulp.enduro_refresh(() => {
				browser_sync.reload()
			})
		})
	}
}

// * ———————————————————————————————————————————————————————— * //
// * 	Sass Task
// *	Processes assets/css/main.scss file
// *	All other scss files need to be imported in main.scss to get compiled
// *	Uses bulkSass for @import subfolder/* funcionality
// * ———————————————————————————————————————————————————————— * //
gulp.task('sass', function() {
	kiska_logger.timestamp('Sass compiling started', 'enduro_events')

	return gulp.src(CMD_FOLDER + '/assets/css/main.scss')
		.pipe(bulkSass())
		.pipe(sourcemaps.init())
		.pipe(sass())
		.on('error', function(err){
			kiska_logger.err_blockStart('Sass error')
			kiska_logger.err(err.message)
			kiska_logger.err_blockEnd()
			this.emit('end')
		})
		.pipe(autoprefixer({
			browsers: ['last 2 versions'],
			cascade: false
		}))
		.pipe(sourcemaps.write())
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/css'))
		.pipe(browser_sync.stream())
		.on('end', () => {
			kiska_logger.timestamp('Sass compiling finished', 'enduro_events')
		})
})

// * ———————————————————————————————————————————————————————— * //
// * 	Scss lint
// * ———————————————————————————————————————————————————————— * //
gulp.task('scss-lint', function() {
	try{
		kiska_logger.timestamp('Sass lint started', 'enduro_events')
		return gulp.src(CMD_FOLDER + '/assets/css/**/*')
			.pipe(checkGem({gemfile: 'scss-lint'}, scsslint(
				{
					'config': __dirname + '/support_files/scss-lint.yml'
				}
			).on('end', () => {
				kiska_logger.timestamp('Sass lint finished', 'enduro_events')
			})))

	}
	catch(err){
		return kiska_logger('No liting. you need to install scss_lint')
	}
})

// * ———————————————————————————————————————————————————————— * //
// * 	js
// *	Todo: require js optimization should go here
// * ———————————————————————————————————————————————————————— * //
gulp.task('js', function() {

	return gulp.src(CMD_FOLDER + '/assets/js/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/js'))

})

// * ———————————————————————————————————————————————————————— * //
// * 	img
// * ———————————————————————————————————————————————————————— * //
gulp.task('img', function() {
	return gulp.src(CMD_FOLDER + '/assets/img/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/img'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	vendor
// * ———————————————————————————————————————————————————————— * //
gulp.task('vendor', function() {
	return gulp.src(CMD_FOLDER + '/assets/vendor/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/vendor'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	fonts
// * ———————————————————————————————————————————————————————— * //
gulp.task('fonts', function() {
	return gulp.src(CMD_FOLDER + '/assets/fonts/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/fonts'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	spriteicons
// *	will get all pngs out of assets/spriteicons folder
// *	and generate spritesheet out of them
// * ———————————————————————————————————————————————————————— * //
gulp.task('png_sprites', function() {
	return gulp.src(CMD_FOLDER + '/assets/spriteicons/*.png')
		.pipe(spritesmith({
			imgName: '_src/assets/spriteicons/spritesheet.png',
			cssName: '_src/_prebuilt/sprites.scss',
			padding: 3,
			cssTemplate: path.join(__dirname, 'support_files', 'sprite_generator.handlebars'),
			retinaSrcFilter: [path.join(CMD_FOLDER, 'assets/spriteicons/*@2x.png')],
			retinaImgName: '_src/assets/spriteicons/spritesheet@2x.png',
		}))
		.pipe(gulp.dest(CMD_FOLDER))
})

// * ———————————————————————————————————————————————————————— * //
// * 	iconfont
// * ———————————————————————————————————————————————————————— * //
gulp.task('iconfont', function(cb){
	return gulp.src([CMD_FOLDER + '/assets/fonticons/*.svg'])
		.pipe(iconfontCss({
			fontName: config.project_slug + '_icons',
			path: 'assets/fonticons/icons_template.scss',
			targetPath: '../../../_src/_prebuilt/icons.scss',
			fontPath: '/assets/iconfont/',
		}))
		.pipe(iconfont({
			fontName: config.project_slug + '_icons',
			prependUnicode: true,
			fontHeight: 1024,
			normalize: true,
			formats: ['ttf', 'eot', 'woff'],
			log: () => {}
		}))
		.on('glyphs', function(glyphs, options) {
			glyphs = glyphs.map(function(glyph){
				glyph.unicode = glyph.unicode[0].charCodeAt(0).toString(16)
				return glyph
			})
			var icon_json_file_path = CMD_FOLDER + '/_src/_prebuilt/icons.json'
			enduro_helpers.ensureDirectoryExistence(icon_json_file_path)
				.then(() => {
					fs.writeFileSync(icon_json_file_path, JSON.stringify(glyphs))
					cb()
				})
		})
		.pipe(gulp.dest('_src/assets/iconfont/'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	JS Handlebars - Not enduro, page-generation related
// * ———————————————————————————————————————————————————————— * //
gulp.task('hbs_templates', function(){
	gulp.src(CMD_FOLDER + '/components/**/*.hbs')
		.pipe(handlebars({
			// Pass local handlebars
			handlebars: __templating_engine
		}))
		.pipe(defineModule('amd'))
		.pipe(flatten())
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/hbs_templates'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	Handlebars helpers
// * ———————————————————————————————————————————————————————— * //
gulp.task('hbs_helpers', function() {
	return gulp.src([CMD_FOLDER + '/assets/hbs_helpers/**/*.js', ENDURO_FOLDER + '/hbs_helpers/**/*.js'])
		.pipe(filterBy(function(file) {
			return file.contents.toString().indexOf('enduro_nojs') == -1
		}))
		.pipe(concat('hbs_helpers.js'))
		.pipe(wrap('define([],function(){ return function(__templating_engine){ \n\n<%= contents %>\n\n }})'))
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/hbs_helpers/'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	Default Task
// * ———————————————————————————————————————————————————————— * //
//gulp.task('default', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync'])
gulp.task('default', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync'])
gulp.task('default_norefresh', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync_norefresh'])

// * ———————————————————————————————————————————————————————— * //
// * 	Preproduction Task
// *	Tasks that need to be done before doing the enduro render
// * ———————————————————————————————————————————————————————— * //
gulp.task('preproduction', ['iconfont', 'png_sprites', pagelist_generator])

// * ———————————————————————————————————————————————————————— * //
// * 	Production Task
// *	No browser_sync, no watching for anything
// * ———————————————————————————————————————————————————————— * //
gulp.task('production', ['sass', 'hbs_templates', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', prettyfier])

// * ———————————————————————————————————————————————————————— * //
// * 	check task
// * ———————————————————————————————————————————————————————— * //
gulp.task('check', [htmlvalidator, prettyfier, 'scss-lint'])

// Export gulp to enable access for enduro
module.exports = gulp<commit_msg>improved climate of gulpfile<commit_after>var gulp = require('gulp')
var watch = require('gulp-watch')
var browser_sync = require('browser-sync').create()
var sass = require('gulp-sass')
var url = require('url')
var fs = require('fs')
var bulkSass = require('gulp-sass-bulk-import')
var kiska_logger = require('./libs/kiska_logger')
var scsslint = require('gulp-scss-lint')
var spritesmith = require('gulp.spritesmith')
var sourcemaps = require('gulp-sourcemaps')
var checkGem = require('gulp-check-gems')
var autoprefixer = require('gulp-autoprefixer')
var iconfont = require('gulp-iconfont')
var iconfontCss = require('gulp-iconfont-css')
var handlebars = require('gulp-handlebars')
var defineModule = require('gulp-define-module')
var flatten = require('gulp-flatten')
var concat = require('gulp-concat')
var filterBy = require('gulp-filter-by')
var wrap = require('gulp-wrap')
var path = require('path')

var enduro_helpers = require(ENDURO_FOLDER + '/libs/flat_utilities/enduro_helpers')

// Gulp tasks
var pagelist_generator = require(ENDURO_FOLDER + '/libs/build_tools/pagelist_generator').init(gulp)
var prettyfier = require(ENDURO_FOLDER + '/libs/build_tools/prettyfier').init(gulp)
var htmlvalidator = require(ENDURO_FOLDER + '/libs/build_tools/html_validator').init(gulp)

gulp.set_refresh = function (callback) {
	gulp.enduro_refresh = callback
}

gulp.enduro_refresh = function () {
	kiska_logger.err('refresh not defined')
}

// * ———————————————————————————————————————————————————————— * //
// * 	browser sync task
// * ———————————————————————————————————————————————————————— * //
gulp.task('browser_sync', ['sass'], function() {
	browsersync_start(false)
})

gulp.task('browser_sync_norefresh', ['sass'], function() {
	browsersync_start(true)
})

gulp.task('browser_sync_stop', [], function() {
	browser_sync.exit()
})

function browsersync_start(norefresh) {
	kiska_logger.timestamp('browsersync started', 'enduro_events')
	browser_sync.init({
		server: {
			baseDir: CMD_FOLDER + '/_src',
			middleware: function(req, res, next) {

				if(req.url.split('/')[1] && config.cultures.indexOf(req.url.split('/')[1]) + 1){
					return next()
				}

				// serve files without html
				if(!(req.url.indexOf('.') + 1) && req.url.length > 3) {
					req.url += '.html'
				}

				// patch to enable development of admin ui in enduro
				static_path_pattern = new RegExp(config.static_path_prefix + '\/(.*)')
				if(static_path_pattern.test(req.url)){
					req.url = '/' + req.url.match(static_path_pattern)[1]
				}

				// server admin/index file on /admin url
				if(req.url == '/admin/'){ req.url = '/admin/index.html' }

				return next()
			},
		},
		ui: false,
		logLevel: 'silent',
		notify: false,
		logPrefix: 'Enduro',
		startPath: START_PATH,
		open: !norefresh
	})
	watch([ CMD_FOLDER + '/assets/css/**/*', CMD_FOLDER + '/assets/fonticons/*', '!' + CMD_FOLDER + '/assets/css/sprites/*'],
				() => { gulp.start('sass') })									// Watch for scss

	if(!flags.nojswatch) {
		watch([CMD_FOLDER + '/assets/js/**/*'], () => { gulp.start('js'); browser_sync.reload() })							// Watch for js
	}

	watch([CMD_FOLDER + '/assets/img/**/*'], () => { gulp.start('img') })						// Watch for images
	watch([CMD_FOLDER + '/assets/vendor/**/*'], () => { gulp.start('vendor') })					// Watch for vendor files
	watch([CMD_FOLDER + '/assets/fonts/**/*'], () => { gulp.start('fonts') })					// Watch for fonts
	watch([CMD_FOLDER + '/assets/hbs_helpers/**/*'], () => { gulp.start('hbs_helpers') })		// Watch for local handlebars helpers
	watch([CMD_FOLDER + '/assets/spriteicons/*.png'], () => { gulp.start('sass') })				// Watch for png icons
	watch([CMD_FOLDER + '/assets/fonticons/*.svg'], () => {
		gulp.start('iconfont')
		gulp.enduro_refresh(() => {})
	})			// Watch for font icon
	watch([CMD_FOLDER + '/components/**/*.hbs'], () => { gulp.start('hbs_templates') })			// Watch for hbs templates

	// Watch for enduro changes
	if(!flags.nocmswatch) {
		watch([CMD_FOLDER + '/pages/**/*.hbs', CMD_FOLDER + '/components/**/*.hbs', CMD_FOLDER + '/cms/**/*.js'], function() {
			gulp.enduro_refresh(() => {
				browser_sync.reload()
			})
		})
	}
}

// * ———————————————————————————————————————————————————————— * //
// * 	Sass Task
// *	Processes assets/css/main.scss file
// *	All other scss files need to be imported in main.scss to get compiled
// *	Uses bulkSass for @import subfolder/* funcionality
// * ———————————————————————————————————————————————————————— * //
gulp.task('sass', function() {
	kiska_logger.timestamp('Sass compiling started', 'enduro_events')

	return gulp.src(CMD_FOLDER + '/assets/css/main.scss')
		.pipe(bulkSass())
		.pipe(sourcemaps.init())
		.pipe(sass())
		.on('error', function(err){
			kiska_logger.err_blockStart('Sass error')
			kiska_logger.err(err.message)
			kiska_logger.err_blockEnd()
			this.emit('end')
		})
		.pipe(autoprefixer({
			browsers: ['last 2 versions'],
			cascade: false,
		}))
		.pipe(sourcemaps.write())
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/css'))
		.pipe(browser_sync.stream())
		.on('end', () => {
			kiska_logger.timestamp('Sass compiling finished', 'enduro_events')
		})
})

// * ———————————————————————————————————————————————————————— * //
// * 	Scss lint
// * ———————————————————————————————————————————————————————— * //
gulp.task('scss-lint', function() {
	try{
		kiska_logger.timestamp('Sass lint started', 'enduro_events')
		return gulp.src(path.join(CMD_FOLDER, '/assets/css/**/*'))
			.pipe(checkGem({gemfile: 'scss-lint'}, scsslint(
				{
					'config': __dirname + '/support_files/scss-lint.yml',
				}
			).on('end', () => {
				kiska_logger.timestamp('Sass lint finished', 'enduro_events')
			})))

	}
	catch(err){
		return kiska_logger('No liting. you need to install scss_lint')
	}
})

// * ———————————————————————————————————————————————————————— * //
// * 	js
// *	Todo: require js optimization should go here
// * ———————————————————————————————————————————————————————— * //
gulp.task('js', function() {

	return gulp.src(CMD_FOLDER + '/assets/js/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/js'))

})

// * ———————————————————————————————————————————————————————— * //
// * 	img
// * ———————————————————————————————————————————————————————— * //
gulp.task('img', function() {
	return gulp.src(CMD_FOLDER + '/assets/img/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/img'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	vendor
// * ———————————————————————————————————————————————————————— * //
gulp.task('vendor', function() {
	return gulp.src(CMD_FOLDER + '/assets/vendor/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/vendor'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	fonts
// * ———————————————————————————————————————————————————————— * //
gulp.task('fonts', function() {
	return gulp.src(CMD_FOLDER + '/assets/fonts/**/*')
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/fonts'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	spriteicons
// *	will get all pngs out of assets/spriteicons folder
// *	and generate spritesheet out of them
// * ———————————————————————————————————————————————————————— * //
gulp.task('png_sprites', function() {
	return gulp.src(CMD_FOLDER + '/assets/spriteicons/*.png')
		.pipe(spritesmith({
			imgName: '_src/assets/spriteicons/spritesheet.png',
			cssName: '_src/_prebuilt/sprites.scss',
			padding: 3,
			cssTemplate: path.join(__dirname, 'support_files', 'sprite_generator.handlebars'),
			retinaSrcFilter: [path.join(CMD_FOLDER, 'assets/spriteicons/*@2x.png')],
			retinaImgName: '_src/assets/spriteicons/spritesheet@2x.png',
		}))
		.pipe(gulp.dest(CMD_FOLDER))
})

// * ———————————————————————————————————————————————————————— * //
// * 	iconfont
// * ———————————————————————————————————————————————————————— * //
gulp.task('iconfont', function(cb){
	return gulp.src([CMD_FOLDER + '/assets/fonticons/*.svg'])
		.pipe(iconfontCss({
			fontName: config.project_slug + '_icons',
			path: 'assets/fonticons/icons_template.scss',
			targetPath: '../../../_src/_prebuilt/icons.scss',
			fontPath: '/assets/iconfont/',
		}))
		.pipe(iconfont({
			fontName: config.project_slug + '_icons',
			prependUnicode: true,
			fontHeight: 1024,
			normalize: true,
			formats: ['ttf', 'eot', 'woff'],
			log: () => {},
		}))
		.on('glyphs', function(glyphs, options) {
			glyphs = glyphs.map(function(glyph){
				glyph.unicode = glyph.unicode[0].charCodeAt(0).toString(16)
				return glyph
			})
			var icon_json_file_path = CMD_FOLDER + '/_src/_prebuilt/icons.json'
			enduro_helpers.ensureDirectoryExistence(icon_json_file_path)
				.then(() => {
					fs.writeFileSync(icon_json_file_path, JSON.stringify(glyphs))
					cb()
				})
		})
		.pipe(gulp.dest('_src/assets/iconfont/'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	JS Handlebars - Not enduro, page-generation related
// * ———————————————————————————————————————————————————————— * //
gulp.task('hbs_templates', function(){
	gulp.src(CMD_FOLDER + '/components/**/*.hbs')
		.pipe(handlebars({
			// Pass local handlebars
			handlebars: __templating_engine,
		}))
		.pipe(defineModule('amd'))
		.pipe(flatten())
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/hbs_templates'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	Handlebars helpers
// * ———————————————————————————————————————————————————————— * //
gulp.task('hbs_helpers', function() {
	return gulp.src([CMD_FOLDER + '/assets/hbs_helpers/**/*.js', ENDURO_FOLDER + '/hbs_helpers/**/*.js'])
		.pipe(filterBy(function(file) {
			return file.contents.toString().indexOf('enduro_nojs') == -1
		}))
		.pipe(concat('hbs_helpers.js'))
		.pipe(wrap('define([],function(){ return function(__templating_engine){ \n\n<%= contents %>\n\n }})'))
		.pipe(gulp.dest(CMD_FOLDER + '/_src/assets/hbs_helpers/'))
})

// * ———————————————————————————————————————————————————————— * //
// * 	Default Task
// * ———————————————————————————————————————————————————————— * //
//gulp.task('default', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync'])
gulp.task('default', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync'])
gulp.task('default_norefresh', ['hbs_templates', 'sass', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', 'browser_sync_norefresh'])

// * ———————————————————————————————————————————————————————— * //
// * 	Preproduction Task
// *	Tasks that need to be done before doing the enduro render
// * ———————————————————————————————————————————————————————— * //
gulp.task('preproduction', ['iconfont', 'png_sprites', pagelist_generator])

// * ———————————————————————————————————————————————————————— * //
// * 	Production Task
// *	No browser_sync, no watching for anything
// * ———————————————————————————————————————————————————————— * //
gulp.task('production', ['sass', 'hbs_templates', 'js', 'img', 'vendor', 'fonts', 'hbs_helpers', prettyfier])

// * ———————————————————————————————————————————————————————— * //
// * 	check task
// * ———————————————————————————————————————————————————————— * //
gulp.task('check', [htmlvalidator, prettyfier, 'scss-lint'])

// Export gulp to enable access for enduro
module.exports = gulp<|endoftext|>


<commit_before>/**
 * @file Gruntfile.js
 * @version 0.0.1
 *
 * @copyright 2014 CoNWeT Lab., Universidad Politécnica de Madrid
 * @license Apache v2 (https://github.com/Wirecloud/room-manager-widget/blob/master/LICENSE)
 */

module.exports = function(grunt) {

  'use strict';

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    banner: ' * @version <%= pkg.version %>\n' +
            ' * \n' +
            ' * @copyright 2014 <%= pkg.author %>\n' +
            ' * @license <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
            ' */',

    concat: {
      options: {
        stripBanners: true
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.js\n<%= banner %>\n\n'
        },
        src: [
          'widget/js/kws-utils.js',
          'widget/js/participant.js',
          'widget/js/room-viewer.js'
        ],
        dest: 'widget/dist/js/<%= pkg.name %>.js'
      }
    },

    uglify: {
      options: {
        preserveComments: false
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.min.js\n<%= banner %>\n'
        },
        src: '<%= concat.dist.dest %>',
        dest: 'widget/dist/js/<%= pkg.name %>.min.js'
      }
    },

    less: {
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.css\n<%= banner %>\n\n'
        },
        src: [
          'widget/less/widget.less'
        ],
        dest: 'widget/dist/css/<%= pkg.name %>.css'
      }
    },

    cssmin: {
      options: {
        keepSpecialComments: 0
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.min.css\n<%= banner %>\n'
        },
        src: '<%= less.dist.dest %>',
        dest: 'widget/dist/css/<%= pkg.name %>.min.css'
      }
    },

    compress: {
      widget: {
        options: {
          archive: '<%= pkg.name %>.zip'
        },
        files: [
          {expand: true, src: ['**/*'], dest: './', cwd: 'widget'}
        ]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-cssmin');

  grunt.loadNpmTasks('grunt-contrib-compress');

  grunt.registerTask('js', ['concat:dist', 'uglify:dist']);
  grunt.registerTask('css', ['less:dist', 'cssmin:dist']);
  grunt.registerTask('zip', ['compress:widget']);

  grunt.registerTask('default', ['js', 'css', 'zip']);

};
<commit_msg>Add kurento-utils.js to Gruntfile<commit_after>/**
 * @file Gruntfile.js
 * @version 0.0.1
 *
 * @copyright 2014 CoNWeT Lab., Universidad Politécnica de Madrid
 * @license Apache v2 (https://github.com/Wirecloud/room-manager-widget/blob/master/LICENSE)
 */

module.exports = function(grunt) {

  'use strict';

  grunt.initConfig({

    pkg: grunt.file.readJSON('package.json'),

    banner: ' * @version <%= pkg.version %>\n' +
            ' * \n' +
            ' * @copyright 2014 <%= pkg.author %>\n' +
            ' * @license <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
            ' */',

    concat: {
      options: {
        stripBanners: true
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.js\n<%= banner %>\n\n'
        },
        src: [
          'widget/js/kurento-utils.js',
          'widget/js/participant.js',
          'widget/js/room-viewer.js'
        ],
        dest: 'widget/dist/js/<%= pkg.name %>.js'
      }
    },

    uglify: {
      options: {
        preserveComments: false
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.min.js\n<%= banner %>\n'
        },
        src: '<%= concat.dist.dest %>',
        dest: 'widget/dist/js/<%= pkg.name %>.min.js'
      }
    },

    less: {
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.css\n<%= banner %>\n\n'
        },
        src: [
          'widget/less/widget.less'
        ],
        dest: 'widget/dist/css/<%= pkg.name %>.css'
      }
    },

    cssmin: {
      options: {
        keepSpecialComments: 0
      },
      dist: {
        options: {
          banner: '/*!\n * @file <%= pkg.name %>.min.css\n<%= banner %>\n'
        },
        src: '<%= less.dist.dest %>',
        dest: 'widget/dist/css/<%= pkg.name %>.min.css'
      }
    },

    compress: {
      widget: {
        options: {
          archive: '<%= pkg.name %>.zip'
        },
        files: [
          {expand: true, src: ['**/*'], dest: './', cwd: 'widget'}
        ]
      }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-cssmin');

  grunt.loadNpmTasks('grunt-contrib-compress');

  grunt.registerTask('js', ['concat:dist', 'uglify:dist']);
  grunt.registerTask('css', ['less:dist', 'cssmin:dist']);
  grunt.registerTask('zip', ['compress:widget']);

  grunt.registerTask('default', ['js', 'css', 'zip']);

};
<|endoftext|>


<commit_before>import React from 'react'

import { connect } from 'react-redux'

import { Limit, Offset } from '../api'

import { setPage } from './actions/Search'

const pageNumbers = (page, totalPages) => {
  const pages = []

  let i = 2
  while (i >= 0) {
    if (page - i > 0) {
      pages.push(page-i)
    }
    i--
  }

  i = 1
  while (pages.length < 5 && page + i <= totalPages) {
    pages.push(page+i)
    i++
  }

  i = 3
  while (pages.length < 5 && page - i > 0) {
    pages.shift(page-i)
    i++
  }
  return pages
}

const Paginator = ({ resultsPerPage, page, totalResults, setPage }) => {
  if (totalResults <= resultsPerPage) {
    return null
  }

  const totalPages = Math.ceil(totalResults/resultsPerPage)
  if (totalPages === 0) {
    return null
  }

  const pages = pageNumbers(page, totalPages).map(p => (<Page key={p} page={p}>{p}</Page>))

  const prevPage = () => {
    if (page === 1) {
      return
    }
    setPage(page-1)
  }

  const nextPage = () => {
    if (page === totalPages) {
      return
    }
    setPage(page+1)
  }

  return (

<

      {pages}

>

  )
}

Paginator.propTypes = {
  resultsPerPage: React.PropTypes.number.isRequired,
  page: React.PropTypes.number.isRequired,
  totalResults: React.PropTypes.number.isRequired
}

const WrappedPaginator = connect(
  (state, props) => {
    const queryStatus = state.query.queryStatus[props.namespace]
    let totalResults = 0
    if (queryStatus && queryStatus.data) {
      totalResults = parseInt(queryStatus.data.searchResponse.totalResults, 10)
    }
    return {
      page: state.search.page,
      resultsPerPage: state.search.resultsPerPage,
      totalResults
    }
  },
  (dispatch) => ({ setPage: (page) => {
    dispatch(setPage(page))
    document.getElementById('sj-overlay').scrollTop = 0
  } })
)(Paginator)

WrappedPaginator.defaultProps = {
  namespace: 'default'
}

const pageLimitOffset = ({ page, resultsPerPage, ...others }) => (

    <Limit limit={resultsPerPage} { ...others } />
    <Offset offset={(page - 1) * resultsPerPage} runOnUpdate={true} { ...others} />

)

pageLimitOffset.propTypes = {
  page: React.PropTypes.number,
  resultsPerPage: React.PropTypes.number
}

pageLimitOffset.defaultProps = {
  page: 1,
  resultsPerPage: 10
}

/* PageLimitOffset renders Limit and Offset api-components which correspond
 * to the current page and resultsPerPage */
const PageLimitOffset = connect(
  ({ search }) => ({ page: search.page, resultsPerPage: search.resultsPerPage }),
)(pageLimitOffset)

const page = ({ currentPage, page, setPage, children }) => (

 setPage(page)}>{ children }

)

/* Page is a component which renders a component which can set the page */
const Page = connect(
  ({ search }) => ({ currentPage: search.page }),
  dispatch => ({ setPage: (page) => {
    dispatch(setPage(page))
    document.getElementById('sj-overlay').scrollTop = 0
  } })
)(page)

export { PageLimitOffset, WrappedPaginator, Paginator }
<commit_msg>ui: Fixed paginator rendering on last pages.<commit_after>import React from 'react'

import { connect } from 'react-redux'

import { Limit, Offset } from '../api'

import { setPage } from './actions/Search'

const pageNumbers = (page, totalPages) => {
  const pages = []

  let i = 2
  while (i >= 0) {
    if (page - i > 0) {
      pages.push(page-i)
    }
    i--
  }

  i = 1
  while (pages.length < 5 && page + i <= totalPages) {
    pages.push(page+i)
    i++
  }

  i = 3
  while (pages.length < 5 && page - i > 0) {
    pages.unshift(page-i)
    i++
  }
  return pages
}

const Paginator = ({ resultsPerPage, page, totalResults, setPage }) => {
  if (totalResults <= resultsPerPage) {
    return null
  }

  const totalPages = Math.ceil(totalResults/resultsPerPage)
  if (totalPages === 0) {
    return null
  }

  const pages = pageNumbers(page, totalPages).map(p => (<Page key={p} page={p}>{p}</Page>))

  const prevPage = () => {
    if (page === 1) {
      return
    }
    setPage(page-1)
  }

  const nextPage = () => {
    if (page === totalPages) {
      return
    }
    setPage(page+1)
  }

  return (

<

      {pages}

>

  )
}

Paginator.propTypes = {
  resultsPerPage: React.PropTypes.number.isRequired,
  page: React.PropTypes.number.isRequired,
  totalResults: React.PropTypes.number.isRequired
}

const WrappedPaginator = connect(
  (state, props) => {
    const queryStatus = state.query.queryStatus[props.namespace]
    let totalResults = 0
    if (queryStatus && queryStatus.data) {
      totalResults = parseInt(queryStatus.data.searchResponse.totalResults, 10)
    }
    return {
      page: state.search.page,
      resultsPerPage: state.search.resultsPerPage,
      totalResults
    }
  },
  (dispatch) => ({ setPage: (page) => {
    dispatch(setPage(page))
    document.getElementById('sj-overlay').scrollTop = 0
  } })
)(Paginator)

WrappedPaginator.defaultProps = {
  namespace: 'default'
}

const pageLimitOffset = ({ page, resultsPerPage, ...others }) => (

    <Limit limit={resultsPerPage} { ...others } />
    <Offset offset={(page - 1) * resultsPerPage} runOnUpdate={true} { ...others} />

)

pageLimitOffset.propTypes = {
  page: React.PropTypes.number,
  resultsPerPage: React.PropTypes.number
}

pageLimitOffset.defaultProps = {
  page: 1,
  resultsPerPage: 10
}

/* PageLimitOffset renders Limit and Offset api-components which correspond
 * to the current page and resultsPerPage */
const PageLimitOffset = connect(
  ({ search }) => ({ page: search.page, resultsPerPage: search.resultsPerPage }),
)(pageLimitOffset)

const page = ({ currentPage, page, setPage, children }) => (

 setPage(page)}>{ children }

)

/* Page is a component which renders a component which can set the page */
const Page = connect(
  ({ search }) => ({ currentPage: search.page }),
  dispatch => ({ setPage: (page) => {
    dispatch(setPage(page))
    document.getElementById('sj-overlay').scrollTop = 0
  } })
)(page)

export { PageLimitOffset, WrappedPaginator, Paginator }
<|endoftext|>