<commit_before>'use strict';

var MEDIA_URL = '/staticuploads/';

/**
 * Handle login with facebook button.
 */
$('.loginBtn--facebook').click(function(){
  event.preventDefault();
  checkLoginState();

  // Check if the "share" button was clicked.
  if($(this).hasClass('fb-share')) {
    shareThisPost();
  }
});

/**
 * Share a post to facebook.
 */
function shareThisPost(){
  var captionText = $('#description').text();
  var url = $(location).attr('href');
  url = url.split("/")[0] + '//' + url.split("/")[2];
  var image = url + $('#FB-image-game').attr('src');

  FB.ui({
    method: 'share',
    name: 'Something',
    picture: image,
    href: url,
    link: url,
    description: captionText,
    caption: 'http://www.whatsbuzz.co.il'

  }, function(response){});
}

/**
 * Handle the quizzes button, when displayed.
 */
$('#quizzes-game').click(function(){
  $('#facebooklogin').hide();
  showSpinner();

  // Show the quiz and hide the play button
  setTimeout(function(){
    $('#quizzes').show();
  }, 5250);
});

/**
 * Handle "show more" button in the nav pages.
 * Get posts, by type, from server and display them on the page.
 */
$('#show-more-in-page').click(function(event){
  event.preventDefault();
  var type = $('.show-more').data('posts-type');
  var start = $('.posts').length;
  $.get("/get-more-posts/" + type + "/" + start, function(data){
    // Convert the data to array of js objects.
    var data = JSON.parse(data[0].posts);

    // Create a post for each of them.
    data.forEach(function(postObject){
      // The title.
      var postTitle = $('<h2>').text(postObject.fields.title);
      // The image banner.
      var postImage = $('<img>').addClass('banner-image').attr('src', MEDIA_URL + postObject.fields.image_banner).attr('alt', postObject.fields.image_banner);
      // The button link.
      var postSlog = $('<a>').attr('href', "/posts/" + postObject.fields.slug).append($('<div>').addClass('row link').append($('<p>').text("התחל משחק")));

      // The whole post card.
      var postObj = $('<div>').addClass('col-sm-6 posts').append($('<div>').addClass('post').append(postTitle).append(postImage).append(postSlog));

      $('#main-posts').append(postObj);
    });
  });
});<commit_msg>Hot fix.<commit_after>'use strict';

var MEDIA_URL = '/staticuploads/';

/**
 * Handle login with facebook button.
 */
$('.loginBtn--facebook').click(function(){
  event.preventDefault();

  // Check if the "share" button was clicked.
  if($(this).hasClass('fb-share')) {
    shareThisPost();
  } else {
    checkLoginState();
  }
});

/**
 * Share a post to facebook.
 */
function shareThisPost(){
  var captionText = $('#description').text();
  var url = $(location).attr('href');
  url = url.split("/")[0] + '//' + url.split("/")[2];
  var image = url + $('#FB-image-game').attr('src');

  FB.ui({
    method: 'share',
    name: 'Something',
    picture: image,
    href: url,
    link: url,
    description: captionText,
    caption: 'http://www.whatsbuzz.co.il'

  }, function(response){});
}

/**
 * Handle the quizzes button, when displayed.
 */
$('#quizzes-game').click(function(){
  $('#facebooklogin').hide();
  showSpinner();

  // Show the quiz and hide the play button
  setTimeout(function(){
    $('#quizzes').show();
  }, 5250);
});

/**
 * Handle "show more" button in the nav pages.
 * Get posts, by type, from server and display them on the page.
 */
$('#show-more-in-page').click(function(event){
  event.preventDefault();
  var type = $('.show-more').data('posts-type');
  var start = $('.posts').length;
  $.get("/get-more-posts/" + type + "/" + start, function(data){
    // Convert the data to array of js objects.
    var data = JSON.parse(data[0].posts);

    // Create a post for each of them.
    data.forEach(function(postObject){
      // The title.
      var postTitle = $('<h2>').text(postObject.fields.title);
      // The image banner.
      var postImage = $('<img>').addClass('banner-image').attr('src', MEDIA_URL + postObject.fields.image_banner).attr('alt', postObject.fields.image_banner);
      // The button link.
      var postSlog = $('<a>').attr('href', "/posts/" + postObject.fields.slug).append($('<div>').addClass('row link').append($('<p>').text("התחל משחק")));

      // The whole post card.
      var postObj = $('<div>').addClass('col-sm-6 posts').append($('<div>').addClass('post').append(postTitle).append(postImage).append(postSlog));

      $('#main-posts').append(postObj);
    });
  });
});<|endoftext|>


<commit_before>// JavaScript Document promisehdr.js: Keyboard management for KeymanWeb demonstration pages

/*
    The keyboard name and/or BCP-47 language code must be specified for each keyboard that is to be available.
    If the same keyboard is used for several languages, it must be listed for each
    language, but the keyboard itself will only be loaded once.
    If two (or more) keyboards are to be available for a given language, both must be listed.
    Any number of keyboards may be specified in one or more calls.
    Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
    The actual keyboard object will be downloaded asynchronously when first selected for use.

    Each argument to addKeyboards() is a string, for example:
      european2         loads the current version of the Eurolatin 2 keyboard (for its default language)
      european2@fr      loads the current version of the Eurolatin 2 keyboard for French
      european2@fr@1.2  loads version 1.2 of the Eurolatin 2 keyboard for French

    Argument syntax also supports the following extensions:
      @fr               load the current version of the default keyboard for French
      @fr$              load all available keyboards (current version) for French

    Each call to addKeyboards() requires a single call to the remote server,
    (unless all keyboards listed are local and fully specified) so it is better
    to use multiple arguments rather than separate function calls.

    Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
    The Toolbar (desktop browser) UI is best suited for allowing users to select
    the appropriate language and keyboard in this case.

    Keyboards may also be specified by language name using addKeyboardsForLanguage()
    for example:
      keymanweb.addKeyboardsForLanguage('Burmese');

    Appending $ to the language name will again cause all available keyboards for that
    language to be loaded rather than the default keyboard.

    The first call to addKeyboardsForLanguage() makes an additional call to the
    keyman API to load the current list of keyboard/language associations.

    In this example, the following function loads the indicated keyboards,
    and is called when the page loads.
*/

  /**
   * Add a keyboard by language name.  Note that the name must be spelled
     correctly, or the keyboard will not be found.  (Using BCP-47 codes is
     usually easier.)
   * @param {string} languages. Could be comma-separated languages
   */
  function addKeyboardsForLanguage(languages) {
    kmw.addKeyboardsForLanguage(languages.split(',').map(item => item.trim())).then(result => {
      console.log('Adding ' + languages + ': ', result);
    }).catch(errorStubs => {
      // Consumer decides how to handle errors
      errorStubs.forEach(e => console.error(e));

      // We'll also concat the error messages to an alert
      let errorMessages = errorStubs.map(e => e.error.message).join('\n');
      alert(errorMessages);
    });
  }

  function loadKeyboards()
  {
    var kmw=keyman;

    // The first keyboard added will be the default keyboard for touch devices.
    // For faster loading, it may be best for the default keyboard to be
    // locally sourced.
    kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'},
      filename:'../us-1.0.js'});

    // Add more keyboards to the language menu, by keyboard name,
    // keyboard name and language code, or just the BCP-47 language code.
    // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases.
    kmw.addKeyboards('french','@he');
    kmw.addKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string.

    // Add a keyboard by language name.  Note that the name must be spelled
    // correctly, or the keyboard will not be found.  (Using BCP-47 codes is
    // usually easier.)
    addKeyboardsForLanguage('Dzongkha');

    // Add a fully-specified, locally-sourced, keyboard with custom font
    kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic',
      languages: {
          id:'lo',name:'Lao',region:'Asia'
        },
      filename:'../lao_2008_basic-1.2.js'
      });

    // The following two optional calls should be delayed until language menus are fully loaded:
    //  (a) a specific mapped input element input is focused, to ensure that the OSK appears
    //  (b) a specific keyboard is loaded, rather than the keyboard last used.
    //window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500);
    //window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000);

    // Note that locally specified keyboards will be listed before keyboards
    // requested from the remote server by user interfaces that do not order
    // keyboards alphabetically by language.
  }

  // Script to allow a user to add any keyboard to the keyboard menu
  function addKeyboard(n)
  {
    var sKbd,kmw=keyman;
    switch(n)
    {
      case 1:
        sKbd=document.getElementById('kbd_id1').value;
        kmw.addKeyboards(sKbd);
        break;
      case 2:
        sKbd=document.getElementById('kbd_id2').value.toLowerCase();
        kmw.addKeyboards('@'+sKbd);
        break;
      case 3:
        // Add keyboard for comma-separated language name(s)
        sKbd=document.getElementById('kbd_id3').value;
        addKeyboardsForLanguage(sKbd);
        break;
    }
  }

  // Add keyboard on Enter (as well as pressing button)
  function clickOnEnter(e,id)
  {
    e = e || window.event;
    if(e.keyCode == 13) addKeyboard(id);
  }

<commit_msg>fix(web): Filter test page for KeyboardStub<commit_after>// JavaScript Document promisehdr.js: Keyboard management for KeymanWeb demonstration pages

/*
    The keyboard name and/or BCP-47 language code must be specified for each keyboard that is to be available.
    If the same keyboard is used for several languages, it must be listed for each
    language, but the keyboard itself will only be loaded once.
    If two (or more) keyboards are to be available for a given language, both must be listed.
    Any number of keyboards may be specified in one or more calls.
    Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
    The actual keyboard object will be downloaded asynchronously when first selected for use.

    Each argument to addKeyboards() is a string, for example:
      european2         loads the current version of the Eurolatin 2 keyboard (for its default language)
      european2@fr      loads the current version of the Eurolatin 2 keyboard for French
      european2@fr@1.2  loads version 1.2 of the Eurolatin 2 keyboard for French

    Argument syntax also supports the following extensions:
      @fr               load the current version of the default keyboard for French
      @fr$              load all available keyboards (current version) for French

    Each call to addKeyboards() requires a single call to the remote server,
    (unless all keyboards listed are local and fully specified) so it is better
    to use multiple arguments rather than separate function calls.

    Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
    The Toolbar (desktop browser) UI is best suited for allowing users to select
    the appropriate language and keyboard in this case.

    Keyboards may also be specified by language name using addKeyboardsForLanguage()
    for example:
      keymanweb.addKeyboardsForLanguage('Burmese');

    Appending $ to the language name will again cause all available keyboards for that
    language to be loaded rather than the default keyboard.

    The first call to addKeyboardsForLanguage() makes an additional call to the
    keyman API to load the current list of keyboard/language associations.

    In this example, the following function loads the indicated keyboards,
    and is called when the page loads.
*/

  /**
   * Add a keyboard by language name.  Note that the name must be spelled
     correctly, or the keyboard will not be found.  (Using BCP-47 codes is
     usually easier.)
   * @param {string} languages. Could be comma-separated languages
   */
  function addKeyboardsForLanguage(languages) {
    kmw.addKeyboardsForLanguage(languages.split(',').map(item => item.trim())).then(stubs => {
      // Filter for just keyboard stubs
      stubs.forEach(s => {
        if (s instanceof com.keyman.keyboards.KeyboardStub) {
          console.log('Adding keyboard for ' + s.KL);
        }
      });
    }).catch(errorStubs => {
      // Consumer decides how to handle errors
      errorStubs.forEach(e => console.error(e));

      // We'll also concat the error messages to an alert
      let errorMessages = errorStubs.map(e => e.error.message).join('\n');
      alert(errorMessages);
    });
  }

  function loadKeyboards()
  {
    var kmw=keyman;

    // The first keyboard added will be the default keyboard for touch devices.
    // For faster loading, it may be best for the default keyboard to be
    // locally sourced.
    kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'},
      filename:'../us-1.0.js'});

    // Add more keyboards to the language menu, by keyboard name,
    // keyboard name and language code, or just the BCP-47 language code.
    // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases.
    kmw.addKeyboards('french','@he');
    kmw.addKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string.

    // Add a keyboard by language name.  Note that the name must be spelled
    // correctly, or the keyboard will not be found.  (Using BCP-47 codes is
    // usually easier.)
    addKeyboardsForLanguage('Dzongkha');

    // Add a fully-specified, locally-sourced, keyboard with custom font
    kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic',
      languages: {
          id:'lo',name:'Lao',region:'Asia'
        },
      filename:'../lao_2008_basic-1.2.js'
      });

    // The following two optional calls should be delayed until language menus are fully loaded:
    //  (a) a specific mapped input element input is focused, to ensure that the OSK appears
    //  (b) a specific keyboard is loaded, rather than the keyboard last used.
    //window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500);
    //window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000);

    // Note that locally specified keyboards will be listed before keyboards
    // requested from the remote server by user interfaces that do not order
    // keyboards alphabetically by language.
  }

  // Script to allow a user to add any keyboard to the keyboard menu
  function addKeyboard(n)
  {
    var sKbd,kmw=keyman;
    switch(n)
    {
      case 1:
        sKbd=document.getElementById('kbd_id1').value;
        kmw.addKeyboards(sKbd);
        break;
      case 2:
        sKbd=document.getElementById('kbd_id2').value.toLowerCase();
        kmw.addKeyboards('@'+sKbd);
        break;
      case 3:
        // Add keyboard for comma-separated language name(s)
        sKbd=document.getElementById('kbd_id3').value;
        addKeyboardsForLanguage(sKbd);
        break;
    }
  }

  // Add keyboard on Enter (as well as pressing button)
  function clickOnEnter(e,id)
  {
    e = e || window.event;
    if(e.keyCode == 13) addKeyboard(id);
  }

<|endoftext|>


<commit_before>/* globals controlplane: true */

/* AppsController
 * Displays top level apps
 */
(function() {
    'use strict';

    controlplane.controller("AppsController", [
        "$rootScope", "$scope", "$routeParams", "$location",
        "$notification", "resourcesFactory", "authService",
        "$modalService", "$translate", "$timeout",
        "$cookies", "miscUtils",
        "ngTableParams", "$filter",
        "Service","InternalService", "$q",
    function($rootScope, $scope, $routeParams, $location,
    $notification, resourcesFactory, authService,
    $modalService, $translate, $timeout,
    $cookies, utils,
    NgTableParams, $filter,
    Service, InternalService, $q){

        // Ensure logged in
        authService.checkLogin($scope);

        // alias hostname instead of using localhost or IP
        $scope.defaultHostAlias = $location.host();

        // redirect to specific service details
        $scope.routeToService = function(service) {
            if (service.isIsvc()) {
                resourcesFactory.routeToInternalServices();
            } else {
                resourcesFactory.routeToService(service.id);
            }
        };

        // redirect to specific pool
        $scope.routeToPool = function(id) {
            resourcesFactory.routeToPool(id);
        };

        $scope.modal_deployWizard = function() {

            // the modal occasionally won't show on page load, so we use a timeout to get around that.
            $timeout(function(){
                $('#addApp').modal('show');

                // don't auto-show this wizard again
                // NOTE: $cookies can only deal with string values
                $cookies.put("autoRunWizardHasRun","true");
            });
        };

        $scope.modal_addTemplate = function() {
            $modalService.create({
                templateUrl: "add-template.html",
                model: $scope,
                title: "template_add",
                actions: [
                    {
                        role: "cancel",
                        action: function(){
                            $scope.newHost = {};
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: "template_add",
                        action: function(){
                            if(this.validate()){
                                var data = new FormData();

                                $.each($("#new_template_filename")[0].files, function(key, value){
                                    data.append("tpl", value);
                                });

                                // disable ok button, and store the re-enable function
                                var enableSubmit = this.disableSubmitButton();

                                resourcesFactory.addAppTemplate(data)
                                    .success(function(data){
                                        $notification.create("Added template", data.Detail).success();
                                        refreshTemplates();
                                        this.close();
                                    }.bind(this))
                                    .error(function(data){
                                        this.createNotification("Adding template failed", data.Detail).error();
                                        enableSubmit();
                                    }.bind(this));
                            }
                        }
                    }
                ]
            });
        };

        $scope.modal_removeService = function(service) {
            $modalService.create({
                template: $translate.instant("warning_remove_service"),
                model: $scope,
                title: "remove_service",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "remove_service",
                        classes: "btn-danger submit",
                        action: function(){
                            if(this.validate()){
                                this.disableSubmitButton();

                                removeService(service)
                                    .success(() => {
                                        $notification.create("Removed App", service.name).success();
                                        refreshApps();
                                        this.close();
                                    })
                                    .error((data, status) => {
                                        $notification.create("Remove App failed", data.Detail).error();
                                        this.close();
                                    });
                            }
                        }
                    }
                ]
            });
        };

        $scope.startService = function(service){
            $scope.modal_startStopService(service, "start");
        };
        $scope.stopService = function(service){
            $scope.modal_startStopService(service, "stop");
        };
        $scope.modal_startStopService = function(service, status) {
            var displayStatus = utils.capitalizeFirst(status);

            $modalService.create({
                template: $translate.instant("confirm_"+ status +"_app"),
                model: $scope,
                title: displayStatus +" Services",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: displayStatus +" Services",
                        action: function(){
                            service[status]();
                            this.close();
                        }
                    }
                ]
            });
        };

        // sets a service to start, stop or restart state
        $scope.setServiceState = function(service, state, skipChildren){
            service[state](skipChildren).error(function(data, status){
                $notification.create("Unable to " + state + " service", data.Detail).error();
            });
        };

        // clicks to a service's start, stop, or restart
        // button should first determine if the service has
        // children and ask the user to choose to start all
        // children or only the top service
        $scope.clickRunning = function(service, state){
            let onStartService = function(modal){
                // the arg here explicitly prevents child services
                // from being started
                $scope.setServiceState(service, state, true);
                modal.close();
            };
            let onStartServiceAndChildren = function(modal){
                $scope.setServiceState(service, state);
                modal.close();
            };

            Service.countAffectedDescendants(service, state)
                .then(count => {
                    $modalService.modals.confirmServiceStateChange(service, state,
                        count, onStartService,
                        onStartServiceAndChildren);
                })
                .catch(err => {
                    console.warn("couldnt get descendant count", err);
                    $modalService.modals.confirmServiceStateChange(service, state,
                        0, onStartService,
                        onStartServiceAndChildren);
                });

            // let the user know they gonna have to hold onto
            // their horses for just one moment.
            $modalService.modals.oneMoment();
        };

        // verifies if use wants to start parent service, or parent
        // and all children
        $scope.modal_confirmSetServiceState = function(service, state, childCount){
            $modalService.create({
                template: ["
"+ $translate.instant("choose_services_"+ state) +"

",
                    "
"+ $translate.instant(state +"_service_name", {name: ""+service.name+""}) +"
",
                    "
"+ $translate.instant(state +"_service_name_and_children", {name: ""+service.name+"", count: ""+childCount+""}) +"

"
                ].join(""),
                model: $scope,
                title: $translate.instant(state +"_service"),
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        classes: " ",
                        label: $translate.instant(state +"_service"),
                        action: function(){
                            // the arg here explicitly prevents child services
                            // from being started
                            $scope.setServiceState(service, state, true);
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: $translate.instant(state +"_service_and_children", {count: childCount}),
                        action: function(){
                            $scope.setServiceState(service, state);
                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.modal_deleteTemplate = function(templateID){
            $modalService.create({
                template: $translate.instant("template_remove_confirm") + ""+ templateID +"",
                model: $scope,
                title: "template_remove",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "template_remove",
                        classes: "btn-danger",
                        action: function(){
                            deleteTemplate(templateID)
                                .success(() => {
                                    $notification.create("Removed Template", templateID).success();
                                    this.close();
                                })
                                .error((data, status) => {
                                    $notification.create("Remove Template failed", data.Detail).error();
                                });
                        }
                    }
                ]
            });
        };

        /*
         * PRIVATE FUNCTIONS
         */
        function refreshTemplates(){
            resourcesFactory.getAppTemplates().success(function(templates) {
                $scope.templates.data = utils.mapToArr(templates);
            });
        }

        function refreshApps() {
            return fetchApps()
                .then(fillOutApps)
                .then(fetchServicesHealth)
                .then(fetchInternalServicesHealth)
                .then(() => touch())
                .catch((error) => console.warn(error));
        }

        function fetchApps() {
            return $q.all([fetchInternalService(), fetchServices()])
                .then(results => {
                    $scope.apps = [];

                    var isvc = results[0];
                    $scope.apps.push(isvc);

                    var services = results[1];
                    services.forEach(s => {
                        $scope.apps.push(s);
                    });
                });
        }

        function fetchChildEndpoints(app) {
            return resourcesFactory.v2.getServiceChildPublicEndpoints(app.id).then(data => {
                app.publicEndpoints = data;
            });
        }

        function fillOutApps() {
            let promises = [];
            $scope.apps.forEach(a => {
                if (a.isIsvc()) {
                    promises.push(() => a.fetchInstances());
                } else {
                    promises.push(fetchChildEndpoints(a));
                }
            });

            return $q.all(promises);
        }

        function fetchServices() {
            let deferred = $q.defer();
            resourcesFactory.v2.getTenants().then( data => {
                    var services = data.map(s => new Service(s));
                    deferred.resolve(services);
                },
                error => {
                    console.warn(error);
                    deferred.reject();
                });
            return deferred.promise;
        }

        function fetchServicesHealth() {
            if (!$scope.apps) { return; }

            $scope.apps.forEach(app => {
                if (!app.isIsvc()) {
                    app.fetchAllStates();
                }
            });
        }

        function fetchInternalService() {
            let deferred = $q.defer();
            resourcesFactory.v2.getInternalServices()
                .then(data => {
                    let parent = data.find(i => !i.Parent);
                    if (parent) {
                        var internalServices = new InternalService(parent);
                        deferred.resolve(internalServices);
                    } else {
                        deferred.reject("Parent not found");
                    }
                },
                error => {
                    console.warn(error);
                    deferred.reject();
                });
            return deferred.promise;
        }

        function fetchInternalServicesHealth() {
            $scope.apps.forEach(app => {
                if (app.isIsvc()) {
                    app.fetchInstances().then(() => {
                        resourcesFactory.v2.getInternalServiceStatuses([app.id]).then(data => {
                            let statusMap = data.reduce((map, s) => {
                                map[s.ServiceID] = s;
                                return map;
                            }, {});

                            app.updateStatus(statusMap[app.id]);
                        });
                    });
                }
            });
        }

        // poll for apps that are being deployed
        $scope.deployingServices = [];
        var lastPollResults = 0;
        function getDeploying(){
            resourcesFactory.getDeployingTemplates().success(function(data) {
                if(data){
                    $scope.deployingServices = data;
                }

                //if we have fewer results than last poll, we need to refresh our table
                //TODO - better checking for deploying apps
                if(lastPollResults > $scope.deployingServices.length){
                    refreshApps();
                }
                lastPollResults = $scope.deployingServices.length;
            });
        }

        function removeService(service) {
            return resourcesFactory.removeService(service.id)
                .success(function(){
                    // NOTE: this is here because services are
                    // incrementally updated, which makes it impossible
                    // to determine if a service has been removed
                    // TODO - once the backend notifies on deleted
                    // services, this should be removed
                    // FIXME - should not modify servicesFactory's
                    // objects!
                    for(var i = 0; i < $scope.apps.length; i++){
                        // find the removed service and remove it
                        if($scope.apps[i].id === service.id){
                            $scope.apps.splice(i, 1);
                            touch();
                            return;
                        }
                    }
                });
        }

        function deleteTemplate(templateID){
            return resourcesFactory.removeAppTemplate(templateID)
                .success(refreshTemplates);
        }

        var lastUpdate;
        function touch() {
            lastUpdate = new Date().getTime();
        }

        // init stuff for this controller
        function init(){
            touch();

            if(utils.needsHostAlias($location.host())){
                resourcesFactory.getHostAlias().success(function(data) {
                    $scope.defaultHostAlias = data.hostalias;
                });
            }

            // configure tables
            // TODO - move table config to view/directive
            $scope.breadcrumbs = [
                { label: 'breadcrumb_deployed', itemClass: 'active' }
            ];

            $scope.servicesTable = {
                sorting: {
                    name: "asc"
                },
                searchColumns: ['name','model.Description', 'model.DeploymentID', 'model.PoolID'],
                getData: function(data, params) {
                    // use built-in angular filter
                    var orderedData = params.sorting() ?
                        $filter('orderBy')(data, params.orderBy()) :
                        data;

                    if(!orderedData){
                        return;
                    }

                    // mark any deploying services so they can be treated differently
                    orderedData.forEach(function(service){
                        service.deploying = false;
                        $scope.deployingServices.forEach(function(deploying){
                            if(service.model.DeploymentID === deploying.DeploymentID){
                                service.deploying = true;
                            }
                        });
                    });

                    return orderedData;
                },
                watchExpression: function(){
                    // TODO - check $scope.deployingServices as well
                    return lastUpdate;
                }
            };

            $scope.templates = { data: [] };
            // table config
            $scope.templatesTable = {
                sorting: {
                    Name: "asc"
                },
                searchColumns: ['Name','ID', 'Description']
            };

            // Get a list of templates
            refreshTemplates();

            // check for deploying apps
            getDeploying();

            refreshApps().then(() => {
                $scope.$emit("ready");

                // if only isvcs are deployed, and this is the first time
                // running deploy wizard, show the deploy apps modal
                if(!$cookies.get("autoRunWizardHasRun") && $scope.apps.length === 1){
                    $scope.modal_deployWizard();
                }
            });

            //register polls
            resourcesFactory.registerPoll("deployingApps", getDeploying, 3000);
            resourcesFactory.registerPoll("templates", refreshTemplates, 5000);
            resourcesFactory.registerPoll("internalServiceHealth", fetchInternalServicesHealth, 3000);
            resourcesFactory.registerPoll("appHealth", fetchServicesHealth, 3000);

            //unregister polls on destroy
            $scope.$on("$destroy", function(){
                resourcesFactory.unregisterAllPolls();
            });

            // be sure to update apps table after deploywiz
            // finishes its dark magicks
            $rootScope.$on("wizard.deployed", () => {
                refreshApps();
            });
        }

        // kick this controller off
        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
        });
    }]);
})();
<commit_msg>wait till app list is updated to notify user that app was removed<commit_after>/* globals controlplane: true */

/* AppsController
 * Displays top level apps
 */
(function() {
    'use strict';

    controlplane.controller("AppsController", [
        "$rootScope", "$scope", "$routeParams", "$location",
        "$notification", "resourcesFactory", "authService",
        "$modalService", "$translate", "$timeout",
        "$cookies", "miscUtils",
        "ngTableParams", "$filter",
        "Service","InternalService", "$q",
    function($rootScope, $scope, $routeParams, $location,
    $notification, resourcesFactory, authService,
    $modalService, $translate, $timeout,
    $cookies, utils,
    NgTableParams, $filter,
    Service, InternalService, $q){

        // Ensure logged in
        authService.checkLogin($scope);

        // alias hostname instead of using localhost or IP
        $scope.defaultHostAlias = $location.host();

        // redirect to specific service details
        $scope.routeToService = function(service) {
            if (service.isIsvc()) {
                resourcesFactory.routeToInternalServices();
            } else {
                resourcesFactory.routeToService(service.id);
            }
        };

        // redirect to specific pool
        $scope.routeToPool = function(id) {
            resourcesFactory.routeToPool(id);
        };

        $scope.modal_deployWizard = function() {

            // the modal occasionally won't show on page load, so we use a timeout to get around that.
            $timeout(function(){
                $('#addApp').modal('show');

                // don't auto-show this wizard again
                // NOTE: $cookies can only deal with string values
                $cookies.put("autoRunWizardHasRun","true");
            });
        };

        $scope.modal_addTemplate = function() {
            $modalService.create({
                templateUrl: "add-template.html",
                model: $scope,
                title: "template_add",
                actions: [
                    {
                        role: "cancel",
                        action: function(){
                            $scope.newHost = {};
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: "template_add",
                        action: function(){
                            if(this.validate()){
                                var data = new FormData();

                                $.each($("#new_template_filename")[0].files, function(key, value){
                                    data.append("tpl", value);
                                });

                                // disable ok button, and store the re-enable function
                                var enableSubmit = this.disableSubmitButton();

                                resourcesFactory.addAppTemplate(data)
                                    .success(function(data){
                                        $notification.create("Added template", data.Detail).success();
                                        refreshTemplates();
                                        this.close();
                                    }.bind(this))
                                    .error(function(data){
                                        this.createNotification("Adding template failed", data.Detail).error();
                                        enableSubmit();
                                    }.bind(this));
                            }
                        }
                    }
                ]
            });
        };

        $scope.modal_removeService = function(service) {
            $modalService.create({
                template: $translate.instant("warning_remove_service"),
                model: $scope,
                title: "remove_service",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "remove_service",
                        classes: "btn-danger submit",
                        action: function(){
                            if(this.validate()){
                                this.disableSubmitButton();

                                removeService(service)
                                    .success(() => {
                                        refreshApps().then(() => {
                                            $notification.create("Removed App", service.name).success();
                                        });
                                        this.close();
                                    })
                                    .error((data, status) => {
                                        $notification.create("Remove App failed", data.Detail).error();
                                        this.close();
                                    });
                            }
                        }
                    }
                ]
            });
        };

        $scope.startService = function(service){
            $scope.modal_startStopService(service, "start");
        };
        $scope.stopService = function(service){
            $scope.modal_startStopService(service, "stop");
        };
        $scope.modal_startStopService = function(service, status) {
            var displayStatus = utils.capitalizeFirst(status);

            $modalService.create({
                template: $translate.instant("confirm_"+ status +"_app"),
                model: $scope,
                title: displayStatus +" Services",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: displayStatus +" Services",
                        action: function(){
                            service[status]();
                            this.close();
                        }
                    }
                ]
            });
        };

        // sets a service to start, stop or restart state
        $scope.setServiceState = function(service, state, skipChildren){
            service[state](skipChildren).error(function(data, status){
                $notification.create("Unable to " + state + " service", data.Detail).error();
            });
        };

        // clicks to a service's start, stop, or restart
        // button should first determine if the service has
        // children and ask the user to choose to start all
        // children or only the top service
        $scope.clickRunning = function(service, state){
            let onStartService = function(modal){
                // the arg here explicitly prevents child services
                // from being started
                $scope.setServiceState(service, state, true);
                modal.close();
            };
            let onStartServiceAndChildren = function(modal){
                $scope.setServiceState(service, state);
                modal.close();
            };

            Service.countAffectedDescendants(service, state)
                .then(count => {
                    $modalService.modals.confirmServiceStateChange(service, state,
                        count, onStartService,
                        onStartServiceAndChildren);
                })
                .catch(err => {
                    console.warn("couldnt get descendant count", err);
                    $modalService.modals.confirmServiceStateChange(service, state,
                        0, onStartService,
                        onStartServiceAndChildren);
                });

            // let the user know they gonna have to hold onto
            // their horses for just one moment.
            $modalService.modals.oneMoment();
        };

        // verifies if use wants to start parent service, or parent
        // and all children
        $scope.modal_confirmSetServiceState = function(service, state, childCount){
            $modalService.create({
                template: ["
"+ $translate.instant("choose_services_"+ state) +"

",
                    "
"+ $translate.instant(state +"_service_name", {name: ""+service.name+""}) +"
",
                    "
"+ $translate.instant(state +"_service_name_and_children", {name: ""+service.name+"", count: ""+childCount+""}) +"

"
                ].join(""),
                model: $scope,
                title: $translate.instant(state +"_service"),
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        classes: " ",
                        label: $translate.instant(state +"_service"),
                        action: function(){
                            // the arg here explicitly prevents child services
                            // from being started
                            $scope.setServiceState(service, state, true);
                            this.close();
                        }
                    },{
                        role: "ok",
                        label: $translate.instant(state +"_service_and_children", {count: childCount}),
                        action: function(){
                            $scope.setServiceState(service, state);
                            this.close();
                        }
                    }
                ]
            });
        };

        $scope.modal_deleteTemplate = function(templateID){
            $modalService.create({
                template: $translate.instant("template_remove_confirm") + ""+ templateID +"",
                model: $scope,
                title: "template_remove",
                actions: [
                    {
                        role: "cancel"
                    },{
                        role: "ok",
                        label: "template_remove",
                        classes: "btn-danger",
                        action: function(){
                            deleteTemplate(templateID)
                                .success(() => {
                                    $notification.create("Removed Template", templateID).success();
                                    this.close();
                                })
                                .error((data, status) => {
                                    $notification.create("Remove Template failed", data.Detail).error();
                                });
                        }
                    }
                ]
            });
        };

        /*
         * PRIVATE FUNCTIONS
         */
        function refreshTemplates(){
            resourcesFactory.getAppTemplates().success(function(templates) {
                $scope.templates.data = utils.mapToArr(templates);
            });
        }

        function refreshApps() {
            return fetchApps()
                .then(fillOutApps)
                .then(fetchServicesHealth)
                .then(fetchInternalServicesHealth)
                .then(() => touch())
                .catch((error) => console.warn(error));
        }

        function fetchApps() {
            return $q.all([fetchInternalService(), fetchServices()])
                .then(results => {
                    $scope.apps = [];

                    var isvc = results[0];
                    $scope.apps.push(isvc);

                    var services = results[1];
                    services.forEach(s => {
                        $scope.apps.push(s);
                    });
                });
        }

        function fetchChildEndpoints(app) {
            return resourcesFactory.v2.getServiceChildPublicEndpoints(app.id).then(data => {
                app.publicEndpoints = data;
            });
        }

        function fillOutApps() {
            let promises = [];
            $scope.apps.forEach(a => {
                if (a.isIsvc()) {
                    promises.push(() => a.fetchInstances());
                } else {
                    promises.push(fetchChildEndpoints(a));
                }
            });

            return $q.all(promises);
        }

        function fetchServices() {
            let deferred = $q.defer();
            resourcesFactory.v2.getTenants().then( data => {
                    var services = data.map(s => new Service(s));
                    deferred.resolve(services);
                },
                error => {
                    console.warn(error);
                    deferred.reject();
                });
            return deferred.promise;
        }

        function fetchServicesHealth() {
            if (!$scope.apps) { return; }

            $scope.apps.forEach(app => {
                if (!app.isIsvc()) {
                    app.fetchAllStates();
                }
            });
        }

        function fetchInternalService() {
            let deferred = $q.defer();
            resourcesFactory.v2.getInternalServices()
                .then(data => {
                    let parent = data.find(i => !i.Parent);
                    if (parent) {
                        var internalServices = new InternalService(parent);
                        deferred.resolve(internalServices);
                    } else {
                        deferred.reject("Parent not found");
                    }
                },
                error => {
                    console.warn(error);
                    deferred.reject();
                });
            return deferred.promise;
        }

        function fetchInternalServicesHealth() {
            $scope.apps.forEach(app => {
                if (app.isIsvc()) {
                    app.fetchInstances().then(() => {
                        resourcesFactory.v2.getInternalServiceStatuses([app.id]).then(data => {
                            let statusMap = data.reduce((map, s) => {
                                map[s.ServiceID] = s;
                                return map;
                            }, {});

                            app.updateStatus(statusMap[app.id]);
                        });
                    });
                }
            });
        }

        // poll for apps that are being deployed
        $scope.deployingServices = [];
        var lastPollResults = 0;
        function getDeploying(){
            resourcesFactory.getDeployingTemplates().success(function(data) {
                if(data){
                    $scope.deployingServices = data;
                }

                //if we have fewer results than last poll, we need to refresh our table
                //TODO - better checking for deploying apps
                if(lastPollResults > $scope.deployingServices.length){
                    refreshApps();
                }
                lastPollResults = $scope.deployingServices.length;
            });
        }

        function removeService(service) {
            return resourcesFactory.removeService(service.id)
                .success(function(){
                    // NOTE: this is here because services are
                    // incrementally updated, which makes it impossible
                    // to determine if a service has been removed
                    // TODO - once the backend notifies on deleted
                    // services, this should be removed
                    // FIXME - should not modify servicesFactory's
                    // objects!
                    for(var i = 0; i < $scope.apps.length; i++){
                        // find the removed service and remove it
                        if($scope.apps[i].id === service.id){
                            $scope.apps.splice(i, 1);
                            touch();
                            return;
                        }
                    }
                });
        }

        function deleteTemplate(templateID){
            return resourcesFactory.removeAppTemplate(templateID)
                .success(refreshTemplates);
        }

        var lastUpdate;
        function touch() {
            lastUpdate = new Date().getTime();
        }

        // init stuff for this controller
        function init(){
            touch();

            if(utils.needsHostAlias($location.host())){
                resourcesFactory.getHostAlias().success(function(data) {
                    $scope.defaultHostAlias = data.hostalias;
                });
            }

            // configure tables
            // TODO - move table config to view/directive
            $scope.breadcrumbs = [
                { label: 'breadcrumb_deployed', itemClass: 'active' }
            ];

            $scope.servicesTable = {
                sorting: {
                    name: "asc"
                },
                searchColumns: ['name','model.Description', 'model.DeploymentID', 'model.PoolID'],
                getData: function(data, params) {
                    // use built-in angular filter
                    var orderedData = params.sorting() ?
                        $filter('orderBy')(data, params.orderBy()) :
                        data;

                    if(!orderedData){
                        return;
                    }

                    // mark any deploying services so they can be treated differently
                    orderedData.forEach(function(service){
                        service.deploying = false;
                        $scope.deployingServices.forEach(function(deploying){
                            if(service.model.DeploymentID === deploying.DeploymentID){
                                service.deploying = true;
                            }
                        });
                    });

                    return orderedData;
                },
                watchExpression: function(){
                    // TODO - check $scope.deployingServices as well
                    return lastUpdate;
                }
            };

            $scope.templates = { data: [] };
            // table config
            $scope.templatesTable = {
                sorting: {
                    Name: "asc"
                },
                searchColumns: ['Name','ID', 'Description']
            };

            // Get a list of templates
            refreshTemplates();

            // check for deploying apps
            getDeploying();

            refreshApps().then(() => {
                $scope.$emit("ready");

                // if only isvcs are deployed, and this is the first time
                // running deploy wizard, show the deploy apps modal
                if(!$cookies.get("autoRunWizardHasRun") && $scope.apps.length === 1){
                    $scope.modal_deployWizard();
                }
            });

            //register polls
            resourcesFactory.registerPoll("deployingApps", getDeploying, 3000);
            resourcesFactory.registerPoll("templates", refreshTemplates, 5000);
            resourcesFactory.registerPoll("internalServiceHealth", fetchInternalServicesHealth, 3000);
            resourcesFactory.registerPoll("appHealth", fetchServicesHealth, 3000);

            //unregister polls on destroy
            $scope.$on("$destroy", function(){
                resourcesFactory.unregisterAllPolls();
            });

            // be sure to update apps table after deploywiz
            // finishes its dark magicks
            $rootScope.$on("wizard.deployed", () => {
                refreshApps();
            });
        }

        // kick this controller off
        init();

        $scope.$on("$destroy", function(){
            resourcesFactory.unregisterAllPolls();
        });
    }]);
})();
<|endoftext|>


<commit_before>import path from 'path'
import fs from 'fs'
import webpack from 'webpack'
import rimraf from 'rimraf'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
const {SENTRY_DSN, CLIENT_DIST_PATH, JWT_SECRET, PORT, isProduction} = config

// Clear dist dir before run
rimraf(`${config.distPath}/server`, {}, () => {})

const definePluginArgs = {
	'process.env.BROWSER': JSON.stringify(false),
	'process.env.PORT': JSON.stringify(PORT),
	'process.env.JWT_SECRET': JSON.stringify(JWT_SECRET),
	'process.env.SENTRY_DSN': JSON.stringify(SENTRY_DSN),
	'process.env.CLIENT_DIST_PATH': JSON.stringify(CLIENT_DIST_PATH)
}

const devtool = isProduction ? 'cheap-source-map' : 'eval'
const entry = isProduction
	? path.join(config.srcPath, './server')
	: path.join(config.srcPath, './server/server')

let nodeModules = {}
fs
	.readdirSync('node_modules')
	.filter(x => {
		return ['.bin'].indexOf(x) === -1
	})
	.forEach(mod => {
		nodeModules[mod] = 'commonjs ' + mod
	})

const baseWebpackConfig = {
	name: 'server',
	entry,
	devtool,
	target: 'node',
	output: {
		path: path.join(config.distPath, './server'),
		filename: 'index.js',
		libraryTarget: 'commonjs2'
	},
	externals: nodeModules,
	performance: {
		hints: false
	},
	resolve: {
		extensions: isomorphicWebpackConfig.resolve.extensions,
		modules: isomorphicWebpackConfig.resolve.modules,
		alias: {
			...isomorphicWebpackConfig.resolve.alias,
			'webpack-assets': `${CLIENT_DIST_PATH}/webpack-assets.json`,
			'favicons-assets': `${CLIENT_DIST_PATH}/favicons-stats.json`,
			locals: `${config.rootPath}/locals`,
			ssl: `${config.srcPath}/server/config/ssl`
		}
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 25000,
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.NormalModuleReplacementPlugin(
			/\.(css|sass|less|scss)$/,
			'node-noop'
		),
		new webpack.DefinePlugin(definePluginArgs)
	]),
	node: {
		__dirname: true,
		global: true
	}
}

export default baseWebpackConfig
<commit_msg>fix(webpack_config): PORT -> HTTP_PORT, remove `ssl` alias<commit_after>import path from 'path'
import fs from 'fs'
import webpack from 'webpack'
import rimraf from 'rimraf'
import config from '../config'
import isomorphicWebpackConfig from '../webpack.isomorphic'
const {SENTRY_DSN, CLIENT_DIST_PATH, JWT_SECRET, HTTP_PORT, isProduction} = config

// Clear dist dir before run
rimraf(`${config.distPath}/server`, {}, () => {})

const definePluginArgs = {
	'process.env.BROWSER': JSON.stringify(false),
	'process.env.HTTP_PORT': JSON.stringify(HTTP_PORT),
	'process.env.JWT_SECRET': JSON.stringify(JWT_SECRET),
	'process.env.SENTRY_DSN': JSON.stringify(SENTRY_DSN),
	'process.env.CLIENT_DIST_PATH': JSON.stringify(CLIENT_DIST_PATH)
}

const devtool = isProduction ? 'cheap-source-map' : 'eval'
const entry = isProduction
	? path.join(config.srcPath, './server')
	: path.join(config.srcPath, './server/server')

let nodeModules = {}
fs
	.readdirSync('node_modules')
	.filter(x => {
		return ['.bin'].indexOf(x) === -1
	})
	.forEach(mod => {
		nodeModules[mod] = 'commonjs ' + mod
	})

const baseWebpackConfig = {
	name: 'server',
	entry,
	devtool,
	target: 'node',
	output: {
		path: path.join(config.distPath, './server'),
		filename: 'index.js',
		libraryTarget: 'commonjs2'
	},
	externals: nodeModules,
	performance: {
		hints: false
	},
	resolve: {
		extensions: isomorphicWebpackConfig.resolve.extensions,
		modules: isomorphicWebpackConfig.resolve.modules,
		alias: {
			...isomorphicWebpackConfig.resolve.alias,
			'webpack-assets': `${CLIENT_DIST_PATH}/webpack-assets.json`,
			'favicons-assets': `${CLIENT_DIST_PATH}/favicons-stats.json`,
			locals: `${config.rootPath}/locals`
		}
	},
	module: {
		rules: isomorphicWebpackConfig.module.rules.concat([
			// NOTE: LQIP loader doesn't work with file-loader and url-loader :(
			// `npm i --save-dev lqip-loader`
			// {
			//   test: /\.(jpe?g|png)$/i,
			//   enforce: 'pre',
			//   loaders: [
			//     {
			//       loader: 'lqip-loader',
			//       options: {
			//         path: '/images-lqip', // your image going to be in media folder in the output dir
			//         name: '[name]-lqip.[hash:8].[ext]' // you can use [hash].[ext] too if you wish
			//       }
			//     }
			//   ]
			// }
			{
				test: /\.(jpe?g|png|gif|svg)$/,
				use: [
					{
						loader: 'url-loader',
						options: {
							limit: 25000,
							name: 'images/[name].[hash:8].[ext]'
						}
					},
					'img-loader'
				]
			}
		])
	},
	plugins: isomorphicWebpackConfig.plugins.concat([
		new webpack.NormalModuleReplacementPlugin(
			/\.(css|sass|less|scss)$/,
			'node-noop'
		),
		new webpack.DefinePlugin(definePluginArgs)
	]),
	node: {
		__dirname: true,
		global: true
	}
}

export default baseWebpackConfig
<|endoftext|>


<commit_before>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
  * Ext.ux.fbk.sonet.BuddyList Extension Class
  *
  * @author  Davide Setti
  * @version 1.0
  * @class Ext.ux.fbk.sonet.BuddyList
  *
This widget show the user connected to the jabber server

*/

var roster = {
  // Online buddies
  online: [],
  // temporary store (save here presence&status until roster's load)
  store: [],
  // Full roster
  roster: [],
  update: function (buddy) {
    for (var i=0, x; x = this.roster[i++];) {
      if (x.compareTo(buddy)) {
        x.update(buddy);
        return;
      }
    }
    this.roster.push(buddy);
  },
  flushPresence: function() {
    //TODO: change this. Once buddies are readed, drop them from store
    for(var i=0, il=this.store.length; i<il; i++) {
        var b = this.store[i];
        this.setPresence(b.jid, b.presence, b.status, b.type);
    }
    rosterStore.load();
  },

  setPresence: function (jid, presence, status, type) {
    if ((type !== 'unavailable') && (!this.roster.length)){
        var b = new Buddy(jid.toString(), '', '', '', presence, status, type);
        this.store.push(b);
        return;
    }

    // this is a dirty way to put ME inside the buddylist
    // the problem is that ME is not sent in the roster, but only as presence/status
    if (jid.toString() == jabber.con.jid){
        try {
            for (var i=0, x; x = this.roster[i++];) {
                if (x.jid.toString() == jid.toString())
                    throw "JidAlreadyPresentException";
            }
            for (var i=0, x; x = this.online[i++];) {
                if (x.jid.toString() == jid.toString())
                    throw "JidAlreadyPresentException";
            }
            // if we're here, Me is not present in roster.roster or roster.online
            var b = new Buddy(jid.toString(), '', '', 'Me', presence, status, type);
            this.roster.push(b);
        } catch (e) {}
    }

    // If the buddy comes online, move them to 'online'
    if (type != 'unavailable') {
      for (var i=0, x; x = this.roster[i++];) {
        if (x.jid.toString() == jid.toString()) {
          this.online.push(x);
          this.roster.remove(x);
          break;
        }
      }
    }

    var sCssClass = 'user-' + (jid.toString().split('@'))[0];
    // IE wants DIV, FF div... and the others? It's better to try to get both instead of using Ext.isIE
    var rule = 'BODY .'+ sCssClass;
    var cssClass = Ext.util.CSS.getRule(rule, true); // for IE
    if (!cssClass) // for FF
        cssClass = Ext.util.CSS.getRule('body .'+ sCssClass, true);

    if (!cssClass) { // if no cssClass has been found, create it
        var s = rule +" {\n}";
        Ext.util.CSS.createStyleSheet(s, rule);

        // now we need to get the class, so we can change its style
        cssClass = Ext.util.CSS.getRule(rule, true); // for IE
        if (!cssClass) // for FF
            cssClass = Ext.util.CSS.getRule('body .'+ sCssClass, true);
    }

    var sBulletPresence;
    if (type == 'unavailable')
        sBulletPresence = 'unavailable';
    else
        sBulletPresence = presence;

    var sStyleBg = 'url(js/portal/shared/icons/fam/'+ hBullets[sBulletPresence] +') left no-repeat';
    cssClass.style.background = sStyleBg;

    for (var i=0, il=this.online.length; i<il; i++) {
      if (this.online[i].jid.toString() == jid.toString()) {
        this.online[i].presence = presence;
        this.online[i].status = status.htmlEnc();
        this.online[i].fancyStatus = status.htmlEnc().smilize().urlize();
        this.online[i].type = type;

        // If the buddy goes offline, remove from online list
        if (type == 'unavailable') {
         var buddy = this.online[i];
         this.online.remove(this.online[i]);
         this.roster.push(buddy);
        }
        break;
      }
    }
    rosterStore.load();
  },
  clear: function () {
    this.online = [];
    this.roster = [];
    rosterStore.load();
  }
};

var rosterStore = new Ext.data.GroupingStore({
  id: 'rosterStore',
  proxy: new Ext.data.MemoryProxy(roster),
  reader: new Ext.data.JsonReader({
    root: 'online'
    },[
      {name: 'jid'},
      {name: 'subscription'},
      {name: 'name'},
      {name: 'group'},
      {name: 'presence'},
      {name: 'status'},
      {name: 'fancyStatus'}
  ]),
  sortInfo: {field: 'jid', direction: "ASC"},
  groupField: 'group'
});
rosterStore.on('load', function(store, records, options) {
    console.log(records);
});
rosterStore.on('loadexception', function(proxy, store, response, e) {
    console.log('loadexception: ' + e.message);
});

BuddyList = function(conf, panel_conf) {
    Ext.apply(this, panel_conf);

    BuddyList.superclass.constructor.call(this, {
        id:'buddylist',
        collapsible: true,
        autoHeight: true,
        /*tbar: [{
            text: 'Logout',
            id: 'logout',
            handler: function(){
                jabber.quit()
            },
            scope: this
        }],*/
        listeners: {
            'resize' : {
                fn: function(panel, panelWidth, panelHeight){
                    panel.items.first().setWidth(panelWidth);
                },
                scope: this
            }
        },
        items: [
            new Ext.grid.GridPanel({
              store: rosterStore,
              autoHeight: true,
              draggable: false,
              hideHeaders: true,
              parent: this,
              columns: [{
                id: 'jid',
                dataIndex: 'jid',
                renderer: function (value, p, record) {
                    var tpl = new Ext.XTemplate(
                        '

'
                        ,''
                        ,'
{jid}'
                            ,'<tpl if="presence">'
                                ,'{presence}'
                            ,'</tpl>'
                        ,'
'
                        ,'<tpl if="status">'
                            ,'
'
                                ,'{fancyStatus}'
                            ,'
'
                        ,'</tpl>'
                        ,'	'
                            ,''
                        ,'	'
                        ,'

'
                    );
                    return tpl.applyTemplate(record.data);
                }},
                {dataIndex: 'group', hidden: true},
                {dataIndex: 'presence', hidden: true},
                {dataIndex: 'subscription', hidden: true},
                {dataIndex: 'status', hidden: true},
                {dataIndex: 'fancyStatus', hidden: true}
              ],
              view: new Ext.grid.GroupingView({
                forceFit: true,
                scrollOffset:2,
                showGroupName: false,
                groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Buddies" : "Buddy"]})',
                emptyText: 'Nobody is visible in chat at the moment'
              }),
              cls: 'blist-grid',
              listeners: {
                rowclick: function() {
                    var buddy = this.getSelectionModel().getSelected().data;
                    if(jabber.u_n != buddy.jid._node)
                        jabberui.createNewChatWindow(buddy.jid);
                    getIdFromJidNode(buddy.jid._node);
                },
                resize : {
                    fn: function(panel, panelWidth, panelHeight){
                        var presence = Ext.getCmp('presence');
                        var status = Ext.getCmp('status');

                        status.setWidth(panelWidth - (presence.width + 20));
                    },
                    scope: this
                }
              },
              tbar: [new Ext.ux.IconCombo({
                  id: 'presence',
                  //name: 'presence',
                  width: 100,
                  listWidth: 130,
                  store: new Ext.data.SimpleStore({
                    fields: ['presence', 'readablePresence', 'iconClass'],
                    data: [
                      ['', 'Available', 'buddyliststate']
                      ,['away', 'Away', 'buddyliststateaway']
                      ,['dnd', 'Do not disturb', 'buddyliststatednd']
                      ,['invisible', 'Invisible', 'buddyliststateinvisible']
                      //,['chat', 'Chatty']
                      //,['unavailable', 'Offline']
                    ]
                  }),
                  panel: this,
                  value:conf.presence ? conf.presence : '',
                  displayField: 'readablePresence',
                  valueField: 'presence',
                  iconClsField: 'iconClass',
                  mode: 'local',
                  forceSelection: true,
                  triggerAction: 'all',
                  editable: false,
                  listeners: {
                    render: function (combo) {
                        combo.initFlags();
                        //combo.setValue(combo.store.collect('presence', true)[0]);
                    },
                    select: function (combo) {
                      var status = Ext.getCmp('status').getValue();
                      var presence = combo.getValue();
                      var type;

                      //store in DB
                      this.panel.setPref('presence', presence);

                      //this XEP isn't very linear...
                      if (presence == 'invisible') {
                        presence = '';
                        type = 'invisible';
                      }

                      jabber.setPresence(combo.getValue(), status, type);
                    }
                  }
                }), ' ',
                new Ext.form.ComboBox({
                  id: 'status'
                  ,emptyText: 'Set status message'
                  ,store: new Ext.data.SimpleStore({
                    fields: ['status']
                    ,data: [[conf.status]] // TODO: Change this in an array
                  })
                  ,displayField: 'status'
                  ,value: conf.status
                  ,panel: this
                  ,mode: 'local'
                  ,width: 145
                  ,queryDelay: 500
                  ,hideLabel: true
                  ,triggerAction: 'all'
                  ,cls:'buddylist-status-field'
                  ,focusClass:'buddylist-status-focus'
                  ,recordType:Ext.data.Record.create(['status'])
                  ,loseFocus: function () {
                     Ext.getCmp('presence').focus();
                     this.fireEvent("blur", this);
                  }
                  //,enableKeyEvents:true
                  // this should go into listeners.keyup, but there are problems in Ext 2.2
                  ,onKeyUp: function (e) {
                      this.collapse();
                      if (e.getKey() == Ext.EventObject.ENTER) {
                        var status = Ext.getCmp('status');
                        var sPresence = Ext.getCmp('presence').getValue();
                        var sStatus = status.getEl().dom.value;

                        rec = new status.recordType({status: sStatus});
                        Ext.getCmp('status').store.add(rec);

                        //store in DB
                        this.panel.setPref('status', sStatus, reloadTimeline);

                        //change jabber status
                        jabber.setPresence(sPresence, sStatus);
                        this.loseFocus();
                      }
                      e.stopEvent();
                  }
                  ,listeners: {
                    blur: function (t) {
                        if(!Ext.isOpera && t.focusClass){ // don't touch in Opera
                            t.el.removeClass(t.focusClass);
                        }
                    }
                    ,select: function (combo, record, index) { //change status from drop down menu
                        var presence = Ext.getCmp('presence').getValue();
                        var status = record.get('status');

                        //store in DB
                        combo.panel.setPref('status', status, reloadTimeline);

                        //change jabber status
                        jabber.setPresence(presence, status);
                    }
                    ,render: function(t){
                        var presence, status, type;
                        var cPresence = Ext.getCmp('presence');

                        if (cPresence.value == 'invisible'){
                            presence = '';
                            type = 'invisible';
                        } else {
                            presence = cPresence.value;
                        }

                        status = t.value ? t.value : '';

                        jabberui.init(presence, status, type);
                    }
                  }
                })]
            })]
    });
};

Ext.extend(BuddyList, Ext.Panel);

//Ext.reg('buddylist', BuddyList);
<commit_msg>increasing rowSelectorDepth value. This fixes row selection (and hover, too) problem in the buddylist widget<commit_after>/**
* This file is part of taolin project (http://taolin.fbk.eu)
* Copyright (C) 2008, 2009 FBK Foundation, (http://www.fbk.eu)
* Authors: SoNet Group (see AUTHORS.txt)
*
* Taolin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* Taolin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Taolin. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
  * Ext.ux.fbk.sonet.BuddyList Extension Class
  *
  * @author  Davide Setti
  * @version 1.0
  * @class Ext.ux.fbk.sonet.BuddyList
  *
This widget show the user connected to the jabber server

*/

var roster = {
  // Online buddies
  online: [],
  // temporary store (save here presence&status until roster's load)
  store: [],
  // Full roster
  roster: [],
  update: function (buddy) {
    for (var i=0, x; x = this.roster[i++];) {
      if (x.compareTo(buddy)) {
        x.update(buddy);
        return;
      }
    }
    this.roster.push(buddy);
  },
  flushPresence: function() {
    //TODO: change this. Once buddies are readed, drop them from store
    for(var i=0, il=this.store.length; i<il; i++) {
        var b = this.store[i];
        this.setPresence(b.jid, b.presence, b.status, b.type);
    }
    rosterStore.load();
  },

  setPresence: function (jid, presence, status, type) {
    if ((type !== 'unavailable') && (!this.roster.length)){
        var b = new Buddy(jid.toString(), '', '', '', presence, status, type);
        this.store.push(b);
        return;
    }

    // this is a dirty way to put ME inside the buddylist
    // the problem is that ME is not sent in the roster, but only as presence/status
    if (jid.toString() == jabber.con.jid){
        try {
            for (var i=0, x; x = this.roster[i++];) {
                if (x.jid.toString() == jid.toString())
                    throw "JidAlreadyPresentException";
            }
            for (var i=0, x; x = this.online[i++];) {
                if (x.jid.toString() == jid.toString())
                    throw "JidAlreadyPresentException";
            }
            // if we're here, Me is not present in roster.roster or roster.online
            var b = new Buddy(jid.toString(), '', '', 'Me', presence, status, type);
            this.roster.push(b);
        } catch (e) {}
    }

    // If the buddy comes online, move them to 'online'
    if (type != 'unavailable') {
      for (var i=0, x; x = this.roster[i++];) {
        if (x.jid.toString() == jid.toString()) {
          this.online.push(x);
          this.roster.remove(x);
          break;
        }
      }
    }

    var sCssClass = 'user-' + (jid.toString().split('@'))[0];
    // IE wants DIV, FF div... and the others? It's better to try to get both instead of using Ext.isIE
    var rule = 'BODY .'+ sCssClass;
    var cssClass = Ext.util.CSS.getRule(rule, true); // for IE
    if (!cssClass) // for FF
        cssClass = Ext.util.CSS.getRule('body .'+ sCssClass, true);

    if (!cssClass) { // if no cssClass has been found, create it
        var s = rule +" {\n}";
        Ext.util.CSS.createStyleSheet(s, rule);

        // now we need to get the class, so we can change its style
        cssClass = Ext.util.CSS.getRule(rule, true); // for IE
        if (!cssClass) // for FF
            cssClass = Ext.util.CSS.getRule('body .'+ sCssClass, true);
    }

    var sBulletPresence;
    if (type == 'unavailable')
        sBulletPresence = 'unavailable';
    else
        sBulletPresence = presence;

    var sStyleBg = 'url(js/portal/shared/icons/fam/'+ hBullets[sBulletPresence] +') left no-repeat';
    cssClass.style.background = sStyleBg;

    for (var i=0, il=this.online.length; i<il; i++) {
      if (this.online[i].jid.toString() == jid.toString()) {
        this.online[i].presence = presence;
        this.online[i].status = status.htmlEnc();
        this.online[i].fancyStatus = status.htmlEnc().smilize().urlize();
        this.online[i].type = type;

        // If the buddy goes offline, remove from online list
        if (type == 'unavailable') {
         var buddy = this.online[i];
         this.online.remove(this.online[i]);
         this.roster.push(buddy);
        }
        break;
      }
    }
    rosterStore.load();
  },
  clear: function () {
    this.online = [];
    this.roster = [];
    rosterStore.load();
  }
};

var rosterStore = new Ext.data.GroupingStore({
  id: 'rosterStore',
  proxy: new Ext.data.MemoryProxy(roster),
  reader: new Ext.data.JsonReader({
    root: 'online'
    },[
      {name: 'jid'},
      {name: 'subscription'},
      {name: 'name'},
      {name: 'group'},
      {name: 'presence'},
      {name: 'status'},
      {name: 'fancyStatus'}
  ]),
  sortInfo: {field: 'jid', direction: "ASC"},
  groupField: 'group'
});
rosterStore.on('load', function(store, records, options) {
    console.log(records);
});
rosterStore.on('loadexception', function(proxy, store, response, e) {
    console.log('loadexception: ' + e.message);
});

BuddyList = function(conf, panel_conf) {
    Ext.apply(this, panel_conf);

    BuddyList.superclass.constructor.call(this, {
        id:'buddylist',
        collapsible: true,
        autoHeight: true,
        /*tbar: [{
            text: 'Logout',
            id: 'logout',
            handler: function(){
                jabber.quit()
            },
            scope: this
        }],*/
        listeners: {
            'resize' : {
                fn: function(panel, panelWidth, panelHeight){
                    panel.items.first().setWidth(panelWidth);
                },
                scope: this
            }
        },
        items: [
            new Ext.grid.GridPanel({
              store: rosterStore,
              autoHeight: true,
              draggable: false,
              hideHeaders: true,
              parent: this,
              columns: [{
                id: 'jid',
                dataIndex: 'jid',
                renderer: function (value, p, record) {
                    var tpl = new Ext.XTemplate(
                        '

'
                            ,''
                                ,'
{jid}'
                                    ,'<tpl if="presence">'
                                        ,'{presence}'
                                    ,'</tpl>'
                                ,'
'
                                ,'<tpl if="status">'
                                    ,'
'
                                        ,'{fancyStatus}'
                                    ,'
'
                                ,'</tpl>'
                            ,'	'
                            ,''
                                ,''
                            ,'	'
                        ,'

'
                    );
                    return tpl.applyTemplate(record.data);
                }},
                {dataIndex: 'group', hidden: true},
                {dataIndex: 'presence', hidden: true},
                {dataIndex: 'subscription', hidden: true},
                {dataIndex: 'status', hidden: true},
                {dataIndex: 'fancyStatus', hidden: true}
              ],
              view: new Ext.grid.GroupingView({
                forceFit: true,
                scrollOffset:2,
                showGroupName: false,
                rowSelectorDepth: 12,
                groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Buddies" : "Buddy"]})',
                emptyText: 'Nobody is visible in chat at the moment'
              }),
              cls: 'blist-grid',
              listeners: {
                rowclick: function() {
                    var buddy = this.getSelectionModel().getSelected().data;
                    if(jabber.u_n != buddy.jid._node)
                        jabberui.createNewChatWindow(buddy.jid);
                    getIdFromJidNode(buddy.jid._node);
                },
                resize : {
                    fn: function(panel, panelWidth, panelHeight){
                        var presence = Ext.getCmp('presence');
                        var status = Ext.getCmp('status');

                        status.setWidth(panelWidth - (presence.width + 20));
                    },
                    scope: this
                }
              },
              tbar: [new Ext.ux.IconCombo({
                  id: 'presence',
                  //name: 'presence',
                  width: 100,
                  listWidth: 130,
                  store: new Ext.data.SimpleStore({
                    fields: ['presence', 'readablePresence', 'iconClass'],
                    data: [
                      ['', 'Available', 'buddyliststate']
                      ,['away', 'Away', 'buddyliststateaway']
                      ,['dnd', 'Do not disturb', 'buddyliststatednd']
                      ,['invisible', 'Invisible', 'buddyliststateinvisible']
                      //,['chat', 'Chatty']
                      //,['unavailable', 'Offline']
                    ]
                  }),
                  panel: this,
                  value:conf.presence ? conf.presence : '',
                  displayField: 'readablePresence',
                  valueField: 'presence',
                  iconClsField: 'iconClass',
                  mode: 'local',
                  forceSelection: true,
                  triggerAction: 'all',
                  editable: false,
                  listeners: {
                    render: function (combo) {
                        combo.initFlags();
                        //combo.setValue(combo.store.collect('presence', true)[0]);
                    },
                    select: function (combo) {
                      var status = Ext.getCmp('status').getValue();
                      var presence = combo.getValue();
                      var type;

                      //store in DB
                      this.panel.setPref('presence', presence);

                      //this XEP isn't very linear...
                      if (presence == 'invisible') {
                        presence = '';
                        type = 'invisible';
                      }

                      jabber.setPresence(combo.getValue(), status, type);
                    }
                  }
                }), ' ',
                new Ext.form.ComboBox({
                  id: 'status'
                  ,emptyText: 'Set status message'
                  ,store: new Ext.data.SimpleStore({
                    fields: ['status']
                    ,data: [[conf.status]] // TODO: Change this in an array
                  })
                  ,displayField: 'status'
                  ,value: conf.status
                  ,panel: this
                  ,mode: 'local'
                  ,width: 145
                  ,queryDelay: 500
                  ,hideLabel: true
                  ,triggerAction: 'all'
                  ,cls:'buddylist-status-field'
                  ,focusClass:'buddylist-status-focus'
                  ,recordType:Ext.data.Record.create(['status'])
                  ,loseFocus: function () {
                     Ext.getCmp('presence').focus();
                     this.fireEvent("blur", this);
                  }
                  //,enableKeyEvents:true
                  // this should go into listeners.keyup, but there are problems in Ext 2.2
                  ,onKeyUp: function (e) {
                      this.collapse();
                      if (e.getKey() == Ext.EventObject.ENTER) {
                        var status = Ext.getCmp('status');
                        var sPresence = Ext.getCmp('presence').getValue();
                        var sStatus = status.getEl().dom.value;

                        rec = new status.recordType({status: sStatus});
                        Ext.getCmp('status').store.add(rec);

                        //store in DB
                        this.panel.setPref('status', sStatus, reloadTimeline);

                        //change jabber status
                        jabber.setPresence(sPresence, sStatus);
                        this.loseFocus();
                      }
                      e.stopEvent();
                  }
                  ,listeners: {
                    blur: function (t) {
                        if(!Ext.isOpera && t.focusClass){ // don't touch in Opera
                            t.el.removeClass(t.focusClass);
                        }
                    }
                    ,select: function (combo, record, index) { //change status from drop down menu
                        var presence = Ext.getCmp('presence').getValue();
                        var status = record.get('status');

                        //store in DB
                        combo.panel.setPref('status', status, reloadTimeline);

                        //change jabber status
                        jabber.setPresence(presence, status);
                    }
                    ,render: function(t){
                        var presence, status, type;
                        var cPresence = Ext.getCmp('presence');

                        if (cPresence.value == 'invisible'){
                            presence = '';
                            type = 'invisible';
                        } else {
                            presence = cPresence.value;
                        }

                        status = t.value ? t.value : '';

                        jabberui.init(presence, status, type);
                    }
                  }
                })]
            })]
    });
};

Ext.extend(BuddyList, Ext.Panel);

//Ext.reg('buddylist', BuddyList);
<|endoftext|>


<commit_before>const path = require('path');

module.exports = {
  module: {
    loaders: [
      {
        test: /.scss$/,
        loader: 'style!css?modules&sourceMap&localIdentName=[name]__[local]___[hash:base64:5]!sass?outputStyle=expanded&sourceMap',
        include: [path.join(process.cwd(), 'src/app/styles')]
      }
    ]
  }
}

<commit_msg>fix code style error lint<commit_after>const path = require('path')

module.exports = {
  module: {
    loaders: [
      {
        test: /.scss$/,
        loader: 'style!css?modules&sourceMap&localIdentName=[name]__[local]___[hash:base64:5]!sass?outputStyle=expanded&sourceMap',
        include: [path.join(process.cwd(), 'src/app/styles')]
      }
    ]
  }
}
<|endoftext|>