<commit_before>/*
 * buildEmbed.js: build embedded NB
 *
 Author
 cf AUTHORS.txt

 License
 Copyright (c) 2010-2012 Massachusetts Institute of Technology.
 MIT License (cf. MIT-LICENSE.txt or http://www.opensource.org/licenses/mit-license.php)
*/
/*global jQuery:true $:true NB$:true NB:true alert:true escape:false console:false*/

(function(GLOB){

    if ("NB$" in window){
        var $ = NB$;
    }
    var $str        = "NB$" in window ? "NB$" : "jQuery";

    var $vp;
    var id_ensemble = null;
    GLOB.pers.iframe_id = "nb_iframe";
    var f_after_successful_login = function(){
        //SACHA: TODO. Do a better job that just displaying the user name, and maybe refactor with pers2._authenticate.
        //for now, just update user name and email on hover. :
        var uinfo = GLOB.conf.userinfo;
        if (!uinfo.guest){
            var screenname = uinfo.firstname === null ? $.E(uinfo.email): $.E(uinfo.firstname) + " " + $.E(uinfo.lastname);
            $("#login-name").text(screenname).attr("title", $.E(uinfo.email));
        }

        //now move stuff here it's supposed to be:
        $vp = $("

").prependTo(".nb_sidebar");
        $("#login-window").appendTo(".nb-widget-header"); // add this here so it's fixed as well
        //TODO: get id_ensemble from cookie or localStorage if available.
        $.concierge.addConstants({res: 288, scale: 25, QUESTION: 1, STAR: 2 });
        $.concierge.addComponents({
                notes_loader:    function(P, cb){GLOB.pers.call("getNotes", P, cb);},
                    note_creator:    function(P, cb){GLOB.pers.call("saveNote", P, cb);},
                    note_editor:    function(P, cb){GLOB.pers.call("editNote", P, cb);}
            });
        GLOB.pers.store = new GLOB.models.Store();
        GLOB.pers.call(
                   "getHTML5Info", {id_ensemble: id_ensemble, url: document.location.href},
                   function(payload){
                       //TODO: refactor (same as in step16.js:createStore)
                       GLOB.pers.store.create(payload, {
                               ensemble:    {pFieldName: "ensembles"},
            section:    {pFieldName: "sections", references: {id_ensemble: "ensemble"}},
                                   file:    {pFieldName: "files", references: {id_ensemble: "ensemble", id_folder: "folder"}},
                                   folder: {pFieldName: "folders", references: {id_ensemble: "ensemble", id_parent: "folder"}},
                                   comment:{references: {id_location: "location"}},
                                   location:{references: {id_ensemble: "ensemble", id_source: "file"}},
                                   html5location:{references: {id_location: "location"}},
                                   link: {pFieldName: "links"},
                                   mark: {},
                                   threadmark: {pFieldName: "threadmarks", references: {location_id: "location"}},
                                   draft: {},
                                   seen:{references: {id_location: "location"}}
                           });

                       //get the section info as well as info whether user is admin:
                       GLOB.pers.call("getSectionsInfo", {id_ensemble: NB.pers.store.get("ensemble", {}).first().ID}, function(P3){
                           var m = GLOB.pers.store;
                           m.add("section", P3["sections"]);
                           NB.pers.store.get("ensemble", {}).first().admin=true; //we only get a callback if we're an admin for this ensemble
                       });

                       //TODO: Take something else than first id_source
                       var source = GLOB.pers.id_source = NB.pers.store.get("file").first();
                       if (source === null){
                           $("

The URL for this page isn't registered on NB. Click this message to close the NB sidebar.

").
                             appendTo(".nb_sidebar>.nb-viewport").click(function() {
                                 $(".nb_sidebar").fadeOut(400);
                             });
                           return;
                       }
                       var id_source = GLOB.pers.id_source = NB.pers.store.get("file").first().ID;
                       $.concierge.setHistoryHelper(function(_payload, cb){
                               _payload["__return"] = {type:"newNotesOnFile", a:{id_source: GLOB.pers.id_source}};
                               GLOB.pers.call("log_history", _payload, cb);
                           }, 120000,  function(P2){
                               //here we override the callback so that we can get new notes.

                               var m = GLOB.pers.store;
                               m.add("comment", P2["comments"]);
                               m.add("location", P2["locations"]);
                               m.add("html5location", P2["html5locations"]);
                               var msg="";
                               var l,c;
                               for (var i in P2["comments"]){
                                   c = m.o.comment[i];
                                   l = m.o.location[c.ID_location];
                                   if (c.id_author !==  $.concierge.get_component("get_userinfo")().id){    //do nothing if I'm the author:
                                       msg+="New comment on page "+l.page+"
";
                                   }
                               }
                               if (msg !== ""){
                                   $.I(msg, true);
                               }
                           });
                       $.concierge.trigger({type:"file", value: id_source});

                       //let's create perspective here:
                       var $pers        = $("
").appendTo($vp);

                       var notesview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1000,
                           desired_height: 50,
                           content: function($div){
                               $div.notepaneView();
                               $div.notepaneView("set_model",GLOB.pers.store );
                           }
                       };
                       var threadview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1000,
                           desired_height: 50,
                           content: function($div){
                               $div.threadview();
                               $div.threadview("set_model",GLOB.pers.store );
                           }
                       };
                       var editorview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1500,
                           desired_height: 50,
                           transcient: true,
                           content: function($div){
                               var m = GLOB.pers.store;
                               var ensemble = m.o.ensemble[m.o.file[id_source].id_ensemble];
                               $div.editorview({allowStaffOnly: ensemble.allow_staffonly, allowAnonymous: ensemble.allow_anonymous});
                               $div.editorview("set_model",GLOB.pers.store );
                           }
                       };

                       //SACHA FIXME: Hack we embed the following into a delay because FF doesn't compute the right window height if we execute this right away
                       setTimeout(function(){
                          $pers.perspective({
                                  ext_separator: {
                                      container: ".nb_sidebar",
                                          orientation: "vertical"

                                          },
                               height: function(){
                                   return $vp.height() - ($pers.offset().top - $vp.offset().top);
                               }, //3rd term is to account for the fact we have NB embedded as part of widget that has a 'fixed' position
                               listens: {
                                   page_peek: function(evt){
                                       //need to add 1 value for uniqueness
                                       $.concierge.logHistory("page", evt.value+"|"+id_source+"|"+(new Date()).getTime());
                                   },
                                   close_view: function(evt){
                                       if (evt.value === this.l.element[0].id){
                                           delete($.concierge.features.doc_viewer[id_source]);
                                       }
                                       $.L("closeview: ", evt, this.l.element[0].id);
                                   }
                               },
                               views: {
                                   v1: { data: notesview },
                                   v2: {
                                       children: {
                                           v1: { data: threadview},
                                           v2: {data: editorview},
                                           orientation: "horizontal"
                                   }},
                                   orientation: "horizontal"
                                   }
                           });

                       //end of perspective creation code

                       var f = GLOB.pers.store.o.file[id_source];
                       $.concierge.get_component("notes_loader")( {file:id_source }, function(P){
                               var m = GLOB.pers.store;
                               m.add("seen", P["seen"]);
                               m.add("comment", P["comments"]);
                               m.add("location", P["locations"]);
                               m.add("html5location", P["html5locations"]);
                               m.add("link", P["links"]);
                               m.add("threadmark", P["threadmarks"]);
                               //now check if need to move to a given annotation:
                               if ("c" in GLOB.pers.params){
                                   window.setTimeout(function(){
                                           var id =  GLOB.pers.params.c;
                                           var c = m.get("comment", {ID: id}).items[id];
                                           if ("reply" in GLOB.pers.params){
                                               $.concierge.trigger({type: "reply_thread", value: c.ID});
                                           }
                                           $.concierge.trigger({type: "select_thread", value: c.ID_location});

                                       }, 300);
                               }
                               else if ("p" in GLOB.pers.params){
                                   window.setTimeout(function(){
                                           var page = GLOB.pers.params.p;
                                           $.concierge.trigger({type: "page", value: page});
                                       }, 300);
                               }
                               else{
                                   window.setTimeout(function(){
                                           $.concierge.trigger({type: "page", value: 1});
                                       }, 300);
                               }
                           });
                           }, 1000);

                       $("body").addClass("nb-active");
                       $(function(){GLOB.html.init();});
                   },
                   function(P){
                       $(".nb-widget-header").append("<button id='login_to_nb'>Login to NB</button>");
                       $("#login_to_nb").click(function(evt){
                               //sacha: disable this for now.
                               //console.log("opening iframe");
                               //                               $("#"+GLOB.pers.iframe_id).removeClass("nb_hidden");
                               $.concierge.get_component("login_user_menu")();

                       });
                   });

};
    GLOB.pers.ckey_from_iframe = null;
    GLOB.pers.f_poll_iframe = function(){
        console.log("polling iframe");
        $("#"+GLOB.pers.iframe_id)[0].contentWindow.postMessage("confkey", "http://localhost:8001");
        if (GLOB.pers.ckey_from_iframe === null){
            setTimeout(GLOB.pers.f_poll_iframe, 500);
        }
        else{
            console.log("got ckey - no more polling", GLOB.pers.ckey_from_iframe);
        }
    };
    GLOB.pers.init = function(){
        GLOB.pers.connection_id = 0;
        GLOB.pers.embedded = true;
        //add our CSS
        var cur =  GLOB.pers.currentScript;
        var server_info =  cur.src.match(/([^:]*):\/\/([^\/]*)/);
        var server_url = server_info[1]+"://"+server_info[2];
        GLOB.pers.add_css(server_url+"/content/compiled/embed_NB.css");
        //GLOB.pers.openid_url=server_url+"/openid/login?next=/embedopenid";
        //sacha: disabled this as well for now.
        GLOB.pers.openid_url="";

        // Make sure concierge won't steal our keys!
        $.concierge.keydown_block = false;

        //register for some events:
        $.concierge.addListeners(GLOB.pers, {
                successful_login: function(evt){
                    GLOB.auth.set_cookie("ckey", evt.value.ckey);
                    GLOB.auth.set_cookie("userinfo", escape(JSON.stringify(evt.value)));
                    GLOB.conf.userinfo = evt.value;
                    $.L("Welcome TO NB !");
                    $("#splash-welcome").parent().dialog("destroy");

                    f_after_successful_login();

                }
            }, "globalPersObject");

        //tell who to make rpc requests to
        GLOB.conf.servers.rpc=GLOB.pers.server_url;

        $("body").append("

");

        $("#nb_loginbutton").click(function(){
                $.concierge.get_component("login_user_menu")();
            });

        //if authenticated already, let's proceed:
        if (GLOB.conf.userinfo){
            f_after_successful_login();
        }

        window.addEventListener('message', function(e){
                console.log("got event: ", e);
                //TODO: clearTimeout
            }, false);

    };

    jQuery(function(){
            GLOB.pers.params = GLOB.dom.getParams();
            GLOB.pers.preinit();
        });

    })(NB);
<commit_msg>HTML ignores hash component of URL<commit_after>/*
 * buildEmbed.js: build embedded NB
 *
 Author
 cf AUTHORS.txt

 License
 Copyright (c) 2010-2012 Massachusetts Institute of Technology.
 MIT License (cf. MIT-LICENSE.txt or http://www.opensource.org/licenses/mit-license.php)
*/
/*global jQuery:true $:true NB$:true NB:true alert:true escape:false console:false*/

(function(GLOB){

    if ("NB$" in window){
        var $ = NB$;
    }
    var $str        = "NB$" in window ? "NB$" : "jQuery";

    var $vp;
    var id_ensemble = null;
    GLOB.pers.iframe_id = "nb_iframe";
    var f_after_successful_login = function(){
        //SACHA: TODO. Do a better job that just displaying the user name, and maybe refactor with pers2._authenticate.
        //for now, just update user name and email on hover. :
        var uinfo = GLOB.conf.userinfo;
        if (!uinfo.guest){
            var screenname = uinfo.firstname === null ? $.E(uinfo.email): $.E(uinfo.firstname) + " " + $.E(uinfo.lastname);
            $("#login-name").text(screenname).attr("title", $.E(uinfo.email));
        }

        //now move stuff here it's supposed to be:
        $vp = $("

").prependTo(".nb_sidebar");
        $("#login-window").appendTo(".nb-widget-header"); // add this here so it's fixed as well
        //TODO: get id_ensemble from cookie or localStorage if available.
        $.concierge.addConstants({res: 288, scale: 25, QUESTION: 1, STAR: 2 });
        $.concierge.addComponents({
                notes_loader:    function(P, cb){GLOB.pers.call("getNotes", P, cb);},
                    note_creator:    function(P, cb){GLOB.pers.call("saveNote", P, cb);},
                    note_editor:    function(P, cb){GLOB.pers.call("editNote", P, cb);}
            });
        GLOB.pers.store = new GLOB.models.Store();
        GLOB.pers.call(
            "getHTML5Info", {id_ensemble: id_ensemble, url: document.location.href.replace(document.location.hash, "")},
                   function(payload){
                       //TODO: refactor (same as in step16.js:createStore)
                       GLOB.pers.store.create(payload, {
                               ensemble:    {pFieldName: "ensembles"},
            section:    {pFieldName: "sections", references: {id_ensemble: "ensemble"}},
                                   file:    {pFieldName: "files", references: {id_ensemble: "ensemble", id_folder: "folder"}},
                                   folder: {pFieldName: "folders", references: {id_ensemble: "ensemble", id_parent: "folder"}},
                                   comment:{references: {id_location: "location"}},
                                   location:{references: {id_ensemble: "ensemble", id_source: "file"}},
                                   html5location:{references: {id_location: "location"}},
                                   link: {pFieldName: "links"},
                                   mark: {},
                                   threadmark: {pFieldName: "threadmarks", references: {location_id: "location"}},
                                   draft: {},
                                   seen:{references: {id_location: "location"}}
                           });

                       //get the section info as well as info whether user is admin:
                       GLOB.pers.call("getSectionsInfo", {id_ensemble: NB.pers.store.get("ensemble", {}).first().ID}, function(P3){
                           var m = GLOB.pers.store;
                           m.add("section", P3["sections"]);
                           NB.pers.store.get("ensemble", {}).first().admin=true; //we only get a callback if we're an admin for this ensemble
                       });

                       //TODO: Take something else than first id_source
                       var source = GLOB.pers.id_source = NB.pers.store.get("file").first();
                       if (source === null){
                           $("

The URL for this page isn't registered on NB. Click this message to close the NB sidebar.

").
                             appendTo(".nb_sidebar>.nb-viewport").click(function() {
                                 $(".nb_sidebar").fadeOut(400);
                             });
                           return;
                       }
                       var id_source = GLOB.pers.id_source = NB.pers.store.get("file").first().ID;
                       $.concierge.setHistoryHelper(function(_payload, cb){
                               _payload["__return"] = {type:"newNotesOnFile", a:{id_source: GLOB.pers.id_source}};
                               GLOB.pers.call("log_history", _payload, cb);
                           }, 120000,  function(P2){
                               //here we override the callback so that we can get new notes.

                               var m = GLOB.pers.store;
                               m.add("comment", P2["comments"]);
                               m.add("location", P2["locations"]);
                               m.add("html5location", P2["html5locations"]);
                               var msg="";
                               var l,c;
                               for (var i in P2["comments"]){
                                   c = m.o.comment[i];
                                   l = m.o.location[c.ID_location];
                                   if (c.id_author !==  $.concierge.get_component("get_userinfo")().id){    //do nothing if I'm the author:
                                       msg+="New comment on page "+l.page+"
";
                                   }
                               }
                               if (msg !== ""){
                                   $.I(msg, true);
                               }
                           });
                       $.concierge.trigger({type:"file", value: id_source});

                       //let's create perspective here:
                       var $pers        = $("
").appendTo($vp);

                       var notesview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1000,
                           desired_height: 50,
                           content: function($div){
                               $div.notepaneView();
                               $div.notepaneView("set_model",GLOB.pers.store );
                           }
                       };
                       var threadview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1000,
                           desired_height: 50,
                           content: function($div){
                               $div.threadview();
                               $div.threadview("set_model",GLOB.pers.store );
                           }
                       };
                       var editorview = {
                           priority: 1,
                           min_width: 650,
                           desired_width: 35,
                           min_height: 1500,
                           desired_height: 50,
                           transcient: true,
                           content: function($div){
                               var m = GLOB.pers.store;
                               var ensemble = m.o.ensemble[m.o.file[id_source].id_ensemble];
                               $div.editorview({allowStaffOnly: ensemble.allow_staffonly, allowAnonymous: ensemble.allow_anonymous});
                               $div.editorview("set_model",GLOB.pers.store );
                           }
                       };

                       //SACHA FIXME: Hack we embed the following into a delay because FF doesn't compute the right window height if we execute this right away
                       setTimeout(function(){
                          $pers.perspective({
                                  ext_separator: {
                                      container: ".nb_sidebar",
                                          orientation: "vertical"

                                          },
                               height: function(){
                                   return $vp.height() - ($pers.offset().top - $vp.offset().top);
                               }, //3rd term is to account for the fact we have NB embedded as part of widget that has a 'fixed' position
                               listens: {
                                   page_peek: function(evt){
                                       //need to add 1 value for uniqueness
                                       $.concierge.logHistory("page", evt.value+"|"+id_source+"|"+(new Date()).getTime());
                                   },
                                   close_view: function(evt){
                                       if (evt.value === this.l.element[0].id){
                                           delete($.concierge.features.doc_viewer[id_source]);
                                       }
                                       $.L("closeview: ", evt, this.l.element[0].id);
                                   }
                               },
                               views: {
                                   v1: { data: notesview },
                                   v2: {
                                       children: {
                                           v1: { data: threadview},
                                           v2: {data: editorview},
                                           orientation: "horizontal"
                                   }},
                                   orientation: "horizontal"
                                   }
                           });

                       //end of perspective creation code

                       var f = GLOB.pers.store.o.file[id_source];
                       $.concierge.get_component("notes_loader")( {file:id_source }, function(P){
                               var m = GLOB.pers.store;
                               m.add("seen", P["seen"]);
                               m.add("comment", P["comments"]);
                               m.add("location", P["locations"]);
                               m.add("html5location", P["html5locations"]);
                               m.add("link", P["links"]);
                               m.add("threadmark", P["threadmarks"]);
                               //now check if need to move to a given annotation:
                               if ("c" in GLOB.pers.params){
                                   window.setTimeout(function(){
                                           var id =  GLOB.pers.params.c;
                                           var c = m.get("comment", {ID: id}).items[id];
                                           if ("reply" in GLOB.pers.params){
                                               $.concierge.trigger({type: "reply_thread", value: c.ID});
                                           }
                                           $.concierge.trigger({type: "select_thread", value: c.ID_location});

                                       }, 300);
                               }
                               else if ("p" in GLOB.pers.params){
                                   window.setTimeout(function(){
                                           var page = GLOB.pers.params.p;
                                           $.concierge.trigger({type: "page", value: page});
                                       }, 300);
                               }
                               else{
                                   window.setTimeout(function(){
                                           $.concierge.trigger({type: "page", value: 1});
                                       }, 300);
                               }
                           });
                           }, 1000);

                       $("body").addClass("nb-active");
                       $(function(){GLOB.html.init();});
                   },
                   function(P){
                       $(".nb-widget-header").append("<button id='login_to_nb'>Login to NB</button>");
                       $("#login_to_nb").click(function(evt){
                               //sacha: disable this for now.
                               //console.log("opening iframe");
                               //                               $("#"+GLOB.pers.iframe_id).removeClass("nb_hidden");
                               $.concierge.get_component("login_user_menu")();

                       });
                   });

};
    GLOB.pers.ckey_from_iframe = null;
    GLOB.pers.f_poll_iframe = function(){
        console.log("polling iframe");
        $("#"+GLOB.pers.iframe_id)[0].contentWindow.postMessage("confkey", "http://localhost:8001");
        if (GLOB.pers.ckey_from_iframe === null){
            setTimeout(GLOB.pers.f_poll_iframe, 500);
        }
        else{
            console.log("got ckey - no more polling", GLOB.pers.ckey_from_iframe);
        }
    };
    GLOB.pers.init = function(){
        GLOB.pers.connection_id = 0;
        GLOB.pers.embedded = true;
        //add our CSS
        var cur =  GLOB.pers.currentScript;
        var server_info =  cur.src.match(/([^:]*):\/\/([^\/]*)/);
        var server_url = server_info[1]+"://"+server_info[2];
        GLOB.pers.add_css(server_url+"/content/compiled/embed_NB.css");
        //GLOB.pers.openid_url=server_url+"/openid/login?next=/embedopenid";
        //sacha: disabled this as well for now.
        GLOB.pers.openid_url="";

        // Make sure concierge won't steal our keys!
        $.concierge.keydown_block = false;

        //register for some events:
        $.concierge.addListeners(GLOB.pers, {
                successful_login: function(evt){
                    GLOB.auth.set_cookie("ckey", evt.value.ckey);
                    GLOB.auth.set_cookie("userinfo", escape(JSON.stringify(evt.value)));
                    GLOB.conf.userinfo = evt.value;
                    $.L("Welcome TO NB !");
                    $("#splash-welcome").parent().dialog("destroy");

                    f_after_successful_login();

                }
            }, "globalPersObject");

        //tell who to make rpc requests to
        GLOB.conf.servers.rpc=GLOB.pers.server_url;

        $("body").append("

");

        $("#nb_loginbutton").click(function(){
                $.concierge.get_component("login_user_menu")();
            });

        //if authenticated already, let's proceed:
        if (GLOB.conf.userinfo){
            f_after_successful_login();
        }

        window.addEventListener('message', function(e){
                console.log("got event: ", e);
                //TODO: clearTimeout
            }, false);

    };

    jQuery(function(){
            GLOB.pers.params = GLOB.dom.getParams();
            GLOB.pers.preinit();
        });

    })(NB);
<|endoftext|>


<commit_before>'use strict';

const lo_isNumber = require('lodash.isnumber');
const lo_isString = require('lodash.isstring');
const lo_isObject = require('lodash.isobject');
const lo_has = require('lodash.has');

const math = require('mathjs');

module.exports = (context) => {
  const app = context.app;
  const clipboard = context.clipboard;
  const toast = context.toast;
  const indexer = context.indexer;

  function startup() {
    indexer.set('math', (query) => {
      const answer = calculate(query, false);
      if (!answer) return;
      return makeResultItem('primaryText', query, answer);
    });
  }

  function search(query, res) {
    const answer = calculate(query, true);
    if (!answer) return;
    res.add(makeResultItem('title', query, answer));
  }

  function makeResultItem(titleKey, query, answer) {
    const result = {};
    result[titleKey] = `${query.trim()} = ${answer}`;
    result.group = 'Math';
    result.payload = answer;
    return result;
  }

  function calculate(query, showRedundantResult) {
    try {
      const ans = math.eval(query);
      if (
        lo_isNumber(ans) ||
        lo_isString(ans) ||
        (lo_isObject(ans) && lo_has(ans, 'value'))
      ) {
        const ansString = Number.parseFloat(ans.toPrecision(10)).toString();
        const isResultMeaningful = ansString.trim() !== query.trim();
        if (isResultMeaningful || showRedundantResult) return ansString;
      }
    } catch (e) {}
  }

  function execute(id, payload, extra) {
    app.setQuery(`=${payload}`);
    clipboard.writeText(payload);
    toast.enqueue(`${payload} has copied into clipboard`);
  }

  return { startup, search, execute };
};
<commit_msg>Plugin: Math - Support European-style decimal separator (#268)<commit_after>'use strict';

const lo_isNumber = require('lodash.isnumber');
const lo_isString = require('lodash.isstring');
const lo_isObject = require('lodash.isobject');
const lo_has = require('lodash.has');

const math = require('mathjs');

const DECIMAL_SEPARATOR_UK = '.';
const DECIMAL_SEPARATOR_EUROPE = ',';

module.exports = (context) => {
  const app = context.app;
  const clipboard = context.clipboard;
  const toast = context.toast;
  const indexer = context.indexer;

  function startup() {
    indexer.set('math', (query) => {
      const answer = calculate(query, false);
      if (!answer) return;
      return makeResultItem('primaryText', query, answer);
    });
  }

  function search(query, res) {
    const answer = calculate(query, true);
    if (!answer) return;
    res.add(makeResultItem('title', query, answer));
  }

  function makeResultItem(titleKey, query, answer) {
    const result = {};
    result[titleKey] = `${query.trim()} = <b>${answer}</b>`;
    result.group = 'Math';
    result.payload = answer;
    return result;
  }

  function calculate(rawQuery, showRedundantResult) {
    try {
      let query = rawQuery;

      // determine input mode by the presence of European-style decimal separators
      let inputMode = DECIMAL_SEPARATOR_UK;

      if (query.includes(DECIMAL_SEPARATOR_EUROPE)) {
        inputMode = DECIMAL_SEPARATOR_EUROPE;

        // replace European-style decimal separators with UK-style decimal separators as required by the MathJS library:
        // http://mathjs.org/examples/browser/custom_separators.html.html
        query = query.replace(
          new RegExp(DECIMAL_SEPARATOR_EUROPE, 'g'),
          DECIMAL_SEPARATOR_UK
        );
      }

      // calculate value by passing the query into MathJS
      const ans = math.eval(query);

      if (
        lo_isNumber(ans) ||
        lo_isString(ans) ||
        (lo_isObject(ans) && lo_has(ans, 'value'))
      ) {
        let ansString = Number.parseFloat(ans.toPrecision(10)).toString();
        const isResultMeaningful = ansString.trim() !== query.trim();

        // if the input mode is the non-standard European-style, take the UK-style output of MathJS and transform it
        // back into the European-style that the user expects
        if (inputMode === DECIMAL_SEPARATOR_EUROPE && ansString.includes('.')) {
          ansString = ansString.replace(
            new RegExp(`\\${DECIMAL_SEPARATOR_UK}`, 'g'),
            DECIMAL_SEPARATOR_EUROPE
          );
        }

        if (isResultMeaningful || showRedundantResult) return ansString;
      }
    } catch (e) {}
  }

  function execute(id, payload, extra) {
    app.setQuery(`=${payload}`);
    clipboard.writeText(payload);
    toast.enqueue(`${payload} has copied into clipboard`);
  }

  return { startup, search, execute };
};
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const electron = require('electron')
const path = require('path')
const childProcess = require('child_process')
const spawn = childProcess.spawn
const spawnSync = childProcess.spawnSync
const execSync = childProcess.execSync
const app = electron.app
const Channel = require('./channel')
let appUserModelId = 'com.squirrel.brave.Brave'
switch (Channel.channel()) {
  case 'nightly':
    appUserModelId = 'com.squirrel.BraveNightly.BraveNightly'
    break
  case 'developer':
    appUserModelId = 'com.squirrel.BraveDeveloper.BraveDeveloper'
    break
  case 'beta':
    appUserModelId = 'com.squirrel.BraveBeta.BraveBeta'
    break
  case 'dev':
    appUserModelId = 'com.squirrel.brave.Brave'
    break
  default:
    appUserModelId = 'com.squirrel.brave.Brave'
    break
}

const getBraveBinPath = () => {
  const appPath = app.getPath('exe')
  return path.dirname(appPath)
}

const getBraveDefaultsBinPath = () => {
  const appDir = getBraveBinPath()
  return path.join(appDir, 'resources', 'braveDefaults.exe')
}

const getVisualElementsManifestPath = () => {
  const appDir = getBraveBinPath()
  return path.join(appDir, 'resources', 'Update.VisualElementsManifest.xml')
}

function CopyManifestFile () {
  const versionedRoot = getBraveBinPath()
  let updateRoot = versionedRoot.split('\\')
  updateRoot.pop()
  updateRoot = updateRoot.join('\\')
  const cmd = 'copy "' + getVisualElementsManifestPath() + '" "' + updateRoot + '"'
  execSync(cmd)
}

 // windows installation events etc...
if (process.platform === 'win32') {
  const shouldQuit = require('electron-squirrel-startup')
  const cmd = process.argv[1]
  const channel = Channel.channel()
  if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
    // The manifest file is used to customize the look of the Start menu tile.
    // This function copies it from the versioned folder to the parent folder
    // (where the auto-update executable lives)
    CopyManifestFile()
    // Launch defaults helper to add defaults on install
    spawn(getBraveDefaultsBinPath(), [], { detached: true })
  } else if (cmd === '--squirrel-uninstall') {
    // Launch defaults helper to remove defaults on uninstall
    // Sync to avoid file path in use on uninstall
    spawnSync(getBraveDefaultsBinPath(), ['-uninstall'])
  }

  if (shouldQuit(channel)) {
    process.exit(0)
  }

  const userDataDirSwitch = '--user-data-dir=brave-' + channel
  if (channel !== 'dev' && !process.argv.includes(userDataDirSwitch)) {
    if (cmd === '--squirrel-firstrun') {
      app.relaunch({args: [userDataDirSwitch, '--relaunch']})
    } else {
      app.relaunch({args: process.argv.slice(1) + [userDataDirSwitch, '--relaunch']})
    }
    app.quit()
  }
}

app.on('will-finish-launching', () => {
  app.setAppUserModelId(appUserModelId)
})
<commit_msg>Missing user-data-dir-name change and address https://github.com/brave/browser-laptop/commit/7317c707667d0b434d94aa916523ad588552f4ed#diff-957f46bacb200ef966023deb70f7be5cR13<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const electron = require('electron')
const path = require('path')
const childProcess = require('child_process')
const spawn = childProcess.spawn
const spawnSync = childProcess.spawnSync
const execSync = childProcess.execSync
const app = electron.app
const Channel = require('./channel')
let appUserModelId = 'com.squirrel.brave.Brave'
switch (Channel.channel()) {
  case 'nightly':
    appUserModelId = 'com.squirrel.BraveNightly.BraveNightly'
    break
  case 'developer':
    appUserModelId = 'com.squirrel.BraveDeveloper.BraveDeveloper'
    break
  case 'beta':
    appUserModelId = 'com.squirrel.BraveBeta.BraveBeta'
    break
  case 'dev':
    appUserModelId = 'com.squirrel.brave.Brave'
    break
  default:
    appUserModelId = 'com.squirrel.brave.Brave'
    break
}

const getBraveBinPath = () => {
  const appPath = app.getPath('exe')
  return path.dirname(appPath)
}

const getBraveDefaultsBinPath = () => {
  const appDir = getBraveBinPath()
  return path.join(appDir, 'resources', 'braveDefaults.exe')
}

const getVisualElementsManifestPath = () => {
  const appDir = getBraveBinPath()
  return path.join(appDir, 'resources', 'Update.VisualElementsManifest.xml')
}

function CopyManifestFile () {
  const versionedRoot = getBraveBinPath()
  let updateRoot = versionedRoot.split('\\')
  updateRoot.pop()
  updateRoot = updateRoot.join('\\')
  const cmd = 'copy "' + getVisualElementsManifestPath() + '" "' + updateRoot + '"'
  execSync(cmd)
}

 // windows installation events etc...
if (process.platform === 'win32') {
  const shouldQuit = require('electron-squirrel-startup')
  const cmd = process.argv[1]
  const channel = Channel.channel()
  if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
    // The manifest file is used to customize the look of the Start menu tile.
    // This function copies it from the versioned folder to the parent folder
    // (where the auto-update executable lives)
    CopyManifestFile()
    // Launch defaults helper to add defaults on install
    spawn(getBraveDefaultsBinPath(), [], { detached: true })
  } else if (cmd === '--squirrel-uninstall') {
    // Launch defaults helper to remove defaults on uninstall
    // Sync to avoid file path in use on uninstall
    spawnSync(getBraveDefaultsBinPath(), ['-uninstall'])
  }

  if (shouldQuit(channel)) {
    process.exit(0)
  }

  const userDataDirSwitch = '--user-data-dir-name=brave-' + channel
  if (channel && channel !== 'dev' && !process.argv.includes(userDataDirSwitch)) {
    if (cmd === '--squirrel-firstrun') {
      app.relaunch({args: [userDataDirSwitch, '--relaunch']})
    } else {
      app.relaunch({args: process.argv.slice(1) + [userDataDirSwitch, '--relaunch']})
    }
    app.quit()
  }
}

app.on('will-finish-launching', () => {
  app.setAppUserModelId(appUserModelId)
})
<|endoftext|>


<commit_before>var pointContain = [];
var pointContainVitesse = [];
var pointContainAcceleration = [];
var differencexa = 0;
var differencexb = 0;
var differenceya = 0;
var differenceyb = 0;
var nombrePointActuelle = 150;
var nombrePoint = 150;
var distanceLigne = 60;
var vitessePoint = 0.02;

function setup() {
    clear();
    createCanvas(windowWidth, windowHeight - 4);

    gui = createGui('Panel de valeur');
    sliderRange(10, 500, 10);
    gui.addGlobals('nombrePoint');
    sliderRange(10, 250, 5);
    gui.addGlobals('distanceLigne');
    sliderRange(0.005, 0.1, 0.005);
    gui.addGlobals('vitessePoint');

    fill(255);
    stroke(255);
    for (var i = 0; i < nombrePoint; i++) {
        pointContain[i] = createVector(random(width), random(height));
        pointContainVitesse[i] = createVector(random(-0.1, 0.1), random(-0.1, 0.1));
    }
    nombrePointActuelle = nombrePoint;
}

function draw() {
    if(nombrePointActuelle != nombrePoint){
        setup();
    }

    background(52);

    for (var i = 0; i < pointContain.length; i++) {

        if (pointContain[i].x < 0) {
            pointContain[i].x = width;
        } else if (pointContain[i].x > width) {
            pointContain[i].x = 0;
        }

        if (pointContain[i].y < 0) {
            pointContain[i].y = height;
        } else if (pointContain[i].y > height) {
            pointContain[i].y = 0;
        }

        pointContainAcceleration[i] = createVector(random(-vitessePoint, vitessePoint), random(-vitessePoint, vitessePoint));

        ellipse(pointContain[i].x, pointContain[i].y, 2, 2);

        pointContain[i].x += pointContainVitesse[i].x;
        pointContain[i].y += pointContainVitesse[i].y;
        pointContainVitesse[i].x += pointContainAcceleration[i].x;
        pointContainVitesse[i].y += pointContainAcceleration[i].y;

        for (var j = 0; j < pointContain.length; j++) {

            differencexa = pointContain[i].x - pointContain[j].x;
            differenceya = pointContain[i].y - pointContain[j].y;
            differencexb = pointContain[j].x - pointContain[i].x;
            differenceyb = pointContain[j].y - pointContain[i].y;

            if (differencexa < distanceLigne && differencexa > 0 || differencexb < distanceLigne && differencexb > 0) {
                if (differenceya < distanceLigne && differenceya > 0 || differenceyb < distanceLigne && differenceyb > 0) {
                    line(pointContain[i].x, pointContain[i].y, pointContain[j].x, pointContain[j].y)
                }
            }
        }

    }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight - 4);
}
<commit_msg>Update<commit_after>var pointContain = [];
var pointContainVitesse = [];
var pointContainAcceleration = [];
var differencexa = 0;
var differencexb = 0;
var differenceya = 0;
var differenceyb = 0;
var nombrePointActuelle = 150;
var nombrePoint = 150;
var distanceLigne = 60;
var vitessePoint = 0.02;

function setup() {
    clear();
    pointContain = [];
    pointContainVitesse = [];
    pointContainAcceleration = [];
    createCanvas(windowWidth, windowHeight - 4);

    gui = createGui('Panel de valeur');
    sliderRange(10, 500, 10);
    gui.addGlobals('nombrePoint');
    sliderRange(10, 100, 5);
    gui.addGlobals('distanceLigne');
    sliderRange(0.005, 0.1, 0.005);
    gui.addGlobals('vitessePoint');

    fill(255);
    stroke(255);
    for (var i = 0; i < nombrePoint; i++) {
        pointContain[i] = createVector(random(width), random(height));
        pointContainVitesse[i] = createVector(random(-0.1, 0.1), random(-0.1, 0.1));
    }
    nombrePointActuelle = nombrePoint;
}

function draw() {
    if(nombrePointActuelle != nombrePoint){
        setup();
    }

    background(52);

    for (var i = 0; i < pointContain.length; i++) {

        if (pointContain[i].x < 0) {
            pointContain[i].x = width;
        } else if (pointContain[i].x > width) {
            pointContain[i].x = 0;
        }

        if (pointContain[i].y < 0) {
            pointContain[i].y = height;
        } else if (pointContain[i].y > height) {
            pointContain[i].y = 0;
        }

        pointContainAcceleration[i] = createVector(random(-vitessePoint, vitessePoint), random(-vitessePoint, vitessePoint));

        ellipse(pointContain[i].x, pointContain[i].y, 2, 2);

        pointContain[i].x += pointContainVitesse[i].x;
        pointContain[i].y += pointContainVitesse[i].y;
        pointContainVitesse[i].x += pointContainAcceleration[i].x;
        pointContainVitesse[i].y += pointContainAcceleration[i].y;

        for (var j = 0; j < pointContain.length; j++) {

            differencexa = pointContain[i].x - pointContain[j].x;
            differenceya = pointContain[i].y - pointContain[j].y;
            differencexb = pointContain[j].x - pointContain[i].x;
            differenceyb = pointContain[j].y - pointContain[i].y;

            if (differencexa < distanceLigne && differencexa > 0 || differencexb < distanceLigne && differencexb > 0) {
                if (differenceya < distanceLigne && differenceya > 0 || differenceyb < distanceLigne && differenceyb > 0) {
                    line(pointContain[i].x, pointContain[i].y, pointContain[j].x, pointContain[j].y)
                }
            }
        }

    }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight - 4);
}
<|endoftext|>


<commit_before>'use strict';

angular.module('confRegistrationWebApp')
  .controller('eventDetailsCtrl', function ($rootScope, $scope, $http, $sce, $timeout, $window, modalMessage, $filter, $location, conference, ConfCache, permissions, permissionConstants, uuid) {
    $rootScope.globalPage = {
      type: 'admin',
      mainClass: 'container event-details',
      bodyClass: '',
      title: conference.name,
      confId: conference.id,
      footer: true
    };
    if (permissions.permissionInt >= permissionConstants.UPDATE) {
      $scope.templateUrl = 'views/eventDetails.html';
    } else {
      $scope.templateUrl = 'views/permissionError.html';
    }

    $scope.tabs = [
      {id: 'eventInfo', name: 'Event Information', view: 'views/eventDetails/eventInformation.html'},
      {id: 'regOptions', name: 'Registration Options', view: 'views/eventDetails/regOptions.html'},
      {id: 'regTypes', name: 'Registration Types', view: 'views/eventDetails/regTypes.html'},
      {id: 'paymentOptions', name: 'Payment Options', view: 'views/eventDetails/paymentOptions.html'},
      {id: 'contactInfo', name: 'Contact Information', view: 'views/eventDetails/contactInfo.html'}
    ];

    $scope.changeTab = function(tab){
      $scope.activeTab = tab;
    };
    $scope.changeTab($scope.tabs[0]);

    $scope.paymentGateways = [
      {id: 'AUTHORIZE_NET', name: 'Authorize.Net'}
    ];

    $scope.conference = angular.copy(conference);

    $scope.$on('$locationChangeStart', function(event, newLocation) {
      if(!angular.equals(conference, $scope.conference)){
        event.preventDefault();
        modalMessage.confirm({
          title: 'Warning: Unsaved Changes',
          question: 'You have some unsaved changes on this page, are you sure you want to leave? Your changes will be lost.',
          yesString: 'Discard changes',
          noString: 'Stay on this page',
          normalSize: true
        }).then(function(){
          conference = angular.copy($scope.conference);
          $location.url($location.url(newLocation).hash());
        });
      }
    });

    $scope.addRegType = function(){
      $scope.conference.registrantTypes.push({
        id: uuid(),
        cost: 0,
        earlyRegistrationCutoff: moment().add(7, 'days').format('YYYY-MM-DD HH:mm:ss')
      });
    };

    $scope.deleteRegType = function(id){
      if ($scope.conference.registrantTypes.length > 1) {
        _.remove($scope.conference.registrantTypes, function(type) { return type.id === id; });
      } else {
        $scope.notify = {
          class: 'alert-danger',
          message: $sce.trustAsHtml('You must have at least one registration type per event.')
        };
        $timeout(function() { $scope.notify = {}; }, 3500);
      }
    };

    $scope.addEarlyRegistrationDiscount = function(type){
      type.earlyRegistrationDiscounts.push({id: uuid(), enabled: true});
    };

    $scope.saveEvent = function () {
      //validation check
      var validationErrors = [];

      //Event Name
      if (_.isEmpty($scope.conference.name)) {
        validationErrors.push('Please enter an event name.');
      }

      //Event Dates
      if ($scope.conference.eventStartTime > $scope.conference.eventEndTime) {
        validationErrors.push('Event end date/time must be after event start date/time.');
      }

      //Registration Window
      if ($scope.conference.registrationStartTime > $scope.conference.registrationEndTime) {
        validationErrors.push('Registration end date/time must be after registration start date/time.');
      }

      //Registrant Name
      angular.forEach($scope.conference.registrantTypes, function(t) {
        if (_.isEmpty(t.name)) {
          validationErrors.push('Please enter a name for all registration types.');
        }
      });

      //Event Cost
      angular.forEach($scope.conference.registrantTypes, function(t) {
        t.cost = Number(t.cost);
        if ( _.isNaN(t.cost) || t.cost < 0) {
          validationErrors.push('Event cost for \'' + t.name + '\' must be a positive number.');
        }
      });

      //Credit cards
      if (_.isEmpty($scope.conference.paymentGatewayId) && _.some($scope.conference.registrantTypes, 'acceptCreditCards')) {
        validationErrors.push('Please enter a credit card Account ID.');
      }

      //Minimum Deposit
      angular.forEach($scope.conference.registrantTypes, function(t) {
        if ($scope.conference.requireLogin && $scope.anyPaymentMethodAccepted(t) && String(t.minimumDeposit).length > 0 && !_.isNull(t.minimumDeposit)) {
          t.minimumDeposit = Number(t.minimumDeposit);
          if (t.minimumDeposit > t.cost) {
            validationErrors.push('The minimum deposit for \'' + t.name + '\' must be less than the cost.');
          }
        } else {
          t.minimumDeposit = null;
        }
      });

      //Early bird discount
      angular.forEach($scope.conference.registrantTypes, function(t) {
        angular.forEach(t.earlyRegistrationDiscounts, function(d, index){
          if (d.enabled) {
            d.amountOfDiscount = Number(d.amountOfDiscount);
            if (d.amountOfDiscount < 0) {
              validationErrors.push('Early registration discount ' + (index + 1) + ' for \'' + t.name + '\' must be a positive number.');
            }
            if (!d.deadline) {
              validationErrors.push('Early registration discount ' + (index + 1) + ' for \'' + t.name + '\' must include a valid date and time.');
            }
          }
        });
      });

      $window.scrollTo(0, 0);
      if (validationErrors.length > 0) {
        var errorMsg = 'Error! Please fix the following issues:
';
        angular.forEach(validationErrors, function (e) {
          errorMsg = errorMsg + '
' + e + '
';
        });
        errorMsg = errorMsg + '
';
        $scope.notify = {
          class: 'alert-danger',
          message: $sce.trustAsHtml(errorMsg)
        };
      } else {
        $scope.notify = {
          class: 'alert-warning',
          message: $sce.trustAsHtml('Saving...')
        };

        $http(
          {method: 'PUT',
            url: 'conferences/' + conference.id,
            data: $scope.conference
        }).success(function () {
            $scope.notify = {
              class: 'alert-success',
              message: $sce.trustAsHtml('Saved! Your event details have been updated.')
            };

            conference = angular.copy($scope.conference);
            //Clear cache
            ConfCache.empty();
          }).error(function (data) {
            $scope.notify = {
              class: 'alert-danger',
              message: $sce.trustAsHtml('Error ' + data.errorMessage)
            };
          });
      }
    };

    $scope.anyPaymentMethodAccepted = function(type){
      return type.acceptCreditCards || type.acceptChecks || type.acceptTransfers || type.acceptScholarships;
    };

    $scope.acceptedPaymentMethods = function(){
      var regTypes = $scope.conference.registrantTypes;

      var paymentMethods = {
        acceptCreditCards: _.some(regTypes, 'acceptCreditCards'),
        acceptChecks:_.some(regTypes, 'acceptChecks'),
        acceptTransfers: _.some(regTypes, 'acceptTransfers'),
        acceptScholarships: _.some(regTypes, 'acceptScholarships')
      };
      return paymentMethods;
    };

    $scope.previewEmail = function(reg){
      var cost = $filter('currency')(reg.cost, '$');
      var eventStartTime = moment(conference.eventStartTime).format('dddd, MMMM D YYYY, h:mm a');
      var eventEndTime = moment(conference.eventEndTime).format('dddd, MMMM D YYYY, h:mm a');
      modalMessage.info({
        'title': 'Email Preview',
        'message': '
Hello ' + $rootScope.globalGreetingName + '!

You are registered for ' + $scope.conference.name + '.
' +
        '
Start Time: ' + eventStartTime + '
End Time: ' + eventEndTime + '
' +
        '
Total Cost: ' + cost + '
Total Amount Paid: ' + cost + '
Remaining Balance: $0.00
' +
        reg.customConfirmationEmailText,
        'okString': 'Close'
      });
    };
  });
<commit_msg>Remove earlyRegistrationCutoff from reg type<commit_after>'use strict';

angular.module('confRegistrationWebApp')
  .controller('eventDetailsCtrl', function ($rootScope, $scope, $http, $sce, $timeout, $window, modalMessage, $filter, $location, conference, ConfCache, permissions, permissionConstants, uuid) {
    $rootScope.globalPage = {
      type: 'admin',
      mainClass: 'container event-details',
      bodyClass: '',
      title: conference.name,
      confId: conference.id,
      footer: true
    };
    if (permissions.permissionInt >= permissionConstants.UPDATE) {
      $scope.templateUrl = 'views/eventDetails.html';
    } else {
      $scope.templateUrl = 'views/permissionError.html';
    }

    $scope.tabs = [
      {id: 'eventInfo', name: 'Event Information', view: 'views/eventDetails/eventInformation.html'},
      {id: 'regOptions', name: 'Registration Options', view: 'views/eventDetails/regOptions.html'},
      {id: 'regTypes', name: 'Registration Types', view: 'views/eventDetails/regTypes.html'},
      {id: 'paymentOptions', name: 'Payment Options', view: 'views/eventDetails/paymentOptions.html'},
      {id: 'contactInfo', name: 'Contact Information', view: 'views/eventDetails/contactInfo.html'}
    ];

    $scope.changeTab = function(tab){
      $scope.activeTab = tab;
    };
    $scope.changeTab($scope.tabs[0]);

    $scope.paymentGateways = [
      {id: 'AUTHORIZE_NET', name: 'Authorize.Net'}
    ];

    $scope.conference = angular.copy(conference);

    $scope.$on('$locationChangeStart', function(event, newLocation) {
      if(!angular.equals(conference, $scope.conference)){
        event.preventDefault();
        modalMessage.confirm({
          title: 'Warning: Unsaved Changes',
          question: 'You have some unsaved changes on this page, are you sure you want to leave? Your changes will be lost.',
          yesString: 'Discard changes',
          noString: 'Stay on this page',
          normalSize: true
        }).then(function(){
          conference = angular.copy($scope.conference);
          $location.url($location.url(newLocation).hash());
        });
      }
    });

    $scope.addRegType = function(){
      $scope.conference.registrantTypes.push({
        id: uuid(),
        cost: 0
      });
    };

    $scope.deleteRegType = function(id){
      if ($scope.conference.registrantTypes.length > 1) {
        _.remove($scope.conference.registrantTypes, function(type) { return type.id === id; });
      } else {
        $scope.notify = {
          class: 'alert-danger',
          message: $sce.trustAsHtml('You must have at least one registration type per event.')
        };
        $timeout(function() { $scope.notify = {}; }, 3500);
      }
    };

    $scope.addEarlyRegistrationDiscount = function(type){
      type.earlyRegistrationDiscounts.push({id: uuid(), enabled: true});
    };

    $scope.saveEvent = function () {
      //validation check
      var validationErrors = [];

      //Event Name
      if (_.isEmpty($scope.conference.name)) {
        validationErrors.push('Please enter an event name.');
      }

      //Event Dates
      if ($scope.conference.eventStartTime > $scope.conference.eventEndTime) {
        validationErrors.push('Event end date/time must be after event start date/time.');
      }

      //Registration Window
      if ($scope.conference.registrationStartTime > $scope.conference.registrationEndTime) {
        validationErrors.push('Registration end date/time must be after registration start date/time.');
      }

      //Registrant Name
      angular.forEach($scope.conference.registrantTypes, function(t) {
        if (_.isEmpty(t.name)) {
          validationErrors.push('Please enter a name for all registration types.');
        }
      });

      //Event Cost
      angular.forEach($scope.conference.registrantTypes, function(t) {
        t.cost = Number(t.cost);
        if ( _.isNaN(t.cost) || t.cost < 0) {
          validationErrors.push('Event cost for \'' + t.name + '\' must be a positive number.');
        }
      });

      //Credit cards
      if (_.isEmpty($scope.conference.paymentGatewayId) && _.some($scope.conference.registrantTypes, 'acceptCreditCards')) {
        validationErrors.push('Please enter a credit card Account ID.');
      }

      //Minimum Deposit
      angular.forEach($scope.conference.registrantTypes, function(t) {
        if ($scope.conference.requireLogin && $scope.anyPaymentMethodAccepted(t) && String(t.minimumDeposit).length > 0 && !_.isNull(t.minimumDeposit)) {
          t.minimumDeposit = Number(t.minimumDeposit);
          if (t.minimumDeposit > t.cost) {
            validationErrors.push('The minimum deposit for \'' + t.name + '\' must be less than the cost.');
          }
        } else {
          t.minimumDeposit = null;
        }
      });

      //Early bird discount
      angular.forEach($scope.conference.registrantTypes, function(t) {
        angular.forEach(t.earlyRegistrationDiscounts, function(d, index){
          if (d.enabled) {
            d.amountOfDiscount = Number(d.amountOfDiscount);
            if (d.amountOfDiscount < 0) {
              validationErrors.push('Early registration discount ' + (index + 1) + ' for \'' + t.name + '\' must be a positive number.');
            }
            if (!d.deadline) {
              validationErrors.push('Early registration discount ' + (index + 1) + ' for \'' + t.name + '\' must include a valid date and time.');
            }
          }
        });
      });

      $window.scrollTo(0, 0);
      if (validationErrors.length > 0) {
        var errorMsg = 'Error! Please fix the following issues:
';
        angular.forEach(validationErrors, function (e) {
          errorMsg = errorMsg + '
' + e + '
';
        });
        errorMsg = errorMsg + '
';
        $scope.notify = {
          class: 'alert-danger',
          message: $sce.trustAsHtml(errorMsg)
        };
      } else {
        $scope.notify = {
          class: 'alert-warning',
          message: $sce.trustAsHtml('Saving...')
        };

        $http(
          {method: 'PUT',
            url: 'conferences/' + conference.id,
            data: $scope.conference
        }).success(function () {
            $scope.notify = {
              class: 'alert-success',
              message: $sce.trustAsHtml('Saved! Your event details have been updated.')
            };

            conference = angular.copy($scope.conference);
            //Clear cache
            ConfCache.empty();
          }).error(function (data) {
            $scope.notify = {
              class: 'alert-danger',
              message: $sce.trustAsHtml('Error ' + data.errorMessage)
            };
          });
      }
    };

    $scope.anyPaymentMethodAccepted = function(type){
      return type.acceptCreditCards || type.acceptChecks || type.acceptTransfers || type.acceptScholarships;
    };

    $scope.acceptedPaymentMethods = function(){
      var regTypes = $scope.conference.registrantTypes;

      var paymentMethods = {
        acceptCreditCards: _.some(regTypes, 'acceptCreditCards'),
        acceptChecks:_.some(regTypes, 'acceptChecks'),
        acceptTransfers: _.some(regTypes, 'acceptTransfers'),
        acceptScholarships: _.some(regTypes, 'acceptScholarships')
      };
      return paymentMethods;
    };

    $scope.previewEmail = function(reg){
      var cost = $filter('currency')(reg.cost, '$');
      var eventStartTime = moment(conference.eventStartTime).format('dddd, MMMM D YYYY, h:mm a');
      var eventEndTime = moment(conference.eventEndTime).format('dddd, MMMM D YYYY, h:mm a');
      modalMessage.info({
        'title': 'Email Preview',
        'message': '
Hello ' + $rootScope.globalGreetingName + '!

You are registered for ' + $scope.conference.name + '.
' +
        '
Start Time: ' + eventStartTime + '
End Time: ' + eventEndTime + '
' +
        '
Total Cost: ' + cost + '
Total Amount Paid: ' + cost + '
Remaining Balance: $0.00
' +
        reg.customConfirmationEmailText,
        'okString': 'Close'
      });
    };
  });
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import DatabaseDropdown from 'shared/components/DatabaseDropdown'

import {writeData} from 'src/data_explorer/apis'
import {publishAutoDismissingNotification} from 'shared/dispatchers'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'

class WriteDataForm extends Component {
  constructor(props) {
    super(props)
    this.state = {
      selectedDatabase: null,
    }

    this.handleSelectDatabase = ::this.handleSelectDatabase
    this.handleError = ::this.handleError
    this.handleWrite = ::this.handleWrite
  }

  handleSelectDatabase(item) {
    this.setState({selectedDatabase: item.text})
  }

  handleError(error) {
    const {errorThrown} = this.props
    errorThrown(error)
  }

  async handleWrite() {
    const {onClose, source, notify, errorThrown} = this.props
    const {selectedDatabase} = this.state
    try {
      await writeData(source, selectedDatabase, this.editor.value)
      notify('success', 'Data was written successfully')
      onClose()
    } catch (response) {
      errorThrown(response, response.data.error)
    }
  }

  render() {
    const {onClose} = this.props
    const {selectedDatabase} = this.state

    return (

Write Data To

            <DatabaseDropdown
              onSelectDatabase={this.handleSelectDatabase}
              database={selectedDatabase}
              onErrorThrown={this.handleError}
            />

          <textarea
            className="query-editor--field"
            autoComplete="off"
            spellCheck="false"
            placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
            ref={editor => this.editor = editor}
          />

            Uses InfluxDB Line Protocol -

              Docs

            <button className="btn btn-primary" onClick={this.handleWrite}>
              Write
            </button>

    )
  }
}

const {func, shape, string} = PropTypes

WriteDataForm.propTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
      queries: string.isRequired,
    }).isRequired,
  }).isRequired,
  notify: func.isRequired,
  errorThrown: func.isRequired,
  onClose: func.isRequired,
}

const mapDispatchToProps = dispatch => ({
  notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
  errorThrown: bindActionCreators(errorThrownAction, dispatch),
})

export default connect(null, mapDispatchToProps)(WriteDataForm)
<commit_msg>close WriteDataForm when clicking outside<commit_after>import React, {Component, PropTypes} from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import DatabaseDropdown from 'shared/components/DatabaseDropdown'
import OnClickOutside from 'shared/components/OnClickOutside'

import {writeData} from 'src/data_explorer/apis'
import {publishAutoDismissingNotification} from 'shared/dispatchers'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'

class WriteDataForm extends Component {
  constructor(props) {
    super(props)
    this.state = {
      selectedDatabase: null,
    }

    this.handleSelectDatabase = ::this.handleSelectDatabase
    this.handleError = ::this.handleError
    this.handleWrite = ::this.handleWrite
    this.handleClickOutside = ::this.handleClickOutside
  }

  handleSelectDatabase(item) {
    this.setState({selectedDatabase: item.text})
  }

  handleError(error) {
    const {errorThrown} = this.props
    errorThrown(error)
  }

  handleClickOutside() {
    const {onClose} = this.props
    onClose()
  }

  async handleWrite() {
    const {onClose, source, notify, errorThrown} = this.props
    const {selectedDatabase} = this.state
    try {
      await writeData(source, selectedDatabase, this.editor.value)
      notify('success', 'Data was written successfully')
      onClose()
    } catch (response) {
      errorThrown(response, response.data.error)
    }
  }

  render() {
    const {onClose} = this.props
    const {selectedDatabase} = this.state

    return (

Write Data To

            <DatabaseDropdown
              onSelectDatabase={this.handleSelectDatabase}
              database={selectedDatabase}
              onErrorThrown={this.handleError}
            />

          <textarea
            className="query-editor--field"
            autoComplete="off"
            spellCheck="false"
            placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
            ref={editor => this.editor = editor}
          />

            Uses InfluxDB Line Protocol -

              Docs

            <button className="btn btn-primary" onClick={this.handleWrite}>
              Write
            </button>

    )
  }
}

const {func, shape, string} = PropTypes

WriteDataForm.propTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
      queries: string.isRequired,
    }).isRequired,
  }).isRequired,
  notify: func.isRequired,
  errorThrown: func.isRequired,
  onClose: func.isRequired,
}

const mapDispatchToProps = dispatch => ({
  notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
  errorThrown: bindActionCreators(errorThrownAction, dispatch),
})

export default connect(null, mapDispatchToProps)(OnClickOutside(WriteDataForm))
<|endoftext|>