<commit_before>var RequestHandler = require('includes/callurl');
var Ui = require('includes/ui');
var Utils = require('includes/utils');

Ti.include('/includes/lib/json.i18n.js');

var win = Ti.UI.currentWindow;

var labelsTNT = ['TF1', 'France 2', 'France 3', 'Canal+', 'France 5', 'M6', 'Arte', 'D8', 'W9', 'TMC', 'NT1', 'NRJ12', 'LCP', 'France 4', 'BFM TV', 'i>TELE', 'D17', 'Gulli', 'France Ô', 'HD1', 'L\'Equipe 21', '6ter', 'Numéro 23', 'RMC Découverte', 'Chérie 25'];
var labelsFree = ['RTL9', 'Vivolta', 'AB1', 'Disney Channel', 'NRJ Hits', 'Clubbing TV', 'O Five', 'BeBlack', 'TV5 Monde', 'BFM Business', 'Euronews', 'Bloomberg', 'Al Jazeera', 'Sky News', 'Guysen TV', 'CNBC', 'MCE', 'France 24', 'Game One', 'Game One Music', 'Lucky Jack', 'Men\'s up', 'Nolife', 'Fashion TV', 'World Fashion', 'Allocine', 'Equidia Live', 'Equidia Life', 'AB Moteurs', 'Poker Channel', 'Liberty TV', 'Montagne TV', 'Luxe.TV', 'Demain TV', 'KTO', 'Wild Earth', 'TNA', 'Souvenirs from Earth', 'Penthouse', 'M6 Boutique', 'Best of Shopping', 'Renault TV', 'Astro Center', 'Radio'];
var labelsCanal = ['Canal+', 'C+ Cinéma', 'C+ Sport', 'C+ Décalé', 'C+ Family'];

var loadingWin = Ui.createLoadingWindow();

win.addEventListener('focus', updateProps);

var tabbedBar = Ti.UI.iOS.createTabbedBar({
	labels: [I('profile.1'), I('profile.2'), I('profile.3')],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	height: 30,
	width: 300,
	backgroundColor: '#787878'
});

tabbedBar.addEventListener('click', function(e) {
	Ti.App.Properties.setInt('profileToUse', e.index + 1);
	updateProps();
});

var dashboardTabs = Ti.UI.iOS.createTabbedBar({
	labels: ['TNT', 'Bouquet Free', 'Bouquet Canal'],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	height: 30,
	width: 300,
	backgroundColor: '#787878',
	index: 0
});

win.setToolbar([Ui.createFlexibleSpace(), dashboardTabs, Ui.createFlexibleSpace()], {
	animated: false
});

win.setTitleControl(tabbedBar);

//we're loading things
loadingWin.open();

//get all three dashboards, one is visible, the others are not
var dashboards = [getDashboard(labelsTNT, true), getDashboard(labelsFree, false), getDashboard(labelsCanal, false)];

//add all of them to the window
for(var i = 0; i < dashboards.length; i++) {
	win.add(dashboards[i]);
}

//stop loading
loadingWin.close();

//if we want to switch to another dashboard
dashboardTabs.addEventListener('click', function(e) {
	//if we actually clicked on a button
	if(e.index != null) {
		for(var i = 0; i < dashboards.length; i++) {
			if(i != e.index) {
				//hide all the ones we don't want to display
				dashboards[i].hide();
			}
		}

		//set the opacity of the one we want to display to 0, and then fade in
		dashboards[e.index].setOpacity(0);
		dashboards[e.index].show();
		dashboards[e.index].animate({
			opacity: 1,
			duration: 400,
			curve: Ti.UI.ANIMATION_CURVE_EASE_OUT
		});
	}
});

//get a single dashboarditem
function getItem(label) {
	var img_icon = Ti.UI.createButton({
		//image: '/img/dashboard.png',
		style: Ti.UI.iPhone.SystemButtonStyle.PLAIN,
		backgroundColor: '#c7c7c7',
		borderColor: '#c8c8c8',
		borderRadius: 43,
		height: 85,
		width: 85
	});

	var img_logo = Ti.UI.createImageView({
		image: '/img/logo/' + Utils.getChannelID(label) + '.png',
		defaultImage: '/img/default_epg.png',
		height: Ti.UI.SIZE,
		width: 55
	});

	img_icon.add(img_logo);

	var item = Ti.UI.createDashboardItem({
		canDelete: false,
		image: img_icon.toImage(null, true),
		channel: Utils.getChannelID(label),
		height: 90,
		width: 90
	});

	return item;
}

//get a single dashboard with an array of labels to display as items
function getDashboard(labels, visible) {
	var dashboard = Ti.UI.createDashboardView({
		editable: false,
		top: 0,
		height: (Ti.Platform.displayCaps.platformHeight < 568) ? 350 : 430,
		rowCount: (Ti.Platform.displayCaps.platformHeight < 568) ? 3 : 4,
		visible: visible
	});

	var data = [];

	//iterate through the labels and add corresponding items to the dashboard
	for(var i = 0; i < labels.length; i++) {
		data.push(getItem(labels[i]));
	}

	dashboard.setData(data);

	//when we click, this should happen
	dashboard.addEventListener('click', function(e) {
		if(e.item !== null) {
			RequestHandler.callMultiKeys(e.item.channel.toString());
		}
	});

	return dashboard;
}

//get properties
function updateProps() {
	RequestHandler.setProfile(Ti.App.Properties.getInt('profileToUse', Profile.PROFILE_1));
	RequestHandler.setHd(Ti.App.Properties.getInt('profile' + RequestHandler.getProfile() + '.hd', HD.HD_1));
	RequestHandler.setCode(Ti.App.Properties.getString('profile' + RequestHandler.getProfile() + '.code', ''));

	tabbedBar.setIndex(RequestHandler.getProfile() - 1);
}<commit_msg>Fix mosaic placement<commit_after>var RequestHandler = require('includes/callurl');
var Ui = require('includes/ui');
var Utils = require('includes/utils');

Ti.include('/includes/lib/json.i18n.js');

var win = Ti.UI.currentWindow;

var labelsTNT = ['TF1', 'France 2', 'France 3', 'Canal+', 'France 5', 'M6', 'Arte', 'D8', 'W9', 'TMC', 'NT1', 'NRJ12', 'LCP', 'France 4', 'BFM TV', 'i>TELE', 'D17', 'Gulli', 'France Ô', 'HD1', 'L\'Equipe 21', '6ter', 'Numéro 23', 'RMC Découverte', 'Chérie 25'];
var labelsFree = ['RTL9', 'Vivolta', 'AB1', 'Disney Channel', 'NRJ Hits', 'Clubbing TV', 'O Five', 'BeBlack', 'TV5 Monde', 'BFM Business', 'Euronews', 'Bloomberg', 'Al Jazeera', 'Sky News', 'Guysen TV', 'CNBC', 'MCE', 'France 24', 'Game One', 'Game One Music', 'Lucky Jack', 'Men\'s up', 'Nolife', 'Fashion TV', 'World Fashion', 'Allocine', 'Equidia Live', 'Equidia Life', 'AB Moteurs', 'Poker Channel', 'Liberty TV', 'Montagne TV', 'Luxe.TV', 'Demain TV', 'KTO', 'Wild Earth', 'TNA', 'Souvenirs from Earth', 'Penthouse', 'M6 Boutique', 'Best of Shopping', 'Renault TV', 'Astro Center', 'Radio'];
var labelsCanal = ['Canal+', 'C+ Cinéma', 'C+ Sport', 'C+ Décalé', 'C+ Family'];

var loadingWin = Ui.createLoadingWindow();

win.addEventListener('focus', updateProps);

var tabbedBar = Ti.UI.iOS.createTabbedBar({
	labels: [I('profile.1'), I('profile.2'), I('profile.3')],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	height: 30,
	width: 300,
	backgroundColor: Ui.getBarColor()
});

tabbedBar.addEventListener('click', function(e) {
	Ti.App.Properties.setInt('profileToUse', e.index + 1);
	updateProps();
});

var dashboardTabs = Ti.UI.iOS.createTabbedBar({
	labels: ['TNT', 'Bouquet Free', 'Bouquet Canal'],
	style: Ti.UI.iPhone.SystemButtonStyle.BAR,
	height: 30,
	width: 300,
	backgroundColor: Ui.getBarColor(),
	index: 0
});

win.setToolbar([Ui.createFlexibleSpace(), dashboardTabs, Ui.createFlexibleSpace()], {
	animated: false
});

win.setTitleControl(tabbedBar);

//we're loading things
loadingWin.open();

//get all three dashboards, one is visible, the others are not
var dashboards = [getDashboard(labelsTNT, true), getDashboard(labelsFree, false), getDashboard(labelsCanal, false)];

//add all of them to the window
for(var i = 0; i < dashboards.length; i++) {
	win.add(dashboards[i]);
}

//stop loading
loadingWin.close();

//if we want to switch to another dashboard
dashboardTabs.addEventListener('click', function(e) {
	//if we actually clicked on a button
	if(e.index != null) {
		for(var i = 0; i < dashboards.length; i++) {
			if(i != e.index) {
				//hide all the ones we don't want to display
				dashboards[i].hide();
			}
		}

		//set the opacity of the one we want to display to 0, and then fade in
		dashboards[e.index].setOpacity(0);
		dashboards[e.index].show();
		dashboards[e.index].animate({
			opacity: 1,
			duration: 400,
			curve: Ti.UI.ANIMATION_CURVE_EASE_OUT
		});
	}
});

//get a single dashboarditem
function getItem(label) {
	var img_icon = Ti.UI.createButton({
		style: Ti.UI.iPhone.SystemButtonStyle.PLAIN,
		backgroundColor: '#c5c5c5',
		borderColor: '#c1c1c1',
		borderRadius: 43,
		height: 85,
		width: 85
	});

	var img_logo = Ti.UI.createImageView({
		image: '/img/logo/' + Utils.getChannelID(label) + '.png',
		defaultImage: '/img/default_epg.png',
		height: Ti.UI.SIZE,
		width: 55
	});

	img_icon.add(img_logo);

	var item = Ti.UI.createDashboardItem({
		canDelete: false,
		image: img_icon.toImage(null, true),
		channel: Utils.getChannelID(label),
		height: 90,
		width: 90
	});

	return item;
}

//get a single dashboard with an array of labels to display as items
function getDashboard(labels, visible) {
	var dashboard = Ti.UI.createDashboardView({
		editable: false,
		height: (Ti.Platform.displayCaps.platformHeight < 568) ? 350 : 430,
		rowCount: (Ti.Platform.displayCaps.platformHeight < 568) ? 3 : 4,
		top: 5,
		visible: visible
	});

	var data = [];

	//iterate through the labels and add corresponding items to the dashboard
	for(var i = 0; i < labels.length; i++) {
		data.push(getItem(labels[i]));
	}

	dashboard.setData(data);

	//when we click, this should happen
	dashboard.addEventListener('click', function(e) {
		if(e.item !== null) {
			RequestHandler.callMultiKeys(e.item.channel.toString());
		}
	});

	return dashboard;
}

//get properties
function updateProps() {
	RequestHandler.setProfile(Ti.App.Properties.getInt('profileToUse', Profile.PROFILE_1));
	RequestHandler.setHd(Ti.App.Properties.getInt('profile' + RequestHandler.getProfile() + '.hd', HD.HD_1));
	RequestHandler.setCode(Ti.App.Properties.getString('profile' + RequestHandler.getProfile() + '.code', ''));

	tabbedBar.setIndex(RequestHandler.getProfile() - 1);
}<|endoftext|>


<commit_before>define([
    'underscore',
    'knockout',
    'views/project-manager/identity-list',
    'models/project'
], function(_, ko, IdentityList, ProjectModel) {
    /**
    * A base viewmodel for project management
    *
    * @constructor
    * @name ProjectManagerViewModel
    *
    * @param  {string} params - a configuration object
    */
    var ProjectManagerViewModel = function(params) {

        var self = this;

        this.identityList = new IdentityList({
            items: ko.observableArray(params.identities)
        });
        this.projects = ko.observableArray(
            params.projects.map(function (project) {
                return new ProjectModel({
                    source: project,
                    identities: params.identities
                });
            })
        );
        this.projectFilter = ko.observable('');
        this.filteredProjects = ko.computed(function () {
            var filter = self.projectFilter();
            var list = self.projects();
            if (filter.length === 0) {
                return list;
            }
            return _.filter(list, function(project) {
                return project.name().toLowerCase().indexOf(filter.toLowerCase()) >= 0;
            });
        });

        this.loading = ko.observable(false);
        this.selectedProject = ko.observable(null);

        this.selectedProject.subscribe(function(val){
            self.identityList.items(val.identities)
            self.identityList.clearSelection();
            self.identityList.items()[0].selected(true);
            if (val) {val.update();}
        });

    };
    return ProjectManagerViewModel;
});
<commit_msg>Removed update of items in list. The project model updates the properties of this list. re #2581<commit_after>define([
    'underscore',
    'knockout',
    'views/project-manager/identity-list',
    'models/project'
], function(_, ko, IdentityList, ProjectModel) {
    /**
    * A base viewmodel for project management
    *
    * @constructor
    * @name ProjectManagerViewModel
    *
    * @param  {string} params - a configuration object
    */
    var ProjectManagerViewModel = function(params) {

        var self = this;

        this.identityList = new IdentityList({
            items: ko.observableArray(params.identities)
        });
        this.projects = ko.observableArray(
            params.projects.map(function (project) {
                return new ProjectModel({
                    source: project,
                    identities: params.identities
                });
            })
        );
        this.projectFilter = ko.observable('');
        this.filteredProjects = ko.computed(function () {
            var filter = self.projectFilter();
            var list = self.projects();
            if (filter.length === 0) {
                return list;
            }
            return _.filter(list, function(project) {
                return project.name().toLowerCase().indexOf(filter.toLowerCase()) >= 0;
            });
        });

        this.loading = ko.observable(false);
        this.selectedProject = ko.observable(null);

        this.selectedProject.subscribe(function(val){
            self.identityList.clearSelection();
            self.identityList.items()[0].selected(true);
            if (val) {val.update();}
        });

    };
    return ProjectManagerViewModel;
});
<|endoftext|>


<commit_before>'use strict'

const TelegramBot = require('node-telegram-bot-api');

const config = require('../config');
const utils = require('./utils');
const Kinospartak = require('./Kinospartak/Kinospartak');

const bot = new TelegramBot(config.TOKEN);

const kinospartak = new Kinospartak();

/**
 * updateSchedule - update schedule and push updates to Telegram channel
 *
 * @return {Promise}
 */
function updateSchedule() {
  return kinospartak.getChanges()
    .then(changes =>
      changes.length
        ? utils.formatSchedule(changes)
        : undefined)
    .then(messages =>
      messages
        ? utils.sendInOrder(bot, config.CHANNEL, messages)
        : undefined)
    .then(() => kinospartak.commitChanges())
};

/**
 * updateNews - update news and push updates to Telegram channel
 *
 * @return {Promise}
 */
function updateNews() {
  return kinospartak.getLatestNews()
    .then(news =>
      news.length
        ? utils.formatNews(news)
        : undefined)
    .then(messages =>
      messages
        ? utils.sendInOrder(bot, config.CHANNEL, messages)
        : undefined)
    .then(() => kinospartak.setNewsOffset(new Date().toString()))
};

function update() {
  return Promise.all([
    updateSchedule,
    updateNews
  ]).catch((err) => {
    setTimeout(() => {
        update();
      }, 60 * 5);
  })
}

update();<commit_msg>Change channel update retry timeout<commit_after>'use strict'

const TelegramBot = require('node-telegram-bot-api');

const config = require('../config');
const utils = require('./utils');
const Kinospartak = require('./Kinospartak/Kinospartak');

const bot = new TelegramBot(config.TOKEN);

const kinospartak = new Kinospartak();

/**
 * updateSchedule - update schedule and push updates to Telegram channel
 *
 * @return {Promise}
 */
function updateSchedule() {
  return kinospartak.getChanges()
    .then(changes =>
      changes.length
        ? utils.formatSchedule(changes)
        : undefined)
    .then(messages =>
      messages
        ? utils.sendInOrder(bot, config.CHANNEL, messages)
        : undefined)
    .then(() => kinospartak.commitChanges())
};

/**
 * updateNews - update news and push updates to Telegram channel
 *
 * @return {Promise}
 */
function updateNews() {
  return kinospartak.getLatestNews()
    .then(news =>
      news.length
        ? utils.formatNews(news)
        : undefined)
    .then(messages =>
      messages
        ? utils.sendInOrder(bot, config.CHANNEL, messages)
        : undefined)
    .then(() => kinospartak.setNewsOffset(new Date().toString()))
};

function update() {
  return Promise.all([
    updateSchedule,
    updateNews
  ]).catch((err) => {
    setTimeout(() => {
        update();
    }, 1000 * 60 * 5);
  })
}

update();<|endoftext|>


<commit_before>var dot_product_project2d = (function() {

var origin = [150, 140],
  scale = 60,
  scatter = [],
  axis = [],
  expectedAxis = [],
  startAngleX = Math.PI,
  startAngleY = 0.,
  startAngleZ = 0.
  axis_len = 2;

let unit = axis_len/10;

var svg = d3.select("#svg_dot_product_project2d");

var lib = space_plot_lib(
  svg,
  origin,
  scale,
  is_2d=true);

svg = svg.call(d3.drag()
         .on('drag', dragged)
         .on('start', drag_start)
         .on('end', drag_end))
         .append('g');

axis = lib.init_float_axis(axis_len=axis_len, unit=unit);

function plot(scatter, axis, tt){

  basis = {
      ex: axis[4][1],
      ey: axis[14][1],
      // ex: axis[axis_len/unit*4 * 0][1],
      // ey: axis[axis_len/unit*14 * 1][1],
      ez: 0.
  };

  scatter.forEach(function(d, i){
    var coord = lib.dot_basis(d, basis);
    if (i == 0) {
      d.text = 'u = ';
    } else {
      d.text = 'v = ';
    }
    d.text += '['.concat(
      coord.x.toFixed(2),
      ', ',
      coord.y.toFixed(2),
      ']');

    d.text_color = d.color;

  })

  lib.plot_lines(axis);

  var lines = [];
  scatter.forEach(function(d){
    lines.push([
        {x: 0., y: 0., z: 0.},
        {x: d.x, y: d.y, z: d.z,
         color: d.color, tt: true}
    ]);
  });

  let mult_vec = scatter[0].x * scatter[1].x +
                 scatter[0].y * scatter[1].y;
  let projectionx = scatter[1].x * mult_vec;
  let projectiony = scatter[1].y * mult_vec;

  lines.push([
    {x: 0, y: 0, z: 0},
    {x: projectionx, y: projectiony, z: 0,
     color: 0, tt:true}
    ]);
  lines[2].text = 'u\u1d40v = '.concat(mult_vec.toFixed(3));
  lines[2].text_color = lines[2].color;
  lines[2].font_size = 15;

  lines.push([
    {x: scatter[0].x, y: scatter[0].y, z: scatter[0].z},
    {x: projectionx, y: projectiony, z: 0,
     tt:true}
    ]);

  lines[3].dash = true;

  lib.plot_lines(lines, tt, 'arrow');
  lib.plot_points(scatter, tt,
                    drag_point_fn=function(d, i){
                      if (i == 0) {
                        dragged_point(i);
                      } else {
                        dragged_point_only();
                      }
                    },
                    drag_start_fn=drag_start,
                    drag_end_fn=drag_end);
  lib.sort();
}

function init(){
  scatter = [];

  scatter.push({
    x: -1.0,
    y: -4.0/3,
    z: 0.,
    color: 4,
  });

  scatter.push({
    x: 1/Math.sqrt(3),
    y: -Math.sqrt(2/3),
    z: 0.,
    color: 2,
  })

  alpha = startAngleX;
  beta = startAngleY;

  expectedScatter = lib.rotate_points(scatter, alpha, beta, startAngleZ);
  expectedAxis = lib.rotate_lines(axis, alpha, beta, startAngleZ);
  plot(expectedScatter,
       expectedAxis,
       1000);
  drag_end();
}

function drag_start(){
  lib.drag_start2d();
}

function dragged(){
  angle_z = lib.get_drag_angle_2d();

  expectedScatter = lib.rotate_points(scatter, 0, 0, angle_z);
  expectedAxis = lib.rotate_lines(axis, 0, 0, angle_z);

  plot(expectedScatter,
       expectedAxis,
       0);
}

function dragged_point_only(){
  angle_z = lib.get_drag_angle_2d();

  expectedScatter = lib.rotate_points(scatter, 0, 0, angle_z);
  // expectedAxis = lib.rotate_lines(axis, 0, 0, angle_z);

  plot(expectedScatter,
       expectedAxis,
       0);
}

function dragged_point(i){
  expectedScatter = [];
  scatter.forEach(function(d, j){
      if (j == i) {
        expectedScatter.push(
            lib.update_point_position_from_mouse(d));
      } else {
        expectedScatter.push(d);
      }
  });

  plot(expectedScatter,
       expectedAxis,
       0);
}

function drag_end(){
  scatter = expectedScatter;
  axis = expectedAxis;
  startAngleX = 0;
  startAngleY = 0;
  startAngleZ = 0;
}

init();

return {
  init: function(){init();}
};

})();<commit_msg>Update dot_product_project2d.js<commit_after>var dot_product_project2d = (function() {

var origin = [150, 140],
  scale = 60,
  scatter = [],
  axis = [],
  expectedAxis = [],
  startAngleX = Math.PI,
  startAngleY = 0.,
  startAngleZ = 0.
  axis_len = 2;

let unit = axis_len/10;

var svg = d3.select("#svg_dot_product_project2d");

var lib = space_plot_lib(
  svg,
  origin,
  scale,
  is_2d=true);

svg = svg.call(d3.drag()
         .on('drag', dragged)
         .on('start', drag_start)
         .on('end', drag_end))
         .append('g');

axis = lib.init_float_axis(axis_len=axis_len, unit=unit);

function plot(scatter, axis, tt){

  basis = {
      ex: axis[1/unit - 1 + axis_len * 0][1],
      ey: axis[1/unit - 1 + axis_len * 1][1],
      ez: {x: 0, y: 0, z: 0}, // dummy
  };

  scatter.forEach(function(d, i){
    var coord = lib.dot_basis(d, basis);
    if (i == 0) {
      d.text = 'u = ';
    } else {
      d.text = 'v = ';
    }
    d.text += '['.concat(
      coord.x.toFixed(2),
      ', ',
      coord.y.toFixed(2),
      ']');

    d.text_color = d.color;

  })

  lib.plot_lines(axis);

  var lines = [];
  scatter.forEach(function(d,i){
    lines.push([
        {x: 0., y: 0., z: 0.},
        {x: d.x, y: d.y, z: d.z,
         color: d.color, tt: true}
    ]);
    if (i == 0) {
      lines.centroid_z = 900;
    }
  });

  let dot_product = scatter[0].x * scatter[1].x +
                 scatter[0].y * scatter[1].y;
  let projectionx = scatter[1].x * dot_product;
  let projectiony = scatter[1].y * dot_product;

  let projection_line = [
      {x: 0, y: 0, z: 0},
      {x: projectionx, y: projectiony, z: 0,
       color: 0, tt:true}
  ];

  projection_line.text = 'u\u1d40v = '.concat(dot_product.toFixed(3));
  projection_line.text_color = 0;
  projection_line.font_size = 15;

  lines.push(projection_line);

  let dash_line = [
      {x: scatter[0].x, y: scatter[0].y, z: scatter[0].z},
      {x: projectionx, y: projectiony, z: 0,
       tt:true}];

  dash_line.dash = true;
  dash_line.centroid_z = -5;
  lines.push(dash_line);

  lib.plot_lines(lines, tt, 'arrow');
  lib.plot_points(scatter, tt,
                    drag_point_fn=function(d, i){
                      if (i == 0) {
                        dragged_point(i);
                      } else {
                        dragged_point_only();
                      }
                    },
                    drag_start_fn=drag_start,
                    drag_end_fn=drag_end);
  lib.sort();
}

function init(){
  scatter = [];

  scatter.push({
    x: -1.0,
    y: -4.0/3,
    z: 0.,
    color: 4,
  });

  scatter.push({
    x: 1/Math.sqrt(3),
    y: -Math.sqrt(2/3),
    z: 0.,
    color: 2,
  })

  alpha = startAngleX;
  beta = startAngleY;

  expectedScatter = lib.rotate_points(scatter, alpha, beta, startAngleZ);
  expectedAxis = lib.rotate_lines(axis, alpha, beta, startAngleZ);
  plot(expectedScatter,
       expectedAxis,
       1000);
  drag_end();
}

function drag_start(){
  lib.drag_start2d();
}

function dragged(){
  angle_z = lib.get_drag_angle_2d();

  expectedScatter = lib.rotate_points(scatter, 0, 0, angle_z);
  expectedAxis = lib.rotate_lines(axis, 0, 0, angle_z);

  plot(expectedScatter,
       expectedAxis,
       0);
}

function dragged_point_only(){
  angle_z = lib.get_drag_angle_2d();

  expectedScatter = lib.rotate_points(scatter, 0, 0, angle_z);

  plot(expectedScatter,
       expectedAxis,
       0);
}

function dragged_point(i){
  expectedScatter = [];
  scatter.forEach(function(d, j){
      if (j == i) {
        expectedScatter.push(
            lib.update_point_position_from_mouse(d));
      } else {
        expectedScatter.push(d);
      }
  });

  plot(expectedScatter,
       expectedAxis,
       0);
}

function drag_end(){
  scatter = expectedScatter;
  axis = expectedAxis;
  startAngleX = 0;
  startAngleY = 0;
  startAngleZ = 0;
}

init();

return {
  init: function(){init();}
};

})();<|endoftext|>


<commit_before>(function(){

	//Sorts objects in array by fields
	var SORT_ASC = 0,
	SORT_DESC = 1,
	SORT_UNKNOWN_VALUE = "}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}",
	_sortGetValue = function(val,field){
		if(typeof val == "object") {
			if(val == null) {
				return SORT_UNKNOWN_VALUE;
			} else if(typeof field == "undefined") {
				return JSON.stringify(val);
			} else if(val[field] || val.hasOwnProperty(field)) {
				return _sortGetValue(val[field]);
			} else {
				return JSON.stringify(val);
			}
		} else if(typeof val == "array") {
			return JSON.stringify(val);
		} else if(typeof val == "undefined") {
			return SORT_UNKNOWN_VALUE;
		}

		return val.toString();
	},
	_sort = function(o1,o2,order,field){
		var v1 = _sortGetValue(o1,field), v2 = _sortGetValue(o2,field);
		if(v1 > v2) {
			return order == SORT_ASC ? +1 : -1;
		} else if(v1 < v2) {
			return order == SORT_DESC ? +1 : -1;
		} else {
			return 0;
		}
	};

	Array.prototype.sortBy = function(fields, order){
		//Check
		if(typeof fields == "string") {
			fields = [fields];
		} else {
			fields = [];
		}
		if(typeof order == "undefined") {
			order = SORT_ASC;
		}

		//Actual sorting
		return this.sort(function(a,b) {
			var argId = 0, r = 0;
			while(argId < fields.length && r == 0) {
				r = _sort(a,b,order,fields[argId]);
				if(r == 0) {
					argId++;
				} else {
					return r;
				}
			}
			return _sort(a,b,order);
		});
	};

	//Removes fields in objects inside of array
	var DEEP_NONE = 0,
	DEEP_ARRAY = 1,
	DEEP_ARRAY_AND_OBJECT = 2,
	_cleanMatch = function(val, params) {
		var found = false;
		//Match
		if(params.fieldsMatch.indexOf(val) > -1) {
			return true;
		}

		//Starts with
		params.fieldsStarts.forEach(function(field){
			if(val.indexOf(field) == 0) {
				found = true;
				return;
			}
		});
		if(found) { return true; }

		//Ends with
		params.fieldsEnds.forEach(function(field){
			if(val.lastIndexOf(field) == val.length-field.length) {
				found = true;
				return;
			}
		});
		if(found) { return true; }

		//Is inside
		params.fieldsInside.forEach(function(field){
			if(val.indexOf(field) > -1) {
				found = true;
				return;
			}
		});

		return found;
	},
	_clean = function(obj, params) {
		if(obj instanceof Array && params.deep > DEEP_NONE) {
			obj.map(function(o){
				return _clean(o, params);
			});

		} else if(typeof obj == "object" && obj != null) {
			Object.keys(obj).forEach(function(key){
				if(_cleanMatch(key.toLowerCase(), params)) {
					delete obj[key];
					return;
				}
				if(params.deep == DEEP_ARRAY_AND_OBJECT) {
					obj[key] = _clean(obj[key], params);
				}

			});

		}

		return obj;
	};
	Array.prototype.clear = function(fields, deepness){
		//Check
		if(typeof fields == "string") {
			fields = [fields];
		} else {
			fields = [];
		}
		if(typeof deepness == "undefined") {
			deepness = DEEP_ARRAY_AND_OBJECT;
		}

		//Categorize
		var params = {
			fieldsMatch: [],
			fieldsStarts: [],
			fieldsEnds: [],
			fieldsInside: [],
			deep: deepness
		};
		for(var a = 0; a < fields.length; a++) {
			var arg = fields[a];
			if(typeof arg == "string") {
				arg = arg.toLowerCase();
				if(arg.indexOf("*") == 0 && arg.lastIndexOf("*") == arg.length-1) {
					params.fieldsInside.push(arg.substring(1,arg.length-1));
				} else if(arg.lastIndexOf("*") == arg.length-1) {
					params.fieldsStarts.push(arg.substring(0,arg.length-1));
				} else if(arg.indexOf("*") == 0) {
					params.fieldsEnds.push(arg.substring(1,arg.length));
				} else {
					params.fieldsMatch.push(arg);
				}
			}
		}

		//Modify data
		if(params.fieldsMatch.length > 0 ||
			params.fieldsStarts.length > 0 ||
			params.fieldsEnds.length > 0 ||
			params.fieldsInside.length > 0) {
			return _clean(this,params);
		}
		return this;
	};

	//Groups objects in array by field
	Array.prototype.groupBy = function(field){
		//Check
		if(typeof field == "undefined") {
			return this;
		}

		//Categorize
		var other = [], mapping = {};
		this.forEach(function(item){
			if(typeof item == "object" && item != null && item.hasOwnProperty(field)) {
				var value = "val_"+JSON.stringify(item[field]);
				if(mapping.hasOwnProperty(value)) {
					mapping[value].push(item);
				} else {
					mapping[value] = [item];
				}
			} else {
				other.push(item);
			}
		});

		//Generate final array
		var finalArray = [];
		if(other.length > 0) {
			other.forEach(function(a){ finalArray.push(a); });
		}
		Object.keys(mapping).forEach(function(key){ finalArray.push(mapping[key]); });
		return finalArray;
	};

	//Returns part of array on stated path
	Array.prototype.getByPath = function(path){
		//Check
		if(path == "" || typeof path != "string") {
			return [];
		}

		//Prepare path
		var p, c = this;
		path = path.split(">").reverse();
		while(p = path.pop()) {
			if(c instanceof Array) {
				//Go trough array
				p = Number(p);
				if(isNaN(p) || p >= c.length) {
					return [];
				} else {
					c = c[p];
				}
			} else if(typeof c == "object" && c != null && c.hasOwnProperty(p)) {
				//Go trough object
				c = c[p];

			} else {
				//Cannot continue
				return [];
			}
		}

		//Return place
		return c;
	};

})();
<commit_msg>groupBy fix<commit_after>(function(){

	//Sorts objects in array by fields
	var SORT_ASC = 0,
	SORT_DESC = 1,
	SORT_UNKNOWN_VALUE = "}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}",
	_sortGetValue = function(val,field){
		if(typeof val == "object") {
			if(val == null) {
				return SORT_UNKNOWN_VALUE;
			} else if(typeof field == "undefined") {
				return JSON.stringify(val);
			} else if(val[field] || val.hasOwnProperty(field)) {
				return _sortGetValue(val[field]);
			} else {
				return JSON.stringify(val);
			}
		} else if(typeof val == "array") {
			return JSON.stringify(val);
		} else if(typeof val == "undefined") {
			return SORT_UNKNOWN_VALUE;
		}

		return val.toString();
	},
	_sort = function(o1,o2,order,field){
		var v1 = _sortGetValue(o1,field), v2 = _sortGetValue(o2,field);
		if(v1 > v2) {
			return order == SORT_ASC ? +1 : -1;
		} else if(v1 < v2) {
			return order == SORT_DESC ? +1 : -1;
		} else {
			return 0;
		}
	};

	Array.prototype.sortBy = function(fields, order){
		//Check
		if(typeof fields == "string") {
			fields = [fields];
		} else {
			fields = [];
		}
		if(typeof order == "undefined") {
			order = SORT_ASC;
		}

		//Actual sorting
		return this.sort(function(a,b) {
			var argId = 0, r = 0;
			while(argId < fields.length && r == 0) {
				r = _sort(a,b,order,fields[argId]);
				if(r == 0) {
					argId++;
				} else {
					return r;
				}
			}
			return _sort(a,b,order);
		});
	};

	//Removes fields in objects inside of array
	var DEEP_NONE = 0,
	DEEP_ARRAY = 1,
	DEEP_ARRAY_AND_OBJECT = 2,
	_cleanMatch = function(val, params) {
		var found = false;
		//Match
		if(params.fieldsMatch.indexOf(val) > -1) {
			return true;
		}

		//Starts with
		params.fieldsStarts.forEach(function(field){
			if(val.indexOf(field) == 0) {
				found = true;
				return;
			}
		});
		if(found) { return true; }

		//Ends with
		params.fieldsEnds.forEach(function(field){
			if(val.lastIndexOf(field) == val.length-field.length) {
				found = true;
				return;
			}
		});
		if(found) { return true; }

		//Is inside
		params.fieldsInside.forEach(function(field){
			if(val.indexOf(field) > -1) {
				found = true;
				return;
			}
		});

		return found;
	},
	_clean = function(obj, params) {
		if(obj instanceof Array && params.deep > DEEP_NONE) {
			obj.map(function(o){
				return _clean(o, params);
			});

		} else if(typeof obj == "object" && obj != null) {
			Object.keys(obj).forEach(function(key){
				if(_cleanMatch(key.toLowerCase(), params)) {
					delete obj[key];
					return;
				}
				if(params.deep == DEEP_ARRAY_AND_OBJECT) {
					obj[key] = _clean(obj[key], params);
				}

			});

		}

		return obj;
	};
	Array.prototype.clear = function(fields, deepness){
		//Check
		if(typeof fields == "string") {
			fields = [fields];
		} else {
			fields = [];
		}
		if(typeof deepness == "undefined") {
			deepness = DEEP_ARRAY_AND_OBJECT;
		}

		//Categorize
		var params = {
			fieldsMatch: [],
			fieldsStarts: [],
			fieldsEnds: [],
			fieldsInside: [],
			deep: deepness
		};
		for(var a = 0; a < fields.length; a++) {
			var arg = fields[a];
			if(typeof arg == "string") {
				arg = arg.toLowerCase();
				if(arg.indexOf("*") == 0 && arg.lastIndexOf("*") == arg.length-1) {
					params.fieldsInside.push(arg.substring(1,arg.length-1));
				} else if(arg.lastIndexOf("*") == arg.length-1) {
					params.fieldsStarts.push(arg.substring(0,arg.length-1));
				} else if(arg.indexOf("*") == 0) {
					params.fieldsEnds.push(arg.substring(1,arg.length));
				} else {
					params.fieldsMatch.push(arg);
				}
			}
		}

		//Modify data
		if(params.fieldsMatch.length > 0 ||
			params.fieldsStarts.length > 0 ||
			params.fieldsEnds.length > 0 ||
			params.fieldsInside.length > 0) {
			return _clean(this,params);
		}
		return this;
	};

	//Groups objects in array by field
	Array.prototype.groupBy = function(field){
		//Check
		if(typeof field == "undefined") {
			return this;
		}

		//Categorize
		var other = [], mapping = {};
		this.forEach(function(item){
			if(typeof item == "object" && item != null && item.hasOwnProperty(field)) {
				var value = "val_"+JSON.stringify(item[field]);
				if(mapping.hasOwnProperty(value)) {
					mapping[value].push(item);
				} else {
					mapping[value] = [item];
				}
			} else {
				other.push(item);
			}
		});

		//Generate final array
		var finalArray = [];
		if(other.length > 0) {
			finalArray.push(other);
		}
		Object.keys(mapping).forEach(function(key){ finalArray.push(mapping[key]); });
		return finalArray;
	};

	//Returns part of array on stated path
	Array.prototype.getByPath = function(path){
		//Check
		if(path == "" || typeof path != "string") {
			return [];
		}

		//Prepare path
		var p, c = this;
		path = path.split(">").reverse();
		while(p = path.pop()) {
			if(c instanceof Array) {
				//Go trough array
				p = Number(p);
				if(isNaN(p) || p >= c.length) {
					return [];
				} else {
					c = c[p];
				}
			} else if(typeof c == "object" && c != null && c.hasOwnProperty(p)) {
				//Go trough object
				c = c[p];

			} else {
				//Cannot continue
				return [];
			}
		}

		//Return place
		return c;
	};

})();
<|endoftext|>


<commit_before>var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var shareBox = document.getElementById('shareBox');

var player = null;
var entities = [];
var mobBrush = "player-knight";

var tileScale = 8
var tileSize = tileScale * 9;
var tileOffset = tileScale / 2;

var backgroundImg = new Image();
backgroundImg.src = "arena-7x14.png";

var updateShareLink = function() {
    var baseLink = "http://astudyinpixels.com/ld37/index.html";

    if (player == null) {
        shareBox.innerHTML = "you must add a player to generate the share url";
        return;
    };

    var link = "?p=" + player.x + "," + player.y;
    link += "&m=";

    if (entities.length <= 1) {
        shareBox.innerHTML = "you must add at least 1 enemy to generate the share url";
        return;
    }

    for (let i = 0; i < entities.length; ++i) {
        // player is handled differently, for probably unnecessary reasons
        let ent = entities[i];
        if (ent.type != "player-knight") {
            link += ent.shortName + "," + ent.x + "," + ent.y + ",";
        }
    }
    link = link.slice(0, -1);

    var finalLink = baseLink + link;
    shareBox.innerHTML = finalLink;

    var testMapDiv = document.getElementById("testMap");
    testMapDiv.innerHTML = "test your map by clicking this";
}
updateShareLink();

var realPosFromTilePos = function(x, y) {
    return {
        x: (x * tileSize),
        y: (y * tileSize),
        s: (tileSize + (tileOffset * 2)),
    };
}

var arenaSizeX = 14;
var arenaSizeY = 7;
var inBounds = function(x, y) {
    return (
        x >= 0 && x < arenaSizeX &&
        y >= 0 && y < arenaSizeY
    );
}

var Mob = function(type, x, y) {
    this.type = type;
    this.x = x;
    this.y = y;
    this.img = new Image();
    this.img.src = type + ".png";
    this.idleImg = new Image();
    this.idleImg.src = type + "2.png";
    this.shortName = validMobShortNames[validBrushTypes.indexOf(this.type)];

    var realPos = realPosFromTilePos(x, y);
    this.realPos = { x: realPos.x, y: realPos.y };
}

// all support entity types
var validBrushTypes = [
    "player-knight",
    "skeleton",
    "ghoul",
    "demon-spear",
    "demon-mage",
    "orc-knight",
    "orc-mage",
    "black-knight"
];

var validMobShortNames = [
    "pk",
    "s",
    "g",
    "ds",
    "dm",
    "ok",
    "om",
    "bk"
]

var getMousePos = function() {
    var rect = canvas.getBoundingClientRect();

    return {
        x: Math.floor((event.clientX - (rect.left + (tileScale / 2))) / tileSize),
        y: Math.floor((event.clientY - (rect.top + (tileScale / 2))) / tileSize)
    };
}

var removeEntityAt = function(x, y) {
    // if entity exists in this spot, replace it
    var idx = -1;
    for (var i = 0; i < entities.length; ++i) {
        if (entities[i].x == x && entities[i].y == y) {
            idx = i;
            break;
        }
    }

    if (idx != -1) {
        entities.splice(idx, 1);
    }
}

canvas.addEventListener('mouseup', function(event) {
    mousePos = getMousePos();

    // is this even possible?
    if (!inBounds(mousePos.x, mousePos.y)) { return; }

    removeEntityAt(mousePos.x, mousePos.y);

    // if brush is player-knight remove any old entity info so there's only one player

    if (mobBrush == "player-knight") {
        if (player != null) {
            removeEntityAt(player.x, player.y);
        }
        player = { x: mousePos.x, y: mousePos.y };
    }

    entities.push(new Mob(mobBrush, mousePos.x, mousePos.y));
    updateShareLink();
});

var generateBrushButtons = function() {
    var brushList = document.getElementById('brushes');

    for (let type of validBrushTypes) {
        let btn = document.createElement("button");
        let text = document.createTextNode(type);

        btn.addEventListener("click", function() {
            var sel = document.getElementById("selected-brush");
            sel.innerHTML = "selected brush: " + type;
            mobBrush = type;
        });

        btn.appendChild(text);
        brushList.appendChild(btn);
    }
}

var drawEntities = function(time) {
    for (var ent of entities) {
        if (time % 1000 < 500) {
            ctx.drawImage(ent.img, ent.realPos.x, ent.realPos.y);
        } else {
            ctx.drawImage(ent.idleImg, ent.realPos.x, ent.realPos.y);
        }
    }
}

var drawLoop = function(time) {
    ctx.drawImage(backgroundImg, 0, 0);

    drawEntities(time);

    requestAnimationFrame(drawLoop);
}

generateBrushButtons();
requestAnimationFrame(drawLoop);<commit_msg>add eraser to map maker<commit_after>var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var shareBox = document.getElementById('shareBox');

var player = null;
var entities = [];
var mobBrush = "player-knight";

var tileScale = 8
var tileSize = tileScale * 9;
var tileOffset = tileScale / 2;

var backgroundImg = new Image();
backgroundImg.src = "arena-7x14.png";

var updateShareLink = function() {
    var baseLink = "http://astudyinpixels.com/ld37/index.html";

    if (player == null) {
        shareBox.innerHTML = "you must add a player to generate the share url";
        return;
    };

    var link = "?p=" + player.x + "," + player.y;
    link += "&m=";

    if (entities.length <= 1) {
        shareBox.innerHTML = "you must add at least 1 enemy to generate the share url";
        return;
    }

    for (let i = 0; i < entities.length; ++i) {
        // player is handled differently, for probably unnecessary reasons
        let ent = entities[i];
        if (ent.type != "player-knight") {
            link += ent.shortName + "," + ent.x + "," + ent.y + ",";
        }
    }
    link = link.slice(0, -1);

    var finalLink = baseLink + link;
    shareBox.innerHTML = finalLink;

    var testMapDiv = document.getElementById("testMap");
    testMapDiv.innerHTML = "test your map by clicking this";
}
updateShareLink();

var realPosFromTilePos = function(x, y) {
    return {
        x: (x * tileSize),
        y: (y * tileSize),
        s: (tileSize + (tileOffset * 2)),
    };
}

var arenaSizeX = 14;
var arenaSizeY = 7;
var inBounds = function(x, y) {
    return (
        x >= 0 && x < arenaSizeX &&
        y >= 0 && y < arenaSizeY
    );
}

var Mob = function(type, x, y) {
    this.type = type;
    this.x = x;
    this.y = y;
    this.img = new Image();
    this.img.src = type + ".png";
    this.idleImg = new Image();
    this.idleImg.src = type + "2.png";
    this.shortName = validMobShortNames[validBrushTypes.indexOf(this.type)];

    var realPos = realPosFromTilePos(x, y);
    this.realPos = { x: realPos.x, y: realPos.y };
}

// all support entity types
var validBrushTypes = [
    "player-knight",
    "skeleton",
    "ghoul",
    "demon-spear",
    "demon-mage",
    "orc-knight",
    "orc-mage",
    "black-knight",
    "ERASE"
];

var validMobShortNames = [
    "pk",
    "s",
    "g",
    "ds",
    "dm",
    "ok",
    "om",
    "bk"
]

var getMousePos = function() {
    var rect = canvas.getBoundingClientRect();

    return {
        x: Math.floor((event.clientX - (rect.left + (tileScale / 2))) / tileSize),
        y: Math.floor((event.clientY - (rect.top + (tileScale / 2))) / tileSize)
    };
}

var removeEntityAt = function(x, y) {
    // if entity exists in this spot, replace it
    var idx = -1;
    for (var i = 0; i < entities.length; ++i) {
        if (entities[i].x == x && entities[i].y == y) {
            idx = i;
            break;
        }
    }

    if (idx != -1) {
        entities.splice(idx, 1);
    }
}

canvas.addEventListener('mouseup', function(event) {
    mousePos = getMousePos();

    // is this even possible?
    if (!inBounds(mousePos.x, mousePos.y)) { return; }

    removeEntityAt(mousePos.x, mousePos.y);

    // if brush is eraser, update the share link and leave
    if (mobBrush == "ERASE") {
        updateShareLink();
        return;
    }

    // if brush is player-knight remove any old entity info so there's only one player
    if (mobBrush == "player-knight") {
        if (player != null) {
            removeEntityAt(player.x, player.y);
        }
        player = { x: mousePos.x, y: mousePos.y };
    }

    entities.push(new Mob(mobBrush, mousePos.x, mousePos.y));
    updateShareLink();
});

var generateBrushButtons = function() {
    var brushList = document.getElementById('brushes');
    var count = 0;

    for (let type of validBrushTypes) {
        let btn = document.createElement("button");
        let text = document.createTextNode(type);

        btn.addEventListener("click", function() {
            var sel = document.getElementById("selected-brush");
            sel.innerHTML = "selected brush: " + type;
            mobBrush = type;
        });

        btn.appendChild(text);
        brushList.appendChild(btn);
        count++;
        if (count % 5 == 0) {
            brushList.appendChild(document.createElement("br"));
        }
    }
}

var drawEntities = function(time) {
    for (var ent of entities) {
        if (time % 1000 < 500) {
            ctx.drawImage(ent.img, ent.realPos.x, ent.realPos.y);
        } else {
            ctx.drawImage(ent.idleImg, ent.realPos.x, ent.realPos.y);
        }
    }
}

var drawLoop = function(time) {
    ctx.drawImage(backgroundImg, 0, 0);

    drawEntities(time);

    requestAnimationFrame(drawLoop);
}

generateBrushButtons();
requestAnimationFrame(drawLoop);<|endoftext|>


<commit_before>const boxHeight = 80
const textHeight = 14
const textMargin = 6

const template = {
  'name': 'MOVEMENTeer 0.3',
  'settings': {
    'nodeSize': {
      'width': boxHeight * 1.5,
      'height': boxHeight * 2.3
    }
  },
  'svg': {
    'big-rect': {
      // Rect with opacity 0, so that one could hover over all the square even
      // if the visible shape is circle
      'type': 'rect',
      'attributes': {
        'x': -boxHeight / 2,
        'y': 0,
        'width': boxHeight,
        'height': boxHeight,
        'opacity': '0'
      }
    },
    'attenders-image': {
      'type': 'image',
      'attributes': {
        'x': -boxHeight * 0.5,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/attenders.png'
      }
    },
    'believers-image': {
      'type': 'image',
      'attributes': {
        'x': -boxHeight * 0.25,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/believers.png'
      }
    },
    'baptized-image': {
      'type': 'image',
      'attributes': {
        'x': boxHeight * 0.1,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/element-baptism.png'
      }
    },
    'church-box': {
      'type': 'rect',
      'attributes': {
        'x': -boxHeight / 2,
        'y': 0,
        'rx': 0.5 * boxHeight,
        'width': boxHeight,
        'height': boxHeight
      }
    }
  },
  'fields': [
    {
      'header': 'id',
      'initial': 0,
      'description': 'Id',
      'type': null
    },
    {
      'header': 'parentId',
      'initial': null,
      'description': 'Parent',
      'type': null
    },
    {
      'header': 'name',
      'initial': "Leader's Name",
      'description': 'Name of the Leader',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + textHeight
        }
      }
    },
    {
      'header': 'leaderType',
      'initial': 'fullTimeMissionary',
      'description': 'Leader',
      'type': 'radio',
      'inheritsFrom': 'church-box',
      'values': [
        {
          'header': 'fullTimeMissionary',
          'description': 'Full time missionary',
          'class': 'full-time-missionary'
        },
        {
          'header': 'existingLayBeliever',
          'description': 'Existing lay believer',
          'class': 'existing-lay-believer'
        },
        {
          'header': 'leadersDisciple',
          'description': "Leader's disciple",
          'class': 'leaders-disciple'
        }
      ]
    },
   {
      'header': 'place',
      'initial': '',
      'description': 'Place',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + 2 * textHeight
        }
      }
    },
    {
      'header': 'date',
      'initial': '',
      'description': 'Date started',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + 3 * textHeight
        }
      }
    },
    {
      'header': 'attenders',
      'initial': 0,
      'description': '# of Attenders',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': -boxHeight * 0.39,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'believers',
      'initial': 0,
      'description': '# of Believers',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': -boxHeight * 0.13,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'baptized',
      'initial': 0,
      'description': '# of Baptized',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.13,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'multipliers',
      'initial': '1',
      'description': '# of Multiplying disciples',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.39,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'church',
      'initial': false,
      'description': 'Is church?',
      'type': 'checkbox',
      'inheritsFrom': 'church-box',
      'attributes': {
        'rx': {
          'checkedTrue': 0,
          'checkedFalse': 0.5 * boxHeight
        }
      }
    },
    {
      'header': 'elementWord',
      'initial': false,
      'description': "Element: God's Word",
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-word.png'
        }
      }
    },
    {
      'header': 'elementPrayer',
      'initial': false,
      'description': 'Element: Prayer',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-prayer.png'
        }
      }
    },
    {
      'header': 'elementLove',
      'initial': false,
      'description': 'Element: Love',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-love.png'
        }
      }
    },
    {
      'header': 'elementWorship',
      'initial': false,
      'description': 'Element: Worship',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-worship.png'
        }
      }
    },
    {
      'header': 'elementMakeDisciples',
      'initial': false,
      'description': 'Element: Make disciples',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-make-disciples.png'
        }
      }
    },
    {
      'header': 'elementLeaders',
      'initial': false,
      'description': 'Element: Leaders',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-leaders.png'
        }
      }
    },
    {
      'header': 'elementGive',
      'initial': false,
      'description': 'Element: Giving',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-give.png'
        }
      }
    },
    {
      'header': 'elementLordsSupper',
      'initial': false,
      'description': "Element: Lord's supper",
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-lords-supper.png'
        }
      }
    },
    {
      'header': 'elementBaptism',
      'initial': false,
      'description': 'Element: Baptism',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-baptism.png'
        }
      }
    },
    {
      'header': 'threeThirds',
      'initial': '',
      'description': 'Elements of 3/3 process',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * -0.7,
          'y': boxHeight * 0.6,
          'transform': 'rotate(90 -56 48)',
          'rotate': -90
        },
        'style': {
          'text-anchor': 'center',
          'letter-spacing': '0.35em'
        }
      }
    },
    {
      'header': 'trainingUsed',
      'initial': '',
      'description': 'Training used',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0,
          'y': boxHeight + 4 * textHeight
        },
        'style': {
          'text-anchor': 'end'
        }
      }
    },
    {
      'header': 'trainingPhase',
      'initial': '',
      'description': 'Training phase',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.1,
          'y': boxHeight + 4 * textHeight
        },
        'style': {
          'text-anchor': 'start'
        }
      }
    },
    {
      'header': 'contact',
      'initial': '',
      'description': 'Contact info',
      'type': 'text',
    },
    {
      'header': 'active',
      'initial': true,
      'description': 'Active',
      'type': 'checkbox'
      // svg defined currently in genmapper.js
    },
    {
      'header': 'actionSteps',
      'initial': '',
      'description': 'Action steps for this month',
      'type': 'text'
    }
  ]
}
<commit_msg>Action steps undefined?<commit_after>const boxHeight = 80
const textHeight = 14
const textMargin = 6

const template = {
  'name': 'MOVEMENTeer 0.3',
  'settings': {
    'nodeSize': {
      'width': boxHeight * 1.5,
      'height': boxHeight * 2.3
    }
  },
  'svg': {
    'big-rect': {
      // Rect with opacity 0, so that one could hover over all the square even
      // if the visible shape is circle
      'type': 'rect',
      'attributes': {
        'x': -boxHeight / 2,
        'y': 0,
        'width': boxHeight,
        'height': boxHeight,
        'opacity': '0'
      }
    },
    'attenders-image': {
      'type': 'image',
      'attributes': {
        'x': -boxHeight * 0.5,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/attenders.png'
      }
    },
    'believers-image': {
      'type': 'image',
      'attributes': {
        'x': -boxHeight * 0.25,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/believers.png'
      }
    },
    'baptized-image': {
      'type': 'image',
      'attributes': {
        'x': boxHeight * 0.1,
        'y': -2.5 * textHeight,
        'width': boxHeight / 4,
        'height': boxHeight / 4,
        'href': 'icons/element-baptism.png'
      }
    },
    'church-box': {
      'type': 'rect',
      'attributes': {
        'x': -boxHeight / 2,
        'y': 0,
        'rx': 0.5 * boxHeight,
        'width': boxHeight,
        'height': boxHeight
      }
    }
  },
  'fields': [
    {
      'header': 'id',
      'initial': 0,
      'description': 'Id',
      'type': null
    },
    {
      'header': 'parentId',
      'initial': null,
      'description': 'Parent',
      'type': null
    },
    {
      'header': 'name',
      'initial': "Leader's Name",
      'description': 'Name of the Leader',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + textHeight
        }
      }
    },
    {
      'header': 'leaderType',
      'initial': 'fullTimeMissionary',
      'description': 'Leader',
      'type': 'radio',
      'inheritsFrom': 'church-box',
      'values': [
        {
          'header': 'fullTimeMissionary',
          'description': 'Full time missionary',
          'class': 'full-time-missionary'
        },
        {
          'header': 'existingLayBeliever',
          'description': 'Existing lay believer',
          'class': 'existing-lay-believer'
        },
        {
          'header': 'leadersDisciple',
          'description': "Leader's disciple",
          'class': 'leaders-disciple'
        }
      ]
    },
   {
      'header': 'place',
      'initial': '',
      'description': 'Place',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + 2 * textHeight
        }
      }
    },
    {
      'header': 'date',
      'initial': '',
      'description': 'Date started',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': 0,
          'y': boxHeight + 3 * textHeight
        }
      }
    },
    {
      'header': 'attenders',
      'initial': 0,
      'description': '# of Attenders',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': -boxHeight * 0.39,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'believers',
      'initial': 0,
      'description': '# of Believers',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': -boxHeight * 0.13,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'baptized',
      'initial': 0,
      'description': '# of Baptized',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.13,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'multipliers',
      'initial': '1',
      'description': '# of Multiplying disciples',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.39,
          'y': -0.5 * textMargin
        },
        'style': {
          'text-anchor': 'center'
        }
      }
    },
    {
      'header': 'church',
      'initial': false,
      'description': 'Is church?',
      'type': 'checkbox',
      'inheritsFrom': 'church-box',
      'attributes': {
        'rx': {
          'checkedTrue': 0,
          'checkedFalse': 0.5 * boxHeight
        }
      }
    },
    {
      'header': 'elementWord',
      'initial': false,
      'description': "Element: God's Word",
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-word.png'
        }
      }
    },
    {
      'header': 'elementPrayer',
      'initial': false,
      'description': 'Element: Prayer',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-prayer.png'
        }
      }
    },
    {
      'header': 'elementLove',
      'initial': false,
      'description': 'Element: Love',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-love.png'
        }
      }
    },
    {
      'header': 'elementWorship',
      'initial': false,
      'description': 'Element: Worship',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-worship.png'
        }
      }
    },
    {
      'header': 'elementMakeDisciples',
      'initial': false,
      'description': 'Element: Make disciples',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': boxHeight * 0.15,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-make-disciples.png'
        }
      }
    },
    {
      'header': 'elementLeaders',
      'initial': false,
      'description': 'Element: Leaders',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.65,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-leaders.png'
        }
      }
    },
    {
      'header': 'elementGive',
      'initial': false,
      'description': 'Element: Giving',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.125,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-give.png'
        }
      }
    },
    {
      'header': 'elementLordsSupper',
      'initial': false,
      'description': "Element: Lord's supper",
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.375,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-lords-supper.png'
        }
      }
    },
    {
      'header': 'elementBaptism',
      'initial': false,
      'description': 'Element: Baptism',
      'type': 'checkbox',
      'svg': {
        'type': 'image',
        'attributes': {
          'x': -boxHeight * 0.4,
          'y': boxHeight * 0.1,
          'width': boxHeight / 4,
          'height': boxHeight / 4,
          'xlink:href': 'icons/element-baptism.png'
        }
      }
    },
    {
      'header': 'threeThirds',
      'initial': '',
      'description': 'Elements of 3/3 process',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * -0.7,
          'y': boxHeight * 0.6,
          'transform': 'rotate(90 -56 48)',
          'rotate': -90
        },
        'style': {
          'text-anchor': 'center',
          'letter-spacing': '0.35em'
        }
      }
    },
    {
      'header': 'trainingUsed',
      'initial': '',
      'description': 'Training used',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0,
          'y': boxHeight + 4 * textHeight
        },
        'style': {
          'text-anchor': 'end'
        }
      }
    },
    {
      'header': 'trainingPhase',
      'initial': '',
      'description': 'Training phase',
      'type': 'text',
      'svg': {
        'type': 'text',
        'attributes': {
          'x': boxHeight * 0.1,
          'y': boxHeight + 4 * textHeight
        },
        'style': {
          'text-anchor': 'start'
        }
      }
    },
    {
      'header': 'contact',
      'initial': '',
      'description': 'Contact info',
      'type': 'text',
    },
    {
      'header': 'active',
      'initial': true,
      'description': 'Active',
      'type': 'checkbox'
      // svg defined currently in genmapper.js
    },
    {
      'header': 'actionSteps',
      'initial': 'action',
      'description': 'Action steps for this month',
      'type': 'text'
    }
  ]
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow strict
 */

'use strict';

const AUTO_INSTANCE_KEY = -1;

export type FlowId = {
  markerId: number,
  instanceKey: number,
};

export type PointData = $Shape<{
  string: ?{[string]: string, ...},
  int: ?{[string]: number, ...},
  double: ?{[string]: number, ...},
  bool: ?{[string]: boolean, ...},
  string_array: ?{[string]: $ReadOnlyArray<string>, ...},
  int_array: ?{[string]: $ReadOnlyArray<number>, ...},
  double_array: ?{[string]: $ReadOnlyArray<number>, ...},
  bool_array: ?{[string]: $ReadOnlyArray<boolean>, ...},
}>;

/**
 * API for tracking reliability of your user interactions
 *
 * Example:
 * const flowId = UserFlow.newFlowId(QuickLogItentifiersExample.EXAMPLE_EVENT);
 * ...
 * UserFlow.start(flowId, "user_click");
 * ...
 * UserFlow.addAnnotation(flowId, "cached", "true");
 * ...
 * UserFlow.addPoint(flowId, "reload");
 * ...
 * UserFlow.endSuccess(flowId);
 */
const UserFlow = {
  /**
   * Creates FlowId from markerId and instanceKey.
   * You will pass FlowId in every other method of UserFlow API.
   *
   * By default, instanceKey will generate unique instance every time you call userFlowGetId with markerId only.
   */
  newFlowId(markerId: number, instanceKey: number = AUTO_INSTANCE_KEY): FlowId {
    var resolvedInstanceKey = instanceKey;
    if (instanceKey === AUTO_INSTANCE_KEY) {
      if (global.nativeUserFlowNextInstanceKey) {
        resolvedInstanceKey = global.nativeUserFlowNextInstanceKey();
      } else {
        // There is no JSI methods installed, API won't do anything
        resolvedInstanceKey = 0;
      }
    }
    return {
      markerId: markerId,
      instanceKey: resolvedInstanceKey,
    };
  },

  start(flowId: FlowId, triggerSource: string): void {
    if (global.nativeUserFlowStart) {
      global.nativeUserFlowStart(
        flowId.markerId,
        flowId.instanceKey,
        triggerSource,
      );
    }
  },

  addAnnotation(
    flowId: FlowId,
    annotationName: string,
    annotationValue: string | boolean,
  ): void {
    if (global.nativeUserFlowAddAnnotation) {
      global.nativeUserFlowAddAnnotation(
        flowId.markerId,
        flowId.instanceKey,
        annotationName,
        annotationValue,
      );
    }
  },

  addPoint(flowId: FlowId, pointName: string, data: ?PointData = null): void {
    if (global.nativeUserFlowAddPoint) {
      global.nativeUserFlowAddPoint(
        flowId.markerId,
        flowId.instanceKey,
        pointName,
        data,
      );
    }
  },

  endSuccess(flowId: FlowId): void {
    if (global.nativeUserFlowEndSuccess) {
      global.nativeUserFlowEndSuccess(flowId.markerId, flowId.instanceKey);
    }
  },

  endFailure(
    flowId: FlowId,
    errorName: string,
    debugInfo: ?string = null,
  ): void {
    if (global.nativeUserFlowEndFail) {
      global.nativeUserFlowEndFail(
        flowId.markerId,
        flowId.instanceKey,
        errorName,
        debugInfo,
      );
    }
  },

  endCancel(flowId: FlowId, cancelReason: string): void {
    if (global.nativeUserFlowEndCancel) {
      global.nativeUserFlowEndCancel(
        flowId.markerId,
        flowId.instanceKey,
        cancelReason,
      );
    }
  },
};

module.exports = UserFlow;
<commit_msg>Migrate jsi wrapper + pass markerId to get next instance key<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 * @flow strict
 */

'use strict';

const AUTO_INSTANCE_KEY = -1;

export type FlowId = {
  markerId: number,
  instanceKey: number,
};

export type PointData = $Shape<{
  string: ?{[string]: string, ...},
  int: ?{[string]: number, ...},
  double: ?{[string]: number, ...},
  bool: ?{[string]: boolean, ...},
  string_array: ?{[string]: $ReadOnlyArray<string>, ...},
  int_array: ?{[string]: $ReadOnlyArray<number>, ...},
  double_array: ?{[string]: $ReadOnlyArray<number>, ...},
  bool_array: ?{[string]: $ReadOnlyArray<boolean>, ...},
}>;

/**
 * API for tracking reliability of your user interactions
 *
 * Example:
 * const flowId = UserFlow.newFlowId(QuickLogItentifiersExample.EXAMPLE_EVENT);
 * ...
 * UserFlow.start(flowId, "user_click");
 * ...
 * UserFlow.addAnnotation(flowId, "cached", "true");
 * ...
 * UserFlow.addPoint(flowId, "reload");
 * ...
 * UserFlow.endSuccess(flowId);
 */
const UserFlow = {
  /**
   * Creates FlowId from markerId and instanceKey.
   * You will pass FlowId in every other method of UserFlow API.
   *
   * By default, instanceKey will generate unique instance every time you call userFlowGetId with markerId only.
   */
  newFlowId(markerId: number, instanceKey: number = AUTO_INSTANCE_KEY): FlowId {
    var resolvedInstanceKey = instanceKey;
    if (instanceKey === AUTO_INSTANCE_KEY) {
      if (global.nativeUserFlowNextInstanceKey) {
        resolvedInstanceKey = global.nativeUserFlowNextInstanceKey(markerId);
      } else {
        // There is no JSI methods installed, API won't do anything
        resolvedInstanceKey = 0;
      }
    }
    return {
      markerId: markerId,
      instanceKey: resolvedInstanceKey,
    };
  },

  start(flowId: FlowId, triggerSource: string): void {
    if (global.nativeUserFlowStart) {
      global.nativeUserFlowStart(
        flowId.markerId,
        flowId.instanceKey,
        triggerSource,
      );
    }
  },

  addAnnotation(
    flowId: FlowId,
    annotationName: string,
    annotationValue: string | boolean,
  ): void {
    if (global.nativeUserFlowAddAnnotation) {
      global.nativeUserFlowAddAnnotation(
        flowId.markerId,
        flowId.instanceKey,
        annotationName,
        annotationValue,
      );
    }
  },

  addPoint(flowId: FlowId, pointName: string, data: ?PointData = null): void {
    if (global.nativeUserFlowAddPoint) {
      global.nativeUserFlowAddPoint(
        flowId.markerId,
        flowId.instanceKey,
        pointName,
        data,
      );
    }
  },

  endSuccess(flowId: FlowId): void {
    if (global.nativeUserFlowEndSuccess) {
      global.nativeUserFlowEndSuccess(flowId.markerId, flowId.instanceKey);
    }
  },

  endFailure(
    flowId: FlowId,
    errorName: string,
    debugInfo: ?string = null,
  ): void {
    if (global.nativeUserFlowEndFail) {
      global.nativeUserFlowEndFail(
        flowId.markerId,
        flowId.instanceKey,
        errorName,
        debugInfo,
      );
    }
  },

  endCancel(flowId: FlowId, cancelReason: string): void {
    if (global.nativeUserFlowEndCancel) {
      global.nativeUserFlowEndCancel(
        flowId.markerId,
        flowId.instanceKey,
        cancelReason,
      );
    }
  },
};

module.exports = UserFlow;
<|endoftext|>


<commit_before>module.exports = function(grunt) {
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),

      chill: {
         folders: {
            pub: './public',
            fonts: '<%= chill.folders.pub %>/fonts',
            bower: './bower_components/',
            css: {
               dist: '<%= chill.folders.pub %>/stylesheets/',
            },
            sass: {
               src: '<%= chill.folders.css.dist %>/sass/',
            }
         }
      },
      bower: {
         install: {
            options: {
               targetDir: '<%= chill.folders.bower %>',
               install: true,
               copy: false,
               //cleanBowerDir: true,
               verbose: true
            }
         }
      },
      copy: {
         scratch: {
            files: [
               {
                  cwd: '<%= chill.folders.bower %>Scratch-CSS-Design/stylesheets/sass',
                  src: ['**', '!_custom.scss'],
                  dest: '<%= chill.folders.sass.src %>',
                  expand: true,
               },
               {
                  cwd: '<%= chill.folders.bower %>Scratch-CSS-Design/fonts/',
                  src: '**',
                  dest: '<%= chill.folders.fonts %>',
                  expand: true,
               }
            ]
         },
         select2: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>select2',
                    src: ['*'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         pikaday: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>pikaday',
                    src: ['css/pikaday.css', 'pikaday.js',  'plugins/pikaday.jquery.js'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         moment: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>moment',
                    src: ['moment.js'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         chill_standard: {
            files: [
               {
                  cwd: './public',
                  src: '**',
                  dest: '../../../../web/bundles/chillmain/',
                  expand: true,
               }
            ]
         }
      },
      sass: {
         dist: {
            files: [{
               expand: true,
               cwd: '<%= chill.folders.sass.src %>',
               src: ['*.scss'],
               dest: '<%= chill.folders.css.dist %>',
               ext: '.css'
            }]
         }
      },
      watch: {
         css: {
            files: [ '<%= chill.folders.sass.src %>/*.scss', '<%= chill.folders.sass.src %>/**/*.scss' ],
            tasks: ['generatecss'],
            /*
            options: {
               spawn: false,
               interrupt: true,
            }
            */
         }
      },
      clean: {
         css: ['<%= chill.folders.css.dist %>/*.css'],
      }
   });

   grunt.loadNpmTasks('grunt-bower-task');
   grunt.loadNpmTasks('grunt-contrib-copy');
   grunt.loadNpmTasks('grunt-contrib-sass');
   grunt.loadNpmTasks('grunt-contrib-watch');
   grunt.loadNpmTasks('grunt-contrib-clean');

   grunt.registerTask('generatecss', ['clean:css', 'sass', 'copy:chill_standard']);
   grunt.registerTask('dependencies', ['bower', 'copy']);
   grunt.registerTask('default', ['dependencies', 'generatecss']);
};<commit_msg>Adding clean:bowerDir command<commit_after>module.exports = function(grunt) {
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),

      chill: {
         folders: {
            pub: './public',
            fonts: '<%= chill.folders.pub %>/fonts',
            bower: './bower_components/',
            css: {
               dist: '<%= chill.folders.pub %>/stylesheets/',
            },
            sass: {
               src: '<%= chill.folders.css.dist %>/sass/',
            }
         }
      },
      bower: {
         install: {
            options: {
               targetDir: '<%= chill.folders.bower %>',
               install: true,
               copy: false,
               //cleanBowerDir: true,
               verbose: true
            }
         }
      },
      copy: {
         scratch: {
            files: [
               {
                  cwd: '<%= chill.folders.bower %>Scratch-CSS-Design/stylesheets/sass',
                  src: ['**', '!_custom.scss'],
                  dest: '<%= chill.folders.sass.src %>',
                  expand: true,
               },
               {
                  cwd: '<%= chill.folders.bower %>Scratch-CSS-Design/fonts/',
                  src: '**',
                  dest: '<%= chill.folders.fonts %>',
                  expand: true,
               }
            ]
         },
         select2: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>select2',
                    src: ['*'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         pikaday: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>pikaday',
                    src: ['css/pikaday.css', 'pikaday.js',  'plugins/pikaday.jquery.js'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         moment: {
            files: [
                {
                    cwd: '<%= chill.folders.bower %>moment',
                    src: ['moment.js'],
                    dest: '<%= chill.folders.pub %>',
                    expand: true,
                }
            ]
         },
         chill_standard: {
            files: [
               {
                  cwd: './public',
                  src: '**',
                  dest: '../../../../web/bundles/chillmain/',
                  expand: true,
               }
            ]
         }
      },
      sass: {
         dist: {
            files: [{
               expand: true,
               cwd: '<%= chill.folders.sass.src %>',
               src: ['*.scss'],
               dest: '<%= chill.folders.css.dist %>',
               ext: '.css'
            }]
         }
      },
      watch: {
         css: {
            files: [ '<%= chill.folders.sass.src %>/*.scss', '<%= chill.folders.sass.src %>/**/*.scss' ],
            tasks: ['generatecss'],
            /*
            options: {
               spawn: false,
               interrupt: true,
            }
            */
         }
      },
      clean: {
         css: ['<%= chill.folders.css.dist %>/*.css'],
         bowerDir: ['<%= chill.folders.bower %>']
      }
   });

   grunt.loadNpmTasks('grunt-bower-task');
   grunt.loadNpmTasks('grunt-contrib-copy');
   grunt.loadNpmTasks('grunt-contrib-sass');
   grunt.loadNpmTasks('grunt-contrib-watch');
   grunt.loadNpmTasks('grunt-contrib-clean');

   grunt.registerTask('generatecss', ['clean:css', 'sass', 'copy:chill_standard']);
   grunt.registerTask('dependencies', ['bower', 'copy']);
   grunt.registerTask('default', ['dependencies', 'generatecss']);
};<|endoftext|>


<commit_before>/**
 * @author Chia-Yuan Hsiung
 */
Ti.include('database.js');

var win = Titanium.UI.currentWindow;

//the data storage empty array
var data = [];
//define search bar which will attach to  table view
var searchBar = Titanium.UI.createSearchBar({
	showCancel:true,
	height :43,
	top:0
});

//print out the searchbar value whenever it changes
searchBar.addEventListener('change' , function(e){

	Ti.API.info('user searching for: ' + e.value);
});
//when the return key is hit, make searchBar get blur
searchBar.addEventListener('return' , function(e){
	searchBar.blur();
});

//when the cancel but ton is tapped,make searchBar get blur too
searchBar.addEventListener('cancel', function(e){
	searchBar.blur();
});
//end of search bar
//create a table view
var favoritesTable = Titanium.UI.createTableView({
	height: 366,
	width: 	320,
	top: 	0,
	left: 	0,
	search: searchBar,
	filterAttribute:'filter',
	editable: true,
	deleteButtonTitle: 'Remove'
});
//tablerow selected function: create new window
if(Ti.Platform.osname == 'iphone'){
favoritesTable.addEventListener('click', function(e){
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>huzzah, a row ("+e.index+") was clicked");

	//get the selected row index
	var theFavorite = data[e.index];

	// create detail window
	var detailWindow = Titanium.UI.createWindow({
		id:theFavorite.id,
		_title:theFavorite.title,
		_description:theFavorite.description,
		_link:theFavorite.link,
		backgroundColor:'#fff',
		title:theFavorite.title,
		url: 'detail.js',
		id:0
	});

	Titanium.UI.currentTab.open(detailWindow);
});
}

favoritesTable.addEventListener('delete', function(e){
	var removedID = data[e.index].id;

	deleteFavorite(removedID);
	Ti.API.info('>>>>>>>>>>>>>>>>>>>>>>Deleted favorite records. (id ' + removedID + ')');

});

win.add(favoritesTable);
favoritesTable.hide();

//no favorite label
var noFavLabel = Titanium.UI.createLabel({
	color:'#999',
	text:'No Favorites yet.',
	font:{fontSize:20,fontFamily:'Helvetica Neue'},
	textAlign:'center',
	height:40,
	width:'auto',
	top: 100,

});
win.add(noFavLabel);
noFavLabel.hide();

function loadFavorites(){

	data = getFavorites();

	if(data.length>0){

		var tableData = [];
		//get through each item
		for(var i = 0; i < data.length; i++)
		{
			var aFavorite = data[i];

			//create table row
			var row = Titanium.UI.createTableViewRow({
				_title:aFavorite.title,
				_description: aFavorite.description,
				_link:aFavorite.link,
				hasChild: true,
				className: 'favorite-row',
				filter: aFavorite.title,
				height:70,
				backgroundColor: '#fff'
			});
			//title label for row at index i
			var titleLabel = Titanium.UI.createLabel({
				text: aFavorite.title,
				font : {fontSize: 14, fontWeight : ' bold' },
				left: 70,
				top: 10,
				height: 50,
				width: 210,
				color:'#232',
				dataIndex:i
			});

			Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>huzzah, a row :"+ aFavorite.title+" id:"+aFavorite.id);

 			if(Ti.Platform.osname != 'iphone'){

				enableSwipe	(titleLabel,false,10);
				titleLabel.addEventListener("swipe", showRemoveButton);
				//titleLabel.addEventListener("click", enterDetailView);
			}

			row.add(titleLabel);

			//add our little icon to the left of the row
			var iconImage = Titanium.UI.createImageView({
				image: 'img/eggcooking.png',
				width: 50,
				height: 50,
				left: 10,
				top: 10
			});

			row.add(iconImage);

			//add the row to data array
			tableData.push(row);
		}
		// set the data to tableview's data
		favoritesTable.data = tableData;
		favoritesTable.show();
		noFavLabel.hide();
	}else{
		favoritesTable.hide();
		noFavLabel.show();
	}

}
//the focus event l istener wi l l ensure that the l ist / / is refreshed whenever the tab is changed
win.addEventListener('focus', loadFavorites);

function removeFavoriteRow(rowIndex)
{
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>> row "+rowIndex+" is going to be deleted.");
	favoritesTable.deleteRow(rowIndex);

}
function enableSwipe (view, allowVertical, tolerance) {
 	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>enableSwipe ");

 	tolerance = tolerance || 2;

    var start;

    view.addEventListener('touchstart', function(evt) {
 		start = evt;

    });

    view.addEventListener('touchend', function (end) {

        var dx = end.x - start.x, dy = end.y - start.y;

        var dist = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));

        // only trigger if dragged further than 50 pixels

        if (dist < 50) {
 			end.source = start.source;
 			Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>huzzah, click at ("+end.source.dataIndex+") fire");
			enterDetailView(end.source.dataIndex);
			//view.fireEvent('click', end);
            return;

        }else{
        	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>huzzah, swip ("+dist+") dist");

        	//view.removeEventListener('click',enterDetailView);
        }

        var isVertical = Math.abs(dx / dy) < 1 / tolerance;

        var isHorizontal = Math.abs(dy / dx) < 1 / tolerance;

        // only trigger if dragged in a particular direction

        if (!isVertical && !isHorizontal) {

            return;

        }

        // disallow vertical swipe, depending on the setting

        if (!allowVertical && isVertical) {

            return;

        }

        // now fire the event off so regular 'swipe' handlers can use this!

        end.direction = isHorizontal ? ((dx < 0) ? 'left' : 'right') : ((dy < 0) ? 'up' : 'down');

        end.type = 'swipe';

 		end.source = start.source;

        view.fireEvent('swipe', end);

    });

}
function showRemoveButton(e)
{
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>show remove button for the row: "+ e.source.dataIndex );

	var aFavorite = data[e.source.dataIndex ];

			//create table row
			var row = Titanium.UI.createTableViewRow({
				_title:aFavorite.title,
				_description: aFavorite.description,
				_link:aFavorite.link,
				hasChild: false,
				className: 'favorite-row',
				filter: aFavorite.title,
				height:70,
				backgroundColor: '#fff'
			});
			//title label for row at index i
			var titleLabel = Titanium.UI.createLabel({
				text: aFavorite.title,
				font : {fontSize: 14, fontWeight : ' bold' },
				left: 70,
				top: 10,
				height: 50,
				width: 160,
				color:'#232',
				dataIndex:e.source.dataIndex
			});

			Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>huzzah, a row :"+ aFavorite.title+" id:"+aFavorite.id);

 			if(Ti.Platform.osname != 'iphone'){

				enableSwipe	(titleLabel,false,10);
				titleLabel.addEventListener("swipe", showRemoveButton);
				//titleLabel.addEventListener("click", enterDetailView);
			}

			row.add(titleLabel);

			//add our little icon to the left of the row
			var iconImage = Titanium.UI.createImageView({
				image: 'img/eggcooking.png',
				width: 50,
				height: 50,
				left: 10,
				top: 10
			});

			row.add(iconImage);

			//remove button
			var removeButton = Titanium.UI.createButton({
				title: 'Remove',
				right: 	10,
				top:	20,
				width: 	61,
				height:	30,
				font : {fontSize: 10, fontWeight : 'bold' },
				color: '#fff',
				shadowColor:"#121",
				backgroundImage:"img/remove_normal.png",
				backgroundSelectedImage:"img/remove_pressed.png"
			});
			removeButton.show();
			row.add(removeButton);
		favoritesTable.updateRow(e.source.dataIndex,row,true);
}
function enterDetailView(dataIndex)
{
	//Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>go  a row: "+ e.source.rowIndex +" detail.");
	var theFavorite = data[dataIndex];
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>go  a recipe: "+ theFavorite.title);

	// create detail window
	var detailWindow = Titanium.UI.createWindow({
		id:theFavorite.id,
		_title:theFavorite.title,
		_description:theFavorite.description,
		_link:theFavorite.link,
		backgroundColor:'#fff',
		title:theFavorite.title,
		url: 'detail.js',
		id:0
	});

	Titanium.UI.currentTab.open(detailWindow);
}
<commit_msg>Try to achieve issue #6: For Android platform, add longclick event listener to each tableviewrow. Noticed that the title label will fire the long click event, not the row itself, when user pressed on the label's coverage. There is one remained problem: I has add 'delete' event listener to the table, it should be triggered when a table row is deleted and it will remove the recipe from db. It works fine on iOS, but the event is not fired on Android.<commit_after>/**
 * @author Chia-Yuan Hsiung
 */
Ti.include('database.js');

var win = Titanium.UI.currentWindow;

//the data storage empty array
var data = [];
//define search bar which will attach to  table view
var searchBar = Titanium.UI.createSearchBar({
	showCancel:true,
	height :43,
	top:0
});

//print out the searchbar value whenever it changes
searchBar.addEventListener('change' , function(e){

	Ti.API.info('user searching for: ' + e.value);
});
//when the return key is hit, make searchBar get blur
searchBar.addEventListener('return' , function(e){
	searchBar.blur();
});

//when the cancel but ton is tapped,make searchBar get blur too
searchBar.addEventListener('cancel', function(e){
	searchBar.blur();
});
//end of search bar
//create a table view
var favoritesTable = Titanium.UI.createTableView({
	height: 366,
	width: 	320,
	top: 	0,
	left: 	0,
	search: searchBar,
	filterAttribute:'filter',
	editable: true,
	deleteButtonTitle: 'Remove'
});
//tablerow selected function: create new window
favoritesTable.addEventListener('click', function(e){
	//get the selected row index
	var theFavoriteIndex = e.index;
	enterDetailView(theFavoriteIndex);
});

favoritesTable.addEventListener('delete', function(e){
	var removedID = data[e.index].id;

	deleteFavorite(removedID);
	Ti.API.info('>>>>>>>>>>>>>>>>>>>>>>Deleted favorite records. (id ' + removedID + ')');

});

win.add(favoritesTable);
favoritesTable.hide();

//no favorite label
var noFavLabel = Titanium.UI.createLabel({
	color:'#999',
	text:'No Favorites yet.',
	font:{fontSize:20,fontFamily:'Helvetica Neue'},
	textAlign:'center',
	height:40,
	width:'auto',
	top: 100,

});
win.add(noFavLabel);
noFavLabel.hide();

function loadFavorites(){

	data = getFavorites();

	if(data.length>0){

		var tableData = [];
		//get through each item
		for(var i = 0; i < data.length; i++)
		{
			var aFavorite = data[i];

			//create table row
			var row = Titanium.UI.createTableViewRow({
				dataIndex:i,
				_title:aFavorite.title,
				_description: aFavorite.description,
				_link:aFavorite.link,
				hasChild: true,
				className: 'favorite-row',
				filter: aFavorite.title,
				height:70,
				backgroundColor: '#fff',

			});
			//title label for row at index i
			var titleLabel = Titanium.UI.createLabel({
				text: aFavorite.title,
				font : {fontSize: 14, fontWeight : ' bold' },
				left: 70,
				top: 10,
				height: 50,
				width: 210,
				color:'#232',
				dataIndex:i
			});

			row.add(titleLabel);

			//add our little icon to the left of the row
			var iconImage = Titanium.UI.createImageView({
				image: 'img/eggcooking.png',
				width: 50,
				height: 50,
				left: 10,
				top: 10
			});

			row.add(iconImage);

			//when app is running on Android platform, show
			//remove favorite alert when longClick event is triggered
			if(Ti.Platform.osname == 'android'){
				row.addEventListener('longclick', function(e){
					Ti.API.info(e.source);

					//get the selected row index
					var theFavoriteIndex = e.source.dataIndex;
					showRemoveAlert(theFavoriteIndex);

				});
			}

			//add the row to data array
			tableData.push(row);
		}
		// set the data to tableview's data
		favoritesTable.data = tableData;
		favoritesTable.show();
		noFavLabel.hide();
	}else{
		favoritesTable.hide();
		noFavLabel.show();
	}

}
//the focus event l istener wi l l ensure that the l ist / / is refreshed whenever the tab is changed
win.addEventListener('focus', loadFavorites);

function removeFavoriteRow(rowIndex)
{
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>> row "+rowIndex+" is going to be deleted.");
	favoritesTable.deleteRow(rowIndex);

}
function showRemoveAlert(theFavoriteIndex)
{
	var aFavorite = data[theFavoriteIndex];
	var alertDialog = Titanium.UI.createAlertDialog({
		rowIndex:theFavoriteIndex,
    	title: 'Remove',
    	message: 'Do you want to remove recipe:\"'+aFavorite.title+'\" from your favories ?',
    	buttonNames: ['OK','Doh!']
	});
	alertDialog.addEventListener('click',removeAlertClick);
	alertDialog.show();
}
function removeAlertClick(e)
{
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>user click: "+ e.index );

	if(e.cancel || e.index == 1)
	{
		return;
	}else{
		removeFavoriteRow(e.source.rowIndex);
	}

}
function enterDetailView(dataIndex)
{
	//Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>go  a row: "+ e.source.rowIndex +" detail.");
	var theFavorite = data[dataIndex];
	Titanium.API.info(">>>>>>>>>>>>>>>>>>>>>>go  a recipe: "+ theFavorite.title);

	// create detail window
	var detailWindow = Titanium.UI.createWindow({
		id:theFavorite.id,
		_title:theFavorite.title,
		_description:theFavorite.description,
		_link:theFavorite.link,
		backgroundColor:'#fff',
		title:theFavorite.title,
		url: 'detail.js',
		id:0
	});

	Titanium.UI.currentTab.open(detailWindow);
}
<|endoftext|>