<commit_before>/*  Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

    Authors: Shamal Faily */

'use strict';

$("#domainPropertyClick").click(function () {
  clearLocalStorage($('#menuBCClick').attr('dimension'));
  $("#objectViewer").empty();
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

$("#domainPropertyMenuClick").click(function () {
  clearLocalStorage($('#menuBCClick').attr('dimension'));
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

function createDomainPropertiesTable(){

  $.ajax({
    type: "GET",
    dataType: "json",
    accept: "application/json",
    data: {
      session_id: String($.session.get('sessionID'))
    },
    crossDomain: true,
    url: serverIP + "/api/domainproperties",
    success: function (data) {
      setTableHeader("DomainProperties");
      var theTable = $(".theTable");
      $(".theTable tr").not(function(){if ($(this).has('th').length){return true}}).remove();
      var textToInsert = [];
      var i = 0;

      var keys = [];
      for (key in data) {
        keys.push(key);
      }
      keys.sort();

      for (var ki = 0; ki < keys.length; ki++) {
        var key = keys[ki];
        var item = data[key];

        textToInsert[i++] = "
";
        textToInsert[i++] = '	';

        textToInsert[i++] = '';
        textToInsert[i++] = key;
        textToInsert[i++] = '	';

        textToInsert[i++] = '';
        textToInsert[i++] = item.theType;
        textToInsert[i++] = '	';

        textToInsert[i++] = '
';
      }

      theTable.append(textToInsert.join(''));
      theTable.css("visibility","visible");
      $.contextMenu('destroy',$('.requirement-rows'));
      $.contextMenu('destroy',$('.domainproperty-rows'));
      $("#mainTable").find("tbody").removeClass();
      activeElement("mainTable");
      sortTableByRow(0);
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  })
}

$(document).on('click', "td.domainproperty-row", function () {
  var dpName = $(this).text();
  refreshObjectBreadCrumb(dpName);
  viewDomainProperty(dpName);
});

function viewDomainProperty(dpName) {
  activeElement("objectViewer");
  $.ajax({
    type: "GET",
    dataType: "json",
    accept: "application/json",
    data: {
      session_id: String($.session.get('sessionID'))
    },
    crossDomain: true,
    url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(dpName),
    success: function (data) {
      fillOptionMenu("fastTemplates/editDomainPropertyOptions.html", "#objectViewer", null, true, true, function () {
        $("#UpdateDomainProperty").text("Update");
        $.session.set("DomainProperty", JSON.stringify(data));
        $('#editDomainPropertyOptionsForm').loadJSON(data, null);

        if (data.theTags.length > 0) {
          var text = "";
          $.each(data.theTags, function (index, type) {
            text += type;
            if (index < (data.theTags.length - 1)) {
              text += ", ";
            }
          });
          $("#theTags").val(text);
        }
        $("#editDomainPropertyOptionsForm").validator('update');
      });
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText + ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
};

var mainContent = $("#objectViewer");

function commitDomainProperty() {
    var dp = JSON.parse($.session.get("DomainProperty"));
    var oldName = dp.theName;
    dp.theName = $("#theName").val();
    dp.theType = $("#theType").val();
    dp.theDescription = $("#theDescription").val();
    var tags = $("#theTags").text().split(", ");
    if(tags[0] != ""){
      dp.theTags = tags;
    }
    if($("#editDomainPropertyOptionsForm").hasClass("new")){
      postDomainProperty(dp, function () {
        clearLocalStorage("domain_property");
        $("#editDomainPropertyOptionsForm").removeClass("new")
        $('#menuBCClick').attr('dimension','domain_property');
        refreshMenuBreadCrumb('domain_property');
      });
    }
    else {
      putDomainProperty(dp, oldName, function () {
        clearLocalStorage("domain_property");
        $('#menuBCClick').attr('dimension','domain_property');
        refreshMenuBreadCrumb('domain_property');
      });
    }
}

$(document).on('click', 'td.deleteDomainPropertyButton', function (e) {
  e.preventDefault();
  var dpName = $(this).find('i').attr("value");
  deleteObject('domainproperty',dpName,function(dpName) {
    $.ajax({
      type: "DELETE",
      dataType: "json",
      contentType: "application/json",
      accept: "application/json",
      crossDomain: true,
      processData: false,
      origin: serverIP,
      url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(dpName) + "?session_id=" + $.session.get('sessionID'),
      success: function (data) {
        $('#menuBCClick').attr('dimension','domain_property');
        showPopup(true);
        refreshMenuBreadCrumb('domain_property');
      },
      error: function (xhr, textStatus, errorThrown) {
        var error = JSON.parse(xhr.responseText);
        showPopup(false, String(error.message));
        debugLogger(String(this.url));
        debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
      }
    });
  });
});

$(document).on("click", "#addNewDomainProperty", function () {
  refreshObjectBreadCrumb('New Domain Property');
  activeElement("objectViewer");
  fillOptionMenu("fastTemplates/editDomainPropertyOptions.html", "#objectViewer", null, true, true, function () {
    $("#editDomainPropertyOptionsForm").validator();
    $("#UpdateDomainProperty").text("Create");
    $("#editDomainPropertyOptionsForm").addClass("new");
    $.session.set("DomainProperty", JSON.stringify(jQuery.extend(true, {},domainPropertyDefault )));
    $("#optionsHeaderGear").text("Domain Property properties");
  });
});

function putDomainProperty(dp, oldName, callback){
  var output = {};
  output.object = dp;
  output.session_id = $.session.get('sessionID');
  output = JSON.stringify(output);

  $.ajax({
    type: "PUT",
    dataType: "json",
    contentType: "application/json",
    accept: "application/json",
    crossDomain: true,
    processData: false,
    origin: serverIP,
    data: output,
    url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(oldName) + "?session_id=" + $.session.get('sessionID'),
    success: function (data) {
      showPopup(true);
      if(jQuery.isFunction(callback)){
        callback();
      }
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
}

function postDomainProperty(dp, callback){
  var output = {};
  output.object = dp;
  output.session_id = $.session.get('sessionID');
  output = JSON.stringify(output);

  $.ajax({
    type: "POST",
    dataType: "json",
    contentType: "application/json",
    accept: "application/json",
    crossDomain: true,
    processData: false,
    origin: serverIP,
    data: output,
    url: serverIP + "/api/domainproperties" + "?session_id=" + $.session.get('sessionID'),
    success: function (data) {
      showPopup(true);
      if(jQuery.isFunction(callback)){
        callback();
      }
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
}

mainContent.on('click', '#CloseDomainProperty', function (e) {
  e.preventDefault();
  clearLocalStorage("domainproperty");
  $("#objectViewer").empty();
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

<commit_msg>Fix #158<commit_after>/*  Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

    Authors: Shamal Faily */

'use strict';

$("#domainPropertyClick").click(function () {
  clearLocalStorage($('#menuBCClick').attr('dimension'));
  $("#objectViewer").empty();
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

$("#domainPropertyMenuClick").click(function () {
  clearLocalStorage($('#menuBCClick').attr('dimension'));
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

function createDomainPropertiesTable(){

  $.ajax({
    type: "GET",
    dataType: "json",
    accept: "application/json",
    data: {
      session_id: String($.session.get('sessionID'))
    },
    crossDomain: true,
    url: serverIP + "/api/domainproperties",
    success: function (data) {
      setTableHeader("DomainProperties");
      var theTable = $(".theTable");
      $(".theTable tr").not(function(){if ($(this).has('th').length){return true}}).remove();
      var textToInsert = [];
      var i = 0;

      var keys = [];
      for (key in data) {
        keys.push(key);
      }
      keys.sort();

      for (var ki = 0; ki < keys.length; ki++) {
        var key = keys[ki];
        var item = data[key];

        textToInsert[i++] = "
";
        textToInsert[i++] = '	';

        textToInsert[i++] = '';
        textToInsert[i++] = key;
        textToInsert[i++] = '	';

        textToInsert[i++] = '';
        textToInsert[i++] = item.theType;
        textToInsert[i++] = '	';

        textToInsert[i++] = '
';
      }

      theTable.append(textToInsert.join(''));
      theTable.css("visibility","visible");
      $.contextMenu('destroy',$('.requirement-rows'));
      $.contextMenu('destroy',$('.domainproperty-rows'));
      $("#mainTable").find("tbody").removeClass();
      activeElement("mainTable");
      sortTableByRow(0);
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  })
}

$(document).on('click', "td.domainproperty-row", function () {
  var dpName = $(this).text();
  refreshObjectBreadCrumb(dpName);
  viewDomainProperty(dpName);
});

function viewDomainProperty(dpName) {
  activeElement("objectViewer");
  $.ajax({
    type: "GET",
    dataType: "json",
    accept: "application/json",
    data: {
      session_id: String($.session.get('sessionID'))
    },
    crossDomain: true,
    url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(dpName),
    success: function (data) {
      fillOptionMenu("fastTemplates/editDomainPropertyOptions.html", "#objectViewer", null, true, true, function () {
        $("#UpdateDomainProperty").text("Update");
        $.session.set("DomainProperty", JSON.stringify(data));
        $('#editDomainPropertyOptionsForm').loadJSON(data, null);

        if (data.theTags.length > 0) {
          var text = "";
          $.each(data.theTags, function (index, type) {
            text += type;
            if (index < (data.theTags.length - 1)) {
              text += ", ";
            }
          });
          $("#theTags").val(text);
        }
        $("#theOriginator").val(data.theOriginator);
        $("#editDomainPropertyOptionsForm").validator('update');
      });
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText + ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
};

var mainContent = $("#objectViewer");

function commitDomainProperty() {
    var dp = JSON.parse($.session.get("DomainProperty"));
    var oldName = dp.theName;
    dp.theName = $("#theName").val();
    dp.theType = $("#theType").val();
    dp.theDescription = $("#theDescription").val();
    dp.theOriginator = $("#theOriginator").val();
    var tags = $("#theTags").text().split(", ");
    if(tags[0] != ""){
      dp.theTags = tags;
    }
    if($("#editDomainPropertyOptionsForm").hasClass("new")){
      postDomainProperty(dp, function () {
        clearLocalStorage("domain_property");
        $("#editDomainPropertyOptionsForm").removeClass("new")
        $('#menuBCClick').attr('dimension','domain_property');
        refreshMenuBreadCrumb('domain_property');
      });
    }
    else {
      putDomainProperty(dp, oldName, function () {
        clearLocalStorage("domain_property");
        $('#menuBCClick').attr('dimension','domain_property');
        refreshMenuBreadCrumb('domain_property');
      });
    }
}

$(document).on('click', 'td.deleteDomainPropertyButton', function (e) {
  e.preventDefault();
  var dpName = $(this).find('i').attr("value");
  deleteObject('domainproperty',dpName,function(dpName) {
    $.ajax({
      type: "DELETE",
      dataType: "json",
      contentType: "application/json",
      accept: "application/json",
      crossDomain: true,
      processData: false,
      origin: serverIP,
      url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(dpName) + "?session_id=" + $.session.get('sessionID'),
      success: function (data) {
        $('#menuBCClick').attr('dimension','domain_property');
        showPopup(true);
        refreshMenuBreadCrumb('domain_property');
      },
      error: function (xhr, textStatus, errorThrown) {
        var error = JSON.parse(xhr.responseText);
        showPopup(false, String(error.message));
        debugLogger(String(this.url));
        debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
      }
    });
  });
});

$(document).on("click", "#addNewDomainProperty", function () {
  refreshObjectBreadCrumb('New Domain Property');
  activeElement("objectViewer");
  fillOptionMenu("fastTemplates/editDomainPropertyOptions.html", "#objectViewer", null, true, true, function () {
    $("#editDomainPropertyOptionsForm").validator();
    $("#UpdateDomainProperty").text("Create");
    $("#editDomainPropertyOptionsForm").addClass("new");
    $.session.set("DomainProperty", JSON.stringify(jQuery.extend(true, {},domainPropertyDefault )));
    $("#optionsHeaderGear").text("Domain Property properties");
  });
});

function putDomainProperty(dp, oldName, callback){
  var output = {};
  output.object = dp;
  output.session_id = $.session.get('sessionID');
  output = JSON.stringify(output);

  $.ajax({
    type: "PUT",
    dataType: "json",
    contentType: "application/json",
    accept: "application/json",
    crossDomain: true,
    processData: false,
    origin: serverIP,
    data: output,
    url: serverIP + "/api/domainproperties/name/" + encodeURIComponent(oldName) + "?session_id=" + $.session.get('sessionID'),
    success: function (data) {
      showPopup(true);
      if(jQuery.isFunction(callback)){
        callback();
      }
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
}

function postDomainProperty(dp, callback){
  var output = {};
  output.object = dp;
  output.session_id = $.session.get('sessionID');
  output = JSON.stringify(output);

  $.ajax({
    type: "POST",
    dataType: "json",
    contentType: "application/json",
    accept: "application/json",
    crossDomain: true,
    processData: false,
    origin: serverIP,
    data: output,
    url: serverIP + "/api/domainproperties" + "?session_id=" + $.session.get('sessionID'),
    success: function (data) {
      showPopup(true);
      if(jQuery.isFunction(callback)){
        callback();
      }
    },
    error: function (xhr, textStatus, errorThrown) {
      var error = JSON.parse(xhr.responseText);
      showPopup(false, String(error.message));
      debugLogger(String(this.url));
      debugLogger("error: " + xhr.responseText +  ", textstatus: " + textStatus + ", thrown: " + errorThrown);
    }
  });
}

mainContent.on('click', '#CloseDomainProperty', function (e) {
  e.preventDefault();
  clearLocalStorage("domainproperty");
  $("#objectViewer").empty();
  $('#menuBCClick').attr('dimension','domain_property');
  refreshMenuBreadCrumb('domain_property');
});

<|endoftext|>


<commit_before>/**
 * Created by Alvaro on 18/03/2017.
 */

// use a cacheName for cache versioning
var CACHE_NAME = 'static-v1';
var urlsToCache = [
  './',
  './js/main.js'
];

// during the install phase you usually want to cache static assets
self.addEventListener('install', function(event) {
  // once the SW is installed, go ahead and fetch the resources to make this work offline
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      console.log('Opening cache for ' + CACHE_NAME);
      return cache.addAll(urlsToCache).then(function() {
        self.skipWaiting();
      });
    })
  );
});

// when the browser fetches a url
self.addEventListener('fetch', function(event) {
  // either respond with the cached object or go ahead and fetch the actual url
  event.respondWith(
    caches.match(event.request).then(function(response) {
      if (response) {
        // retrieve from cache
        return response;
      }
      // fetch as normal
      return fetch(event.request);
    })
  );
});<commit_msg>Add more objects to cache in the service worker.<commit_after>/**
 * Created by Alvaro on 18/03/2017.
 */

// use a cacheName for cache versioning
var CACHE_NAME = 'static-v0.0.1';
var urlsToCache = [
  './',
  './js/main.js',
  './js/build/ObjectivesList.js',
  './js/vendor/react.min.js',
  './js/vendor/react-com.min.js'
];

// during the install phase you usually want to cache static assets
self.addEventListener('install', function(event) {
  // once the SW is installed, go ahead and fetch the resources to make this work offline
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      console.log('Opening cache for ' + CACHE_NAME);
      return cache.addAll(urlsToCache).then(function() {
        self.skipWaiting();
      });
    })
  );
});

// when the browser fetches a url
self.addEventListener('fetch', function(event) {
  // either respond with the cached object or go ahead and fetch the actual url
  event.respondWith(
    caches.match(event.request).then(function(response) {
      if (response) {
        // retrieve from cache
        return response;
      }
      // fetch as normal
      return fetch(event.request);
    })
  );
});<|endoftext|>


<commit_before>angular.module('app.controllers')

.controller('dishesCtrl', function($scope, $state, DishesService, SharesService, BillService, ionicToast, $ionicScrollDelegate) {

  function init() {

    // scope definitions
    angular.extend($scope, {

      currentDish: DishesService.new(),
      dishes: DishesService.all(),
      people: SharesService.all(),
      billTotal: 0,

      isSelectedPerson: function(person) {
        var currentPeople = $scope.currentDish.people;

        return currentPeople.some(function(currentPerson) {
          return person.name === currentPerson.name;
        });
      },

      togglePerson: function(event, person) {
        var checkbox = event.target;

        if (checkbox.checked) {
          addPersonToCurrentDish(person);
        } else {
          removePersonFromCurrentDish(person);
        }
      },

      addDish: function() {
        var validation = DishesService.save($scope.currentDish);

        if (!validation.valid) {
          return showToast(validation.messages[0]);
        }

        $scope.currentDish = DishesService.new();

        calculateLeftAmount();
      },

      removeDish: function(dish) {
        DishesService.delete(dish);
        $scope.currentDish = DishesService.new();
        calculateLeftAmount();
      },

      editDish: function(dish) {
        $scope.currentDish = angular.copy(dish);

        $ionicScrollDelegate.scrollTop();
      },

      validateNext : function() {
        if( $scope.billTotal == 0  ) {
          $state.go("pay");
        } else {
          showToast('You have not split all dishes. Please make it until amount goes zero');
        }
      }
    });

    calculateLeftAmount();
  }

  function addPersonToCurrentDish(person) {
    var currentPeople = $scope.currentDish.people;

    currentPeople.push(person);
  }

  function removePersonFromCurrentDish(person) {
    var currentPeople = $scope.currentDish.people,
        currentIndex = currentPeople.findIndex(function(currentPerson) {
          return currentPerson.id === person.id;
        });

    currentPeople.splice(currentIndex, 1);
  }

  function calculateLeftAmount() {
    var billTotal = BillService.getBill().totalAmount;
    var totalShare = 0;

    $scope.dishes.forEach(function(dish){
      totalShare += dish.price;
    })

    $scope.billTotal = billTotal - totalShare;
  }

  function showToast(message) {
    ionicToast.show(message, 'top', false, 2500);
  }

  init();

});
<commit_msg>force fully calculation by number<commit_after>angular.module('app.controllers')

.controller('dishesCtrl', function($scope, $state, DishesService, SharesService, BillService, ionicToast, $ionicScrollDelegate) {

  function init() {

    // scope definitions
    angular.extend($scope, {

      currentDish: DishesService.new(),
      dishes: DishesService.all(),
      people: SharesService.all(),
      billTotal: 0,

      isSelectedPerson: function(person) {
        var currentPeople = $scope.currentDish.people;

        return currentPeople.some(function(currentPerson) {
          return person.name === currentPerson.name;
        });
      },

      togglePerson: function(event, person) {
        var checkbox = event.target;

        if (checkbox.checked) {
          addPersonToCurrentDish(person);
        } else {
          removePersonFromCurrentDish(person);
        }
      },

      addDish: function() {
        var validation = DishesService.save($scope.currentDish);

        if (!validation.valid) {
          return showToast(validation.messages[0]);
        }

        $scope.currentDish = DishesService.new();

        calculateLeftAmount();
      },

      removeDish: function(dish) {
        DishesService.delete(dish);
        $scope.currentDish = DishesService.new();
        calculateLeftAmount();
      },

      editDish: function(dish) {
        $scope.currentDish = angular.copy(dish);

        $ionicScrollDelegate.scrollTop();
      },

      validateNext : function() {
        if( $scope.billTotal == 0  ) {
          $state.go("pay");
        } else {
          showToast('You have not split all dishes. Please make it until amount goes zero');
        }
      }
    });

    calculateLeftAmount();
  }

  function addPersonToCurrentDish(person) {
    var currentPeople = $scope.currentDish.people;

    currentPeople.push(person);
  }

  function removePersonFromCurrentDish(person) {
    var currentPeople = $scope.currentDish.people,
        currentIndex = currentPeople.findIndex(function(currentPerson) {
          return currentPerson.id === person.id;
        });

    currentPeople.splice(currentIndex, 1);
  }

  function calculateLeftAmount() {
    var billTotal = BillService.getBill().totalAmount;
    var totalShare = 0;

    $scope.dishes.forEach(function(dish){
      totalShare += Number(dish.price);
    })

    $scope.billTotal = billTotal - totalShare;
  }

  function showToast(message) {
    ionicToast.show(message, 'top', false, 2500);
  }

  init();

});
<|endoftext|>


<commit_before>/*
These are routes as defined in https://docs.google.com/document/d/1337m6i7Y0GPULKLsKpyHR4NRzRwhoxJnAZNnDFCigkc/edit#
Each route implementes a basic parameter/payload validation and a swagger API documentation description
*/
'use strict';

const Joi = require('joi'),
  handlers = require('./controllers/handler');

module.exports = function(server) {
  //Get activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide'),
          id: Joi.string()
          //  id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Get a list of activities (example id: 8; id:000000000000000000000000 recreates mockup data)'
    }
  });

  //Get all activities from database and return the entire list (when not available, return NOT FOUND).
  server.route({
    method: 'GET',
    path: '/activities/all',
    handler: handlers.getAllActivities,
    config: {
      tags: ['api'],
      description: 'Get a list of all activities'
    }
  });

  //Get limited number of activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{id}/more/{start}/{limit}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          id: Joi.string(),
          //id: Joi.string().alphanum().lowercase(),
          start: Joi.string(),
          limit: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Get a list of {limit} activities starting from {start} )'
    }
  });

  //Get limited number of activities with content_kind and content id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}/more/{start}/{limit}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide'),
          id: Joi.string(),
          //id: Joi.string().alphanum().lowercase(),
          start: Joi.string(),
          limit: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Get a list of {limit} activities starting from {start} )'
    }
  });

  //Get activities matching subscriptions from database and return the entire list (when not available, return NOT FOUND).
  server.route({
    method: 'GET',
    path: '/activities/subscribed/{subscriptions*}',
    handler: handlers.getActivitiesSubscribed,
    config: {
      tags: ['api'],
      description: 'Get a list of subscribed activities (example parameter: u112233445566778899000001/s8) )'
    }
  });//TODO if the url length is critical -> use POST instead?

  //Get activity with id id from database and return it (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activity/{id}',
    handler: handlers.getActivity,
    config: {
      validate: {
        params: {
          id: Joi.string()
          //id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Get the activity'
    }
  });

  //Create new activity (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activity/new',
    handler: handlers.newActivity,
    config: {
      validate: {
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          //user_id: Joi.string().alphanum().lowercase(),
          content_id: Joi.string(),
          //content_id: Joi.string().alphanum().lowercase(),
          content_kind: Joi.string().valid('deck', 'slide'),
          content_name: Joi.string(),
          content_owner_id: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            //content_id: Joi.string().alphanum().lowercase(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            //comment_id: Joi.string().alphanum().lowercase(),
            text: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            //target_id: Joi.string().alphanum().lowercase(),
            target_name: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
      },
      tags: ['api'],
      description: 'Create a new activity'
    }
  });

  //Update activity with id id (by payload) and return it (...). Validate payload
  server.route({
    method: 'PUT',
    path: '/activity/{id}',
    handler: handlers.updateActivity,
    config: {
      validate: {
        params: {
          id: Joi.string().alphanum().lowercase()
        },
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          // user_id: Joi.string().alphanum().lowercase(),
          content_id: Joi.string(),
          // content_id: Joi.string().alphanum().lowercase(),
          content_kind: Joi.string().valid('deck', 'slide'),
          content_name: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            //content_id: Joi.string().alphanum().lowercase(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            //comment_id: Joi.string().alphanum().lowercase(),
            text: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            // target_id: Joi.string().alphanum().lowercase(),
            target_name: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
      },
      tags: ['api'],
      description: 'Replace an activity'
    }
  });

  //Delete activity with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activity/delete',
    handler: handlers.deleteActivity,
    config: {
      validate: {
        payload: {
          id: Joi.string()
          //id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Delete an activity'
    }
  });

  //Delete activities with content id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activities/delete',
    handler: handlers.deleteActivities,
    config: {
      validate: {
        payload: {
          content_id: Joi.string()
          //content_id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Delete all activities for the content (example id: 8)'
    }
  });
};
<commit_msg>Changed a route description<commit_after>/*
These are routes as defined in https://docs.google.com/document/d/1337m6i7Y0GPULKLsKpyHR4NRzRwhoxJnAZNnDFCigkc/edit#
Each route implementes a basic parameter/payload validation and a swagger API documentation description
*/
'use strict';

const Joi = require('joi'),
  handlers = require('./controllers/handler');

module.exports = function(server) {
  //Get activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide'),
          id: Joi.string()
          //  id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Get a list of activities'
    }
  });

  //Get all activities from database and return the entire list (when not available, return NOT FOUND).
  server.route({
    method: 'GET',
    path: '/activities/all',
    handler: handlers.getAllActivities,
    config: {
      tags: ['api'],
      description: 'Get a list of all activities'
    }
  });

  //Get limited number of activities with content id id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{id}/more/{start}/{limit}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          id: Joi.string(),
          //id: Joi.string().alphanum().lowercase(),
          start: Joi.string(),
          limit: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Get a list of {limit} activities starting from {start} )'
    }
  });

  //Get limited number of activities with content_kind and content id from database and return the entire list (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activities/{content_kind}/{id}/more/{start}/{limit}',
    handler: handlers.getActivities,
    config: {
      validate: {
        params: {
          content_kind: Joi.string().valid('deck', 'slide'),
          id: Joi.string(),
          //id: Joi.string().alphanum().lowercase(),
          start: Joi.string(),
          limit: Joi.string()
        },
      },
      tags: ['api'],
      description: 'Get a list of {limit} activities starting from {start} )'
    }
  });

  //Get activities matching subscriptions from database and return the entire list (when not available, return NOT FOUND).
  server.route({
    method: 'GET',
    path: '/activities/subscribed/{subscriptions*}',
    handler: handlers.getActivitiesSubscribed,
    config: {
      tags: ['api'],
      description: 'Get a list of subscribed activities (example parameter: u112233445566778899000001/s8) )'
    }
  });//TODO if the url length is critical -> use POST instead?

  //Get activity with id id from database and return it (when not available, return NOT FOUND). Validate id
  server.route({
    method: 'GET',
    path: '/activity/{id}',
    handler: handlers.getActivity,
    config: {
      validate: {
        params: {
          id: Joi.string()
          //id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Get the activity'
    }
  });

  //Create new activity (by payload) and return it (...). Validate payload
  server.route({
    method: 'POST',
    path: '/activity/new',
    handler: handlers.newActivity,
    config: {
      validate: {
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          //user_id: Joi.string().alphanum().lowercase(),
          content_id: Joi.string(),
          //content_id: Joi.string().alphanum().lowercase(),
          content_kind: Joi.string().valid('deck', 'slide'),
          content_name: Joi.string(),
          content_owner_id: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            //content_id: Joi.string().alphanum().lowercase(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            //comment_id: Joi.string().alphanum().lowercase(),
            text: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            //target_id: Joi.string().alphanum().lowercase(),
            target_name: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
      },
      tags: ['api'],
      description: 'Create a new activity'
    }
  });

  //Update activity with id id (by payload) and return it (...). Validate payload
  server.route({
    method: 'PUT',
    path: '/activity/{id}',
    handler: handlers.updateActivity,
    config: {
      validate: {
        params: {
          id: Joi.string().alphanum().lowercase()
        },
        payload: Joi.object().keys({
          activity_type: Joi.string(),
          user_id: Joi.string(),
          // user_id: Joi.string().alphanum().lowercase(),
          content_id: Joi.string(),
          // content_id: Joi.string().alphanum().lowercase(),
          content_kind: Joi.string().valid('deck', 'slide'),
          content_name: Joi.string(),
          translation_info: Joi.object().keys({
            content_id: Joi.string(),
            //content_id: Joi.string().alphanum().lowercase(),
            language: Joi.string()
          }),
          share_info: Joi.object().keys({
            postURI: Joi.string(),
            platform: Joi.string()
          }),
          comment_info: Joi.object().keys({
            comment_id: Joi.string(),
            //comment_id: Joi.string().alphanum().lowercase(),
            text: Joi.string()
          }),
          use_info: Joi.object().keys({
            target_id: Joi.string(),
            // target_id: Joi.string().alphanum().lowercase(),
            target_name: Joi.string()
          }),
          react_type: Joi.string(),
          rate_type: Joi.string()
        }).requiredKeys('content_id', 'user_id', 'activity_type'),
      },
      tags: ['api'],
      description: 'Replace an activity'
    }
  });

  //Delete activity with id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activity/delete',
    handler: handlers.deleteActivity,
    config: {
      validate: {
        payload: {
          id: Joi.string()
          //id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Delete an activity'
    }
  });

  //Delete activities with content id id (by payload). Validate payload
  server.route({
    method: 'DELETE',
    path: '/activities/delete',
    handler: handlers.deleteActivities,
    config: {
      validate: {
        payload: {
          content_id: Joi.string()
          //content_id: Joi.string().alphanum().lowercase()
        },
      },
      tags: ['api'],
      description: 'Delete all activities for the content (example id: 8)'
    }
  });
};
<|endoftext|>


<commit_before>importScripts('js/Configs.js');
var CACHENAME = 'shapeclear';
var VERSION = 'v0.7.1';
var myPath = location.origin + location.pathname;
var cacheEnableTest =
    Configs.get('cacheEnabled').then(function (r) {
        return r !== false;
    });

Configs.get('cacheEnabled').then(function (r) {
    if (r === undefined) Configs.set('cacheEnabled', true);
});

myPath = myPath.match(/(.*\/)/)[1];

self.addEventListener('fetch', function(event) {
    if (event.request) {
        var url = event.request.url;
        if (url.startsWith(myPath + 'cache/')) {
            cacheSettings(url.substring(myPath.length + 6), event);
        }
        else if (!url.startsWith(myPath) && url.indexOf('?') !== -1) {
            // don't cache hit counter!!
            event.respondWith(fetch(event.request));
        }
        else {
            event.respondWith(fromCache(event.request, event));
        }
    }
});

function cacheSettings(url, event) {
    if (url === 'delete') {
        event.waitUntil(preLoad());
        event.respondWith(new Response('ok'));
        console.log('cache cleared');
    }
    else if (url === 'version') {
        event.respondWith(new Response(VERSION));
    }
    else if (url === "disable") {
        event.waitUntil(Configs.set('cacheEnabled', false));
        cacheEnableTest = Promise.resolve(false);
        event.respondWith(new Response('ok'));
    }
    else if (url === "enable") {
        event.waitUntil(Configs.set('cacheEnabled', true));
        cacheEnableTest = Promise.resolve(true);
        event.respondWith(new Response('ok'));
    }
    else {
        event.respondWith(noPage()); // need to get a promise
    }
}

addEventListener('install', function (event) {
    event.waitUntil(preLoad());
    skipWaiting();
});

addEventListener('activate', function (event) {
    event.waitUntil(clients.claim());
});

// with help from https://serviceworke.rs/strategy-cache-and-update_service-worker_doc.html
function preLoad() {
    var mustDownload = [
      'js/swLoader.js',
      'js/GameLoader.js',
      'js/alertbox.js',
      'css/fullscreen.css',
      'css/alertbox.css',
      'game.html',
      'index.html',
      '',
      '404.html',
      'config.html',
      'LICENSE'
    ];
    for (var i = 0; i < mustDownload.length; i++) {
        mustDownload[i] = myPath + mustDownload[i];
    }
    var c, names = [], must = new Set(mustDownload);
    return caches.delete(CACHENAME).then(function (success) {
        return caches.open(CACHENAME);
    }).then(function (cache) {
        return cache.addAll(mustDownload);
    })['catch'](function (x) {
        console.log(x);
    });
}

function fromCache(req, event) {
    var nocache = false;
    var c;
    return cacheEnableTest.then(function (yes) {
        if (!yes) return Promise.reject("cache disabled");
        return caches.open(CACHENAME);
    }).then(function (cache) {
        c = cache;
        // manually strip search string to make Chrome faster
        var i = req.url.indexOf('?');
        if (i !== -1) req = req.url.substring(0, i);
        return c.match(req).then(function (result) {
            if (result) {
                // don't update cache
                //if (event) event.waitUntil(updateCache(req, cache));
                return result;
            }
            nocache = true;
            return Promise.reject("cache miss");
        });
    })['catch'](function (x) {
        if (!nocache) {
            console.log(x);
        }
        return fetch(req);
    }).then(function (result) {
        // add to cache
        if (nocache && event && result.ok) {
            event.waitUntil(c.put(req, result.clone()));
        }
        return result;
    })['catch'](noPage);
}

function updateCache(req, cache) {
    return fetch(req).then(function (result) {
        if (result.ok) {
            return cache.put(req, result);
        }
    })['catch'](function (x) {
        console.log(x);
    });
}

function noPage() {
    return caches.match('404.html').then(function (result) {
        if (result) return new Response(result.body, {status: 404});
        return new Response(
          '<!DOCTYPE html>\n' +
          '<meta charset="UTF-8">\n' +
          '<meta name="viewport" content="width=device-width, initial-scale=1.0">\n' +
          '<title>File not found</title>\n' +
          '
File not found
'
        , {status: 404, headers: {'Content-Type': 'text/html'}}
        );
    });
}
<commit_msg>still update cache, revert some of 7a43a1c88fb7673d6c603<commit_after>importScripts('js/Configs.js');
var CACHENAME = 'shapeclear';
var VERSION = 'v0.7.1';
var myPath = location.origin + location.pathname;
var cacheEnableTest =
    Configs.get('cacheEnabled').then(function (r) {
        return r !== false;
    });

Configs.get('cacheEnabled').then(function (r) {
    if (r === undefined) Configs.set('cacheEnabled', true);
});

myPath = myPath.match(/(.*\/)/)[1];

self.addEventListener('fetch', function(event) {
    if (event.request) {
        var url = event.request.url;
        if (url.startsWith(myPath + 'cache/')) {
            cacheSettings(url.substring(myPath.length + 6), event);
        }
        else if (!url.startsWith(myPath) && url.indexOf('?') !== -1) {
            // don't cache hit counter!!
            event.respondWith(fetch(event.request));
        }
        else {
            event.respondWith(fromCache(event.request, event));
        }
    }
});

function cacheSettings(url, event) {
    if (url === 'delete') {
        event.waitUntil(preLoad());
        event.respondWith(new Response('ok'));
        console.log('cache cleared');
    }
    else if (url === 'version') {
        event.respondWith(new Response(VERSION));
    }
    else if (url === "disable") {
        event.waitUntil(Configs.set('cacheEnabled', false));
        cacheEnableTest = Promise.resolve(false);
        event.respondWith(new Response('ok'));
    }
    else if (url === "enable") {
        event.waitUntil(Configs.set('cacheEnabled', true));
        cacheEnableTest = Promise.resolve(true);
        event.respondWith(new Response('ok'));
    }
    else {
        event.respondWith(noPage()); // need to get a promise
    }
}

addEventListener('install', function (event) {
    event.waitUntil(preLoad());
    skipWaiting();
});

addEventListener('activate', function (event) {
    event.waitUntil(clients.claim());
});

// with help from https://serviceworke.rs/strategy-cache-and-update_service-worker_doc.html
function preLoad() {
    var mustDownload = [
      'js/swLoader.js',
      'js/GameLoader.js',
      'js/alertbox.js',
      'css/fullscreen.css',
      'css/alertbox.css',
      'game.html',
      'index.html',
      '',
      '404.html',
      'config.html',
      'LICENSE'
    ];
    for (var i = 0; i < mustDownload.length; i++) {
        mustDownload[i] = myPath + mustDownload[i];
    }
    var c, names = [], must = new Set(mustDownload);
    return caches.delete(CACHENAME).then(function (success) {
        return caches.open(CACHENAME);
    }).then(function (cache) {
        return cache.addAll(mustDownload);
    })['catch'](function (x) {
        console.log(x);
    });
}

function fromCache(req, event) {
    var nocache = false;
    var c;
    return cacheEnableTest.then(function (yes) {
        if (!yes) return Promise.reject("cache disabled");
        return caches.open(CACHENAME);
    }).then(function (cache) {
        c = cache;
        // manually strip search string to make Chrome faster
        var i = req.url.indexOf('?');
        if (i !== -1) req = req.url.substring(0, i);
        return c.match(req).then(function (result) {
            if (result) {
                // update cache
                if (event) event.waitUntil(updateCache(req, cache));
                return result;
            }
            nocache = true;
            return Promise.reject("cache miss");
        });
    })['catch'](function (x) {
        if (!nocache) {
            console.log(x);
        }
        return fetch(req);
    }).then(function (result) {
        // add to cache
        if (nocache && event && result.ok) {
            event.waitUntil(c.put(req, result.clone()));
        }
        return result;
    })['catch'](noPage);
}

function updateCache(req, cache) {
    return fetch(req).then(function (result) {
        if (result.ok) {
            return cache.put(req, result);
        }
    })['catch'](function (x) {
        console.log(x);
    });
}

function noPage() {
    return caches.match('404.html').then(function (result) {
        if (result) return new Response(result.body, {status: 404});
        return new Response(
          '<!DOCTYPE html>\n' +
          '<meta charset="UTF-8">\n' +
          '<meta name="viewport" content="width=device-width, initial-scale=1.0">\n' +
          '<title>File not found</title>\n' +
          '
File not found
'
        , {status: 404, headers: {'Content-Type': 'text/html'}}
        );
    });
}
<|endoftext|>


<commit_before>var VERSION = '16';

this.addEventListener('install', function(e) {
  e.waitUntil(caches.open(VERSION).then(cache => {
    return cache.addAll([
      '/',
      '/index.html',
      '/sw.js',
      '/stylesheets/default.css',
      '/javascripts/default.js'
    ]);
  }))
});

this.addEventListener('fetch', function(e) {
  var tryInCachesFirst = caches.open(VERSION).then(cache => {
    return cache.match(e.request).then(response => {
      return response || handleNoCacheMatch(e);
    });
  });
  e.respondWith(tryInCachesFirst);
});

this.addEventListener('activate', function(e) {
  e.waitUntil(caches.keys().then(keys => {
    return Promise.all(keys.map(key => {
      if (key !== VERSION)
        return caches.delete(key);
    }));
  }));
});

function handleNoCacheMatch(e) {
  return fetch(e.request).then(res => {
    return caches.open(VERSION).then(cache => {
      cache.put(e.request, res.clone());
      return res;
    });
  });
}
<commit_msg>service worker should check for updates in the bg.<commit_after>var VERSION = '16';

this.addEventListener('install', function(e) {
  e.waitUntil(caches.open(VERSION).then(cache => {
    return cache.addAll([
      '/',
      '/index.html',
      '/sw.js',
      '/stylesheets/default.css',
      '/javascripts/default.js'
    ]);
  }))
});

this.addEventListener('fetch', function(e) {
  var tryInCachesFirst = caches.open(VERSION).then(cache => {
    return cache.match(e.request).then(response => {
      if (!response) {
        return handleNoCacheMatch(e);
      }
      // Update cache record in the background
      fetchFromNetworkAndCache(e);
      // Reply with stale data
      return response
    });
  });
  e.respondWith(tryInCachesFirst);
});

this.addEventListener('activate', function(e) {
  e.waitUntil(caches.keys().then(keys => {
    return Promise.all(keys.map(key => {
      if (key !== VERSION)
        return caches.delete(key);
    }));
  }));
});

function fetchFromNetworkAndCache(e) {
  return fetch(e.request).then(res => {
    // don't cache ANY foreign requests right now.
    if (new URL(res.url).origin !== location.origin) return res;

    return caches.open(VERSION).then(cache => {
      // TODO: figure out if the content is new and therefore the page needs a reload.
      cache.put(e.request, res.clone());
      return res;
    });
  });
}

function handleNoCacheMatch(e) {
  return fetchFromNetworkAndCache(e);
}<|endoftext|>


<commit_before>self.addEventListener('install', function(event) {
    event.waitUntil(
      caches.open('v1').then(function(cache) {
        return cache.addAll([
          '/',
          '/index.html',
          '/css/style.css',
          '/css/images/',
          '/css/images/bg.jpg'
        ]);
      })
    );
  });<commit_msg>changes<commit_after>self.addEventListener('install', function(event) {
    event.waitUntil(
      caches.open('v1').then(function(cache) {
        return cache.addAll([
          '/',
          '/index.html',
          '/css/style.css',
          '/css/images/',
          '/css/images/bg.jpg'
        ]);
      })
    );
  });

  <|endoftext|>


<commit_before>/* global __dirname */

var rootDir = process.env.PWD,
    settings = require('./gulpsettings.js'),
    gulp = require('gulp'),
    gutil = require('gulp-util'),
    less = require('gulp-less'),
    clean = require('gulp-clean'),
    jshint = require('gulp-jshint'),
    inject = require('gulp-inject'),
    templateCache = require('gulp-angular-templatecache'),
    // ngmin = require('gulp-ngmin'),
    // uglify = require('gulp-uglify'),
    minifyCss = require('gulp-minify-css'),
    rename = require('gulp-rename'),
    // concat =  require('gulp-concat'),
    shell  = require('gulp-shell'),
    green = gutil.colors.green,
    cyan = gutil.colors.cyan,
    startLog = function (log) {
      return gutil.log(gutil.colors.bold(log));
    };

/**
 * Clean the build dir.
 */
gulp.task('_clean', function () {
  startLog(':: Cleaning the build directory');

  return gulp
    .src(settings.buildDir, {read: false})
    .pipe(clean());
});

/**
 * Build CSS files.
 */
gulp.task('_buildCSS', ['clean'], function () {
  startLog(':: Build CSS files');

  return gulp
    .src('./public/less/**/main.less')
    .pipe(less())
    .pipe(gulp.dest(settings.buildDir + '/css'));
});

/**
 * Compile CSS files.
 */
gulp.task('_compileCSS', ['clean'], function () {
  startLog(':: Compile CSS files');

  return gulp
    .src('./public/less/**/main.less')
    .pipe(less())
    .pipe(minifyCss())
    .pipe(gulp.dest(settings.buildDir + '/css'));
});

/**
 * Copy images to the build dir.
 */
gulp.task('_copyImages', ['clean'], function () {
  startLog(':: Copy images');

  return gulp
    .src('./public/images/**/*')
    .pipe(gulp.dest(settings.buildDir + '/images'));
});

/**
 * Copy fonts to the build dir.
 */
gulp.task('_copyFonts', ['clean'], function () {
  startLog(':: Copy fonts');

  return gulp
    .src('./public/fonts/**/*')
    .pipe(gulp.dest(settings.buildDir + '/fonts'));
});

/**
 * Lint the server JS files.
 */
gulp.task('_lintServer', function () {
  startLog(':: Lint server files');

  return gulp
    .src(settings.serverFiles)
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

/**
 * Lint the public JS files.
 */
gulp.task('_lintPublic', function () {
  startLog(':: Lint public files');

  return gulp
    .src('./public/js/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

/**
 * Build templates to Angular templates in the build dir.
 */
gulp.task('_buildTemplates', ['_clean'], function () {
  startLog(':: Build templates');
  return gulp
    .src('./public/templates/**/*.html')
    .pipe(templateCache({
      module: 'templates',
      standalone: true
    }))
    .pipe(gulp.dest(settings.buildDir + '/js'));
});

/**
 * Build JS files.
 */
gulp.task('_buildJS', ['clean', '_lintPublic'], function () {
  startLog(':: Build public JS');

  return gulp
    .src((settings.vendorFiles).concat('./public/js/**/*.js'))
    .pipe(gulp.dest(function (file) {
      return file.path
        .replace(__dirname + '/public', settings.buildDir)
        .split('/').slice(0, -1).join('/');
    }));
});

/**
 * Compile JS files.
 */
// gulp.task('_compileJS', ['clean', '_lintPublic'], function () {
//   startLog(':: Compile public JS');

//   return gulp
//     .src((settings.vendorFiles).concat(
//       './public/js/**/*.js'
//     ))
//     .pipe(ngmin())
//     .pipe(uglify())
//     .pipe(concat(settings.appName + '.js'))
//     .pipe(gulp.dest(settings.buildDir + '/js'));
// });
//
//

/**
 * Inject the builded assets in the main layout.
 */
gulp.task('_buildAssets',
  ['clean', '_buildCSS', '_buildTemplates', '_buildJS'], function () {
  startLog(':: Inject assets in the layout');

  return gulp
    .src(rootDir + '/app/views/_layout.html')
    .pipe(
      inject(gulp
        .src([
          settings.buildDir + '/vendor/**/*.js',
          settings.buildDir + '/js/**/*.js',
          settings.buildDir + '/css/main.css'
        ], { read: false }),
        {
          ignorePath: '/build'
        }
      )
    )
    .pipe(rename('layout.html'))
    .pipe(gulp.dest(rootDir + '/app/views'));
});

/**
 * Inject the compiled assets in the main layout.
 */
// gulp.task(
//   '_compileAssets',
//   ['clean', '_compileCSS', '_lintPublic', '_compileJS', '_compileImages'],
//   function () {

//   startLog(':: Inject assets in the layout');

//   return injectAssets(settings.binDir);
// });

/**
 * Watch the various files and runs their respective tasks.
 */
gulp.task('_watch', function () {
  gulp.watch(settings.serverFiles, ['_lintServer']);
  gulp.watch(settings.buildDir + '/../../views/_layout.html', ['build']);
  gulp.watch([
    'public/less/**/*.less',
    'public/templates/**/*.html',
    'public/js/**/*.js'
  ], ['build']);

  // gulp
  //   .src([
  //     './views/**/*.html',
  //     './public/css/**/*.min.css',
  //     './public/js/**/*.min.js'
  //   ])
  //   .pipe(watch());
});

/**
 * Start a local server.
 */
gulp.task('_serve', shell.task([
  'nodemon -L --watch . --debug app.js'
]));

/**
 * Start the debugger
 */
gulp.task('_debug', shell.task(['node-inspector --web-port=8081']));

/**
 * Display some help.
 */
gulp.task('help', function() {
  gutil.log('');
  gutil.log(cyan('To install:') + ':');
  gutil.log(' - npm install');
  gutil.log(' - bower install');
  gutil.log(' - ./gulp build');
  gutil.log(' - ./gulp serve');

  gutil.log('');

  gutil.log(cyan('Available tasks') + ':');
  // gutil.log(' - ' + green('test') + ': launch Karma unittests');
  gutil.log(' - ' + green('watch') + ': watch JS and less files and trigger' +
    ' the build task on modifications');
  gutil.log(' - ' + green('build') + ': build less and JS files.');
  gutil.log(' - ' + green('compile') + ': compile (minify) less and JS files.');
  gutil.log(' - ' + green('watch') + ': watch files and build on modification.');
  gutil.log(' - ' + green('serve') + ': start the apps.');
  gutil.log(' - ' + green('debug') + ': launch node-inspector.');
  gutil.log('');
});

/**
 * Public tasks.
 */
gulp.task('default', ['help']);
gulp.task('clean', ['_clean']);
gulp.task('build', [
  '_buildCSS', '_lintPublic', '_buildJS', '_copyImages', '_copyFonts',
  '_buildAssets']);
gulp.task('compile', [
  '_compileCSS', '_lintPublic', '_compileJS', '_copyImages', '_copyFonts',
  '_compileAssets']);
gulp.task('watch', ['build', '_watch']);
gulp.task('serve', ['_serve']);
gulp.task('debug', ['_debug']);
<commit_msg>Only watch server files in the serve task.<commit_after>/* global __dirname */

var rootDir = process.env.PWD,
    settings = require('./gulpsettings.js'),
    gulp = require('gulp'),
    gutil = require('gulp-util'),
    less = require('gulp-less'),
    clean = require('gulp-clean'),
    jshint = require('gulp-jshint'),
    inject = require('gulp-inject'),
    templateCache = require('gulp-angular-templatecache'),
    // ngmin = require('gulp-ngmin'),
    // uglify = require('gulp-uglify'),
    minifyCss = require('gulp-minify-css'),
    rename = require('gulp-rename'),
    // concat =  require('gulp-concat'),
    shell  = require('gulp-shell'),
    green = gutil.colors.green,
    cyan = gutil.colors.cyan,
    startLog = function (log) {
      return gutil.log(gutil.colors.bold(log));
    };

/**
 * Clean the build dir.
 */
gulp.task('_clean', function () {
  startLog(':: Cleaning the build directory');

  return gulp
    .src(settings.buildDir, {read: false})
    .pipe(clean());
});

/**
 * Build CSS files.
 */
gulp.task('_buildCSS', ['clean'], function () {
  startLog(':: Build CSS files');

  return gulp
    .src('./public/less/**/main.less')
    .pipe(less())
    .pipe(gulp.dest(settings.buildDir + '/css'));
});

/**
 * Compile CSS files.
 */
gulp.task('_compileCSS', ['clean'], function () {
  startLog(':: Compile CSS files');

  return gulp
    .src('./public/less/**/main.less')
    .pipe(less())
    .pipe(minifyCss())
    .pipe(gulp.dest(settings.buildDir + '/css'));
});

/**
 * Copy images to the build dir.
 */
gulp.task('_copyImages', ['clean'], function () {
  startLog(':: Copy images');

  return gulp
    .src('./public/images/**/*')
    .pipe(gulp.dest(settings.buildDir + '/images'));
});

/**
 * Copy fonts to the build dir.
 */
gulp.task('_copyFonts', ['clean'], function () {
  startLog(':: Copy fonts');

  return gulp
    .src('./public/fonts/**/*')
    .pipe(gulp.dest(settings.buildDir + '/fonts'));
});

/**
 * Lint the server JS files.
 */
gulp.task('_lintServer', function () {
  startLog(':: Lint server files');

  return gulp
    .src(settings.serverFiles)
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

/**
 * Lint the public JS files.
 */
gulp.task('_lintPublic', function () {
  startLog(':: Lint public files');

  return gulp
    .src('./public/js/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('jshint-stylish'));
});

/**
 * Build templates to Angular templates in the build dir.
 */
gulp.task('_buildTemplates', ['_clean'], function () {
  startLog(':: Build templates');
  return gulp
    .src('./public/templates/**/*.html')
    .pipe(templateCache({
      module: 'templates',
      standalone: true
    }))
    .pipe(gulp.dest(settings.buildDir + '/js'));
});

/**
 * Build JS files.
 */
gulp.task('_buildJS', ['clean', '_lintPublic'], function () {
  startLog(':: Build public JS');

  return gulp
    .src((settings.vendorFiles).concat('./public/js/**/*.js'))
    .pipe(gulp.dest(function (file) {
      return file.path
        .replace(__dirname + '/public', settings.buildDir)
        .split('/').slice(0, -1).join('/');
    }));
});

/**
 * Compile JS files.
 */
// gulp.task('_compileJS', ['clean', '_lintPublic'], function () {
//   startLog(':: Compile public JS');

//   return gulp
//     .src((settings.vendorFiles).concat(
//       './public/js/**/*.js'
//     ))
//     .pipe(ngmin())
//     .pipe(uglify())
//     .pipe(concat(settings.appName + '.js'))
//     .pipe(gulp.dest(settings.buildDir + '/js'));
// });
//
//

/**
 * Inject the builded assets in the main layout.
 */
gulp.task('_buildAssets',
  ['clean', '_buildCSS', '_buildTemplates', '_buildJS'], function () {
  startLog(':: Inject assets in the layout');

  return gulp
    .src(rootDir + '/app/views/_layout.html')
    .pipe(
      inject(gulp
        .src([
          settings.buildDir + '/vendor/**/*.js',
          settings.buildDir + '/js/**/*.js',
          settings.buildDir + '/css/main.css'
        ], { read: false }),
        {
          ignorePath: '/build'
        }
      )
    )
    .pipe(rename('layout.html'))
    .pipe(gulp.dest(rootDir + '/app/views'));
});

/**
 * Inject the compiled assets in the main layout.
 */
// gulp.task(
//   '_compileAssets',
//   ['clean', '_compileCSS', '_lintPublic', '_compileJS', '_compileImages'],
//   function () {

//   startLog(':: Inject assets in the layout');

//   return injectAssets(settings.binDir);
// });

/**
 * Watch the various files and runs their respective tasks.
 */
gulp.task('_watch', function () {
  gulp.watch(settings.serverFiles, ['_lintServer']);
  gulp.watch(settings.buildDir + '/../../views/_layout.html', ['build']);
  gulp.watch([
    'public/less/**/*.less',
    'public/templates/**/*.html',
    'public/js/**/*.js'
  ], ['build']);

  // gulp
  //   .src([
  //     './views/**/*.html',
  //     './public/css/**/*.min.css',
  //     './public/js/**/*.min.js'
  //   ])
  //   .pipe(watch());
});

/**
 * Start a local server.
 */
gulp.task('_serve', shell.task([
  'nodemon -L --watch ./app/app --debug app.js'
]));

/**
 * Start the debugger
 */
gulp.task('_debug', shell.task(['node-inspector --web-port=8081']));

/**
 * Display some help.
 */
gulp.task('help', function() {
  gutil.log('');
  gutil.log(cyan('To install:') + ':');
  gutil.log(' - npm install');
  gutil.log(' - bower install');
  gutil.log(' - ./gulp build');
  gutil.log(' - ./gulp serve');

  gutil.log('');

  gutil.log(cyan('Available tasks') + ':');
  // gutil.log(' - ' + green('test') + ': launch Karma unittests');
  gutil.log(' - ' + green('watch') + ': watch JS and less files and trigger' +
    ' the build task on modifications');
  gutil.log(' - ' + green('build') + ': build less and JS files.');
  gutil.log(' - ' + green('compile') + ': compile (minify) less and JS files.');
  gutil.log(' - ' + green('watch') + ': watch files and build on modification.');
  gutil.log(' - ' + green('serve') + ': start the apps.');
  gutil.log(' - ' + green('debug') + ': launch node-inspector.');
  gutil.log('');
});

/**
 * Public tasks.
 */
gulp.task('default', ['help']);
gulp.task('clean', ['_clean']);
gulp.task('build', [
  '_buildCSS', '_lintPublic', '_buildJS', '_copyImages', '_copyFonts',
  '_buildAssets']);
gulp.task('compile', [
  '_compileCSS', '_lintPublic', '_compileJS', '_copyImages', '_copyFonts',
  '_compileAssets']);
gulp.task('watch', ['build', '_watch']);
gulp.task('serve', ['_serve']);
gulp.task('debug', ['_debug']);
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var Browser = Model.create({
  name: 'Browser',

  extendsModel: 'AbstractView',

  properties: [
    {
      name: 'project'
    },
    {
      name: 'projectName',
      scope: 'project',
      defaultValueFn: function() { return this.project.projectName; }
    },
    {
      name: 'url',
      scope: 'project',
      defaultValueFn: function() { return this.project.url; }
    },
    {
      name: 'IssueDAO',
      scope: 'project',
      defaultValueFn: function() { return this.project.IssueDAO; }
    },
    {
      name: 'syncManager',
      scope: 'project',
      defaultValueFn: function() { return this.project.syncManager; }
    },

    {
      name: 'rowSelection',
      valueFactory: function() { return SimpleValue.create(); }
    },
    {
      name: 'window'
    },
    {
      name: 'timer',
      valueFactory: function() { return Timer.create(); }
    },
    {
      name: 'view',
      valueFactory: function() { return createView(this.rowSelection, this); }
    },
    {
      name: 'memento',
      setter: function(m) {
        m.hasOwnProperty('q') && this.searchField.value.set(m.q);
        this.view.memento = m;
      },
      getter: function() {
        var m = this.view.memento;
        m.q = this.searchField.value.get();
        return m;
      }
    },

    {
      name: 'linkButton',
      valueFactory: function() {
        return ActionButton.create({
          action: this.model_.LINK,
          value: SimpleValue.create(this)
        });
      }
    },
    {
      name: 'countField',
      type: 'TextFieldView',
      valueFactory: function() {
        return TextFieldView.create({
          name: 'count',
          mode: 'read-only',
          displayWidth: 40
        });
      }
    },
    {
      name: 'searchChoice',
      valueFactory: function() {
        return ChoiceView.create({
          helpText: 'Search within:',
          choices:[
            ['',                            ' All issues'],
            ['-status=Closed,Fixed,Done',   ' Open issues'], // Should this be just 'Closed'?
            ['owner=me -status=Closed',     ' Open and owned by me'],
            ['-status=Closed reporter=me',  ' Open and reported by me'],
            ['-status=Closed is:starred',   ' Open and starred by me'],
            ['-status=Closed commentby:me', ' Open and comment by me'],
            ['status=New',                  ' New issues'],
            ['status=Fixed,Done',           ' Issues to verify']
          ]});
      }
    },
    {
      name: 'searchField',
      valueFactory: function() { return TextFieldView.create({ name: 'search', displayWidth: 60 }); }
    },
    {
      name: 'logo',
      valueFactory: function() {
        return ImageView.create({value: SimpleValue.create(this.url + '/logo')});
      }
    }
  ],

  listeners: [
    {
      model_: 'Method',
      name: 'performQuery',
      code: function(evt) {
        this.maybeImportCrbugUrl(this.searchField.value.get());

        this.search(AND(
          CIssueQueryParser.parseString(this.searchChoice.value.get()) || TRUE,
          CIssueQueryParser.parseString(this.searchField.value.get()) || TRUE
        ).partialEval());
      }
    },
    {
      model_: 'Method',
      name: 'layout',
      code: function() {
        var H = window.innerHeight;
        this.view.$.style.height = (H-this.view.$.offsetTop-30) + 'px';

        console.log(this.crbugUrl());
      }
    }

  ],

  actions: [
    {
      model_: 'Action',
      name:  'link',
      label: '',
      iconUrl: 'images/link.svg',
      help:  'Link',

      action: function() {
        var url = this.crbugUrl();
        console.log(url);
        this.openURL(url);
      }
    }
  ],

  methods: {
    initHTML: function() {
      this.SUPER();

      this.window.addEventListener('resize', this.layout, false);

      this.searchChoice.value.addListener(this.performQuery);
      this.searchField.value.addListener(this.performQuery);

      this.syncManager.propertyValue('isSyncing').addListener(function() {
        if ( this.syncManager.isSyncing ) {
          this.timer.step();
          this.timer.start();
        } else {
          this.timer.stop();
          this.view.choice = this.view.choice;
        }
      }.bind(this));

      this.rowSelection.addListener(function(_,_,_,issue) {
        var url = this.url + '/issues/detail?id=' + issue.id;
        this.openURL(url);
      }.bind(this));

      this.logo.$.onclick = this.syncManager.forceSync.bind(this.syncManager);

      var timer = this.timer;
      Events.dynamic(function() {
        this.logo.$.style.webkitTransform = 'rotate(' + -timer.i + 'deg)';
      }.bind(this));

      this.layout();
      this.search(TRUE);
    },

    preview: function() {},

    /** Import a cr(1)bug URL. **/
    maybeImportCrbugUrl: function(url) {
      url = url.trim();
      if ( ! url ) return;
      if ( ! url.startsWith('http') ) return;

      var idx = url.indexOf('?');
      if ( idx == -1 ) return;

      url = url.substring(idx+1);
      var params = url.split('&');
      var memento = {};
      for ( var i = 0 ; i < params.length ; i++ ) {
        var param = params[i];
        var keyValue = param.split('=');
        memento[decodeURIComponent(keyValue[0])] =
          decodeURIComponent(keyValue[1]).replace(/\+/g, ' ');
      }

      this.memento = memento;
    },

    /** Filter data with the supplied predicate, or select all data if null. **/
    search: function(p) {
      if ( p ) console.log('SEARCH: ', p.toSQL());
      this.view.dao = p ? this.IssueDAO.where(p) : this.IssueDAO;
      var self = this;
      apar(
        this.view.dao.select(COUNT()),
        this.IssueDAO.select(COUNT()))(function(x, y) {
          self.countField.value.value = x.count.toLocaleString() + ' of ' + y.count.toLocaleString() + ' selected';
        }
      );

      console.log(this.crbugUrl());
    },

    /** Convert current state to a cr(1)bug URL. **/
    crbugUrl: function() {
      var u = this.url + '/issues/list';
      var m = this.memento;
      var d = '?';
      for ( var key in m ) {
        u += d;

        u += key + '=' + encodeURIComponent(m[key]);
        d = '&';
      }

      console.log('*****************URL ', u);

      return u;
    },

    openURL: function(url) {
      document.location = url;
    }
  },

  templates: [
    {
      name: "toHTML"
    }
  ]
});

var ChromeAppBrowser = Model.create({
  name: 'ChromeAppBrowser',

  extendsModel: 'Browser',

  methods: {
    openURL: function(url) {
      console.log('openURL: ', url);
      window.open(url);
    },

    /** Open a preview window when the user hovers over an issue id. **/
    preview: function(e, id) {
      console.log('preview', e, id);
      if ( this.currentPreview ) this.currentPreview.close();
      if ( ! id ) return;

      var v = this.currentPreview = PreviewView.create({url: this.url, id: id});
      this.view.$.insertAdjacentHTML('beforebegin', v.toHTML());
      v.$.style.left = e.x + 40;
      var viewHeight = v.$.style.height.replace('px','');
      var screenHeight = this.view.$.ownerDocument.defaultView.innerHeight;
      var top = e.y - viewHeight/2;
      v.$.style.top = Math.max(100, Math.min(screenHeight-viewHeight-15, top));
    }
  }

});<commit_msg>Crbug: Added 'canned queries' to mementos and Cr1bug URL's.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var Browser = Model.create({
  name: 'Browser',

  extendsModel: 'AbstractView',

  properties: [
    {
      name: 'project'
    },
    {
      name: 'projectName',
      scope: 'project',
      defaultValueFn: function() { return this.project.projectName; }
    },
    {
      name: 'url',
      scope: 'project',
      defaultValueFn: function() { return this.project.url; }
    },
    {
      name: 'IssueDAO',
      scope: 'project',
      defaultValueFn: function() { return this.project.IssueDAO; }
    },
    {
      name: 'syncManager',
      scope: 'project',
      defaultValueFn: function() { return this.project.syncManager; }
    },

    {
      name: 'rowSelection',
      valueFactory: function() { return SimpleValue.create(); }
    },
    {
      name: 'window'
    },
    {
      name: 'timer',
      valueFactory: function() { return Timer.create(); }
    },
    {
      name: 'view',
      valueFactory: function() { return createView(this.rowSelection, this); }
    },
    {
      name: 'memento',
      setter: function(m) {
        this.searchChoice.memento = m.can;
        if ( m.hasOwnProperty('q') ) this.searchField.value.set(m.q);
        this.view.memento = m;
      },
      getter: function() {
        var m = this.view.memento;
        m.can = this.searchChoice.memento;
        m.q = this.searchField.value.get();
        return m;
      }
    },

    {
      name: 'linkButton',
      valueFactory: function() {
        return ActionButton.create({
          action: this.model_.LINK,
          value: SimpleValue.create(this)
        });
      }
    },
    {
      name: 'countField',
      type: 'TextFieldView',
      valueFactory: function() {
        return TextFieldView.create({
          name: 'count',
          mode: 'read-only',
          displayWidth: 40
        });
      }
    },
    {
      name: 'searchChoice',
      valueFactory: function() {
        return ChoiceView.create({
          helpText: 'Search within:',
          choices:[
            ['',                            ' All issues'],
            ['-status=Closed,Fixed,Done',   ' Open issues'], // Should this be just 'Closed'?
            ['owner=me -status=Closed',     ' Open and owned by me'],
            ['-status=Closed reporter=me',  ' Open and reported by me'],
            ['-status=Closed is:starred',   ' Open and starred by me'],
            ['-status=Closed commentby:me', ' Open and comment by me'],
            ['status=New',                  ' New issues'],
            ['status=Fixed,Done',           ' Issues to verify']
          ]});
      }
    },
    {
      name: 'searchField',
      valueFactory: function() { return TextFieldView.create({ name: 'search', displayWidth: 60 }); }
    },
    {
      name: 'logo',
      valueFactory: function() {
        return ImageView.create({value: SimpleValue.create(this.url + '/logo')});
      }
    }
  ],

  listeners: [
    {
      model_: 'Method',
      name: 'performQuery',
      code: function(evt) {
        this.maybeImportCrbugUrl(this.searchField.value.get());

        this.search(AND(
          CIssueQueryParser.parseString(this.searchChoice.value.get()) || TRUE,
          CIssueQueryParser.parseString(this.searchField.value.get()) || TRUE
        ).partialEval());
      }
    },
    {
      model_: 'Method',
      name: 'layout',
      code: function() {
        var H = window.innerHeight;
        this.view.$.style.height = (H-this.view.$.offsetTop-30) + 'px';

        console.log(this.crbugUrl());
      }
    }

  ],

  actions: [
    {
      model_: 'Action',
      name:  'link',
      label: '',
      iconUrl: 'images/link.svg',
      help:  'Link',

      action: function() {
        var url = this.crbugUrl();
        console.log(url);
        this.openURL(url);
      }
    }
  ],

  methods: {
    initHTML: function() {
      this.SUPER();

      this.window.addEventListener('resize', this.layout, false);

      this.searchChoice.value.addListener(this.performQuery);
      this.searchField.value.addListener(this.performQuery);

      this.syncManager.propertyValue('isSyncing').addListener(function() {
        if ( this.syncManager.isSyncing ) {
          this.timer.step();
          this.timer.start();
        } else {
          this.timer.stop();
          this.view.choice = this.view.choice;
        }
      }.bind(this));

      this.rowSelection.addListener(function(_,_,_,issue) {
        var url = this.url + '/issues/detail?id=' + issue.id;
        this.openURL(url);
      }.bind(this));

      this.logo.$.onclick = this.syncManager.forceSync.bind(this.syncManager);

      var timer = this.timer;
      Events.dynamic(function() {
        this.logo.$.style.webkitTransform = 'rotate(' + -timer.i + 'deg)';
      }.bind(this));

      this.layout();
      this.search(TRUE);
    },

    preview: function() {},

    /** Filter data with the supplied predicate, or select all data if null. **/
    search: function(p) {
      if ( p ) console.log('SEARCH: ', p.toSQL());
      this.view.dao = p ? this.IssueDAO.where(p) : this.IssueDAO;
      var self = this;
      apar(
        this.view.dao.select(COUNT()),
        this.IssueDAO.select(COUNT()))(function(x, y) {
          self.countField.value.value = x.count.toLocaleString() + ' of ' + y.count.toLocaleString() + ' selected';
        }
      );

      console.log(this.crbugUrl());
    },

    // Crbug doesn't order canned-queries sequentially
    idToCrbugCan: [1, 2, 3, 4, 5, 8, 6, 7],
    crbugCanToId: [0, 0, 1, 2, 3, 4, 6, 7, 5],

    /** Import a cr(1)bug URL. **/
    maybeImportCrbugUrl: function(url) {
      url = url.trim();
      if ( ! url ) return;
      if ( ! url.startsWith('http') ) return;

      var idx = url.indexOf('?');
      if ( idx == -1 ) return;

      url = url.substring(idx+1);
      var params = url.split('&');
      var memento = {};
      for ( var i = 0 ; i < params.length ; i++ ) {
        var param = params[i];
        var keyValue = param.split('=');
        memento[decodeURIComponent(keyValue[0])] =
          decodeURIComponent(keyValue[1]).replace(/\+/g, ' ');
      }

      if ( memento.hasOwnProperty('can') ) memento.can = this.crbugCanToId[memento.can];

      this.memento = memento;
    },

    /** Convert current state to a cr(1)bug URL. **/
    crbugUrl: function() {
      var u = this.url + '/issues/list';
      var m = this.memento;
      var d = '?';

      if ( m.hasOwnProperty('can') ) m.can = this.idToCrbugCan[m.can];

      for ( var key in m ) {
        u += d;

        u += key + '=' + encodeURIComponent(m[key]);
        d = '&';
      }

      console.log('*****************URL ', u);

      return u;
    },

    openURL: function(url) {
      document.location = url;
    }
  },

  templates: [
    {
      name: "toHTML"
    }
  ]
});

var ChromeAppBrowser = Model.create({
  name: 'ChromeAppBrowser',

  extendsModel: 'Browser',

  methods: {
    openURL: function(url) {
      console.log('openURL: ', url);
      window.open(url);
    },

    /** Open a preview window when the user hovers over an issue id. **/
    preview: function(e, id) {
      console.log('preview', e, id);
      if ( this.currentPreview ) this.currentPreview.close();
      if ( ! id ) return;

      var v = this.currentPreview = PreviewView.create({url: this.url, id: id});
      this.view.$.insertAdjacentHTML('beforebegin', v.toHTML());
      v.$.style.left = e.x + 40;
      var viewHeight = v.$.style.height.replace('px','');
      var screenHeight = this.view.$.ownerDocument.defaultView.innerHeight;
      var top = e.y - viewHeight/2;
      v.$.style.top = Math.max(100, Math.min(screenHeight-viewHeight-15, top));
    }
  }

});<|endoftext|>


<commit_before>(function(gui,urllib) {
	'use strict';
	var win = gui.Window.get();
	var validSlackRedirect = /(.+\.)?slack-redir.com/i;

	win.on('new-win-policy',function (frame, url, policy) {
		console.log(policy);
		var openRequest = urllib.parse(url);

		if ( validSlackRedirect.test(openRequest.host)) {
			gui.Shell.openExternal(url);
			policy.ignore();
			console.log('Requested to open: '+ JSON.stringify(openRequest));
		}

	});
})(require('nw.gui'),require('url'));
<commit_msg>Remove log lines<commit_after>(function(gui,urllib) {
	'use strict';
	var win = gui.Window.get();
	var validSlackRedirect = /(.+\.)?slack-redir.com/i;

	win.on('new-win-policy',function (frame, url, policy) {
		var openRequest = urllib.parse(url);

		if ( validSlackRedirect.test(openRequest.host)) {
			gui.Shell.openExternal(url);
			policy.ignore();
			console.log('Allowing browser to handle: '+ JSON.stringify(openRequest));
		}

	});
})(require('nw.gui'),require('url'));
<|endoftext|>