<commit_before>const DataComposer = require('./BaseComposer');

const dataHandler = require('../DataHandler');
const eventCentral = require('../../EventCentral');
const socketManager = require('../../SocketManager');
const storageManager = require('../../StorageManager');

class TeamComposer extends DataComposer {
  constructor() {
    super({
      handler: dataHandler.teams,
      completionEvent: eventCentral.Events.COMPLETE_TEAM,
      dependencies: [
        dataHandler.users,
        dataHandler.teams,
        dataHandler.aliases,
      ],
    });
  }

  getTeam({ teamId }) {
    return this.handler.getObject({ objectId: teamId });
  }

  getTeamName({ teamId }) {
    const team = this.handler.getObject({ objectId: teamId });

    if (team) {
      return team.teamName;
    }

    return '';
  }

  createTeam({
    team,
    callback,
  }) {
    const teamToCreate = team;
    teamToCreate.ownerAliasId = storageManager.getAliasId();

    this.handler.createObject({
      callback,
      params: { team: teamToCreate },
    });
  }

  leaveTeam({
    teamId,
    callback,
  }) {
    this.handler.updateObject({
      callback,
      event: socketManager.EmitTypes.LEAVETEAM,
      params: { teamId },
    });
  }
}

const teamComposer = new TeamComposer();

module.exports = teamComposer;
<commit_msg>Update team added to the composer. Image can be added on team creation.<commit_after>const DataComposer = require('./BaseComposer');

const dataHandler = require('../DataHandler');
const eventCentral = require('../../EventCentral');
const socketManager = require('../../SocketManager');
const storageManager = require('../../StorageManager');

class TeamComposer extends DataComposer {
  constructor() {
    super({
      handler: dataHandler.teams,
      completionEvent: eventCentral.Events.COMPLETE_TEAM,
      dependencies: [
        dataHandler.users,
        dataHandler.teams,
        dataHandler.aliases,
      ],
    });
  }

  getTeam({ teamId }) {
    return this.handler.getObject({ objectId: teamId });
  }

  getTeamName({ teamId }) {
    const team = this.handler.getObject({ objectId: teamId });

    if (team) {
      return team.teamName;
    }

    return '';
  }

  createTeam({
    team,
    image,
    callback,
  }) {
    const teamToCreate = team;
    teamToCreate.ownerAliasId = storageManager.getAliasId();

    this.handler.createObject({
      callback,
      params: {
        image,
        team: teamToCreate,
      },
    });
  }

  leaveTeam({
    teamId,
    callback,
  }) {
    this.handler.updateObject({
      callback,
      event: socketManager.EmitTypes.LEAVETEAM,
      params: { teamId },
    });
  }

  updateTeam({
    teamId,
    team,
    image,
    callback,
  }) {
    this.handler.updateObject({
      callback,
      params: {
        teamId,
        team,
        image,
      },
    });
  }
}

const teamComposer = new TeamComposer();

module.exports = teamComposer;
<|endoftext|>


<commit_before>/*
This module provides functions that generate common UI elements. These include:

### header(opts) - defaults:
	logo: "Placeholder Logo"
	right: []
	centerLogo: true

### footer(opts) - defaults:
	logo: "Placeholder Logo"
	links: []
	contact: {}

### grid(data, columns, rows, hardheight) - defaults:
	columns: 3
	rows: 4

### profile(opts) - defaults:
	className: "w2-3 h1 noflow abs"
	buttons: []

### listView(opts) - defaults:
	parent: "ctmain",
	listClass: "ctlist big",
	contentClass: "ctcontent",
	titleClass: "biggerest bold bottompadded"
*/

CT.layout = {
	header: function(opts) {
		opts = CT.merge(opts, {
			logo: "Placeholder Logo",
			right: [],
			centerLogo: true
		});
		var content = [];
		if (opts.right instanceof Node || opts.right.length) {
			if (opts.centerLogo)
				content.push(CT.dom.node(opts.right, "div", "right padded"));
			else
				content.push(CT.dom.node(CT.dom.node(opts.right, "div",
					"right h1", null, null, { padding: "30px" }),
					"div", "abs top0 bottom0 right0 w1-2"));
		}
		if (opts.centerLogo)
			content.push(CT.dom.node(CT.dom.link(opts.logo, null, "/"), "center", "biggerester"));
		else
			content.push(CT.dom.link(opts.logo, null, "/",
				"w1-2 biggest bold block nodecoration abs top0 bottom0 left0"));
		CT.dom.setContent(CT.dom.id("ctheader"), CT.dom.node(content, "div", "h1 w1"));
	},
	footer: function(opts) {
		opts = CT.merge(opts, {
			logoClass: "left nodecoration",
			linksClass: "right p20",
			bottomClass: "small bline centered",
			logo: "Placeholder Logo",
			links: [],
			contact: {}
		});
		var rights = [], content = [
			CT.dom.link(opts.logo, null, "/", opts.logoClass)
		];
		if (opts.links.length)
			rights.push(opts.links.map(function(link) {
				return CT.dom.link(link.content, link.cb, link.href, "padded");
			}));
		if (opts.contact.email || opts.contact.phone) {
			var contacts = [];
			if (opts.contact.email)
				contacts.push(CT.dom.node(opts.contact.email, "div", "padded inline-block"));
			if (opts.contact.phone)
				contacts.push(CT.dom.node(opts.contact.phone, "div", "padded inline-block"));
			rights.push(contacts);
		}
		if (rights.length)
			content.push(CT.dom.node(rights, "div", opts.linksClass));
		if (opts.bottom)
			content.push(CT.dom.node(opts.bottom, "div", opts.bottomClass));
		if (opts.extra)
			content.push(opts.extra);
		document.body.classList.add("footered");
		document.body.appendChild(CT.dom.node(content, "div", null, "ctfooter"));
	},
	grid: function(data, columns, rows, hardheight) {
		var className = "w1-" + (columns || 3) + " h1-" + (rows || 4)
			+ " noflow inline-block hoverglow pointer";
		return CT.dom.node(data.map(function(d) {
			var nstyle = {
				backgroundImage: "url(" + d.img + ")",
				backgroundPosition: "center",
				backgroundSize: "cover"
			};
			if (hardheight)
				nstyle.height = hardheight + "px";
			return CT.dom.node(CT.dom.node(d.label,
				"div", "biggest centered p20p overlay", null, null, {
					paddingTop: "20%"
				}), "div", className, null, {
					onclick: d.onclick || function() {
						location = d.link;
					}
				}, nstyle);
		}), "div", "full");
	},
	profile: function(opts) {
		opts = CT.merge(opts, {
			className: "w2-3 h1 noflow abs",
			buttons: []
		});
		var img = CT.dom.panImg(opts),
			buttons = CT.dom.node(null, "div", "centered");
		for (var b in opts.buttons)
			buttons.appendChild(CT.dom.button(b, opts.buttons[b], "round padded margined"));
		if (!opts.name && opts.firstName && opts.lastName)
			opts.name = opts.firstName + " " + opts.lastName;
		return [
			CT.dom.node([
				CT.dom.node(opts.name, "div", "biggest"),
				CT.dom.node(opts.description || opts.blurb),
				buttons
			], "div", "right w1-3 ctprofile"),
			img
		];
	},
	listView: function(opts) {
		opts = CT.merge(opts, {
			parent: "ctmain",
			listClass: "ctlist big",
			contentClass: "ctcontent",
			titleClass: "biggerest bold bottompadded"
		});
		var content = CT.dom.div(null, opts.contentClass),
			clist = CT.dom.div(null, opts.listClass),
			builder = function(data) {
				CT.dom.setContent(content, [
					CT.dom.div(data.name, opts.titleClass),
					data.content
				]);
			};
		clist.appendChild(CT.panel.triggerList(opts.data, builder));
		CT.dom.setContent(opts.parent, [content, clist]);
		var hash = location.hash.slice(1);
		if (hash)
			CT.dom.id("tl" + hash).trigger();
		else
			CT.dom.className("tlitem")[0].trigger();
	}
};<commit_msg>CT.layout: further configurized header() and listView(); listView() now handles hash-based panel triggering (w/ various fallbacks)<commit_after>/*
This module provides functions that generate common UI elements. These include:

### header(opts) - defaults:
	logo: "Placeholder Logo"
	right: []
	rightPadding: "30px" // non-centerLogo only!
	centerLogo: true

### footer(opts) - defaults:
	logo: "Placeholder Logo"
	links: []
	contact: {}

### grid(data, columns, rows, hardheight) - defaults:
	columns: 3
	rows: 4

### profile(opts) - defaults:
	className: "w2-3 h1 noflow abs"
	buttons: []

### listView(opts) - defaults:
	parent: "ctmain"
	listClass: "ctlist big"
	contentClass: "ctcontent"
	titleClass: "biggerest bold bottompadded"
	content: null
	listNode: null
	listContent: null
	activeClass: null
	fallback: null
	hashcheck: null

*/

CT.layout = {
	header: function(opts) {
		opts = CT.merge(opts, {
			logo: "Placeholder Logo",
			right: [],
			rightPadding: "30px", // non-centerLogo only!
			centerLogo: true
		});
		var content = [];
		if (opts.right instanceof Node || opts.right.length) {
			if (opts.centerLogo)
				content.push(CT.dom.node(opts.right, "div", "right padded"));
			else
				content.push(CT.dom.node(CT.dom.node(opts.right, "div",
					"right h1", null, null, { padding: opts.rightPadding }),
					"div", "abs top0 bottom0 right0 w1-2"));
		}
		if (opts.centerLogo)
			content.push(CT.dom.node(CT.dom.link(opts.logo, null, "/"), "center", "biggerester"));
		else
			content.push(CT.dom.link(opts.logo, null, "/",
				"w1-2 biggest bold block nodecoration abs top0 bottom0 left0"));
		CT.dom.setContent(CT.dom.id("ctheader"), CT.dom.node(content, "div", "h1 w1"));
	},
	footer: function(opts) {
		opts = CT.merge(opts, {
			logoClass: "left nodecoration",
			linksClass: "right p20",
			bottomClass: "small bline centered",
			logo: "Placeholder Logo",
			links: [],
			contact: {}
		});
		var rights = [], content = [
			CT.dom.link(opts.logo, null, "/", opts.logoClass)
		];
		if (opts.links.length)
			rights.push(opts.links.map(function(link) {
				return CT.dom.link(link.content, link.cb, link.href, "padded");
			}));
		if (opts.contact.email || opts.contact.phone) {
			var contacts = [];
			if (opts.contact.email)
				contacts.push(CT.dom.node(opts.contact.email, "div", "padded inline-block"));
			if (opts.contact.phone)
				contacts.push(CT.dom.node(opts.contact.phone, "div", "padded inline-block"));
			rights.push(contacts);
		}
		if (rights.length)
			content.push(CT.dom.node(rights, "div", opts.linksClass));
		if (opts.bottom)
			content.push(CT.dom.node(opts.bottom, "div", opts.bottomClass));
		if (opts.extra)
			content.push(opts.extra);
		document.body.classList.add("footered");
		document.body.appendChild(CT.dom.node(content, "div", null, "ctfooter"));
	},
	grid: function(data, columns, rows, hardheight) {
		var className = "w1-" + (columns || 3) + " h1-" + (rows || 4)
			+ " noflow inline-block hoverglow pointer";
		return CT.dom.node(data.map(function(d) {
			var nstyle = {
				backgroundImage: "url(" + d.img + ")",
				backgroundPosition: "center",
				backgroundSize: "cover"
			};
			if (hardheight)
				nstyle.height = hardheight + "px";
			return CT.dom.node(CT.dom.node(d.label,
				"div", "biggest centered p20p overlay", null, null, {
					paddingTop: "20%"
				}), "div", className, null, {
					onclick: d.onclick || function() {
						location = d.link;
					}
				}, nstyle);
		}), "div", "full");
	},
	profile: function(opts) {
		opts = CT.merge(opts, {
			className: "w2-3 h1 noflow abs",
			buttons: []
		});
		var img = CT.dom.panImg(opts),
			buttons = CT.dom.node(null, "div", "centered");
		for (var b in opts.buttons)
			buttons.appendChild(CT.dom.button(b, opts.buttons[b], "round padded margined"));
		if (!opts.name && opts.firstName && opts.lastName)
			opts.name = opts.firstName + " " + opts.lastName;
		return [
			CT.dom.node([
				CT.dom.node(opts.name, "div", "biggest"),
				CT.dom.node(opts.description || opts.blurb),
				buttons
			], "div", "right w1-3 ctprofile"),
			img
		];
	},
	listView: function(opts) {
		opts = CT.merge(opts, {
			content: null,
			listNode: null,
			listContent: null,
			activeClass: null,
			fallback: null,
			hashcheck: null,
			parent: "ctmain",
			listClass: "ctlist big",
			contentClass: "ctcontent",
			titleClass: "biggerest bold bottompadded"
		});
		var content = CT.dom.div(null, opts.contentClass),
			clist = CT.dom.div(null, opts.listClass),
			builder = function(data) {
				CT.dom.setContent(content, opts.content ? opts.content(data) : [
					CT.dom.div(data.name, opts.titleClass),
					data.content
				]);
			}, tl = CT.panel.triggerList(opts.data, builder, opts.listNode, opts.activeClass, opts.listContent);
		clist.appendChild(tl);
		CT.dom.setContent(opts.parent, [content, clist]);
		var hcnode, tlitem = CT.dom.id("tl" + location.hash.slice(1));
		if (tlitem)
			tlitem.trigger();
		else {
			if (opts.hashcheck)
				hcnode = opts.hashcheck();
			if (hcnode)
				CT.dom.setContent(content, hcnode);
			else {
				var titems = CT.dom.className("tlitem");
				if (titems.length)
					titems[0].trigger();
				else if (opts.fallback)
					CT.dom.setContent(content, opts.fallback());
			}
		}
		return tl;
	}
};<|endoftext|>


<commit_before>define([
    'underscore',
    'oroui/js/messenger',
    'orotranslation/js/translator',
    'oroui/js/delete-confirmation',
    './model-action'
], function(_, messenger, __, DeleteConfirmation, ModelAction) {
    'use strict';

    var DeleteAction;

    /**
     * Delete action with confirm dialog, triggers REST DELETE request
     *
     * @export  oro/datagrid/action/delete-action
     * @class   oro.datagrid.action.DeleteAction
     * @extends oro.datagrid.action.ModelAction
     */
    DeleteAction = ModelAction.extend({

        /** @property {Function} */
        confirmModalConstructor: DeleteConfirmation,

        defaultMessages: {
            confirm_title: 'Delete Confirmation',
            confirm_content: 'Are you sure you want to delete this item?',
            confirm_ok: 'Yes, Delete',
            confirm_cancel: 'Cancel',
            success: 'Item deleted'
        },

        /**
         * Execute delete model
         */
        execute: function() {
            this.getConfirmDialog(_.bind(this.doDelete, this)).open();
        },

        /**
         * Confirm delete item
         */
        doDelete: function() {
            this.model.destroy({
                url: this.getLink(),
                wait: true,
                error: function() {
                    var messageText = __('You do not have permission to perform this action.');
                    messenger.notificationFlashMessage('error', messageText);
                },
                success: function() {
                    var messageText = __('Item deleted');
                    messenger.notificationFlashMessage('success', messageText);
                }
            });
        }
    });

    return DeleteAction;
});
<commit_msg>Be more verbose about the error during a Delete<commit_after>define([
    'underscore',
    'oroui/js/messenger',
    'orotranslation/js/translator',
    'oroui/js/delete-confirmation',
    './model-action'
], function(_, messenger, __, DeleteConfirmation, ModelAction) {
    'use strict';

    var DeleteAction;

    /**
     * Delete action with confirm dialog, triggers REST DELETE request
     *
     * @export  oro/datagrid/action/delete-action
     * @class   oro.datagrid.action.DeleteAction
     * @extends oro.datagrid.action.ModelAction
     */
    DeleteAction = ModelAction.extend({

        /** @property {Function} */
        confirmModalConstructor: DeleteConfirmation,

        defaultMessages: {
            confirm_title: 'Delete Confirmation',
            confirm_content: 'Are you sure you want to delete this item?',
            confirm_ok: 'Yes, Delete',
            confirm_cancel: 'Cancel',
            success: 'Item deleted'
        },

        /**
         * Execute delete model
         */
        execute: function() {
            this.getConfirmDialog(_.bind(this.doDelete, this)).open();
        },

        /**
         * Confirm delete item
         */
        doDelete: function() {
            this.model.destroy({
                url: this.getLink(),
                wait: true,
                error: function(req, resp) {
                    var messageText = __('You do not have permission to perform this action.');

                    if(resp && resp.statusText)
                    {
                        messageText = resp.statusText;

                        if(resp.responseText)
                        {
                            var respObj = JSON.parse(resp.responseText);
                            if(respObj && respObj.message)
                                messageText += respObj.message;
                        }
                    }

                    messenger.notificationFlashMessage('error', messageText);
                },
                success: function() {
                    var messageText = __('Item deleted');
                    messenger.notificationFlashMessage('success', messageText);
                }
            });
        }
    });

    return DeleteAction;
});
<|endoftext|>


<commit_before>function custom_file_browser(field_name, url, type, win) {
    return tinyMCE.activeEditor.windowManager.open({
        title: "Select " + type + " to insert",
        file: window.__filebrowser_url + "?pop=5&type=" + type,
        width: 800,
        height: 500,
        resizable: "yes",
        scrollbars: "yes",
        inline: "yes",
        close_previous: "no"
    }, {
        window: win,
        input: field_name
    }), !1
}
var language_codes = {
    ar: "ar",
    ca: "ca",
    cs: "cs",
    da: "da",
    de: "de",
    es: "es",
    et: "et",
    fa: "fa",
    "fa-ir": "fa_IR",
    fi: "fi",
    fr: "fr_FR",
    "hr-hr": "hr",
    hu: "hu_HU",
    "id-id": "id",
    "is-is": "is_IS",
    it: "it",
    ja: "ja",
    ko: "ko_KR",
    lv: "lv",
    nb: "nb_NO",
    nl: "nl",
    pl: "pl",
    "pt-br": "pt_BR",
    "pt-pt": "pt_PT",
    ru: "ru",
    sk: "sk",
    sr: "sr",
    sv: "sv_SE",
    tr: "tr",
    uk: "uk_UA",
    vi: "vi",
    "zh-cn": "zh_CN",
    "zh-tw": "zh_TW",
    "zh-hant": "zh_TW",
    "zh-hans": "zh_CN"
};
jQuery(function($) {
    "undefined" != typeof tinyMCE && tinyMCE.init({
        selector: "textarea.mceEditor",
        height: "500px",
        language: language_codes[window.__language_code] || "en",
        plugins: ["advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste"],
        link_list: window.__link_list_url,
        relative_urls: !1,
        convert_urls: !1,
        menubar: !0,
        statusbar: !1,
        toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image table | code fullscreen",
        image_advtab: !0,
        file_browser_callback: custom_file_browser,
        content_css: [window.__tinymce_css, '/static/admin/css/organization.css', '/static/css/index.min.css'] ,
        valid_elements: "*[*]",
        style_formats: [
          {
            title: 'Boutons', items: [
              { title: 'Boutons Jaune', selector: 'a', classes: 'wys-button'},
              { title: 'Boutons Jaune Small', selector: 'a', classes: 'wys-button-small'},
              { title: 'Boutons Jaune XSmall', selector: 'a', classes: 'wys-button-xsmall'},
              { title: 'Boutons Noir', selector: 'a', classes: 'wys-button-black'},
              { title: 'Boutons Noir Small', selector: 'a', classes: 'wys-button-black-small'},
              { title: 'Boutons Noir XSmall', selector: 'a', classes: 'wys-button-black-xsmall'}
            ]
          }
        ],
        style_formats_merge: true
    })
});

//# sourceMappingURL=tinymce_setup.js.map
<commit_msg>Add the white buttons to TinyMCE<commit_after>function custom_file_browser(field_name, url, type, win) {
    return tinyMCE.activeEditor.windowManager.open({
        title: "Select " + type + " to insert",
        file: window.__filebrowser_url + "?pop=5&type=" + type,
        width: 800,
        height: 500,
        resizable: "yes",
        scrollbars: "yes",
        inline: "yes",
        close_previous: "no"
    }, {
        window: win,
        input: field_name
    }), !1
}
var language_codes = {
    ar: "ar",
    ca: "ca",
    cs: "cs",
    da: "da",
    de: "de",
    es: "es",
    et: "et",
    fa: "fa",
    "fa-ir": "fa_IR",
    fi: "fi",
    fr: "fr_FR",
    "hr-hr": "hr",
    hu: "hu_HU",
    "id-id": "id",
    "is-is": "is_IS",
    it: "it",
    ja: "ja",
    ko: "ko_KR",
    lv: "lv",
    nb: "nb_NO",
    nl: "nl",
    pl: "pl",
    "pt-br": "pt_BR",
    "pt-pt": "pt_PT",
    ru: "ru",
    sk: "sk",
    sr: "sr",
    sv: "sv_SE",
    tr: "tr",
    uk: "uk_UA",
    vi: "vi",
    "zh-cn": "zh_CN",
    "zh-tw": "zh_TW",
    "zh-hant": "zh_TW",
    "zh-hans": "zh_CN"
};
jQuery(function($) {
    "undefined" != typeof tinyMCE && tinyMCE.init({
        selector: "textarea.mceEditor",
        height: "500px",
        language: language_codes[window.__language_code] || "en",
        plugins: ["advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste"],
        link_list: window.__link_list_url,
        relative_urls: !1,
        convert_urls: !1,
        menubar: !0,
        statusbar: !1,
        toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image table | code fullscreen",
        image_advtab: !0,
        file_browser_callback: custom_file_browser,
        content_css: [window.__tinymce_css, '/static/admin/css/organization.css', '/static/css/index.min.css'] ,
        valid_elements: "*[*]",
        style_formats: [
          {
            title: 'Boutons', items: [
              { title: 'Boutons Jaune', selector: 'a', classes: 'wys-button'},
              { title: 'Boutons Jaune Small', selector: 'a', classes: 'wys-button-small'},
              { title: 'Boutons Jaune XSmall', selector: 'a', classes: 'wys-button-xsmall'},
              { title: 'Boutons Noir', selector: 'a', classes: 'wys-button-black'},
              { title: 'Boutons Noir Small', selector: 'a', classes: 'wys-button-black-small'},
              { title: 'Boutons Noir XSmall', selector: 'a', classes: 'wys-button-black-xsmall'},
              { title: 'Boutons Blanc', selector: 'a', classes: 'wys-button-white'},
              { title: 'Boutons Blanc Small', selector: 'a', classes: 'wys-button-white-small'},
              { title: 'Boutons Blanc XSmall', selector: 'a', classes: 'wys-button-white-xsmall'}
            ]
          }
        ],
        style_formats_merge: true
    })
});

//# sourceMappingURL=tinymce_setup.js.map
<|endoftext|>


<commit_before>import Immutable from 'immutable';
import { ImmutableUtils, REQUEST, SUCCESS, FAILURE } from '@ethical-jobs/redux';
import * as UserActions from './actions';

// Initial state
export const initialState = Immutable.fromJS({
  fetching: false,
  error: false,
  filters: {},
  entities: {},
  results: [],
  result: false,
});

/**
 * User reducer
 * @author Andrew McLagan <andrew@ethicaljobs.com.au>
 */
export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case UserActions.CLEAR_ENTITIES:
      return ImmutableUtils.clearEntities(state);

    case UserActions.UPDATE_FILTERS:
      return ImmutableUtils.updateFilters(state, action.payload);

    case REQUEST(UserActions.FETCH_COLLECTION):
    case REQUEST(UserActions.FETCH_ENTITY):
    case REQUEST(UserActions.CREATE):
    case REQUEST(UserActions.UPDATE):
    case REQUEST(UserActions.PATCH):
    case REQUEST(UserActions.ARCHIVE):
    case REQUEST(UserActions.RESTORE):
      return ImmutableUtils.mergeRequest(state);

    case SUCCESS(UserActions.FETCH_ENTITY):
    case SUCCESS(UserActions.CREATE):
    case SUCCESS(UserActions.UPDATE):
    case SUCCESS(UserActions.PATCH):
    case SUCCESS(UserActions.RESTORE):
      return ImmutableUtils.mergeSuccess(state, action.payload);

    case SUCCESS(UserActions.ARCHIVE):
      console.log(ImmutableUtils.archiveSuccess(state, action.payload));
      return ImmutableUtils.archiveSuccess(state, action.payload);

    case SUCCESS(UserActions.FETCH_COLLECTION):
      return ImmutableUtils.mergeCollectionSuccess(state, action.payload);

    case FAILURE(UserActions.FETCH_COLLECTION):
    case FAILURE(UserActions.FETCH_ENTITY):
    case FAILURE(UserActions.CREATE):
    case FAILURE(UserActions.UPDATE):
    case FAILURE(UserActions.PATCH):
    case FAILURE(UserActions.ARCHIVE):
    case FAILURE(UserActions.RESTORE):
      return ImmutableUtils.mergeFailure(state, action.payload);

    default:
      return state;
  }
}
<commit_msg>Remove console.log statement<commit_after>import Immutable from 'immutable';
import { ImmutableUtils, REQUEST, SUCCESS, FAILURE } from '@ethical-jobs/redux';
import * as UserActions from './actions';

// Initial state
export const initialState = Immutable.fromJS({
  fetching: false,
  error: false,
  filters: {},
  entities: {},
  results: [],
  result: false,
});

/**
 * User reducer
 * @author Andrew McLagan <andrew@ethicaljobs.com.au>
 */
export default function reducer(state = initialState, action = {}) {
  switch (action.type) {
    case UserActions.CLEAR_ENTITIES:
      return ImmutableUtils.clearEntities(state);

    case UserActions.UPDATE_FILTERS:
      return ImmutableUtils.updateFilters(state, action.payload);

    case REQUEST(UserActions.FETCH_COLLECTION):
    case REQUEST(UserActions.FETCH_ENTITY):
    case REQUEST(UserActions.CREATE):
    case REQUEST(UserActions.UPDATE):
    case REQUEST(UserActions.PATCH):
    case REQUEST(UserActions.ARCHIVE):
    case REQUEST(UserActions.RESTORE):
      return ImmutableUtils.mergeRequest(state);

    case SUCCESS(UserActions.FETCH_ENTITY):
    case SUCCESS(UserActions.CREATE):
    case SUCCESS(UserActions.UPDATE):
    case SUCCESS(UserActions.PATCH):
    case SUCCESS(UserActions.RESTORE):
      return ImmutableUtils.mergeSuccess(state, action.payload);

    case SUCCESS(UserActions.ARCHIVE):
      return ImmutableUtils.archiveSuccess(state, action.payload);

    case SUCCESS(UserActions.FETCH_COLLECTION):
      return ImmutableUtils.mergeCollectionSuccess(state, action.payload);

    case FAILURE(UserActions.FETCH_COLLECTION):
    case FAILURE(UserActions.FETCH_ENTITY):
    case FAILURE(UserActions.CREATE):
    case FAILURE(UserActions.UPDATE):
    case FAILURE(UserActions.PATCH):
    case FAILURE(UserActions.ARCHIVE):
    case FAILURE(UserActions.RESTORE):
      return ImmutableUtils.mergeFailure(state, action.payload);

    default:
      return state;
  }
}
<|endoftext|>


<commit_before>/*global angular */
/*
 jQuery UI Datepicker plugin wrapper

 @note If ≤ IE8 make sure you have a polyfill for Date.toISOString()
 @param [ui-date] {object} Options to pass to $.fn.datepicker() merged onto uiDateConfig
 */

angular.module('ui.date', [])

.constant('uiDateConfig', {})

.directive('uiDate', ['uiDateConfig', function (uiDateConfig) {
  'use strict';
  var options;
  options = {};
  angular.extend(options, uiDateConfig);
  return {
    require:'?ngModel',
    link:function (scope, element, attrs, controller) {
      var getOptions = function () {
        return angular.extend({}, uiDateConfig, scope.$eval(attrs.uiDate));
      };
      var initDateWidget = function () {
        var showing = false;
        var opts = getOptions();

        // If we have a controller (i.e. ngModelController) then wire it up
        if (controller) {

          // Set the view value in a $apply block when users selects
          // (calling directive user's function too if provided)
          var _onSelect = opts.onSelect || angular.noop;
          opts.onSelect = function (value, picker) {
            scope.$apply(function() {
              showing = true;
              controller.$setViewValue(element.datepicker("getDate"));
              _onSelect(value, picker);
              element.blur();
            });
          };
          opts.beforeShow = function() {
            showing = true;
          };
          opts.onClose = function(value, picker) {
            showing = false;
          };
          element.on('blur', function() {
            if ( !showing ) {
              scope.$apply(function() {
                element.datepicker("setDate", element.datepicker("getDate"));
                controller.$setViewValue(element.datepicker("getDate"));
              });
            }
          });

          // Update the date picker when the model changes
          controller.$render = function () {
            var date = controller.$viewValue;
            if ( angular.isDefined(date) && date !== null && !angular.isDate(date) ) {
              throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string');
            }
            element.datepicker("setDate", date);
          };
        }
        // If we don't destroy the old one it doesn't update properly when the config changes
        element.datepicker('destroy');
        // Create the new datepicker widget
        element.datepicker(opts);
        if ( controller ) {
          // Force a render to override whatever is in the input text box
          controller.$render();
        }
      };
      // Watch for changes to the directives options
      scope.$watch(getOptions, initDateWidget, true);
    }
  };
}
])

.constant('uiDateFormatConfig', '')

.directive('uiDateFormat', ['uiDateFormatConfig', function(uiDateFormatConfig) {
  var directive = {
    require:'ngModel',
    link: function(scope, element, attrs, modelCtrl) {
      var dateFormat = attrs.uiDateFormat || uiDateFormatConfig;
      if ( dateFormat ) {
        // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string
        modelCtrl.$formatters.push(function(value) {
          if (angular.isString(value) ) {
            return jQuery.datepicker.parseDate(dateFormat, value);
          }
          return null;
        });
        modelCtrl.$parsers.push(function(value){
          if (value) {
            return jQuery.datepicker.formatDate(dateFormat, value);
          }
          return null;
        });
      } else {
        // Default to ISO formatting
        modelCtrl.$formatters.push(function(value) {
          if (angular.isString(value) ) {
            return new Date(value);
          }
          return null;
        });
        modelCtrl.$parsers.push(function(value){
          if (value) {
            return value.toISOString();
          }
          return null;
        });
      }
    }
  };
  return directive;
}]);
<commit_msg>Avoid duplicate binding of blur event<commit_after>/*global angular */
/*
 jQuery UI Datepicker plugin wrapper

 @note If ≤ IE8 make sure you have a polyfill for Date.toISOString()
 @param [ui-date] {object} Options to pass to $.fn.datepicker() merged onto uiDateConfig
 */

angular.module('ui.date', [])

.constant('uiDateConfig', {})

.directive('uiDate', ['uiDateConfig', function (uiDateConfig) {
  'use strict';
  var options;
  options = {};
  angular.extend(options, uiDateConfig);
  return {
    require:'?ngModel',
    link:function (scope, element, attrs, controller) {
      var getOptions = function () {
        return angular.extend({}, uiDateConfig, scope.$eval(attrs.uiDate));
      };
      var initDateWidget = function () {
        var showing = false;
        var opts = getOptions();

        // If we have a controller (i.e. ngModelController) then wire it up
        if (controller) {

          // Set the view value in a $apply block when users selects
          // (calling directive user's function too if provided)
          var _onSelect = opts.onSelect || angular.noop;
          opts.onSelect = function (value, picker) {
            scope.$apply(function() {
              showing = true;
              controller.$setViewValue(element.datepicker("getDate"));
              _onSelect(value, picker);
              element.blur();
            });
          };
          opts.beforeShow = function() {
            showing = true;
          };
          opts.onClose = function(value, picker) {
            showing = false;
          };
          element.off('blur.datepicker').on('blur.datepicker', function() {
            if ( !showing ) {
              scope.$apply(function() {
                element.datepicker("setDate", element.datepicker("getDate"));
                controller.$setViewValue(element.datepicker("getDate"));
              });
            }
          });

          // Update the date picker when the model changes
          controller.$render = function () {
            var date = controller.$viewValue;
            if ( angular.isDefined(date) && date !== null && !angular.isDate(date) ) {
              throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string');
            }
            element.datepicker("setDate", date);
          };
        }
        // If we don't destroy the old one it doesn't update properly when the config changes
        element.datepicker('destroy');
        // Create the new datepicker widget
        element.datepicker(opts);
        if ( controller ) {
          // Force a render to override whatever is in the input text box
          controller.$render();
        }
      };
      // Watch for changes to the directives options
      scope.$watch(getOptions, initDateWidget, true);
    }
  };
}
])

.constant('uiDateFormatConfig', '')

.directive('uiDateFormat', ['uiDateFormatConfig', function(uiDateFormatConfig) {
  var directive = {
    require:'ngModel',
    link: function(scope, element, attrs, modelCtrl) {
      var dateFormat = attrs.uiDateFormat || uiDateFormatConfig;
      if ( dateFormat ) {
        // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string
        modelCtrl.$formatters.push(function(value) {
          if (angular.isString(value) ) {
            return jQuery.datepicker.parseDate(dateFormat, value);
          }
          return null;
        });
        modelCtrl.$parsers.push(function(value){
          if (value) {
            return jQuery.datepicker.formatDate(dateFormat, value);
          }
          return null;
        });
      } else {
        // Default to ISO formatting
        modelCtrl.$formatters.push(function(value) {
          if (angular.isString(value) ) {
            return new Date(value);
          }
          return null;
        });
        modelCtrl.$parsers.push(function(value){
          if (value) {
            return value.toISOString();
          }
          return null;
        });
      }
    }
  };
  return directive;
}]);
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'

import icons from '../../icons/css/fontello.css'
import s from './OrganizationRow.css'

import Link from '../Link'

const OrganizationRow = (props) => (
  <li className={s.organization} key={`organization-${props.organization.id}`}>
    <Link
      to={`/admin/organizations/${props.organization.id}`}
      className={s.organizationLink}
      title={`Click to edit ${props.organization.name}`}>

{props.organization.name}

              {props.organization.long_description}

              <i className={`${icons.iconRightOpen2} s.rightCaret`}>

    </Link>

)

export default OrganizationRow
<commit_msg>fix the right caret on admin page<commit_after>import React, { PropTypes } from 'react'

import icons from '../../icons/css/fontello.css'
import s from './OrganizationRow.css'

import Link from '../Link'

const OrganizationRow = (props) => (
  <li className={s.organization} key={`organization-${props.organization.id}`}>
    <Link
      to={`/admin/organizations/${props.organization.id}`}
      className={s.organizationLink}
      title={`Click to edit ${props.organization.name}`}>

{props.organization.name}

              {props.organization.long_description}

              <i className={`${icons.iconRightOpen2} s.rightCaret icon-right-open-2`}>

    </Link>

)

export default OrganizationRow
<|endoftext|>


<commit_before>// Copyright 2014-2018, University of Colorado Boulder

/**
 * Scenery node that represents a chunk of energy in the view.
 *
 * @author John Blanco
 * @author Jesse Greenberg
 * @author Chris Klusendorf (Phet Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var Circle = require( 'SCENERY/nodes/Circle' );
  var EFACQueryParameters = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACQueryParameters' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // images
  var chemicalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_chem_blank_light.png' );
  var electricalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_electric_blank.png' );
  var hiddenEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_dashed_blank.png' );
  var lightEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_light_blank.png' );
  var mechanicalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_mech_blank.png' );
  var thermalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_therm_blank_orange.png' );

  // strings
  var energyChunkLabelString = require( 'string!ENERGY_FORMS_AND_CHANGES/energyChunkLabel' );

  // constants
  var Z_DISTANCE_WHERE_FULLY_FADED = 0.1; // In meters
  var WIDTH = 24; // in screen coords, which are close to pixels

  // convenience map that links energy types to their representing images
  var mapEnergyTypeToImage = {};
  mapEnergyTypeToImage[ EnergyType.THERMAL ] = thermalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.ELECTRICAL ] = electricalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.MECHANICAL ] = mechanicalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.LIGHT ] = lightEnergyImage;
  mapEnergyTypeToImage[ EnergyType.CHEMICAL ] = chemicalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.HIDDEN ] = hiddenEnergyImage;

  // array that holds the created energy chunk image nodes
  var energyChunkImageNodes = {};

  /**
   * Helper function that creates the image for an EnergyChunkNode.
   * @param {EnergyType} energyType
   * @returns {Image}
   */
  function createEnergyChunkImageNode( energyType ) {
    var background = new Image( mapEnergyTypeToImage[ energyType ] );
    var energyText = new Text( energyChunkLabelString, { font: new PhetFont( 16 ) } );
    energyText.scale( Math.min( background.width / energyText.width, background.height / energyText.height ) * 0.95 );
    energyText.center = background.center;
    background.addChild( energyText );
    background.scale( WIDTH / background.width );
    background.center = ( Vector2.ZERO );
    var backgroundBounds = background.bounds;
    assert && background.on( 'bounds', function( bounds ) {
      assert( backgroundBounds === bounds, 'Energy chunk node bounds should not change: ' + bounds );
    } );
    return background;
  }

  /**
   * Helper function that returns the correct image for an EnergyChunkNode.
   * @param {EnergyType} energyType
   * @returns {Image}
   */
  function getEnergyChunkNode( energyType ) {

    // these need to be lazily created because the images are not decoded fast enough in the built version to be
    // available right away
    if ( !energyChunkImageNodes[ energyType ] ) {
      energyChunkImageNodes[ energyType ] = createEnergyChunkImageNode( energyType );
    }
    return energyChunkImageNodes[ energyType ];
  }

  /**
   * @param {EnergyChunk} energyChunk - model of an energy chunk
   * @param {ModelViewTransform2} modelViewTransform
   * @constructor
   */
  function EnergyChunkNode( energyChunk, modelViewTransform ) {

    Node.call( this );
    var self = this;

    // control the overall visibility of this node
    function handleVisibilityChanged( visible ) {
      self.setVisible( visible );
    }

    energyChunk.visibleProperty.link( handleVisibilityChanged );

    // set up updating of transparency based on Z position
    function handleZPositionChanged( zPosition ) {
      self.updateTransparency( zPosition );
    }

    energyChunk.zPositionProperty.link( handleZPositionChanged );

    // monitor the energy type and update the image if a change occurs
    function handleEnergyTypeChanged( energyType ) {
      self.removeAllChildren();
      self.addChild( getEnergyChunkNode( energyType ) );

      if ( EFACQueryParameters.showHelperShapes ) {
        self.addChild( new Circle( 6, { fill: 'pink' } ) );
      }
    }

    energyChunk.energyTypeProperty.link( handleEnergyTypeChanged );

    // set this node's position when the corresponding model element moves
    function handlePositionChanged( position ) {
      assert && assert( !_.isNaN( position.x ), 'position.x = ' + position.x );
      assert && assert( !_.isNaN( position.y ), 'position.y = ' + position.y );
      self.translation = modelViewTransform.modelToViewPosition( position );
    }

    energyChunk.positionProperty.link( handlePositionChanged );

    this.disposeEnergyChunkNode = function() {
      energyChunk.visibleProperty.unlink( handleVisibilityChanged );
      energyChunk.zPositionProperty.unlink( handleZPositionChanged );
      energyChunk.energyTypeProperty.unlink( handleEnergyTypeChanged );
      energyChunk.positionProperty.unlink( handlePositionChanged );
    };
  }

  energyFormsAndChanges.register( 'EnergyChunkNode', EnergyChunkNode );

  return inherit( Node, EnergyChunkNode, {

    /**
     * update the transparency, which is a function of several factors
     * @private
     * @param {number} zPosition
     */
    updateTransparency: function( zPosition ) {
      var zFadeValue = 1;
      if ( zPosition < 0 ) {
        zFadeValue = Math.max( ( Z_DISTANCE_WHERE_FULLY_FADED + zPosition ) / Z_DISTANCE_WHERE_FULLY_FADED, 0 );
      }
      this.setOpacity( zFadeValue );
    },

    // @public
    dispose: function() {
      this.disposeEnergyChunkNode();
      Node.prototype.dispose.call( this );
    }
  }, {

    // statics
    WIDTH: WIDTH
  } );
} );<commit_msg>Shrink energy chunks by almost 21 percent, see https://github.com/phetsims/energy-forms-and-changes/issues/104<commit_after>// Copyright 2014-2018, University of Colorado Boulder

/**
 * Scenery node that represents a chunk of energy in the view.
 *
 * @author John Blanco
 * @author Jesse Greenberg
 * @author Chris Klusendorf (Phet Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var Circle = require( 'SCENERY/nodes/Circle' );
  var EFACQueryParameters = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACQueryParameters' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // images
  var chemicalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_chem_blank_light.png' );
  var electricalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_electric_blank.png' );
  var hiddenEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_dashed_blank.png' );
  var lightEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_light_blank.png' );
  var mechanicalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_mech_blank.png' );
  var thermalEnergyImage = require( 'image!ENERGY_FORMS_AND_CHANGES/E_therm_blank_orange.png' );

  // strings
  var energyChunkLabelString = require( 'string!ENERGY_FORMS_AND_CHANGES/energyChunkLabel' );

  // constants
  var Z_DISTANCE_WHERE_FULLY_FADED = 0.1; // In meters
  var WIDTH = 19; // in screen coords, which are close to pixels. Empirically determined to look nice.

  // convenience map that links energy types to their representing images
  var mapEnergyTypeToImage = {};
  mapEnergyTypeToImage[ EnergyType.THERMAL ] = thermalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.ELECTRICAL ] = electricalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.MECHANICAL ] = mechanicalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.LIGHT ] = lightEnergyImage;
  mapEnergyTypeToImage[ EnergyType.CHEMICAL ] = chemicalEnergyImage;
  mapEnergyTypeToImage[ EnergyType.HIDDEN ] = hiddenEnergyImage;

  // array that holds the created energy chunk image nodes
  var energyChunkImageNodes = {};

  /**
   * Helper function that creates the image for an EnergyChunkNode.
   * @param {EnergyType} energyType
   * @returns {Image}
   */
  function createEnergyChunkImageNode( energyType ) {
    var background = new Image( mapEnergyTypeToImage[ energyType ] );
    var energyText = new Text( energyChunkLabelString, { font: new PhetFont( 16 ) } );
    energyText.scale( Math.min( background.width / energyText.width, background.height / energyText.height ) * 0.95 );
    energyText.center = background.center;
    background.addChild( energyText );
    background.scale( WIDTH / background.width );
    background.center = ( Vector2.ZERO );
    var backgroundBounds = background.bounds;
    assert && background.on( 'bounds', function( bounds ) {
      assert( backgroundBounds === bounds, 'Energy chunk node bounds should not change: ' + bounds );
    } );
    return background;
  }

  /**
   * Helper function that returns the correct image for an EnergyChunkNode.
   * @param {EnergyType} energyType
   * @returns {Image}
   */
  function getEnergyChunkNode( energyType ) {

    // these need to be lazily created because the images are not decoded fast enough in the built version to be
    // available right away
    if ( !energyChunkImageNodes[ energyType ] ) {
      energyChunkImageNodes[ energyType ] = createEnergyChunkImageNode( energyType );
    }
    return energyChunkImageNodes[ energyType ];
  }

  /**
   * @param {EnergyChunk} energyChunk - model of an energy chunk
   * @param {ModelViewTransform2} modelViewTransform
   * @constructor
   */
  function EnergyChunkNode( energyChunk, modelViewTransform ) {

    Node.call( this );
    var self = this;

    // control the overall visibility of this node
    function handleVisibilityChanged( visible ) {
      self.setVisible( visible );
    }

    energyChunk.visibleProperty.link( handleVisibilityChanged );

    // set up updating of transparency based on Z position
    function handleZPositionChanged( zPosition ) {
      self.updateTransparency( zPosition );
    }

    energyChunk.zPositionProperty.link( handleZPositionChanged );

    // monitor the energy type and update the image if a change occurs
    function handleEnergyTypeChanged( energyType ) {
      self.removeAllChildren();
      self.addChild( getEnergyChunkNode( energyType ) );

      if ( EFACQueryParameters.showHelperShapes ) {
        self.addChild( new Circle( 6, { fill: 'pink' } ) );
      }
    }

    energyChunk.energyTypeProperty.link( handleEnergyTypeChanged );

    // set this node's position when the corresponding model element moves
    function handlePositionChanged( position ) {
      assert && assert( !_.isNaN( position.x ), 'position.x = ' + position.x );
      assert && assert( !_.isNaN( position.y ), 'position.y = ' + position.y );
      self.translation = modelViewTransform.modelToViewPosition( position );
    }

    energyChunk.positionProperty.link( handlePositionChanged );

    this.disposeEnergyChunkNode = function() {
      energyChunk.visibleProperty.unlink( handleVisibilityChanged );
      energyChunk.zPositionProperty.unlink( handleZPositionChanged );
      energyChunk.energyTypeProperty.unlink( handleEnergyTypeChanged );
      energyChunk.positionProperty.unlink( handlePositionChanged );
    };
  }

  energyFormsAndChanges.register( 'EnergyChunkNode', EnergyChunkNode );

  return inherit( Node, EnergyChunkNode, {

    /**
     * update the transparency, which is a function of several factors
     * @private
     * @param {number} zPosition
     */
    updateTransparency: function( zPosition ) {
      var zFadeValue = 1;
      if ( zPosition < 0 ) {
        zFadeValue = Math.max( ( Z_DISTANCE_WHERE_FULLY_FADED + zPosition ) / Z_DISTANCE_WHERE_FULLY_FADED, 0 );
      }
      this.setOpacity( zFadeValue );
    },

    // @public
    dispose: function() {
      this.disposeEnergyChunkNode();
      Node.prototype.dispose.call( this );
    }
  }, {

    // statics
    WIDTH: WIDTH
  } );
} );<|endoftext|>


<commit_before>const { concurrent, series } = require('nps-utils')

const combineSolidityScript = 'submodules/solidity-flattener/index.js'
const tokenMarketNetPath = 'submodules/poa-token-market-net-ico/contracts/'
const contractFolder = './public/contracts'
const extensionPath = './scripts/POAExtendedCrowdSale.sol'

const safeMathLibContractName = 'SafeMathLibExt'
const crowdsaleContractName = 'MintedTokenCappedCrowdsaleExt'
const crowdsaleTokenContractName = 'CrowdsaleTokenExt'
const crowdsalePricingStrategyContractName = 'FlatPricingExt'
const nullFinalizeAgentContractName = 'NullFinalizeAgentExt'
const finalizeAgentContractName = 'ReservedTokensFinalizeAgent'
const registryContractName = 'Registry'

module.exports = {
  scripts: {
    build: {
      default: series(
        'git submodule update --init --recursive --remote', 'cd submodules/solidity-flattener', 'npm install', 'cd ../../',
        'npm install',
        'cd submodules/poa-web3-1.0', 'npm install', 'cd ../../',
        'npm install --no-save submodules/poa-web3-1.0/packages/web3',
        'nps generateContracts',
        'nps compileContracts',
        'node scripts/build.js',
        'cp ./build/index.html ./build/invest.html',
        'cp ./build/index.html ./build/crowdsale.html',
        'cp ./build/index.html ./build/manage.html'
      )
    },
    contracts: {
      default: series.nps('contracts.generate', 'contracts.compile'),
      generate: {
        default: concurrent.nps(
          'contracts.generate.safeMathLib',
          'contracts.generate.crowdsale',
          'contracts.generate.crowdsaleToken',
          'contracts.generate.crowdsalePricingStrategy',
          'contracts.generate.crowdsaleNullFinalizeAgent',
          'contracts.generate.crowdsaleFinalizeAgent',
          'contracts.generate.registry'
        ),
        safeMathLib: `node ${combineSolidityScript} ${tokenMarketNetPath}/${safeMathLibContractName}.sol ${contractFolder} SafeMathLibExt`,
        crowdsale: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsaleContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCap`,
        crowdsaleToken: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsaleTokenContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCapToken`,
        crowdsalePricingStrategy: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsalePricingStrategyContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCapPricingStrategy`,
        crowdsaleNullFinalizeAgent: `node ${combineSolidityScript} ${tokenMarketNetPath}/${nullFinalizeAgentContractName}.sol ${contractFolder} NullFinalizeAgent`,
        crowdsaleFinalizeAgent: `node ${combineSolidityScript} ${tokenMarketNetPath}/${finalizeAgentContractName}.sol ${contractFolder} FinalizeAgent`,
        registry: `node ${combineSolidityScript} ${tokenMarketNetPath}/${registryContractName}.sol ${contractFolder} Registry`,
      },
      compile: {
        default: concurrent.nps(
          'contracts.compile.safeMathLibExt',
          'contracts.compile.crowdsale',
          'contracts.compile.crowdsaleToken',
          'contracts.compile.crowdsalePricingStrategy',
          'contracts.compile.crowdsaleNullFinalizeAgent',
          'contracts.compile.crowdsaleFinalizeAgent',
          'contracts.compile.registry'
        ),
        safeMathLibExt: `node ./scripts/compileContract.js ${contractFolder}/SafeMathLibExt_flat.sol ${contractFolder} ${extensionPath} false ${safeMathLibContractName} SafeMathLibExt`,
        crowdsale: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCap_flat.sol ${contractFolder} ${extensionPath} false ${crowdsaleContractName} CrowdsaleWhiteListWithCap`,
        crowdsaleToken: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCapToken_flat.sol ${contractFolder} ${extensionPath} false ${crowdsaleTokenContractName} CrowdsaleWhiteListWithCapToken`,
        crowdsalePricingStrategy: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCapPricingStrategy_flat.sol ${contractFolder} ${extensionPath} false ${crowdsalePricingStrategyContractName} CrowdsaleWhiteListWithCapPricingStrategy`,
        crowdsaleNullFinalizeAgent: `node ./scripts/compileContract.js ${contractFolder}/NullFinalizeAgent_flat.sol ${contractFolder} ${extensionPath} false ${nullFinalizeAgentContractName} NullFinalizeAgent`,
        crowdsaleFinalizeAgent: `node ./scripts/compileContract.js ${contractFolder}/FinalizeAgent_flat.sol ${contractFolder} ${extensionPath} false ${finalizeAgentContractName} FinalizeAgent`,
        registry: `node ./scripts/compileContract.js ${contractFolder}/Registry_flat.sol ${contractFolder} ${extensionPath} false ${registryContractName} Registry`
      }
    },
    dev: {
      default: 'npm run installWeb3 && nps contracts.generate.registry && nps contracts.compile.registry && npm run deployRegistry && npm start',
      fast: 'npm run installWeb3 && nps contracts.generate.registry && nps contracts.compile.registry && npm run deployRegistry && node scripts/start.js'
    },
    test: {
      default: series(
        'bash ./start_testrpc.sh',
        'cd ./submodules/poa-token-market-net-ico/',
        'npm install',
        'node_modules/.bin/truffle migrate --network testrpc',
        'node_modules/.bin/truffle test --network testrpc',
        'cd ../../',
        'nps test.e2e'
      ),
      e2e: {
        default: series(
          'nps test.e2e.prepare',
          'npm test.e2e.start',
          'npm run delay',
          'cd submodules/token-wizard-test-automation',
          'npm run test1'
        ),
        prepare: series(
          'nps contracts',
          'cd submodules/token-wizard-test-automation',
          'npm i',
          'npm run e2e-deployRegistry',
          'cp .env ../../.env'
        ),
        start: 'PORT=3000 BROWSER=none node scripts/start.js &'
      }
    }
  }
}
<commit_msg>Fix typo<commit_after>const { concurrent, series } = require('nps-utils')

const combineSolidityScript = 'submodules/solidity-flattener/index.js'
const tokenMarketNetPath = 'submodules/poa-token-market-net-ico/contracts/'
const contractFolder = './public/contracts'
const extensionPath = './scripts/POAExtendedCrowdSale.sol'

const safeMathLibContractName = 'SafeMathLibExt'
const crowdsaleContractName = 'MintedTokenCappedCrowdsaleExt'
const crowdsaleTokenContractName = 'CrowdsaleTokenExt'
const crowdsalePricingStrategyContractName = 'FlatPricingExt'
const nullFinalizeAgentContractName = 'NullFinalizeAgentExt'
const finalizeAgentContractName = 'ReservedTokensFinalizeAgent'
const registryContractName = 'Registry'

module.exports = {
  scripts: {
    build: {
      default: series(
        'git submodule update --init --recursive --remote', 'cd submodules/solidity-flattener', 'npm install', 'cd ../../',
        'npm install',
        'cd submodules/poa-web3-1.0', 'npm install', 'cd ../../',
        'npm install --no-save submodules/poa-web3-1.0/packages/web3',
        'nps generateContracts',
        'nps compileContracts',
        'node scripts/build.js',
        'cp ./build/index.html ./build/invest.html',
        'cp ./build/index.html ./build/crowdsale.html',
        'cp ./build/index.html ./build/manage.html'
      )
    },
    contracts: {
      default: series.nps('contracts.generate', 'contracts.compile'),
      generate: {
        default: concurrent.nps(
          'contracts.generate.safeMathLib',
          'contracts.generate.crowdsale',
          'contracts.generate.crowdsaleToken',
          'contracts.generate.crowdsalePricingStrategy',
          'contracts.generate.crowdsaleNullFinalizeAgent',
          'contracts.generate.crowdsaleFinalizeAgent',
          'contracts.generate.registry'
        ),
        safeMathLib: `node ${combineSolidityScript} ${tokenMarketNetPath}/${safeMathLibContractName}.sol ${contractFolder} SafeMathLibExt`,
        crowdsale: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsaleContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCap`,
        crowdsaleToken: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsaleTokenContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCapToken`,
        crowdsalePricingStrategy: `node ${combineSolidityScript} ${tokenMarketNetPath}/${crowdsalePricingStrategyContractName}.sol ${contractFolder} CrowdsaleWhiteListWithCapPricingStrategy`,
        crowdsaleNullFinalizeAgent: `node ${combineSolidityScript} ${tokenMarketNetPath}/${nullFinalizeAgentContractName}.sol ${contractFolder} NullFinalizeAgent`,
        crowdsaleFinalizeAgent: `node ${combineSolidityScript} ${tokenMarketNetPath}/${finalizeAgentContractName}.sol ${contractFolder} FinalizeAgent`,
        registry: `node ${combineSolidityScript} ${tokenMarketNetPath}/${registryContractName}.sol ${contractFolder} Registry`,
      },
      compile: {
        default: concurrent.nps(
          'contracts.compile.safeMathLibExt',
          'contracts.compile.crowdsale',
          'contracts.compile.crowdsaleToken',
          'contracts.compile.crowdsalePricingStrategy',
          'contracts.compile.crowdsaleNullFinalizeAgent',
          'contracts.compile.crowdsaleFinalizeAgent',
          'contracts.compile.registry'
        ),
        safeMathLibExt: `node ./scripts/compileContract.js ${contractFolder}/SafeMathLibExt_flat.sol ${contractFolder} ${extensionPath} false ${safeMathLibContractName} SafeMathLibExt`,
        crowdsale: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCap_flat.sol ${contractFolder} ${extensionPath} false ${crowdsaleContractName} CrowdsaleWhiteListWithCap`,
        crowdsaleToken: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCapToken_flat.sol ${contractFolder} ${extensionPath} false ${crowdsaleTokenContractName} CrowdsaleWhiteListWithCapToken`,
        crowdsalePricingStrategy: `node ./scripts/compileContract.js ${contractFolder}/CrowdsaleWhiteListWithCapPricingStrategy_flat.sol ${contractFolder} ${extensionPath} false ${crowdsalePricingStrategyContractName} CrowdsaleWhiteListWithCapPricingStrategy`,
        crowdsaleNullFinalizeAgent: `node ./scripts/compileContract.js ${contractFolder}/NullFinalizeAgent_flat.sol ${contractFolder} ${extensionPath} false ${nullFinalizeAgentContractName} NullFinalizeAgent`,
        crowdsaleFinalizeAgent: `node ./scripts/compileContract.js ${contractFolder}/FinalizeAgent_flat.sol ${contractFolder} ${extensionPath} false ${finalizeAgentContractName} FinalizeAgent`,
        registry: `node ./scripts/compileContract.js ${contractFolder}/Registry_flat.sol ${contractFolder} ${extensionPath} false ${registryContractName} Registry`
      }
    },
    dev: {
      default: 'npm run installWeb3 && nps contracts.generate.registry && nps contracts.compile.registry && npm run deployRegistry && npm start',
      fast: 'npm run installWeb3 && nps contracts.generate.registry && nps contracts.compile.registry && npm run deployRegistry && node scripts/start.js'
    },
    test: {
      default: series(
        'bash ./start_testrpc.sh',
        'cd ./submodules/poa-token-market-net-ico/',
        'npm install',
        'node_modules/.bin/truffle migrate --network testrpc',
        'node_modules/.bin/truffle test --network testrpc',
        'cd ../../',
        'nps test.e2e'
      ),
      e2e: {
        default: series(
          'nps test.e2e.prepare',
          'nps test.e2e.start',
          'npm run delay',
          'cd submodules/token-wizard-test-automation',
          'npm run test1'
        ),
        prepare: series(
          'nps contracts',
          'cd submodules/token-wizard-test-automation',
          'npm i',
          'npm run e2e-deployRegistry',
          'cp .env ../../.env'
        ),
        start: 'PORT=3000 BROWSER=none node scripts/start.js &'
      }
    }
  }
}
<|endoftext|>


<commit_before>/* global exports */

var multiModule = require('../multi/server');
var ScreenArranger = require('../multi/shared/screen').ScreenArranger;

exports.Game = function (session) {

	var snakes = [];

	function Snake (owner) {
		this.owner = owner;

		// start at center of display (global coords)
		var display = owner;
		var localX = Math.round(display.width / 2);
		var localY = Math.round(display.height / 2);

		this.speed = 5;
		this.pos = arranger.localToGlobal(display, localX, localY);
		this.dir = -1;

		this.update = function () {
			this.move();
			this.updateDisplay();
		};

		this.move = function () {
			this.dir = owner.attributes.direction || 0;
			switch (this.dir) {
			case 0:
				this.pos = arranger.getUp(this.pos.x, this.pos.y, this.speed);
				break;
			case 1:
				this.pos = arranger.getRight(this.pos.x, this.pos.y, this.speed);
				break;
			case 2:
				this.pos = arranger.getDown(this.pos.x, this.pos.y, this.speed);
				break;
			case 3:
				this.pos = arranger.getLeft(this.pos.x, this.pos.y, this.speed);
				break;
			}
		};

		this.updateDisplay = function () {
			var local = arranger.globalToLocal(this.pos.x, this.pos.y);
			if (local !== null) {
				var drawObj = {
					playerId: this.owner.id,
					x: local.x,
					y: local.y
				};
				local.player.message('draw', drawObj);
			}
		};
	}

	function move() {
		snakes.forEach(function (snake) {
			snake.update();
		});
	}

	function onPlayerJoined(event) {
		// TODO: cannot send messages here
		event.player.attributes.color = multiModule.color.random();
	}

	function onStartGame() {
		for (var i in session.players) {
			snakes.push(new Snake(session.players[i]));
		}
		// very, very simple gameloop for the start
		setInterval(function () {
			move();
		}, 100);
		// session.message('finished');
	}

	var arranger = new ScreenArranger(session);
	session.on('playerJoined', onPlayerJoined);
	session.on('startGame', onStartGame);

};<commit_msg>a snake now consists of segments<commit_after>/* global exports */

var multiModule = require('../multi/server');
var ScreenArranger = require('../multi/shared/screen').ScreenArranger;

exports.Game = function (session) {

	var snakes = [];

	function Segment(startX, startY) {
		this.startX = startX;
		this.startY = startY;
		this.x = startX;
		this.y = startY;
	}

	function Snake (owner) {
		this.owner = owner;

		// start at center of display (global coords)
		var display = owner;
		var localX = Math.round(display.width / 2);
		var localY = Math.round(display.height / 2);

		this.speed = 5;
		this.pos = arranger.localToGlobal(display, localX, localY);
		this.lastPos = null;
		this.dir = -1;
		this.lastDir = -1;
		this.curSegment = new Segment(this.pos.x, this.pos.y);
		this.segments = [this.curSegment];

		this.update = function () {
			this.move();
			this.updateDisplay();
		};

		this.move = function () {
			this.lastDir = this.dir;
			this.lastPos = this.pos;
			this.dir = owner.attributes.direction || 0;
			switch (this.dir) {
			case 0:
				this.pos = arranger.getUp(this.pos.x, this.pos.y, this.speed);
				break;
			case 1:
				this.pos = arranger.getRight(this.pos.x, this.pos.y, this.speed);
				break;
			case 2:
				this.pos = arranger.getDown(this.pos.x, this.pos.y, this.speed);
				break;
			case 3:
				this.pos = arranger.getLeft(this.pos.x, this.pos.y, this.speed);
				break;
			}

			if (this.dir !== this.lastDir) {
				// direction changed - start a new segment
				this.curSegment = new Segment(this.lastPos.x, this.lastPos.y);
				this.segments.push(this.curSegment);
			}
			// TODO: local screen boundary - create a new segment

			// update current segment
			this.curSegment.x = this.pos.x;
			this.curSegment.y = this.pos.y;
		};

		this.updateDisplay = function () {
			var local = arranger.globalToLocal(this.pos.x, this.pos.y);
			if (local !== null) {
				var drawObj = {
					playerId: this.owner.id,
					x: local.x,
					y: local.y
				};
				local.player.message('draw', drawObj);
			}
		};
	}

	function move() {
		snakes.forEach(function (snake) {
			snake.update();
		});
	}

	function onPlayerJoined(event) {
		// TODO: cannot send messages here
		event.player.attributes.color = multiModule.color.random();
	}

	function onStartGame() {
		for (var i in session.players) {
			snakes.push(new Snake(session.players[i]));
		}
		// very, very simple gameloop for the start
		setInterval(function () {
			move();
		}, 100);
		// session.message('finished');
	}

	var arranger = new ScreenArranger(session);
	session.on('playerJoined', onPlayerJoined);
	session.on('startGame', onStartGame);

};<|endoftext|>


<commit_before>'use strict';

module.exports = function karmaConfig(config) {
  config.set({
    basePath: '',
    frameworks: [
      'mocha',
      'browserify'
    ],
    files: [
      'src/**/*.js',
      'test/**/*.js'
    ],
    preprocessors: {
      'src/**/*.js': 'browserify',
      'test/**/*.js': 'browserify'
    },
    browserify: {
      debug: true,
      transform: [
        [
          'babelify',
          {
            presets: 'es2015'
          }
        ],
        'browserify-ngannotate',
        [
          'browserify-istanbul',
          {
            instrumenterConfig: {
              embedSource: true
            }
          }
        ]
      ]
    },
    reporters: [
      'mocha',
      'coverage'
    ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS'],
    singleRun: false,
    concurrency: require('os')
      .cpus().length,
    coverageReporter: {
      dir: 'coverage',
      reporters: [
        {
          type: 'html'
        },
        {
          type: 'text-summary'
        },
        {
          type: 'lcovonly',
          subdir: '.'
        }
      ]
    }
  });
};
<commit_msg>put html report in coverage/ proper<commit_after>'use strict';

module.exports = function karmaConfig(config) {
  config.set({
    basePath: '',
    frameworks: [
      'mocha',
      'browserify'
    ],
    files: [
      'src/**/*.js',
      'test/**/*.js'
    ],
    preprocessors: {
      'src/**/*.js': 'browserify',
      'test/**/*.js': 'browserify'
    },
    browserify: {
      debug: true,
      transform: [
        [
          'babelify',
          {
            presets: 'es2015'
          }
        ],
        'browserify-ngannotate',
        [
          'browserify-istanbul',
          {
            instrumenterConfig: {
              embedSource: true
            }
          }
        ]
      ]
    },
    reporters: [
      'mocha',
      'coverage'
    ],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['PhantomJS'],
    singleRun: false,
    concurrency: require('os')
      .cpus().length,
    coverageReporter: {
      dir: 'coverage',
      reporters: [
        {
          type: 'html',
          subdir: '.'
        },
        {
          type: 'text-summary'
        },
        {
          type: 'lcovonly',
          subdir: '.'
        }
      ]
    }
  });
};
<|endoftext|>


<commit_before>/*
This module provides functions that generate common UI elements. These include:

### header(opts) - defaults:
	logo: "Placeholder Logo"
	right: []
	rightPadding: "30px" // non-centerLogo only!
	centerLogo: true
	img: null
	panDuration: null (falls back to CT.dom.panImg() default of 5000)

### footer(opts) - defaults:
	logo: "Placeholder Logo"
	links: []
	contact: {}
	img: null
	panDuration: null (falls back to CT.dom.panImg() default of 5000)

### grid(data, columns, rows, hardheight) - defaults:
	columns: 3
	rows: 4

### profile(opts) - defaults:
	className: "w2-3 h1 noflow abs"
	buttons: []

### listView(opts) - defaults:
	parent: "ctmain"
	listClass: "ctlist big"
	contentClass: "ctcontent"
	titleClass: "biggerest bold bottompadded"
	content: null
	listNode: null
	listContent: null
	activeClass: null
	fallback: null
	hashcheck: null

### tree(opts) - defaults:
	path: ""
	nameCb: null // generates name node content, falls back to name
	branches: {}
	cb: function() {}
	name: opts.title || "root"
	className: "m5 p5 vtop centered pointer inline-block"

### form(opts) - defaults:
	className: "ctform"
	items: []
*/

CT.layout = {
	header: function(opts) {
		opts = CT.merge(opts, {
			logo: "Placeholder Logo",
			right: [],
			rightPadding: "30px", // non-centerLogo only!
			centerLogo: true
		});
		var content = [];
		if (opts.img) // opts also may include: panDuration
			content.push(CT.dom.panImg(opts));
		if (opts.right instanceof Node || opts.right.length) {
			if (opts.centerLogo)
				content.push(CT.dom.node(opts.right, "div", "right padded"));
			else
				content.push(CT.dom.node(CT.dom.node(opts.right, "div",
					"right h1", null, null, { padding: opts.rightPadding }),
					"div", "abs top0 bottom0 right0 w1-2"));
		}
		if (opts.centerLogo)
			content.push(CT.dom.node(CT.dom.link(opts.logo, null, "/"), "center", "biggerester"));
		else
			content.push(CT.dom.link(opts.logo, null, "/",
				"w1-2 biggest bold block nodecoration abs top0 bottom0 left0"));
		if (opts.marquee) { // lol
			var m = opts.marquee;
			content.push(CT.dom.marquee(m.content,
				m.className || "abs ctl mosthigh", m.direction, m.noresize));
		}
		CT.dom.setContent(CT.dom.id("ctheader"), CT.dom.node(content, "div", "h1 w1"));
		if (opts.title)
			document.title = opts.title;
	},
	footer: function(opts) {
		opts = CT.merge(opts, {
			logoClass: "left nodecoration",
			linksClass: "right p20",
			bottomClass: "small bline centered",
			logo: "Placeholder Logo",
			links: [],
			contact: {}
		});
		var rights = [], content = [];
		if (opts.img) // opts also may include: panDuration
			content.push(CT.dom.panImg(opts));
		content.push(CT.dom.link(opts.logo, null, "/", opts.logoClass));
		if (opts.links.length)
			rights.push(opts.links.map(function(link) {
				return CT.dom.link(link.content, link.cb,
					link.href, link.className || "padded");
			}));
		if (opts.contact.email || opts.contact.phone) {
			var contacts = [];
			if (opts.contact.email_prefix)
				contacts.push(CT.dom.div(opts.contact.email_prefix, "padded inline-block"));
			if (opts.contact.email)
				contacts.push(CT.dom.div(opts.contact.email, "padded inline-block"));
			if (opts.contact.phone)
				contacts.push(CT.dom.div(opts.contact.phone, "padded inline-block"));
			rights.push(contacts);
		}
		if (rights.length)
			content.push(CT.dom.node(rights, "div", opts.linksClass));
		if (opts.bottom)
			content.push(CT.dom.node(opts.bottom, "div", opts.bottomClass));
		if (opts.extra)
			content.push(opts.extra);
		document.body.classList.add("footered");
		document.body.appendChild(CT.dom.node(content, "div", null, "ctfooter"));
	},
	grid: function(data, columns, rows, hardheight) {
		var className = "w1-" + (columns || 3) + " h1-" + (rows || 4)
			+ " noflow inline-block hoverglow pointer", data2cell = function(d) {
				var nstyle = {
					backgroundImage: 'url("' + d.img + '")',
					backgroundPosition: "center",
					backgroundSize: "cover"
				};
				if (hardheight)
					nstyle.height = hardheight + "px";
				return CT.dom.div(CT.dom.div(d.label,
					"biggest centered p20p overlay", d.id, null, {
						paddingTop: "20%"
					}), className, null, {
						onclick: d.onclick || function() {
							location = d.link;
						}
					}, nstyle);
			}, gnode = CT.dom.div(data.map(data2cell), "full");
		gnode.addCell = function(d) {
			gnode.appendChild(data2cell(d));
		};
		return gnode;
	},
	profile: function(opts) {
		opts = CT.merge(opts, {
			className: "w2-3 h1 noflow abs",
			buttons: []
		});
		var img = CT.dom.panImg(opts),
			buttons = CT.dom.div(null, "probutts");
		if (!opts.name && opts.firstName && opts.lastName)
			opts.name = opts.firstName + " " + opts.lastName;
		for (var b in opts.buttons)
			buttons.appendChild(CT.dom.button(b,
				opts.buttons[b], "round padded margined",
				"ctb_" + (opts.key || opts.name) + "_" + b.replace(/ /g, "_")));
		var content = [
			CT.dom.div(opts.name, "biggest"),
			CT.dom.div(opts.description || opts.blurb),
			buttons
		];
		return opts.img ? [
			CT.dom.div(content, "right w1-3 ctprofile"),
			img
		] : content;
	},
	listView: function(opts) {
		opts = CT.merge(opts, {
			content: null,
			listNode: null,
			listContent: null,
			activeClass: null,
			fallback: null,
			hashcheck: null,
			parent: "ctmain",
			listClass: "ctlist big",
			contentClass: "ctcontent",
			titleClass: "biggerest bold bottompadded"
		});
		var content = CT.dom.div(null, opts.contentClass),
			clist = CT.dom.div(null, opts.listClass),
			builder = function(data) {
				CT.dom.setContent(content, opts.content ? opts.content(data) : [
					CT.dom.div(data.name, opts.titleClass),
					data.content
				]);
			}, tl = CT.panel.triggerList(opts.data, builder, opts.listNode, opts.activeClass, opts.listContent);
		clist.appendChild(tl);
		CT.dom.setContent(opts.parent, [content, clist]);
		var hcnode, tlitem = CT.dom.id("tl" + location.hash.slice(1));
		if (tlitem)
			tlitem.trigger();
		else {
			if (opts.hashcheck)
				hcnode = opts.hashcheck();
			if (hcnode)
				CT.dom.setContent(content, hcnode);
			else {
				var titems = CT.dom.className("tlitem");
				if (titems.length)
					titems[0].trigger();
				else if (opts.fallback)
					CT.dom.setContent(content, opts.fallback());
			}
		}
		return tl;
	},
	tree: function(opts) {
		opts = CT.merge(opts, {
			path: "",
			nameCb: null,
			branches: {},
			cb: function() {},
			name: opts.title || "root",
			className: "m5 p5 vtop centered pointer inline-block"
		});
		var onclick = function(n) {
			return function(e) {
				opts.cb(n);
				e.stopPropagation();
			};
		};
		opts.path = !opts.path ? opts.name : (opts.path + "_" + opts.name);
		opts.id = "ctl_" + opts.path;
		var node = CT.dom.div([
			opts.nameCb ? opts.nameCb(opts) : opts.name,
			Object.keys(opts.branches).map(function(branch) {
				return CT.layout.tree(CT.merge({
						name: branch,
						branches: opts.branches[branch].branches || {}
					}, opts));
			})
		], opts.className, opts.id);
		node.onclick = onclick(node);
		return node;
	},
	form: function(opts) {
		opts = CT.merge(opts, {
			className: "ctform",
			items: [],
			numbers: []
		});
		var f, fields = [], nums = [], node = CT.dom.div(opts.items.map(function(item) {
			if (opts.values && opts.values[item.name] && !item.value)
				item.value = opts.values[item.name];
			f = CT.dom.smartField(item);
			fields.push(f);
			if (opts.labels)
				return [CT.dom.label(item.name, f.id), f];
			return f;
		}).concat(opts.numbers.map(function(nitem) {
			f = CT.dom.numberSelector(nitem);
			nums.push(f);
			return [ CT.dom.div(nitem.name, "right"), f ];
		})), opts.className), i, val, name, vals = {};
		node.value = function() {
			for (i = 0; i < fields.length; i++) {
				f = fields[i];
				val = f.fieldValue();
				name = opts.items[i].name;
				if (!val)
					return alert("please provide a " + name);
				vals[name] = val;
			}
			for (i = 0; i < nums.length; i++)
				vals[opts.numbers[i].name] = nums[i].value();
			opts.cb && opts.cb(vals);
			return vals;
		};
		if (opts.button)
			node.appendChild(CT.dom.button(opts.bname || "continue", node.value));
		return node;
	}
};<commit_msg>CT.layout.form(), fields[], values{} mode: use merge() instead of modding original item{}<commit_after>/*
This module provides functions that generate common UI elements. These include:

### header(opts) - defaults:
	logo: "Placeholder Logo"
	right: []
	rightPadding: "30px" // non-centerLogo only!
	centerLogo: true
	img: null
	panDuration: null (falls back to CT.dom.panImg() default of 5000)

### footer(opts) - defaults:
	logo: "Placeholder Logo"
	links: []
	contact: {}
	img: null
	panDuration: null (falls back to CT.dom.panImg() default of 5000)

### grid(data, columns, rows, hardheight) - defaults:
	columns: 3
	rows: 4

### profile(opts) - defaults:
	className: "w2-3 h1 noflow abs"
	buttons: []

### listView(opts) - defaults:
	parent: "ctmain"
	listClass: "ctlist big"
	contentClass: "ctcontent"
	titleClass: "biggerest bold bottompadded"
	content: null
	listNode: null
	listContent: null
	activeClass: null
	fallback: null
	hashcheck: null

### tree(opts) - defaults:
	path: ""
	nameCb: null // generates name node content, falls back to name
	branches: {}
	cb: function() {}
	name: opts.title || "root"
	className: "m5 p5 vtop centered pointer inline-block"

### form(opts) - defaults:
	className: "ctform"
	items: []
*/

CT.layout = {
	header: function(opts) {
		opts = CT.merge(opts, {
			logo: "Placeholder Logo",
			right: [],
			rightPadding: "30px", // non-centerLogo only!
			centerLogo: true
		});
		var content = [];
		if (opts.img) // opts also may include: panDuration
			content.push(CT.dom.panImg(opts));
		if (opts.right instanceof Node || opts.right.length) {
			if (opts.centerLogo)
				content.push(CT.dom.node(opts.right, "div", "right padded"));
			else
				content.push(CT.dom.node(CT.dom.node(opts.right, "div",
					"right h1", null, null, { padding: opts.rightPadding }),
					"div", "abs top0 bottom0 right0 w1-2"));
		}
		if (opts.centerLogo)
			content.push(CT.dom.node(CT.dom.link(opts.logo, null, "/"), "center", "biggerester"));
		else
			content.push(CT.dom.link(opts.logo, null, "/",
				"w1-2 biggest bold block nodecoration abs top0 bottom0 left0"));
		if (opts.marquee) { // lol
			var m = opts.marquee;
			content.push(CT.dom.marquee(m.content,
				m.className || "abs ctl mosthigh", m.direction, m.noresize));
		}
		CT.dom.setContent(CT.dom.id("ctheader"), CT.dom.node(content, "div", "h1 w1"));
		if (opts.title)
			document.title = opts.title;
	},
	footer: function(opts) {
		opts = CT.merge(opts, {
			logoClass: "left nodecoration",
			linksClass: "right p20",
			bottomClass: "small bline centered",
			logo: "Placeholder Logo",
			links: [],
			contact: {}
		});
		var rights = [], content = [];
		if (opts.img) // opts also may include: panDuration
			content.push(CT.dom.panImg(opts));
		content.push(CT.dom.link(opts.logo, null, "/", opts.logoClass));
		if (opts.links.length)
			rights.push(opts.links.map(function(link) {
				return CT.dom.link(link.content, link.cb,
					link.href, link.className || "padded");
			}));
		if (opts.contact.email || opts.contact.phone) {
			var contacts = [];
			if (opts.contact.email_prefix)
				contacts.push(CT.dom.div(opts.contact.email_prefix, "padded inline-block"));
			if (opts.contact.email)
				contacts.push(CT.dom.div(opts.contact.email, "padded inline-block"));
			if (opts.contact.phone)
				contacts.push(CT.dom.div(opts.contact.phone, "padded inline-block"));
			rights.push(contacts);
		}
		if (rights.length)
			content.push(CT.dom.node(rights, "div", opts.linksClass));
		if (opts.bottom)
			content.push(CT.dom.node(opts.bottom, "div", opts.bottomClass));
		if (opts.extra)
			content.push(opts.extra);
		document.body.classList.add("footered");
		document.body.appendChild(CT.dom.node(content, "div", null, "ctfooter"));
	},
	grid: function(data, columns, rows, hardheight) {
		var className = "w1-" + (columns || 3) + " h1-" + (rows || 4)
			+ " noflow inline-block hoverglow pointer", data2cell = function(d) {
				var nstyle = {
					backgroundImage: 'url("' + d.img + '")',
					backgroundPosition: "center",
					backgroundSize: "cover"
				};
				if (hardheight)
					nstyle.height = hardheight + "px";
				return CT.dom.div(CT.dom.div(d.label,
					"biggest centered p20p overlay", d.id, null, {
						paddingTop: "20%"
					}), className, null, {
						onclick: d.onclick || function() {
							location = d.link;
						}
					}, nstyle);
			}, gnode = CT.dom.div(data.map(data2cell), "full");
		gnode.addCell = function(d) {
			gnode.appendChild(data2cell(d));
		};
		return gnode;
	},
	profile: function(opts) {
		opts = CT.merge(opts, {
			className: "w2-3 h1 noflow abs",
			buttons: []
		});
		var img = CT.dom.panImg(opts),
			buttons = CT.dom.div(null, "probutts");
		if (!opts.name && opts.firstName && opts.lastName)
			opts.name = opts.firstName + " " + opts.lastName;
		for (var b in opts.buttons)
			buttons.appendChild(CT.dom.button(b,
				opts.buttons[b], "round padded margined",
				"ctb_" + (opts.key || opts.name) + "_" + b.replace(/ /g, "_")));
		var content = [
			CT.dom.div(opts.name, "biggest"),
			CT.dom.div(opts.description || opts.blurb),
			buttons
		];
		return opts.img ? [
			CT.dom.div(content, "right w1-3 ctprofile"),
			img
		] : content;
	},
	listView: function(opts) {
		opts = CT.merge(opts, {
			content: null,
			listNode: null,
			listContent: null,
			activeClass: null,
			fallback: null,
			hashcheck: null,
			parent: "ctmain",
			listClass: "ctlist big",
			contentClass: "ctcontent",
			titleClass: "biggerest bold bottompadded"
		});
		var content = CT.dom.div(null, opts.contentClass),
			clist = CT.dom.div(null, opts.listClass),
			builder = function(data) {
				CT.dom.setContent(content, opts.content ? opts.content(data) : [
					CT.dom.div(data.name, opts.titleClass),
					data.content
				]);
			}, tl = CT.panel.triggerList(opts.data, builder, opts.listNode, opts.activeClass, opts.listContent);
		clist.appendChild(tl);
		CT.dom.setContent(opts.parent, [content, clist]);
		var hcnode, tlitem = CT.dom.id("tl" + location.hash.slice(1));
		if (tlitem)
			tlitem.trigger();
		else {
			if (opts.hashcheck)
				hcnode = opts.hashcheck();
			if (hcnode)
				CT.dom.setContent(content, hcnode);
			else {
				var titems = CT.dom.className("tlitem");
				if (titems.length)
					titems[0].trigger();
				else if (opts.fallback)
					CT.dom.setContent(content, opts.fallback());
			}
		}
		return tl;
	},
	tree: function(opts) {
		opts = CT.merge(opts, {
			path: "",
			nameCb: null,
			branches: {},
			cb: function() {},
			name: opts.title || "root",
			className: "m5 p5 vtop centered pointer inline-block"
		});
		var onclick = function(n) {
			return function(e) {
				opts.cb(n);
				e.stopPropagation();
			};
		};
		opts.path = !opts.path ? opts.name : (opts.path + "_" + opts.name);
		opts.id = "ctl_" + opts.path;
		var node = CT.dom.div([
			opts.nameCb ? opts.nameCb(opts) : opts.name,
			Object.keys(opts.branches).map(function(branch) {
				return CT.layout.tree(CT.merge({
						name: branch,
						branches: opts.branches[branch].branches || {}
					}, opts));
			})
		], opts.className, opts.id);
		node.onclick = onclick(node);
		return node;
	},
	form: function(opts) {
		opts = CT.merge(opts, {
			className: "ctform",
			items: [],
			numbers: []
		});
		var f, fields = [], nums = [], node = CT.dom.div(opts.items.map(function(item) {
			if (opts.values && opts.values[item.name] && !item.value)
				item = CT.merge(item, { value: opts.values[item.name] });
			f = CT.dom.smartField(item);
			fields.push(f);
			if (opts.labels)
				return [CT.dom.label(item.name, f.id), f];
			return f;
		}).concat(opts.numbers.map(function(nitem) {
			f = CT.dom.numberSelector(nitem);
			nums.push(f);
			return [ CT.dom.div(nitem.name, "right"), f ];
		})), opts.className), i, val, name, vals = {};
		node.value = function() {
			for (i = 0; i < fields.length; i++) {
				f = fields[i];
				val = f.fieldValue();
				name = opts.items[i].name;
				if (!val)
					return alert("please provide a " + name);
				vals[name] = val;
			}
			for (i = 0; i < nums.length; i++)
				vals[opts.numbers[i].name] = nums[i].value();
			opts.cb && opts.cb(vals);
			return vals;
		};
		if (opts.button)
			node.appendChild(CT.dom.button(opts.bname || "continue", node.value));
		return node;
	}
};<|endoftext|>


<commit_before>import { utcToZonedTime } from 'date-fns-tz'
import parse from 'date-fns/parse'
import format from 'date-fns/format'
import isValid from 'date-fns/isValid'
import { getUserTimeZoneId } from './time'
import { toPercentage } from './common'
import { QUARTER_NAMES } from './constant'
import { getNickNamesByTriCode } from '../utils/teams'
import getApiDate from './getApiDate'

const getStats = (old, points) => {
  if (!old) {
    return {}
  }
  return {
    assists: old.ast,
    blocks: old.blk,
    field_goals_attempted: old.fga,
    field_goals_made: old.fgm,
    field_goals_percentage: toPercentage(+old.fgm / +old.fga),
    fouls: old.pf,
    free_throws_attempted: old.fta,
    free_throws_made: old.ftm,
    free_throws_percentage: toPercentage(+old.ftm / +old.fta),
    points,
    rebounds_defensive: old.dreb,
    rebounds_offensive: old.oreb,
    steals: old.stl,
    team_fouls: old.tf,
    team_rebounds: old.tmreb,
    team_turnovers: old.tmtov,
    three_pointers_attempted: old.tpa,
    three_pointers_made: old.tpm,
    three_pointers_percentage: toPercentage(+old.tpm / +old.tpa),
    turnovers: old.tov,
  }
}

const getPlayers = (players = []) => {
  return players.map((player) => ({
    assists: player.ast,
    blocks: player.blk,
    field_goals_attempted: player.fga,
    field_goals_made: player.fgm,
    first_name: player.fn,
    fouls: player.pf,
    free_throws_attempted: player.fta,
    free_throws_made: player.ftm,
    last_name: player.ln,
    minutes: player.min,
    on_court: player.court,
    person_id: player.pid,
    plus_minus: player.pm,
    points: player.pts,
    rebounds_defensive: player.dreb,
    rebounds_offensive: player.oreb,
    seconds: player.sec,
    starting_position: player.pos,
    steals: player.stl,
    three_pointers_attempted: player.tpa,
    three_pointers_made: player.tpm,
    turnovers: player.tov,
  }))
}

const getLinescores = (stats, p) => {
  const pluck = ({
    q1,
    q2,
    q3,
    q4,
    ot1,
    ot2,
    ot3,
    ot4,
    ot5,
    ot6,
    ot7,
    ot8,
    ot9,
    ot10,
  }) => [q1, q2, q3, q4, ot1, ot2, ot3, ot4, ot5, ot6, ot7, ot8, ot9, ot10]
  return pluck(stats)
    .slice(0, p)
    .map((period, i) => ({
      period_name: QUARTER_NAMES[i],
      period_value: i.toString(),
      score: period.toString(),
    }))
}

// this is for http://data.nba.net/prod/v2/dateStr/scoreboard.json endpoint
export const convertDaily2 = (game) => {
  const {
    startTimeUTC,
    endTimeUTC,
    statusNum,
    clock,
    hTeam: h,
    vTeam: v,
    period: { current: p, isHalftime, isEndOfPeriod },
    watch: {
      broadcast: {
        broadcasters: { national, vTeam, hTeam },
      },
    },
    playoffs,
    nugget,
  } = game

  const addQuarterNames = (linescores) =>
    linescores.map((ls, i) => ({
      period_name: QUARTER_NAMES[i],
      period_value: i.toString(),
      score: ls.score,
    }))

  // there is no field for game status
  const formatGameStatus = () => {
    // special case for postponed games
    if (
      nugget != null &&
      nugget.text != null &&
      typeof nugget.text === 'string' &&
      nugget.text.toLowerCase().includes('postponed')) {
      return 'PPD'
    }
    if (endTimeUTC != null) {
      return 'Final'
    } else if (isHalftime) {
      return 'Halftime'
    } else if (statusNum === 1) {
      return format(
        utcToZonedTime(startTimeUTC, getUserTimeZoneId()),
        'hh:mm a'
      )
    } else if (isEndOfPeriod) {
      if (p > 4) {
        const otP = p - 4
        return `End of ${otP} OT`
      }
      return `End of ${p} Qtr`
    } else {
      // normal period
      if (p > 4) {
        const otP = p - 4
        return `${otP} OT`
      }
      return `${p} Qtr`
    }
  }

  const getBroadcasters = () => {
    return [
      ...national.map((c) => ({ scope: 'natl', display_name: c.shortName })),
      ...vTeam.map((c) => ({ scope: 'local', display_name: c.shortName })),
      ...hTeam.map((c) => ({ scope: 'local', display_name: c.shortName })),
    ]
  }

  const getPlayoffs = () => {
    if (playoffs == null || playoffs.hTeam == null || playoffs.vTeam == null) {
      return undefined
    }

    return {
      home_wins: playoffs.hTeam.seriesWin,
      visitor_wins: playoffs.vTeam.seriesWin,
    }
  }

  return {
    broadcasters: getBroadcasters(),
    home: {
      abbreviation: h.triCode,
      city: '',
      linescores: { period: addQuarterNames(h.linescore) },
      nickname: getNickNamesByTriCode(h.triCode),
      score: h.score,
    },
    visitor: {
      abbreviation: v.triCode,
      city: '',
      linescores: { period: addQuarterNames(h.linescore) },
      nickname: getNickNamesByTriCode(v.triCode),
      score: v.score,
    },
    periodTime: {
      // have not start
      periodStatus: formatGameStatus(),
      gameClock: clock,
      gameStatus: `${statusNum}`,
      periodValue: `${p}`,
    },
    playoffs: getPlayoffs(),
  }
}

export const convertDaily = (game) => {
  const { cl, h, p, st, stt, v } = game

  const gameTime = parse(stt, 'hh:mm a', getApiDate())
  const isStatusValidDate = isValid(gameTime)
  return {
    periodTime: {
      periodValue: `${p}`,
      periodStatus:
        st == 1 && isStatusValidDate
          ? format(
            utcToZonedTime(gameTime.toISOString(), getUserTimeZoneId()),
            'hh:mm a'
          )
          : stt,
      gameClock: cl || '',
      gameStatus: `${st}`,
    },
    home: {
      abbreviation: h.ta,
      city: h.tc,
      linescores: { period: getLinescores(h, p) },
      nickname: h.tn,
      score: `${h.s}`,
    },
    visitor: {
      abbreviation: v.ta,
      city: v.tc,
      linescores: { period: getLinescores(v, p) },
      nickname: v.tn,
      score: `${v.s}`,
    },
  }
}

export const convertBS = (old) => {
  const { cl, hls, offs, p, st, stt, vls } = old
  let officials = []
  if (offs && offs.off) {
    officials = offs.off.map((person) => ({
      first_name: person.fn,
      last_name: person.ln,
      person_id: person.num,
    }))
  }

  return {
    officials,
    periodTime: {
      periodValue: `${p}`,
      periodStatus: `${stt}`,
      gameClock: cl,
      gameStatus: `${st}`,
    },
    home: {
      abbreviation: hls.ta,
      city: hls.tc,
      linescores: { period: getLinescores(hls, p) },
      nickname: hls.tn,
      players: { player: getPlayers(hls.pstsg) },
      score: hls.s,
      stats: getStats(hls.tstsg, hls.s),
    },
    visitor: {
      abbreviation: vls.ta,
      city: vls.tc,
      linescores: { period: getLinescores(vls, p) },
      nickname: vls.tn,
      players: { player: getPlayers(vls.pstsg) },
      score: vls.s,
      stats: getStats(vls.tstsg, vls.s),
    },
  }
}
<commit_msg>fix: equal whole word<commit_after>import { utcToZonedTime } from 'date-fns-tz'
import parse from 'date-fns/parse'
import format from 'date-fns/format'
import isValid from 'date-fns/isValid'
import { getUserTimeZoneId } from './time'
import { toPercentage } from './common'
import { QUARTER_NAMES } from './constant'
import { getNickNamesByTriCode } from '../utils/teams'
import getApiDate from './getApiDate'

const getStats = (old, points) => {
  if (!old) {
    return {}
  }
  return {
    assists: old.ast,
    blocks: old.blk,
    field_goals_attempted: old.fga,
    field_goals_made: old.fgm,
    field_goals_percentage: toPercentage(+old.fgm / +old.fga),
    fouls: old.pf,
    free_throws_attempted: old.fta,
    free_throws_made: old.ftm,
    free_throws_percentage: toPercentage(+old.ftm / +old.fta),
    points,
    rebounds_defensive: old.dreb,
    rebounds_offensive: old.oreb,
    steals: old.stl,
    team_fouls: old.tf,
    team_rebounds: old.tmreb,
    team_turnovers: old.tmtov,
    three_pointers_attempted: old.tpa,
    three_pointers_made: old.tpm,
    three_pointers_percentage: toPercentage(+old.tpm / +old.tpa),
    turnovers: old.tov,
  }
}

const getPlayers = (players = []) => {
  return players.map((player) => ({
    assists: player.ast,
    blocks: player.blk,
    field_goals_attempted: player.fga,
    field_goals_made: player.fgm,
    first_name: player.fn,
    fouls: player.pf,
    free_throws_attempted: player.fta,
    free_throws_made: player.ftm,
    last_name: player.ln,
    minutes: player.min,
    on_court: player.court,
    person_id: player.pid,
    plus_minus: player.pm,
    points: player.pts,
    rebounds_defensive: player.dreb,
    rebounds_offensive: player.oreb,
    seconds: player.sec,
    starting_position: player.pos,
    steals: player.stl,
    three_pointers_attempted: player.tpa,
    three_pointers_made: player.tpm,
    turnovers: player.tov,
  }))
}

const getLinescores = (stats, p) => {
  const pluck = ({
    q1,
    q2,
    q3,
    q4,
    ot1,
    ot2,
    ot3,
    ot4,
    ot5,
    ot6,
    ot7,
    ot8,
    ot9,
    ot10,
  }) => [q1, q2, q3, q4, ot1, ot2, ot3, ot4, ot5, ot6, ot7, ot8, ot9, ot10]
  return pluck(stats)
    .slice(0, p)
    .map((period, i) => ({
      period_name: QUARTER_NAMES[i],
      period_value: i.toString(),
      score: period.toString(),
    }))
}

// this is for http://data.nba.net/prod/v2/dateStr/scoreboard.json endpoint
export const convertDaily2 = (game) => {
  const {
    startTimeUTC,
    endTimeUTC,
    statusNum,
    clock,
    hTeam: h,
    vTeam: v,
    period: { current: p, isHalftime, isEndOfPeriod },
    watch: {
      broadcast: {
        broadcasters: { national, vTeam, hTeam },
      },
    },
    playoffs,
    nugget,
  } = game

  const addQuarterNames = (linescores) =>
    linescores.map((ls, i) => ({
      period_name: QUARTER_NAMES[i],
      period_value: i.toString(),
      score: ls.score,
    }))

  // there is no field for game status
  const formatGameStatus = () => {
    // special case for postponed games
    if (
      nugget != null &&
      nugget.text != null &&
      typeof nugget.text === 'string' &&
      nugget.text.toLowerCase().trim() === 'postponed') {
      return 'PPD'
    }
    if (endTimeUTC != null) {
      return 'Final'
    } else if (isHalftime) {
      return 'Halftime'
    } else if (statusNum === 1) {
      return format(
        utcToZonedTime(startTimeUTC, getUserTimeZoneId()),
        'hh:mm a'
      )
    } else if (isEndOfPeriod) {
      if (p > 4) {
        const otP = p - 4
        return `End of ${otP} OT`
      }
      return `End of ${p} Qtr`
    } else {
      // normal period
      if (p > 4) {
        const otP = p - 4
        return `${otP} OT`
      }
      return `${p} Qtr`
    }
  }

  const getBroadcasters = () => {
    return [
      ...national.map((c) => ({ scope: 'natl', display_name: c.shortName })),
      ...vTeam.map((c) => ({ scope: 'local', display_name: c.shortName })),
      ...hTeam.map((c) => ({ scope: 'local', display_name: c.shortName })),
    ]
  }

  const getPlayoffs = () => {
    if (playoffs == null || playoffs.hTeam == null || playoffs.vTeam == null) {
      return undefined
    }

    return {
      home_wins: playoffs.hTeam.seriesWin,
      visitor_wins: playoffs.vTeam.seriesWin,
    }
  }

  return {
    broadcasters: getBroadcasters(),
    home: {
      abbreviation: h.triCode,
      city: '',
      linescores: { period: addQuarterNames(h.linescore) },
      nickname: getNickNamesByTriCode(h.triCode),
      score: h.score,
    },
    visitor: {
      abbreviation: v.triCode,
      city: '',
      linescores: { period: addQuarterNames(h.linescore) },
      nickname: getNickNamesByTriCode(v.triCode),
      score: v.score,
    },
    periodTime: {
      // have not start
      periodStatus: formatGameStatus(),
      gameClock: clock,
      gameStatus: `${statusNum}`,
      periodValue: `${p}`,
    },
    playoffs: getPlayoffs(),
  }
}

export const convertDaily = (game) => {
  const { cl, h, p, st, stt, v } = game

  const gameTime = parse(stt, 'hh:mm a', getApiDate())
  const isStatusValidDate = isValid(gameTime)
  return {
    periodTime: {
      periodValue: `${p}`,
      periodStatus:
        st == 1 && isStatusValidDate
          ? format(
            utcToZonedTime(gameTime.toISOString(), getUserTimeZoneId()),
            'hh:mm a'
          )
          : stt,
      gameClock: cl || '',
      gameStatus: `${st}`,
    },
    home: {
      abbreviation: h.ta,
      city: h.tc,
      linescores: { period: getLinescores(h, p) },
      nickname: h.tn,
      score: `${h.s}`,
    },
    visitor: {
      abbreviation: v.ta,
      city: v.tc,
      linescores: { period: getLinescores(v, p) },
      nickname: v.tn,
      score: `${v.s}`,
    },
  }
}

export const convertBS = (old) => {
  const { cl, hls, offs, p, st, stt, vls } = old
  let officials = []
  if (offs && offs.off) {
    officials = offs.off.map((person) => ({
      first_name: person.fn,
      last_name: person.ln,
      person_id: person.num,
    }))
  }

  return {
    officials,
    periodTime: {
      periodValue: `${p}`,
      periodStatus: `${stt}`,
      gameClock: cl,
      gameStatus: `${st}`,
    },
    home: {
      abbreviation: hls.ta,
      city: hls.tc,
      linescores: { period: getLinescores(hls, p) },
      nickname: hls.tn,
      players: { player: getPlayers(hls.pstsg) },
      score: hls.s,
      stats: getStats(hls.tstsg, hls.s),
    },
    visitor: {
      abbreviation: vls.ta,
      city: vls.tc,
      linescores: { period: getLinescores(vls, p) },
      nickname: vls.tn,
      players: { player: getPlayers(vls.pstsg) },
      score: vls.s,
      stats: getStats(vls.tstsg, vls.s),
    },
  }
}
<|endoftext|>


<commit_before>// TODO: conditional defaults

const defaults = {
  thing: '',
  date: '2000-01-01',
  done: false,
  updated: false,
  options: {
    backgroundColor: '#c5cefa',
    doneButtonColor: '#009387'
  }
}

function onInstalled(e) {
  if (e.reason === 'install') {
    chrome.storage.sync.set(defaults);
    chrome.tabs.create({
      "url": `../pages/welcome/welcome.html?reason=install`
    })
  } else if (e.reason === 'updated') {
    chrome.storage.local.set({ updated: true });
  }
}

chrome.runtime.onInstalled.addListener(onInstalled)
<commit_msg>Fix update not being detected correctly<commit_after>// TODO: conditional defaults

const defaults = {
  thing: '',
  date: '2000-01-01',
  done: false,
  updated: false,
  options: {
    backgroundColor: '#c5cefa',
    doneButtonColor: '#009387'
  }
};

function onInstalled(e) {
  if (e.reason === 'install') {
    chrome.storage.sync.set(defaults);
    chrome.tabs.create({
      "url": `../pages/welcome/welcome.html?reason=install`
    })
  } else if (e.reason === 'update') {
    chrome.storage.local.set({ updated: true });
  }
}

chrome.runtime.onInstalled.addListener(onInstalled);
<|endoftext|>