<commit_before>var app = angular.module('app', ['ngRoute']);

app.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/Sprints', {
        templateUrl: 'partials/sprints',
        controller: 'sprintsCtrl'
    }).
      when('/ProductBacklog', {
        templateUrl: 'partials/productBacklog',
        controller: 'productBacklogCtrl'
      }).
      when('/ReleaseBacklog', {
        templateUrl: 'partials/releaseBacklog',
        controller: 'releaseBacklogCtrl'
      }).
      otherwise({
        redirectTo: '/ProductBacklog'
      });
}]);

app.controller('detalleProyectoCtrl', ['$scope', '$http', function($scope, $http){
    $scope.scrumMaster ={};
    $scope.productOwner={};
    $scope.idProyecto={};
    $scope.desarrolladores = [];
    $scope.liberaciones = [];

    $scope.init = function(scrumMaster, owner, idProyecto){
      $scope.scrumMaster =scrumMaster;
      $scope.productOwner=owner;
      $scope.idProyecto = idProyecto;
      $scope.getDesarrolladores();
    }

    $scope.historia = new Object();
    $scope.crearHistoria = function () {
        $scope.historia.proyecto = $scope.idProyecto;
        socket.emit('newHistoria', $scope.historia);
    };

    var socket = io.connect({'forceNew': true});
    $scope.historias = $scope.historias || [];

    socket.on('sendHistorias', function (data) {
        $scope.findHistoriasByProyecto();
        $scope.$apply();
    });

    socket.on('sendHistoria', function () {
        $scope.findHistoriasByProyecto();
        $scope.$apply();
    });

    $scope.findHistoriasByProyecto = function(){
      $http.get('/find/historias/proyecto/'+$scope.idProyecto).success(function(data) {
            $scope.historias = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.findReleaseByProyecto = function(){
      $http.get('/find/release/proyecto/'+$scope.idProyecto).success(function(data) {
            $scope.liberaciones = data;
            console.log("--------")
            console.log(data);
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.getNombreCompleto = function(obj){
      if(obj.google){
        return obj.google.name;
      } else if (obj.twitter){
        return obj.twitter.displayName;
      } else if (obj.facebook){
        return obj.facebook.name;
      }
      return obj.nombre;
    };
    $scope.usuarios =[];

    $scope.getUsuarios = function(){
      $http.get('findUsuarios').success(function(data) {
            $scope.usuarios = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.getDesarrolladores = function(){
      $http.get('/detalleProyecto/findDevelopers/'+$scope.idProyecto).success(function(data) {
            $scope.desarrolladores = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.asignarOwner = function(id){
      console.log(id);
      $http({
        url:'/agregarOwner',
        method:'POST',
        data: {usuarioOwner:id,
        idProyecto:$scope.idProyecto}
      }).then(function(data){
        //TODO:GetOwner
      }, function(data){
        //TODO:Error
      });
    };

    $scope.asignarDesarrollador = function(id){
    $http({
      url:'/agregarDesarrollador',
      method:'POST',
      data: {usuarioOwner:id,
      idProyecto:$scope.idProyecto}
    }).then(function(data){
      $scope.getDesarrolladores();
    }, function(data){
      //TODO:Error
    });
  };
}]);

app.controller('productBacklogCtrl',['$scope', function($scope){
  $scope.mensaje = "aszdxfhgndfxcbsxzcvx";
  $scope.titulo = "Titulo 1";
}]);

app.controller('releaseBacklogCtrl',['$scope','$http', '$window', function($scope, $http, $window){
  $scope.verDetalles = false;
  $scope.historiasSprint = [];
  $scope.release = {}

  $scope.init = function(idProy, historias){
    $scope.idProyecto = idProy;
    $scope.historias = historias;
    console.log("Nombre Release");
    console.log($scope.release.nombreRelease);
    console.log($scope.release.descripcionRelease);

  };

  $scope.agregarHistoriaSprint = function(idHistoria){
    var i =0;
    for(i = 0; i<$scope.historias.length;i++){
      if($scope.historias[i]._id === idHistoria){
          $scope.historiasSprint.push($scope.historias[i]);
          break;
      }
    };
    $scope.historias.splice(i,1);
  };

  $scope.crearRelease = function(){
    $scope.release.proyecto = $scope.idProyecto
    $http({
      url:'/crearRelease',
      method:'POST',
      data: {historias:$scope.historiasSprint,
      release:$scope.release}
    }).then(function(data){
      $window.location.href = "/detalleProyecto";
    }, function(data){
      $window.location.href = "/addReleaseBacklog";
    });
  };

}]);

app.controller('showReleaseBacklogCtrl',['$scope','$http', '$window', function($scope, $http, $window){
  $scope.verDetalles = false;
  $scope.historiasSprint = [];
  $scope.sprint = {}
  $scope.historiaSeleccionada="";

  $scope.init = function(idProy, idRelease){
    $scope.idProyecto = idProy;
    $scope.idRelease = idRelease;
    $scope.findHistoriasByRelease();
    $scope.findSprintsByRelease();

  };

  $scope.agregarHistoriaSprint = function(idHistoria){
    var i =0;
    for(i = 0; i<$scope.historias.length;i++){
      if($scope.historias[i]._id === idHistoria){
          $scope.historiasSprint.push($scope.historias[i]);
          break;
      }
    };
    $scope.historias.splice(i,1);
  };

  $scope.findHistoriasByRelease = function(){
    $http.get("/find/historias/release/"+$scope.idRelease).success(function(data){
      $scope.historias = data;
    });
  }

  $scope.findSprintsByRelease = function(){
    $http.get("/find/sprints/release/"+$scope.idRelease).success(function(data){
      $scope.sprints = data;
    });
  }

  $scope.crearSprint = function(){
    $scope.sprint.liberacionBacklog = $scope.idRelease;
    $http({
      url:'/crearSprint',
      method:'POST',
      data: {historias:$scope.historiasSprint,
      sprint:$scope.sprint}
    }).then(function(data){
      $window.location.href = "/showReleaseBacklog";
    }, function(data){
      $window.location.href = "/showReleaseBacklog";
    });
  };

}]);

app.controller('sprintsCtrl',['$scope', function($scope){
  $scope.mensaje = "no se";
  $scope.titulo = "Titulo 3";
}]);

app.controller('profileCtrl', ['$scope', '$http', function($scope, $http){

    $scope.skills = $scope.skills || [];
    $scope.init= function(skillz){
        $scope.skills = skillz;
    }
    $scope.removeSkill = function(index){
        $scope.skills.splice(index, 1);
    }
    $scope.agregarHabilidad = function(){
        var skill = {
            habilidad: $scope.user.habilidad,
            nivel: $scope.user.nivel
        };
        $scope.skills.push(skill);
        $scope.user.habilidad = '';
        $scope.user.nivel = '';
    }

}]);

app.controller("dashBoardController", ['$scope', '$http', function($scope, $http){

  $scope.idUsuario = "";
  $scope.proyectos = [];
  $scope.totalScrum = 0;
  $scope.totalOwner = 0;
  $scope.totalDeveloper = 0;
  $scope.init = function(usuario){
    $scope.idUsuario = usuario;
  }

  $scope.getProyectosScrum = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"scrum-master").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }

  $scope.getProyectosOwner = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"product-owner").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }

  $scope.getProyectosDeveloper = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"developer").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }
}]);
<commit_msg>Se arregla visualizacion de los release en el detalle proyecto.<commit_after>var app = angular.module('app', ['ngRoute']);

app.config(['$routeProvider',
  function($routeProvider) {
    $routeProvider.
      when('/Sprints', {
        templateUrl: 'partials/sprints',
        controller: 'sprintsCtrl'
    }).
      when('/ProductBacklog', {
        templateUrl: 'partials/productBacklog',
        controller: 'productBacklogCtrl'
      }).
      when('/ReleaseBacklog', {
        templateUrl: 'partials/releaseBacklog',
        controller: 'releaseBacklogCtrl'
      }).
      otherwise({
        redirectTo: '/ProductBacklog'
      });
}]);

app.controller('detalleProyectoCtrl', ['$scope', '$http', function($scope, $http){
    $scope.scrumMaster ={};
    $scope.productOwner={};
    $scope.idProyecto={};
    $scope.desarrolladores = [];
    $scope.liberaciones = [];

    $scope.init = function(scrumMaster, owner, idProyecto){
      $scope.scrumMaster =scrumMaster;
      $scope.productOwner=owner;
      $scope.idProyecto = idProyecto;
      $scope.getDesarrolladores();
      $scope.findReleaseByProyecto();
    }

    $scope.historia = new Object();
    $scope.crearHistoria = function () {
        $scope.historia.proyecto = $scope.idProyecto;
        socket.emit('newHistoria', $scope.historia);
    };

    var socket = io.connect({'forceNew': true});
    $scope.historias = $scope.historias || [];

    socket.on('sendHistorias', function (data) {
        $scope.findHistoriasByProyecto();
        $scope.$apply();
    });

    socket.on('sendHistoria', function () {
        $scope.findHistoriasByProyecto();
        $scope.$apply();
    });

    $scope.findHistoriasByProyecto = function(){
      $http.get('/find/historias/proyecto/'+$scope.idProyecto).success(function(data) {
            $scope.historias = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.findReleaseByProyecto = function(){
      $http.get('/find/release/proyecto/'+$scope.idProyecto).success(function(data) {
            $scope.liberaciones = data;
            console.log("--------")
            console.log(data);
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.getNombreCompleto = function(obj){
      if(obj.google){
        return obj.google.name;
      } else if (obj.twitter){
        return obj.twitter.displayName;
      } else if (obj.facebook){
        return obj.facebook.name;
      }
      return obj.nombre;
    };
    $scope.usuarios =[];

    $scope.getUsuarios = function(){
      $http.get('findUsuarios').success(function(data) {
            $scope.usuarios = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.getDesarrolladores = function(){
      $http.get('/detalleProyecto/findDevelopers/'+$scope.idProyecto).success(function(data) {
            $scope.desarrolladores = data;
        }).error(function(data){
          //TODO:Error
          });
    };

    $scope.asignarOwner = function(id){
      console.log(id);
      $http({
        url:'/agregarOwner',
        method:'POST',
        data: {usuarioOwner:id,
        idProyecto:$scope.idProyecto}
      }).then(function(data){
        //TODO:GetOwner
      }, function(data){
        //TODO:Error
      });
    };

    $scope.asignarDesarrollador = function(id){
    $http({
      url:'/agregarDesarrollador',
      method:'POST',
      data: {usuarioOwner:id,
      idProyecto:$scope.idProyecto}
    }).then(function(data){
      $scope.getDesarrolladores();
    }, function(data){
      //TODO:Error
    });
  };
}]);

app.controller('productBacklogCtrl',['$scope', function($scope){
  $scope.mensaje = "aszdxfhgndfxcbsxzcvx";
  $scope.titulo = "Titulo 1";
}]);

app.controller('releaseBacklogCtrl',['$scope','$http', '$window', function($scope, $http, $window){
  $scope.verDetalles = false;
  $scope.historiasSprint = [];
  $scope.release = {}

  $scope.init = function(idProy, historias){
    $scope.idProyecto = idProy;
    $scope.historias = historias;
    console.log("Nombre Release");
    console.log($scope.release.nombreRelease);
    console.log($scope.release.descripcionRelease);

  };

  $scope.agregarHistoriaSprint = function(idHistoria){
    var i =0;
    for(i = 0; i<$scope.historias.length;i++){
      if($scope.historias[i]._id === idHistoria){
          $scope.historiasSprint.push($scope.historias[i]);
          break;
      }
    };
    $scope.historias.splice(i,1);
  };

  $scope.crearRelease = function(){
    $scope.release.proyecto = $scope.idProyecto
    $http({
      url:'/crearRelease',
      method:'POST',
      data: {historias:$scope.historiasSprint,
      release:$scope.release}
    }).then(function(data){
      $window.location.href = "/detalleProyecto";
    }, function(data){
      $window.location.href = "/addReleaseBacklog";
    });
  };

}]);

app.controller('showReleaseBacklogCtrl',['$scope','$http', '$window', function($scope, $http, $window){
  $scope.verDetalles = false;
  $scope.historiasSprint = [];
  $scope.sprint = {}
  $scope.historiaSeleccionada="";

  $scope.init = function(idProy, idRelease){
    $scope.idProyecto = idProy;
    $scope.idRelease = idRelease;
    $scope.findHistoriasByRelease();
    $scope.findSprintsByRelease();

  };

  $scope.agregarHistoriaSprint = function(idHistoria){
    var i =0;
    for(i = 0; i<$scope.historias.length;i++){
      if($scope.historias[i]._id === idHistoria){
          $scope.historiasSprint.push($scope.historias[i]);
          break;
      }
    };
    $scope.historias.splice(i,1);
  };

  $scope.findHistoriasByRelease = function(){
    $http.get("/find/historias/release/"+$scope.idRelease).success(function(data){
      $scope.historias = data;
    });
  }

  $scope.findSprintsByRelease = function(){
    $http.get("/find/sprints/release/"+$scope.idRelease).success(function(data){
      $scope.sprints = data;
    });
  }

  $scope.crearSprint = function(){
    $scope.sprint.liberacionBacklog = $scope.idRelease;
    $http({
      url:'/crearSprint',
      method:'POST',
      data: {historias:$scope.historiasSprint,
      sprint:$scope.sprint}
    }).then(function(data){
      $window.location.href = "/showReleaseBacklog";
    }, function(data){
      $window.location.href = "/showReleaseBacklog";
    });
  };

}]);

app.controller('sprintsCtrl',['$scope', function($scope){
  $scope.mensaje = "no se";
  $scope.titulo = "Titulo 3";
}]);

app.controller('profileCtrl', ['$scope', '$http', function($scope, $http){

    $scope.skills = $scope.skills || [];
    $scope.init= function(skillz){
        $scope.skills = skillz;
    }
    $scope.removeSkill = function(index){
        $scope.skills.splice(index, 1);
    }
    $scope.agregarHabilidad = function(){
        var skill = {
            habilidad: $scope.user.habilidad,
            nivel: $scope.user.nivel
        };
        $scope.skills.push(skill);
        $scope.user.habilidad = '';
        $scope.user.nivel = '';
    }

}]);

app.controller("dashBoardController", ['$scope', '$http', function($scope, $http){

  $scope.idUsuario = "";
  $scope.proyectos = [];
  $scope.totalScrum = 0;
  $scope.totalOwner = 0;
  $scope.totalDeveloper = 0;
  $scope.init = function(usuario){
    $scope.idUsuario = usuario;
  }

  $scope.getProyectosScrum = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"scrum-master").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }

  $scope.getProyectosOwner = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"product-owner").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }

  $scope.getProyectosDeveloper = function(){
    $http.get('/getProyectos/dashboard/'+$scope.idUsuario+"/"+"developer").success(function(data) {
          if(data != "{}"){
            $scope.proyectos = data;
          } else {
            $scope.proyectos = [];
          }
      }).error(function(data){
              console.log("Algo paso");
        });
  }
}]);
<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.provide("erpnext.accounts");
erpnext.accounts.CostCenterController = wn.ui.form.Controller.extend({
	onload: function() {
		this.setup_queries();
	},

	setup_queries: function() {
		var me = this;
		if(this.frm.fields_dict["budget_details"].grid.get_field("account")) {
			this.frm.set_query("account", "budget_details", function() {
				return {
					filters:[
						['Account', 'company', '=', me.frm.doc.company],
						['Account', 'is_pl_account', '=', 'Yes'],
						['Account', 'debit_or_credit', '=', 'Debit'],
						['Account', 'group_or_ledger', '!=', 'Group'],
					]
				}
			});
		}

		this.frm.set_query("parent_cost_center", function() {
			return {
				filters:[
					['Cost Center', 'group_or_ledger', '=', 'Group'],
					['Cost Center', 'company', '=', me.frm.doc.company],
				]
			}
		});
	}
});

$.extend(cur_frm.cscript, new erpnext.accounts.CostCenterController({frm: cur_frm}));

cur_frm.cscript.refresh = function(doc, cdt, cdn) {
	var intro_txt = '';
	cur_frm.toggle_display('cost_center_name', doc.__islocal);
	cur_frm.toggle_enable(['group_or_ledger', 'company'], doc.__islocal);

	if(!doc.__islocal && doc.group_or_ledger=='Group') {
		intro_txt += '
Note: This Cost Center is a Group, \
			Accounting Entries are not allowed against groups.
';
	}

	cur_frm.cscript.hide_unhide_group_ledger(doc);

	cur_frm.toggle_display('sb1', doc.group_or_ledger=='Ledger')
	cur_frm.set_intro(intro_txt);

	cur_frm.add_custom_button('Chart of Cost Centers',
		function() { wn.set_route("Accounts Browser", "Cost Center"); }, 'icon-sitemap')
}

cur_frm.cscript.parent_cost_center = function(doc,cdt,cdn){
	if(!doc.company){
		alert('Please enter company name first');
	}
}

cur_frm.cscript.hide_unhide_group_ledger = function(doc) {
	if (cstr(doc.group_or_ledger) == 'Group') {
		cur_frm.add_custom_button('Convert to Ledger',
			function() { cur_frm.cscript.convert_to_ledger(); }, 'icon-retweet')
	} else if (cstr(doc.group_or_ledger) == 'Ledger') {
		cur_frm.add_custom_button('Convert to Group',
			function() { cur_frm.cscript.convert_to_group(); }, 'icon-retweet')
	}
}

cur_frm.cscript.convert_to_ledger = function(doc, cdt, cdn) {
	return $c_obj(cur_frm.get_doclist(),'convert_group_to_ledger','',function(r,rt) {
		if(r.message == 1) {
			cur_frm.refresh();
		}
	});
}

cur_frm.cscript.convert_to_group = function(doc, cdt, cdn) {
	return $c_obj(cur_frm.get_doclist(),'convert_ledger_to_group','',function(r,rt) {
		if(r.message == 1) {
			cur_frm.refresh();
		}
	});
}
<commit_msg>Fix translate Cost_center.js<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.provide("erpnext.accounts");
erpnext.accounts.CostCenterController = wn.ui.form.Controller.extend({
	onload: function() {
		this.setup_queries();
	},

	setup_queries: function() {
		var me = this;
		if(this.frm.fields_dict["budget_details"].grid.get_field("account")) {
			this.frm.set_query("account", "budget_details", function() {
				return {
					filters:[
						['Account', 'company', '=', me.frm.doc.company],
						['Account', 'is_pl_account', '=', 'Yes'],
						['Account', 'debit_or_credit', '=', 'Debit'],
						['Account', 'group_or_ledger', '!=', 'Group'],
					]
				}
			});
		}

		this.frm.set_query("parent_cost_center", function() {
			return {
				filters:[
					['Cost Center', 'group_or_ledger', '=', 'Group'],
					['Cost Center', 'company', '=', me.frm.doc.company],
				]
			}
		});
	}
});

$.extend(cur_frm.cscript, new erpnext.accounts.CostCenterController({frm: cur_frm}));

cur_frm.cscript.refresh = function(doc, cdt, cdn) {
	var intro_txt = '';
	cur_frm.toggle_display('cost_center_name', doc.__islocal);
	cur_frm.toggle_enable(['group_or_ledger', 'company'], doc.__islocal);

	if(!doc.__islocal && doc.group_or_ledger=='Group') {
		intro_txt += '
Note:'+ wn._('This Cost Center is a')+ ''+wn._('Group')+''+ wn._(', \
			Accounting Entries are not allowed against groups.')+'
';
	}

	cur_frm.cscript.hide_unhide_group_ledger(doc);

	cur_frm.toggle_display('sb1', doc.group_or_ledger=='Ledger')
	cur_frm.set_intro(intro_txt);

	cur_frm.add_custom_button(wn._('Chart of Cost Centers'),
		function() { wn.set_route("Accounts Browser", "Cost Center"); }, 'icon-sitemap')
}

cur_frm.cscript.parent_cost_center = function(doc,cdt,cdn){
	if(!doc.company){
		alert(wn._('Please enter company name first'));
	}
}

cur_frm.cscript.hide_unhide_group_ledger = function(doc) {
	if (cstr(doc.group_or_ledger) == 'Group') {
		cur_frm.add_custom_button(wn._('Convert to Ledger'),
			function() { cur_frm.cscript.convert_to_ledger(); }, 'icon-retweet')
	} else if (cstr(doc.group_or_ledger) == 'Ledger') {
		cur_frm.add_custom_button(wn._('Convert to Group'),
			function() { cur_frm.cscript.convert_to_group(); }, 'icon-retweet')
	}
}

cur_frm.cscript.convert_to_ledger = function(doc, cdt, cdn) {
	return $c_obj(cur_frm.get_doclist(),'convert_group_to_ledger','',function(r,rt) {
		if(r.message == 1) {
			cur_frm.refresh();
		}
	});
}

cur_frm.cscript.convert_to_group = function(doc, cdt, cdn) {
	return $c_obj(cur_frm.get_doclist(),'convert_ledger_to_group','',function(r,rt) {
		if(r.message == 1) {
			cur_frm.refresh();
		}
	});
}
<|endoftext|>


<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.
 */
var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {

        var client = new WindowsAzure.MobileServiceClient('ZUMOAPPURL', 'ZUMOAPPKEY');
        todoItemTable = client.getTable('todoitem');

        // Read current data and rebuild UI.
        // If you plan to generate complex UIs like this, consider using a JavaScript templating library.
        function refreshTodoItems() {
            $('#summary').html("Loading...");
            var query = todoItemTable.where({ complete: false });

            query.read().then(function(todoItems) {
                var listItems = $.map(todoItems, function(item) {
                    return $('
')
                        .attr('data-todoitem-id', item.id)
                        .append($('<button class="item-delete">Delete</button>'))
                        .append($('<input type="checkbox" class="item-complete">').prop('checked', item.complete))
                        .append($('
').append($('<input class="item-text">').val(item.text)));
                });

                $('#todo-items').empty().append(listItems).toggle(listItems.length > 0);
                $('#summary').html('' + todoItems.length + ' item(s)');
            }, handleError);
        }

        function handleError(error) {
            var text = error + (error.request ? ' - ' + error.request.status : '');
            $('#errorlog').append($('
').text(text));
        }

        function getTodoItemId(formElement) {
            return $(formElement).closest('li').attr('data-todoitem-id');
        }

        // Handle insert
        $('#add-item').submit(function(evt) {
            var textbox = $('#new-item-text'),
                itemText = textbox.val();
            if (itemText !== '') {
                todoItemTable.insert({ text: itemText, complete: false }).then(refreshTodoItems, handleError);
            }
            textbox.val('').focus();
            evt.preventDefault();
        });

        $('#refresh').click(function(evt) {
            refreshTodoItems();
            evt.preventDefault();
        });

        // Handle update
        $(document.body).on('change', '.item-text', function() {
            var newText = $(this).val();
            todoItemTable.update({ id: getTodoItemId(this), text: newText }).then(null, handleError);
        });

        $(document.body).on('change', '.item-complete', function() {
            var isComplete = $(this).prop('checked');
            todoItemTable.update({ id: getTodoItemId(this), complete: isComplete }).then(refreshTodoItems, handleError);
        });

        // Handle delete
        $(document.body).on('click', '.item-delete', function () {
            todoItemTable.del({ id: getTodoItemId(this) }).then(refreshTodoItems, handleError);
        });

        // On initial load, start by fetching the current data
        refreshTodoItems();
    },
};
<commit_msg>Update MobileServiceClient constructor<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.
 */
var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {

        var client = new WindowsAzure.MobileServiceClient('ZUMOAPPURL');
        todoItemTable = client.getTable('todoitem');

        // Read current data and rebuild UI.
        // If you plan to generate complex UIs like this, consider using a JavaScript templating library.
        function refreshTodoItems() {
            $('#summary').html("Loading...");
            var query = todoItemTable.where({ complete: false });

            query.read().then(function(todoItems) {
                var listItems = $.map(todoItems, function(item) {
                    return $('
')
                        .attr('data-todoitem-id', item.id)
                        .append($('<button class="item-delete">Delete</button>'))
                        .append($('<input type="checkbox" class="item-complete">').prop('checked', item.complete))
                        .append($('
').append($('<input class="item-text">').val(item.text)));
                });

                $('#todo-items').empty().append(listItems).toggle(listItems.length > 0);
                $('#summary').html('' + todoItems.length + ' item(s)');
            }, handleError);
        }

        function handleError(error) {
            var text = error + (error.request ? ' - ' + error.request.status : '');
            $('#errorlog').append($('
').text(text));
        }

        function getTodoItemId(formElement) {
            return $(formElement).closest('li').attr('data-todoitem-id');
        }

        // Handle insert
        $('#add-item').submit(function(evt) {
            var textbox = $('#new-item-text'),
                itemText = textbox.val();
            if (itemText !== '') {
                todoItemTable.insert({ text: itemText, complete: false }).then(refreshTodoItems, handleError);
            }
            textbox.val('').focus();
            evt.preventDefault();
        });

        $('#refresh').click(function(evt) {
            refreshTodoItems();
            evt.preventDefault();
        });

        // Handle update
        $(document.body).on('change', '.item-text', function() {
            var newText = $(this).val();
            todoItemTable.update({ id: getTodoItemId(this), text: newText }).then(null, handleError);
        });

        $(document.body).on('change', '.item-complete', function() {
            var isComplete = $(this).prop('checked');
            todoItemTable.update({ id: getTodoItemId(this), complete: isComplete }).then(refreshTodoItems, handleError);
        });

        // Handle delete
        $(document.body).on('click', '.item-delete', function () {
            todoItemTable.del({ id: getTodoItemId(this) }).then(refreshTodoItems, handleError);
        });

        // On initial load, start by fetching the current data
        refreshTodoItems();
    },
};
<|endoftext|>


<commit_before>var LineItemTemplate = require("../views/templates/line_item");

module.exports = Backbone.View.extend({
    initialize: function(element, options) {
        this.$el = $(element);
        if (options) _.extend(this, options);
        _.bindAll(this, "navigate", "loadCancerList", "initGeneTypeahead");

        $.ajax({ url:"svc/data/lookups/cancers", type:"GET", dataType:"text", success:this.loadCancerList });
        $.ajax({ url:"svc/data/lookups/genes", type:"GET", dataType:"text", success:this.initGeneTypeahead });
    },

    navigate: function(target, view_options, query_options) {
        var source = target.data("source");
        var view_name = target.data("view");
        var linked_to = target.data("linked");
        if (source && view_name) {
            var afn = function(link) {
                return $(link).data("id")
            };

            var cancerList = _.map($(".cancer-selector .active a"), function(link) {
                return $(link).data("id");
            });
            var geneList = _.map($(".gene-selector .item-remover"), function(link) {
                return $(link).data("id");
            });

            // TODO : Standardize how we store and lookup cancers
            var qCancerList = cancerList;
            if (target.data("lowercase") && target.data("lowercase") == true) {
                qCancerList = _.map(cancerList, function(cancerItem) {
                    return cancerItem.toLowerCase();
                });
            }
            var v_options = _.extend({ "genes": geneList, "cancers": cancerList, "hideSelector": true }, view_options);
            var q_options = _.extend({ "gene": geneList, "cancer": qCancerList }, query_options);

            var view = this.viewsByUri($(target), source, view_name, v_options, q_options);
            if (linked_to) {
                var _this = this;
                view.on("selected", function(selected) {
                    var gene = [selected.gene.toUpperCase()];
                    var cancer = [selected.cancer.toUpperCase()];
                    var qoptns = { "cancer": cancer, "gene": gene };
                    var voptns = { "cancers": cancer, "genes": gene };
                    _this.navigate($(linked_to).find(".map-contents"), voptns, qoptns);
                });
            }
        }
    },

    viewsByUri: function($el, uri, view_name, options, query) {
        console.log("viewsByUri(" + uri + "," + view_name + "," + JSON.stringify(options) + "," + JSON.stringify(query) + ")");
        var parts = uri.split("/");
        var data_root = parts[0];
        var analysis_id = parts[1];
        var dataset_id = parts[2];
        var model_unit = qed.Datamodel.get(data_root)[analysis_id];
        var catalog = model_unit.catalog;
        var catalog_unit = catalog[dataset_id];
        var modelName = model_unit.model || catalog_unit.model;
        var serviceUri = catalog_unit.service || model_unit.service || "data/" + uri;
        var Model = qed.Models[modelName || "Default"];

        var model_optns = _.extend(options, {
            "data_uri": "svc/" + serviceUri,
            "analysis_id": analysis_id,
            "dataset_id": dataset_id,
            "model_unit": model_unit,
            "catalog_unit": catalog_unit
        });
        // TODO: Determine which views need annotations
        // qed.FetchAnnotations(dataset_id);

        var model = new Model(model_optns);
        _.defer(function() {
            model.fetch({
                "data": query,
                "traditional": true,
                success:function () {
                    model.trigger('load');
                }
            });
        });

        var view_options = _.extend({"model":model}, (model_unit.view_options || {}), (options || {}));

        var ViewClass = qed.Views[view_name];
        var view = new ViewClass(view_options);
        $el.html(view.render().el);
        return view;
    },

    loadCancerList: function(txt) {
        var cancerList = txt.trim().split("\n");
        var UL = $(".cancer-selector");
        _.each(cancerList, function(cancerItem, idx) {
            UL.append(LineItemTemplate({"li_class":"active","a_class":"toggle-active","id":cancerItem,"label":cancerItem}));
        });

        UL.find(".toggle-active").click(function(e) {
            $(e.target).parent().toggleClass("active");
        });
    },

    initGeneTypeahead: function(txt) {
        var genelist = txt.trim().split("\n");

        var UL = $(".gene-selector");
        $(".genes-typeahead").typeahead({
            source:function (q, p) {
                p(_.compact(_.flatten(_.map(q.toLowerCase().split(" "), function (qi) {
                    return _.map(genelist, function (geneitem) {
                        if (geneitem.toLowerCase().indexOf(qi) >= 0) return geneitem;
                    });
                }))));
            },

            updater:function (gene) {
                UL.append(LineItemTemplate({ "label":gene, "id":gene, "a_class":"item-remover", "i_class":"icon-trash" }));
                UL.find(".item-remover").click(function(e) {
                    $(e.target).parent().remove();
                });
                return "";
            }
        });

        UL.find(".item-remover").click(function(e) {
            $(e.target).parent().remove();
        });
    },

    zoom: function(level) {
        // TODO : Figure out way to center screen on where the mouse has clicked
        $(".atlas-zoom").zoomTo({
            "duration":1000,
            "scalemode": "both",
            "easing": "ease",
            "nativeanimation": true,
            "root": $(".atlas-canvas"),
            "closeclick": false,
            "targetsize":level
        });
    }
});<commit_msg>ignore unknown views<commit_after>var LineItemTemplate = require("../views/templates/line_item");

module.exports = Backbone.View.extend({
    initialize: function(element, options) {
        this.$el = $(element);
        if (options) _.extend(this, options);
        _.bindAll(this, "navigate", "loadCancerList", "initGeneTypeahead");

        $.ajax({ url:"svc/data/lookups/cancers", type:"GET", dataType:"text", success:this.loadCancerList });
        $.ajax({ url:"svc/data/lookups/genes", type:"GET", dataType:"text", success:this.initGeneTypeahead });
    },

    navigate: function(target, view_options, query_options) {
        var source = target.data("source");
        var view_name = target.data("view");
        var linked_to = target.data("linked");
        if (source && view_name) {
            var afn = function(link) {
                return $(link).data("id")
            };

            var cancerList = _.map($(".cancer-selector .active a"), function(link) {
                return $(link).data("id");
            });
            var geneList = _.map($(".gene-selector .item-remover"), function(link) {
                return $(link).data("id");
            });

            // TODO : Standardize how we store and lookup cancers
            var qCancerList = cancerList;
            if (target.data("lowercase") && target.data("lowercase") == true) {
                qCancerList = _.map(cancerList, function(cancerItem) {
                    return cancerItem.toLowerCase();
                });
            }
            var v_options = _.extend({ "genes": geneList, "cancers": cancerList, "hideSelector": true }, view_options);
            var q_options = _.extend({ "gene": geneList, "cancer": qCancerList }, query_options);

            var view = this.viewsByUri($(target), source, view_name, v_options, q_options);
            if (linked_to) {
                var _this = this;
                view.on("selected", function(selected) {
                    var gene = [selected.gene.toUpperCase()];
                    var cancer = [selected.cancer.toUpperCase()];
                    var qoptns = { "cancer": cancer, "gene": gene };
                    var voptns = { "cancers": cancer, "genes": gene };
                    _this.navigate($(linked_to).find(".map-contents"), voptns, qoptns);
                });
            }
        }
    },

    viewsByUri: function($el, uri, view_name, options, query) {
        console.log("viewsByUri(" + uri + "," + view_name + "," + JSON.stringify(options) + "," + JSON.stringify(query) + ")");
        var ViewClass = qed.Views[view_name];
        if (ViewClass) {
            var parts = uri.split("/");
            var data_root = parts[0];
            var analysis_id = parts[1];
            var dataset_id = parts[2];
            var model_unit = qed.Datamodel.get(data_root)[analysis_id];
            var catalog = model_unit.catalog;
            var catalog_unit = catalog[dataset_id];
            var modelName = model_unit.model || catalog_unit.model;
            var serviceUri = catalog_unit.service || model_unit.service || "data/" + uri;
            var Model = qed.Models[modelName || "Default"];

            var model_optns = _.extend(options, {
                "data_uri": "svc/" + serviceUri,
                "analysis_id": analysis_id,
                "dataset_id": dataset_id,
                "model_unit": model_unit,
                "catalog_unit": catalog_unit
            });
            // TODO: Determine which views need annotations
            // qed.FetchAnnotations(dataset_id);

            var model = new Model(model_optns);
            _.defer(function() {
                model.fetch({
                    "data": query,
                    "traditional": true,
                    success:function () {
                        model.trigger('load');
                    }
                });
            });

            var view_options = _.extend({"model":model}, (model_unit.view_options || {}), (options || {}));

            console.log("viewsByUri(" + uri + "," + view_name + "):loading view");
            var view = new ViewClass(view_options);
            $el.html(view.render().el);
            return view;
        }
        return null;
    },

    loadCancerList: function(txt) {
        var cancerList = txt.trim().split("\n");
        var UL = $(".cancer-selector");
        _.each(cancerList, function(cancerItem, idx) {
            UL.append(LineItemTemplate({"li_class":"active","a_class":"toggle-active","id":cancerItem,"label":cancerItem}));
        });

        UL.find(".toggle-active").click(function(e) {
            $(e.target).parent().toggleClass("active");
        });
    },

    initGeneTypeahead: function(txt) {
        var genelist = txt.trim().split("\n");

        var UL = $(".gene-selector");
        $(".genes-typeahead").typeahead({
            source:function (q, p) {
                p(_.compact(_.flatten(_.map(q.toLowerCase().split(" "), function (qi) {
                    return _.map(genelist, function (geneitem) {
                        if (geneitem.toLowerCase().indexOf(qi) >= 0) return geneitem;
                    });
                }))));
            },

            updater:function (gene) {
                UL.append(LineItemTemplate({ "label":gene, "id":gene, "a_class":"item-remover", "i_class":"icon-trash" }));
                UL.find(".item-remover").click(function(e) {
                    $(e.target).parent().remove();
                });
                return "";
            }
        });

        UL.find(".item-remover").click(function(e) {
            $(e.target).parent().remove();
        });
    },

    zoom: function(level) {
        // TODO : Figure out way to center screen on where the mouse has clicked
        $(".atlas-zoom").zoomTo({
            "duration":1000,
            "scalemode": "both",
            "easing": "ease",
            "nativeanimation": true,
            "root": $(".atlas-canvas"),
            "closeclick": false,
            "targetsize":level
        });
    }
});<|endoftext|>


<commit_before>'use strict';

// A place to hold default settings. Useful so environments can reference the defaults when they override

var crypto = require('crypto');
var bunyan = require('bunyan');
var PrettyStream = require('bunyan-prettystream');

var prettyStdOut = new PrettyStream({
  mode: 'short' // 'long' is useful if you want to see PID and/or hostname
});
prettyStdOut.pipe(process.stdout);

var env = process.env.NODE_ENV || 'development';

var createLogger = function (name) {
  return bunyan.createLogger({
    name: name,
    serializers: bunyan.stdSerializers,
    streams: [
      // human-readable output on stdout
      {
        level: 'debug',
        type: 'raw',
        stream: prettyStdOut
      },

      // machine-readable output in log file
      {
        level: 'info',
        type: 'rotating-file',
        path: __dirname + '/../../logs/' + name + '.log',
        period: '1d', // rotate daily, bunyan doesn't support size-based rotation :(
        count: 3 // number of back copies
      }
    ]
  });
};

var logger = createLogger('fracas');

function ElasticSearchLogger () {
  var logger = createLogger('elasticsearch');

  this.error = logger.error.bind(logger);
  this.warning = logger.warn.bind(logger);
  this.info = logger.info.bind(logger);
  this.debug = logger.debug.bind(logger);
  this.trace = function (method, requestUrl, body, responseBody, responseStatus) {
    logger.trace({
      method: method,
      requestUrl: requestUrl,
      body: body,
      responseBody: responseBody,
      responseStatus: responseStatus
    });
  };
  this.close = function () {};
}

module.exports = {
  env: env,
  port: process.env.PORT || 9000,
  logger: logger,

  // Connect session middleware secret: http://www.senchalabs.org/connect/session.html
  // Using a random secret means sessions won't be preserved across server restarts, but we'd need a persistent
  // session store for that anyway
  sessionSecret: crypto.randomBytes(1024).toString('hex'),

  // Base port for PhantomJS cluster. Worker n is assigned phantomBasePort + n, e.g. 12301 for the first worker.
  // 12300 is the default port number used by phantom-cluster. We specify it here in case they ever change it.
  // https://github.com/dailymuse/phantom-cluster/blob/87ebc9f2c5fc81792aa4c98ae1c6cf44c784cc5e/index.coffee#L105
  phantomBasePort: 12300,

  // elasticsearch settings, duh
  elasticsearch: {
    host: 'http://localhost:9200',
    log: ElasticSearchLogger,
    apiVersion: '1.0'
  },

  // Database settings. Fracas doesn't use a relational database, but we still need connection info for things like
  // importing data. If you're not using a features that require connecting to a DB, then you can skip this.
  db: {
    url: 'jdbc:postgresql://localhost:5432/fracas',
    user: 'postgres',
    password: '',
    driver: 'org.postgresql.Driver'
  }
};
<commit_msg>Disable log rotation for now<commit_after>'use strict';

// A place to hold default settings. Useful so environments can reference the defaults when they override

var crypto = require('crypto');
var bunyan = require('bunyan');
var PrettyStream = require('bunyan-prettystream');

var prettyStdOut = new PrettyStream({
  mode: 'short' // 'long' is useful if you want to see PID and/or hostname
});
prettyStdOut.pipe(process.stdout);

var env = process.env.NODE_ENV || 'development';

var createLogger = function (name) {
  return bunyan.createLogger({
    name: name,
    serializers: bunyan.stdSerializers,
    streams: [
      // human-readable output on stdout
      {
        level: 'debug',
        type: 'raw',
        stream: prettyStdOut
      }

      // TODO machine-readable output in log file
      // We need log rotation, but bunyan's implementation has issues
      // (see https://github.com/trentm/node-bunyan/pull/97 for example). Log rotation is a big enough problem that
      // it should be handled independently, e.g. by logrotate on Linux. All the more reason to deploy to a managed
      // container.
    ]
  });
};

var logger = createLogger('fracas');

function ElasticSearchLogger () {
  var logger = createLogger('elasticsearch');

  this.error = logger.error.bind(logger);
  this.warning = logger.warn.bind(logger);
  this.info = logger.info.bind(logger);
  this.debug = logger.debug.bind(logger);
  this.trace = function (method, requestUrl, body, responseBody, responseStatus) {
    logger.trace({
      method: method,
      requestUrl: requestUrl,
      body: body,
      responseBody: responseBody,
      responseStatus: responseStatus
    });
  };
  this.close = function () {};
}

module.exports = {
  env: env,
  port: process.env.PORT || 9000,
  logger: logger,

  // Connect session middleware secret: http://www.senchalabs.org/connect/session.html
  // Using a random secret means sessions won't be preserved across server restarts, but we'd need a persistent
  // session store for that anyway
  sessionSecret: crypto.randomBytes(1024).toString('hex'),

  // Base port for PhantomJS cluster. Worker n is assigned phantomBasePort + n, e.g. 12301 for the first worker.
  // 12300 is the default port number used by phantom-cluster. We specify it here in case they ever change it.
  // https://github.com/dailymuse/phantom-cluster/blob/87ebc9f2c5fc81792aa4c98ae1c6cf44c784cc5e/index.coffee#L105
  phantomBasePort: 12300,

  // elasticsearch settings, duh
  elasticsearch: {
    host: 'http://localhost:9200',
    log: ElasticSearchLogger,
    apiVersion: '1.0'
  },

  // Database settings. Fracas doesn't use a relational database, but we still need connection info for things like
  // importing data. If you're not using a features that require connecting to a DB, then you can skip this.
  db: {
    url: 'jdbc:postgresql://localhost:5432/fracas',
    user: 'postgres',
    password: '',
    driver: 'org.postgresql.Driver'
  }
};
<|endoftext|>


<commit_before>var data;
var order_html = "\

\

\
            link\

\

\

2015/12/31
\

\

\

asdasd
\

\

\

\

\
                    \
                        寄送日期：\
                    \
                    \

\

\
                    \
                        寄送地址：\
                    \
                    \

\

\

\

\
                    \
                        匯款日期：\
                    \
                    \

\

\
                    \
                        匯款帳戶：\
                    \
                    \

\

\

\

\

\
";

var chip_html = "\

\

\

\

CHIP
\

\

\

\

\

\

\

單價
\

\

\

\

\

\

\

數量
\

\

\

\

\

\

\

總價 (單價X數量)
\

\

\

\

\

\
"
var data_list = []
var current_data_index;
$.get("/user_history_digikey/", function(d){
    list = JSON.parse(d);
    list = list.reverse();
    $(document).ready(function(){
        order_list = $("#order-list")
        for (var i = 0; i < list.length; i ++){
            order_list.append(order_html);
        }
        counter = 0
        $('.order').each(function(index){
            var item = $(this)
            $.get("/order_info_digikey?UUID=" + list[index], function(d){
                data = JSON.parse(d)
                data_list[index] = data
                counter += 1
                item.find('.order-date').each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    $(this).text(text);
                })

                item.find('.order-price').each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    text = '$ ' + text;
                    $(this).text(text);
                })

                item.find(".sent").each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    if (!text || text == "None"){
                        text = "尚未寄送";
                    }
                    $(this).text(text);
                })
                item.find(".paid").each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    if (!text || text == "None"){
                        text = "尚未付款";
                    }
                    $(this).text(text);
                })
                item.find(".order-info-link").attr("index", index)

                if(counter == list.length){
                    addEventForLinks()
                }
            })
        })
        //$("label[type=shipping_address]").each(function(index){
            //console.log(data[index]['shipping_address'])
        //})
        $('#order-info').bind("mousewheel DOMMouseScroll", function(e) {
            var scrollTo = null;
            if (e.type == 'mousewheel') {
                scrollTo = (e.originalEvent.wheelDelta * -1);
            } else if (e.type == 'DOMMouseScroll') {
                scrollTo = 1000 * e.originalEvent.detail;
            }

            if (scrollTo) {
                e.preventDefault();
                $(this).scrollTop(scrollTo + $(this).scrollTop());
            }
        });
    })

    $(document).on('keyup',function(evt) {
        if (evt.keyCode == 27) {
            $("#order-info").hide();
            disableEditPaidInfoMode();
        }
    });

    $("#close-order-info").click(function(){
        $("#order-info").hide();
        disableEditPaidInfoMode();
    })

    $("#paid-info-button").click(function(e){
        button = $(this)
        action = button.attr("action")
        if(action == "edit"){
            editPaidInfo();
        }else if (action == "save"){
            sendPaidInfo();
        }
    })

})
function addEventForLinks(){
    $(".order-info-link").click(function(e){
        $(".chip").remove()
        var ind = $(this).attr("index")
        $("#info-shipping-address").text(data_list[ind]["shipping_address"])
        $("#info-sent-date").text(data_list[ind]["sent_date"])
        $("#info-net").text(data_list[ind]["net"])
        if(data_list[ind]["paid_account"] == "None"){
            $("#info-paid-date").text("尚未填寫")
        }else{
            $("#info-paid-date").text(data_list[ind]["paid_date"])
        }
        if(data_list[ind]["paid_account"] == null){
            $("#info-paid-account").text("尚未填寫")
        }else{
            $("#info-paid-account").text(data_list[ind]["paid_account"])
        }

        current_data_index = ind;
        showChipList(ind);
    })

}

function showChipList(ind){
        for (var i = 0; i < data_list[ind]['components'].length; i ++){
            $("#chip-list").append(chip_html)
        }
        $("#chip-list .chip").each(function(){
            var chip = $(this)
            var comp = data_list[ind]['components'][chip.index()]
            chip.find(".part-number").text(comp['part_number'])
            chip.find(".unit-price").text(comp['unit_price'])
            chip.find(".quantity").text(comp['quantity'])
            chip.find(".chip-total-price").text(comp['quantity'] * comp['unit_price'])
        })
        $("#order-info").show()
}

function editPaidInfo(){
    $("#info-paid-account").prop("contenteditable", true);
    $("#info-paid-account").css("box-shadow", "0 0 2px 0px #0000cc");
    $("#info-paid-date").prop("contenteditable", true);
    $("#info-paid-date").css("box-shadow", "0 0 2px 0px #0000cc");
    button.text("儲存");
    button.attr("action", "save")
}

function sendPaidInfo(){
    var oid = data_list[current_data_index]['uuid'];
    var account = $("#info-paid-account").text();
    var date = new Date($("#info-paid-date").text());
    var month = date.getMonth() + 1;
    var day = date.getDate();
    if (!isNaN(month) && !isNaN(day)){
        $.get("http://127.0.0.1:8000/pay_digikey/",
            {'OID': oid, 'PACCOUNT': account, 'PMONTH': month, 'PDAY': day})
            .success(function(d){
                disableEditPaidInfoMode();
            })
            .error(function(d){
                alert("儲存失敗");
            })
    }else{
        alert("錯誤的日期格式")
    }
}

function disableEditPaidInfoMode(){
    $("#info-paid-account").prop("contenteditable", false);
    $("#info-paid-account").css("box-shadow", "");
    $("#info-paid-date").prop("contenteditable", false);
    $("#info-paid-date").css("box-shadow", "");
    button.text("編輯");
    button.attr("action", "edit")
}

function parseDate(str){
    var minutes = 1000 * 60
    var hours = minutes * 60
    var days = hours * 24
    var years = days * 365
    var t = Date.parse("Jul 8, 2005")
    var y = t / years;
}
<commit_msg>The Request address should be ralative<commit_after>var data;
var order_html = "\

\

\
            link\

\

\

2015/12/31
\

\

\

asdasd
\

\

\

\

\
                    \
                        寄送日期：\
                    \
                    \

\

\
                    \
                        寄送地址：\
                    \
                    \

\

\

\

\
                    \
                        匯款日期：\
                    \
                    \

\

\
                    \
                        匯款帳戶：\
                    \
                    \

\

\

\

\

\
";

var chip_html = "\

\

\

\

CHIP
\

\

\

\

\

\

\

單價
\

\

\

\

\

\

\

數量
\

\

\

\

\

\

\

總價 (單價X數量)
\

\

\

\

\

\
"
var data_list = []
var current_data_index;
$.get("/user_history_digikey/", function(d){
    list = JSON.parse(d);
    list = list.reverse();
    $(document).ready(function(){
        order_list = $("#order-list")
        for (var i = 0; i < list.length; i ++){
            order_list.append(order_html);
        }
        counter = 0
        $('.order').each(function(index){
            var item = $(this)
            $.get("/order_info_digikey?UUID=" + list[index], function(d){
                data = JSON.parse(d)
                data_list[index] = data
                counter += 1
                item.find('.order-date').each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    $(this).text(text);
                })

                item.find('.order-price').each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    text = '$ ' + text;
                    $(this).text(text);
                })

                item.find(".sent").each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    if (!text || text == "None"){
                        text = "尚未寄送";
                    }
                    $(this).text(text);
                })
                item.find(".paid").each(function(){
                    var type = $(this).attr("type");
                    var text = data[type];
                    if (!text || text == "None"){
                        text = "尚未付款";
                    }
                    $(this).text(text);
                })
                item.find(".order-info-link").attr("index", index)

                if(counter == list.length){
                    addEventForLinks()
                }
            })
        })
        //$("label[type=shipping_address]").each(function(index){
            //console.log(data[index]['shipping_address'])
        //})
        $('#order-info').bind("mousewheel DOMMouseScroll", function(e) {
            var scrollTo = null;
            if (e.type == 'mousewheel') {
                scrollTo = (e.originalEvent.wheelDelta * -1);
            } else if (e.type == 'DOMMouseScroll') {
                scrollTo = 1000 * e.originalEvent.detail;
            }

            if (scrollTo) {
                e.preventDefault();
                $(this).scrollTop(scrollTo + $(this).scrollTop());
            }
        });
    })

    $(document).on('keyup',function(evt) {
        if (evt.keyCode == 27) {
            $("#order-info").hide();
            disableEditPaidInfoMode();
        }
    });

    $("#close-order-info").click(function(){
        $("#order-info").hide();
        disableEditPaidInfoMode();
    })

    $("#paid-info-button").click(function(e){
        button = $(this)
        action = button.attr("action")
        if(action == "edit"){
            editPaidInfo();
        }else if (action == "save"){
            sendPaidInfo();
        }
    })

})
function addEventForLinks(){
    $(".order-info-link").click(function(e){
        $(".chip").remove()
        var ind = $(this).attr("index")
        $("#info-shipping-address").text(data_list[ind]["shipping_address"])
        $("#info-sent-date").text(data_list[ind]["sent_date"])
        $("#info-net").text(data_list[ind]["net"])
        if(data_list[ind]["paid_account"] == "None"){
            $("#info-paid-date").text("尚未填寫")
        }else{
            $("#info-paid-date").text(data_list[ind]["paid_date"])
        }
        if(data_list[ind]["paid_account"] == null){
            $("#info-paid-account").text("尚未填寫")
        }else{
            $("#info-paid-account").text(data_list[ind]["paid_account"])
        }

        current_data_index = ind;
        showChipList(ind);
    })

}

function showChipList(ind){
        for (var i = 0; i < data_list[ind]['components'].length; i ++){
            $("#chip-list").append(chip_html)
        }
        $("#chip-list .chip").each(function(){
            var chip = $(this)
            var comp = data_list[ind]['components'][chip.index()]
            chip.find(".part-number").text(comp['part_number'])
            chip.find(".unit-price").text(comp['unit_price'])
            chip.find(".quantity").text(comp['quantity'])
            chip.find(".chip-total-price").text(comp['quantity'] * comp['unit_price'])
        })
        $("#order-info").show()
}

function editPaidInfo(){
    $("#info-paid-account").prop("contenteditable", true);
    $("#info-paid-account").css("box-shadow", "0 0 2px 0px #0000cc");
    $("#info-paid-date").prop("contenteditable", true);
    $("#info-paid-date").css("box-shadow", "0 0 2px 0px #0000cc");
    button.text("儲存");
    button.attr("action", "save")
}

function sendPaidInfo(){
    var oid = data_list[current_data_index]['uuid'];
    var account = $("#info-paid-account").text();
    var date = new Date($("#info-paid-date").text());
    var month = date.getMonth() + 1;
    var day = date.getDate();
    if (!isNaN(month) && !isNaN(day)){
        $.get("pay_digikey/",
            {'OID': oid, 'PACCOUNT': account, 'PMONTH': month, 'PDAY': day})
            .success(function(d){
                disableEditPaidInfoMode();
            })
            .error(function(d){
                alert("儲存失敗");
            })
    }else{
        alert("錯誤的日期格式")
    }
}

function disableEditPaidInfoMode(){
    $("#info-paid-account").prop("contenteditable", false);
    $("#info-paid-account").css("box-shadow", "");
    $("#info-paid-date").prop("contenteditable", false);
    $("#info-paid-date").css("box-shadow", "");
    button.text("編輯");
    button.attr("action", "edit")
}

function parseDate(str){
    var minutes = 1000 * 60
    var hours = minutes * 60
    var days = hours * 24
    var years = days * 365
    var t = Date.parse("Jul 8, 2005")
    var y = t / years;
}
<|endoftext|>


<commit_before>import Component from '@ember/component';

export default Component.extend({
  displayedColumnsPanel: false,
  hasToggleableColumns: false,

  handleClick(event) {
    if (event.target.closest('.button-column-visibility-panel')) {
      this.toggleProperty('displayedColumnsPanel');
    }
    else {
      this.set('displayedColumnsPanel', false);
    }
  },

  init(){
    this._super();

    this.set('bindHandleClick', this.get('handleClick').bind(this));
  },

  willInsertElement() {
    document.addEventListener('click', this.get('bindHandleClick'), false);
  },

  willDestroyElement(){
    document.removeEventListener('click', this.get('bindHandleClick'), false);
  }
});
<commit_msg>Fix panel close when click on it<commit_after>import Component from '@ember/component';

export default Component.extend({
  displayedColumnsPanel: false,
  hasToggleableColumns: false,

  handleClick(event) {
    if (event.target.closest('.button-column-visibility-panel') != null) {
      this.toggleProperty('displayedColumnsPanel');
    }
    else if (event.target.closest('.side-panel--appearance') == null) {
      this.set('displayedColumnsPanel', false);
    }
  },

  init(){
    this._super();

    this.set('bindHandleClick', this.get('handleClick').bind(this));
  },

  willInsertElement() {
    document.addEventListener('click', this.get('bindHandleClick'), false);
  },

  willDestroyElement(){
    document.removeEventListener('click', this.get('bindHandleClick'), false);
  }
});
<|endoftext|>


<commit_before>(function(window, Models) {

  function Browser() {
    var self = this;

    self._isMobileSafariStandalone = function() {
      return self.isMobileSafari && window.navigator.standalone;
    };

  }

  Browser.prototype.isChromeiOS = function() {
    return (/CriOS\/\S+ Mobile\/\S+ Safari\//).test(window.navigator.userAgent);
  };

  Browser.prototype.isMobileSafari = function() {
    return (/Version\/\S+ Mobile\/\w+ Safari\//).test(window.navigator.userAgent);
  };

  Browser.prototype.canScanCode = function() {
    return (this.isMobileSafari() || this.isChromeiOS) && !this._isMobileSafariStandalone();
  };

  Browser.prototype.hasCryptoGetRandomValues = function() {
    var crypto = window.crypto || window.msCrypto;

    if (crypto && crypto.getRandomValues) {
      return true;
    } else {
      return false;
    }
  };

  Browser.prototype.canUseLocalStorage = function() {
    var result = true;

    try {
      localStorage.setItem('localStorageCheck', '');
    } catch(e) {
      result = false;
    }

    return result;
  };

  Models.browser = new Browser();
})(window, CoinPocketApp.Models);
<commit_msg>Fix scan code button<commit_after>(function(window, Models) {

  function Browser() {
    var self = this;

    self._isMobileSafariStandalone = function() {
      return self.isMobileSafari() && window.navigator.standalone;
    };

  }

  Browser.prototype.isChromeiOS = function() {
    return (/CriOS\/\S+ Mobile\/\S+ Safari\//).test(window.navigator.userAgent);
  };

  Browser.prototype.isMobileSafari = function() {
    return (/Version\/\S+ Mobile\/\w+ Safari\//).test(window.navigator.userAgent);
  };

  Browser.prototype.canScanCode = function() {
    return (this.isMobileSafari() || this.isChromeiOS()) && !this._isMobileSafariStandalone();
  };

  Browser.prototype.hasCryptoGetRandomValues = function() {
    var crypto = window.crypto || window.msCrypto;

    if (crypto && crypto.getRandomValues) {
      return true;
    } else {
      return false;
    }
  };

  Browser.prototype.canUseLocalStorage = function() {
    var result = true;

    try {
      localStorage.setItem('localStorageCheck', '');
    } catch(e) {
      result = false;
    }

    return result;
  };

  Models.browser = new Browser();
})(window, CoinPocketApp.Models);
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp.node', ['ngRoute', 'drupalService'])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/node', {
            templateUrl: 'node/node.html',
            controller: 'NodeCtrl'
        });
    }])

    .controller('NodeCtrl', function ($scope, $http, Node, User, TaxonomyTerm) {
        var anonymousUser = {
            name: [
                {
                    value: "Anonymous"
                }
            ]
        };

        // Bind tags globally to be usable to print next to each node.
        $scope.tags = {};
        $scope.breadcrumb = [
            {
                path: '',
                title: 'Home'
            }, {
                path: '#node',
                title: 'Node'
            }
        ];

        $scope.nodes = Node.query({}, function (nodes) {
            for (var i = 0; i < $scope.nodes.length; i++) {
                if ($scope.nodes[i].uid[0].target_id == 0) {
                    $scope.nodes[i].user = anonymousUser;
                } else {
                    $scope.nodes[i].user = User.get({uid: $scope.nodes[i].uid[0].target_id})
                }

                $scope.nodes[i].field_tags.forEach(function (element, index, array) {
                    if ($scope.tags[element.target_id] == undefined) {
                        $scope.tags[element.target_id] = TaxonomyTerm.get({tid: element.target_id});
                    }
                });
            }
        });
    });
<commit_msg>Added delete node.<commit_after>'use strict';

angular.module('myApp.node', ['ngRoute', 'drupalService'])

    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/node', {
            templateUrl: 'node/node.html',
            controller: 'NodeCtrl'
        });
    }])

    .controller('NodeCtrl', function ($scope, $http, Node, User, TaxonomyTerm) {
        var anonymousUser = {
            name: [
                {
                    value: "Anonymous"
                }
            ]
        };

        // Bind tags globally to be usable to print next to each node.
        $scope.tags = {};
        $scope.breadcrumb = [
            {
                path: '',
                title: 'Home'
            }, {
                path: '#node',
                title: 'Node'
            }
        ];

        $scope.deleteNode = function (nid) {
            Node.delete({nid: nid[0].value}, $scope.newComment, function (response) {
                // Comment posted, refresh the comment list
                $scope.nodes = Node.query({});
            });
        };

        $scope.nodes = Node.query({}, function (nodes) {
            for (var i = 0; i < $scope.nodes.length; i++) {
                if ($scope.nodes[i].uid[0].target_id == 0) {
                    $scope.nodes[i].user = anonymousUser;
                } else {
                    $scope.nodes[i].user = User.get({uid: $scope.nodes[i].uid[0].target_id})
                }

                $scope.nodes[i].field_tags.forEach(function (element, index, array) {
                    if ($scope.tags[element.target_id] == undefined) {
                        $scope.tags[element.target_id] = TaxonomyTerm.get({tid: element.target_id});
                    }
                });
            }
        });
    });
<|endoftext|>


<commit_before>import $ from "jquery";

import * as blueslip from "./blueslip";
import * as channel from "./channel";
import {$t_html} from "./i18n";
import * as loading from "./loading";
import * as message_flags from "./message_flags";
import * as message_list from "./message_list";
import * as message_lists from "./message_lists";
import * as message_live_update from "./message_live_update";
import * as message_store from "./message_store";
import * as message_viewport from "./message_viewport";
import * as notifications from "./notifications";
import * as people from "./people";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as ui_report from "./ui_report";
import * as unread from "./unread";
import * as unread_ui from "./unread_ui";

const NUM_OF_MESSAGES_UPDATED_PER_BATCH = 5000;
let loading_indicator_displayed = false;

export function mark_all_as_read(args = {}) {
    args = {
        anchor: "first_unread",
        include_anchor: true,
        messages_read_till_now: 0,
        ...args,
    };
    const request = {
        anchor: args.anchor,
        include_anchor: args.include_anchor,
        num_before: 0,
        num_after: NUM_OF_MESSAGES_UPDATED_PER_BATCH,
        op: "add",
        flag: "read",
        // Since there's a database index on is:unread, it's a fast
        // search query and thus worth including here as an optimization.
        narrow: JSON.stringify([{operator: "is", operand: "unread", negated: false}]),
    };
    channel.post({
        url: "/json/messages/flags/narrow",
        data: request,
        success(data) {
            const messages_read_till_now = args.messages_read_till_now + data.updated_count;

            if (!data.found_newest) {
                // If we weren't able to make everything as read in a
                // single API request, then show a loading indicator.
                ui_report.loading(
                    $t_html(
                        {defaultMessage: "Working… {N} messages marked as read so far."},
                        {N: messages_read_till_now},
                    ),
                    $("#request-progress-status-banner"),
                );
                if (!loading_indicator_displayed) {
                    loading.make_indicator(
                        $("#request-progress-status-banner .loading-indicator"),
                        {abs_positioned: true},
                    );
                    loading_indicator_displayed = true;
                }

                mark_all_as_read({
                    include_anchor: false,
                    anchor: data.last_processed_id,
                    messages_read_till_now,
                });
            } else {
                if (loading_indicator_displayed) {
                    // Only show the success message if a progress banner was displayed.
                    ui_report.loading(
                        $t_html(
                            {defaultMessage: "Done! {N} messages marked as read."},
                            {N: messages_read_till_now},
                        ),
                        $("#request-progress-status-banner"),
                        true,
                    );
                    loading_indicator_displayed = false;
                }

                if (unread.old_unreads_missing) {
                    // In the rare case that the user had more than
                    // 50K total unreads on the server, the client
                    // won't have known about all of them; this was
                    // communicated to the client via
                    // unread.old_unreads_missing.
                    //
                    // However, since we know we just marked
                    // **everything** as read, we know that we now
                    // have a correct data set of unreads.
                    unread.clear_old_unreads_missing();
                    blueslip.log("Cleared old_unreads_missing after bankruptcy.");
                }
            }
        },
        error(xhr) {
            // If we hit the rate limit, just continue without showing any error.
            if (xhr.responseJSON.code === "RATE_LIMIT_HIT") {
                const milliseconds_to_wait = 1000 * xhr.responseJSON["retry-after"];
                setTimeout(() => mark_all_as_read(args), milliseconds_to_wait);
            } else {
                // TODO: Ideally this would be a ui_report.error();
                // the user needs to know that our operation failed.
                blueslip.error("Failed to mark messages as read: " + xhr.responseText);
            }
        },
    });
}

function process_newly_read_message(message, options) {
    for (const msg_list of message_lists.all_rendered_message_lists()) {
        msg_list.show_message_as_read(message, options);
    }
    notifications.close_notification(message);
    recent_topics_ui.update_topic_unread_count(message);
}

export function mark_as_unread_from_here(
    message_id,
    include_message = true,
    messages_marked_unread_till_now = 0,
    narrow,
) {
    if (narrow === undefined) {
        narrow = JSON.stringify(message_lists.current.data.filter.operators());
    }
    message_lists.current.prevent_reading();
    const opts = {
        anchor: message_id,
        include_anchor: include_message,
        num_before: 0,
        num_after: NUM_OF_MESSAGES_UPDATED_PER_BATCH,
        narrow,
        op: "remove",
        flag: "read",
    };
    channel.post({
        url: "/json/messages/flags/narrow",
        data: opts,
        success(data) {
            messages_marked_unread_till_now += data.updated_count;

            if (!data.found_newest) {
                // If we weren't able to complete the request fully in
                // the current batch, show a progress indicator.
                ui_report.loading(
                    $t_html(
                        {
                            defaultMessage: "Working… {N} messages marked as unread so far.",
                        },
                        {N: messages_marked_unread_till_now},
                    ),
                    $("#request-progress-status-banner"),
                );
                if (!loading_indicator_displayed) {
                    loading.make_indicator(
                        $("#request-progress-status-banner .loading-indicator"),
                        {abs_positioned: true},
                    );
                    loading_indicator_displayed = true;
                }
                mark_as_unread_from_here(
                    data.last_processed_id,
                    false,
                    messages_marked_unread_till_now,
                    narrow,
                );
            } else if (loading_indicator_displayed) {
                // If we were showing a loading indicator, then
                // display that we finished. For the common case where
                // the operation succeeds in a single batch, we don't
                // bother distracting the user with the indication;
                // the success will be obvious from the UI updating.
                loading_indicator_displayed = false;
                ui_report.loading(
                    $t_html(
                        {
                            defaultMessage:
                                "Done! {messages_marked_unread_till_now} messages marked as unread.",
                        },
                        {messages_marked_unread_till_now},
                    ),
                    $("#request-progress-status-banner"),
                    true,
                );
            }
        },
        error(xhr) {
            // If we hit the rate limit, just continue without showing any error.
            if (xhr.responseJSON.code === "RATE_LIMIT_HIT") {
                const milliseconds_to_wait = 1000 * xhr.responseJSON["retry-after"];
                setTimeout(
                    () =>
                        mark_as_unread_from_here(
                            message_id,
                            false,
                            messages_marked_unread_till_now,
                            narrow,
                        ),
                    milliseconds_to_wait,
                );
            } else {
                // TODO: Ideally, this case would communicate the
                // failure to the user, with some manual retry
                // offered, since the most likely cause is a 502.
                blueslip.error("Unexpected error marking messages as unread: " + xhr.responseText);
            }
        },
    });
}

export function resume_reading() {
    message_lists.current.resume_reading();
}

export function process_read_messages_event(message_ids) {
    /*
        This code has a lot in common with notify_server_messages_read,
        but there are subtle differences due to the fact that the
        server can tell us about unread messages that we didn't
        actually read locally (and which we may not have even
        loaded locally).
    */
    const options = {from: "server"};

    message_ids = unread.get_unread_message_ids(message_ids);
    if (message_ids.length === 0) {
        return;
    }

    for (const message_id of message_ids) {
        if (message_lists.current === message_list.narrowed) {
            // I'm not sure this entirely makes sense for all server
            // notifications.
            unread.set_messages_read_in_narrow(true);
        }

        unread.mark_as_read(message_id);

        const message = message_store.get(message_id);

        if (message) {
            process_newly_read_message(message, options);
        }
    }

    unread_ui.update_unread_counts();
}

export function process_unread_messages_event({message_ids, message_details}) {
    // This is the reverse of  process_unread_messages_event.
    message_ids = unread.get_read_message_ids(message_ids);
    if (message_ids.length === 0) {
        return;
    }

    if (message_lists.current === message_list.narrowed) {
        unread.set_messages_read_in_narrow(false);
    }

    for (const message_id of message_ids) {
        const message = message_store.get(message_id);

        if (message) {
            message.unread = true;
        }

        const message_info = message_details[message_id];

        let user_ids_string;

        if (message_info.type === "private") {
            user_ids_string = people.pm_lookup_key_from_user_ids(message_info.user_ids);
        }

        unread.process_unread_message({
            id: message_id,
            mentioned: message_info.mentioned,
            stream_id: message_info.stream_id,
            topic: message_info.topic,
            type: message_info.type,
            unread: true,
            user_ids_string,
        });

        if (message_info.type === "stream") {
            // TODO: Rather than passing a fake partial message, we
            // should probably define a proper type for unread message
            // data where we don't have the full message object, that
            // we can use both in this function and pass to recent
            // topics here.
            recent_topics_ui.update_topic_unread_count({
                stream_id: message_info.stream_id,
                topic: message_info.topic,
                type: message_info.type,
            });
        }
    }

    /*
        We use a big-hammer approach now to updating the message view.
        This is relatively harmless, since the only time we are called is
        when the user herself marks her message as unread.  But we
        do eventually want to be more surgical here, especially once we
        have a final scheme for how best to structure the HTML within
        the message to indicate read-vs.-unread.  Currently we use a
        green border, but that may change.
    */
    message_live_update.rerender_messages_view();

    if (
        !message_lists.current.can_mark_messages_read() &&
        message_lists.current.has_unread_messages()
    ) {
        unread_ui.notify_messages_remain_unread();
    }

    unread_ui.update_unread_counts();
}

// Takes a list of messages and marks them as read.
// Skips any messages that are already marked as read.
export function notify_server_messages_read(messages, options = {}) {
    messages = unread.get_unread_messages(messages);
    if (messages.length === 0) {
        return;
    }

    message_flags.send_read(messages);

    for (const message of messages) {
        if (message_lists.current === message_list.narrowed) {
            unread.set_messages_read_in_narrow(true);
        }

        unread.mark_as_read(message.id);
        process_newly_read_message(message, options);
    }

    unread_ui.update_unread_counts();
}

export function notify_server_message_read(message, options) {
    notify_server_messages_read([message], options);
}

export function process_scrolled_to_bottom() {
    if (recent_topics_util.is_visible()) {
        // First, verify the current message list is visible.
        return;
    }

    if (message_lists.current.can_mark_messages_read()) {
        mark_current_list_as_read();
        return;
    }

    // For message lists that don't support marking messages as read
    // automatically, we display a banner offering to let you mark
    // them as read manually, only if there are unreads present.
    if (message_lists.current.has_unread_messages()) {
        unread_ui.notify_messages_remain_unread();
    }
}

// If we ever materially change the algorithm for this function, we
// may need to update notifications.received_messages as well.
export function process_visible() {
    if (message_viewport.is_visible_and_focused() && message_viewport.bottom_message_visible()) {
        process_scrolled_to_bottom();
    }
}

export function mark_current_list_as_read(options) {
    notify_server_messages_read(message_lists.current.all_messages(), options);
}

export function mark_stream_as_read(stream_id, cont) {
    channel.post({
        url: "/json/mark_stream_as_read",
        data: {stream_id},
        success: cont,
    });
}

export function mark_topic_as_read(stream_id, topic, cont) {
    channel.post({
        url: "/json/mark_topic_as_read",
        data: {stream_id, topic_name: topic},
        success: cont,
    });
}

export function mark_pm_as_read(user_ids_string) {
    // user_ids_string is a stringified list of user ids which are
    // participants in the conversation other than the current
    // user. Eg: "123,124" or "123"
    const unread_msg_ids = unread.get_msg_ids_for_user_ids_string(user_ids_string);
    message_flags.mark_as_read(unread_msg_ids);
}
<commit_msg>unread_ops: Fix plural and singular forms of text.<commit_after>import $ from "jquery";

import * as blueslip from "./blueslip";
import * as channel from "./channel";
import {$t_html} from "./i18n";
import * as loading from "./loading";
import * as message_flags from "./message_flags";
import * as message_list from "./message_list";
import * as message_lists from "./message_lists";
import * as message_live_update from "./message_live_update";
import * as message_store from "./message_store";
import * as message_viewport from "./message_viewport";
import * as notifications from "./notifications";
import * as people from "./people";
import * as recent_topics_ui from "./recent_topics_ui";
import * as recent_topics_util from "./recent_topics_util";
import * as ui_report from "./ui_report";
import * as unread from "./unread";
import * as unread_ui from "./unread_ui";

const NUM_OF_MESSAGES_UPDATED_PER_BATCH = 5000;
let loading_indicator_displayed = false;

export function mark_all_as_read(args = {}) {
    args = {
        anchor: "first_unread",
        include_anchor: true,
        messages_read_till_now: 0,
        ...args,
    };
    const request = {
        anchor: args.anchor,
        include_anchor: args.include_anchor,
        num_before: 0,
        num_after: NUM_OF_MESSAGES_UPDATED_PER_BATCH,
        op: "add",
        flag: "read",
        // Since there's a database index on is:unread, it's a fast
        // search query and thus worth including here as an optimization.
        narrow: JSON.stringify([{operator: "is", operand: "unread", negated: false}]),
    };
    channel.post({
        url: "/json/messages/flags/narrow",
        data: request,
        success(data) {
            const messages_read_till_now = args.messages_read_till_now + data.updated_count;

            if (!data.found_newest) {
                // If we weren't able to make everything as read in a
                // single API request, then show a loading indicator.
                ui_report.loading(
                    $t_html(
                        {
                            defaultMessage:
                                "{N, plural, one {Working… {N} message marked as read so far.} other {Working… {N} messages marked as read so far.}}",
                        },
                        {N: messages_read_till_now},
                    ),
                    $("#request-progress-status-banner"),
                );
                if (!loading_indicator_displayed) {
                    loading.make_indicator(
                        $("#request-progress-status-banner .loading-indicator"),
                        {abs_positioned: true},
                    );
                    loading_indicator_displayed = true;
                }

                mark_all_as_read({
                    include_anchor: false,
                    anchor: data.last_processed_id,
                    messages_read_till_now,
                });
            } else {
                if (loading_indicator_displayed) {
                    // Only show the success message if a progress banner was displayed.
                    ui_report.loading(
                        $t_html(
                            {
                                defaultMessage:
                                    "{N, plural, one {Done! {N} message marked as read.} other {Done! {N} messages marked as read.}}",
                            },
                            {N: messages_read_till_now},
                        ),
                        $("#request-progress-status-banner"),
                        true,
                    );
                    loading_indicator_displayed = false;
                }

                if (unread.old_unreads_missing) {
                    // In the rare case that the user had more than
                    // 50K total unreads on the server, the client
                    // won't have known about all of them; this was
                    // communicated to the client via
                    // unread.old_unreads_missing.
                    //
                    // However, since we know we just marked
                    // **everything** as read, we know that we now
                    // have a correct data set of unreads.
                    unread.clear_old_unreads_missing();
                    blueslip.log("Cleared old_unreads_missing after bankruptcy.");
                }
            }
        },
        error(xhr) {
            // If we hit the rate limit, just continue without showing any error.
            if (xhr.responseJSON.code === "RATE_LIMIT_HIT") {
                const milliseconds_to_wait = 1000 * xhr.responseJSON["retry-after"];
                setTimeout(() => mark_all_as_read(args), milliseconds_to_wait);
            } else {
                // TODO: Ideally this would be a ui_report.error();
                // the user needs to know that our operation failed.
                blueslip.error("Failed to mark messages as read: " + xhr.responseText);
            }
        },
    });
}

function process_newly_read_message(message, options) {
    for (const msg_list of message_lists.all_rendered_message_lists()) {
        msg_list.show_message_as_read(message, options);
    }
    notifications.close_notification(message);
    recent_topics_ui.update_topic_unread_count(message);
}

export function mark_as_unread_from_here(
    message_id,
    include_message = true,
    messages_marked_unread_till_now = 0,
    narrow,
) {
    if (narrow === undefined) {
        narrow = JSON.stringify(message_lists.current.data.filter.operators());
    }
    message_lists.current.prevent_reading();
    const opts = {
        anchor: message_id,
        include_anchor: include_message,
        num_before: 0,
        num_after: NUM_OF_MESSAGES_UPDATED_PER_BATCH,
        narrow,
        op: "remove",
        flag: "read",
    };
    channel.post({
        url: "/json/messages/flags/narrow",
        data: opts,
        success(data) {
            messages_marked_unread_till_now += data.updated_count;

            if (!data.found_newest) {
                // If we weren't able to complete the request fully in
                // the current batch, show a progress indicator.
                ui_report.loading(
                    $t_html(
                        {
                            defaultMessage:
                                "{N, plural, one {Working… {N} message marked as unread so far.} other {Working… {N} messages marked as unread so far.}}",
                        },
                        {N: messages_marked_unread_till_now},
                    ),
                    $("#request-progress-status-banner"),
                );
                if (!loading_indicator_displayed) {
                    loading.make_indicator(
                        $("#request-progress-status-banner .loading-indicator"),
                        {abs_positioned: true},
                    );
                    loading_indicator_displayed = true;
                }
                mark_as_unread_from_here(
                    data.last_processed_id,
                    false,
                    messages_marked_unread_till_now,
                    narrow,
                );
            } else if (loading_indicator_displayed) {
                // If we were showing a loading indicator, then
                // display that we finished. For the common case where
                // the operation succeeds in a single batch, we don't
                // bother distracting the user with the indication;
                // the success will be obvious from the UI updating.
                loading_indicator_displayed = false;
                ui_report.loading(
                    $t_html(
                        {
                            defaultMessage:
                                "{N, plural, one {Done! {N} message marked as unread.} other {Done! {N} messages marked as unread.}}",
                        },
                        {N: messages_marked_unread_till_now},
                    ),
                    $("#request-progress-status-banner"),
                    true,
                );
            }
        },
        error(xhr) {
            // If we hit the rate limit, just continue without showing any error.
            if (xhr.responseJSON.code === "RATE_LIMIT_HIT") {
                const milliseconds_to_wait = 1000 * xhr.responseJSON["retry-after"];
                setTimeout(
                    () =>
                        mark_as_unread_from_here(
                            message_id,
                            false,
                            messages_marked_unread_till_now,
                            narrow,
                        ),
                    milliseconds_to_wait,
                );
            } else {
                // TODO: Ideally, this case would communicate the
                // failure to the user, with some manual retry
                // offered, since the most likely cause is a 502.
                blueslip.error("Unexpected error marking messages as unread: " + xhr.responseText);
            }
        },
    });
}

export function resume_reading() {
    message_lists.current.resume_reading();
}

export function process_read_messages_event(message_ids) {
    /*
        This code has a lot in common with notify_server_messages_read,
        but there are subtle differences due to the fact that the
        server can tell us about unread messages that we didn't
        actually read locally (and which we may not have even
        loaded locally).
    */
    const options = {from: "server"};

    message_ids = unread.get_unread_message_ids(message_ids);
    if (message_ids.length === 0) {
        return;
    }

    for (const message_id of message_ids) {
        if (message_lists.current === message_list.narrowed) {
            // I'm not sure this entirely makes sense for all server
            // notifications.
            unread.set_messages_read_in_narrow(true);
        }

        unread.mark_as_read(message_id);

        const message = message_store.get(message_id);

        if (message) {
            process_newly_read_message(message, options);
        }
    }

    unread_ui.update_unread_counts();
}

export function process_unread_messages_event({message_ids, message_details}) {
    // This is the reverse of  process_unread_messages_event.
    message_ids = unread.get_read_message_ids(message_ids);
    if (message_ids.length === 0) {
        return;
    }

    if (message_lists.current === message_list.narrowed) {
        unread.set_messages_read_in_narrow(false);
    }

    for (const message_id of message_ids) {
        const message = message_store.get(message_id);

        if (message) {
            message.unread = true;
        }

        const message_info = message_details[message_id];

        let user_ids_string;

        if (message_info.type === "private") {
            user_ids_string = people.pm_lookup_key_from_user_ids(message_info.user_ids);
        }

        unread.process_unread_message({
            id: message_id,
            mentioned: message_info.mentioned,
            stream_id: message_info.stream_id,
            topic: message_info.topic,
            type: message_info.type,
            unread: true,
            user_ids_string,
        });

        if (message_info.type === "stream") {
            // TODO: Rather than passing a fake partial message, we
            // should probably define a proper type for unread message
            // data where we don't have the full message object, that
            // we can use both in this function and pass to recent
            // topics here.
            recent_topics_ui.update_topic_unread_count({
                stream_id: message_info.stream_id,
                topic: message_info.topic,
                type: message_info.type,
            });
        }
    }

    /*
        We use a big-hammer approach now to updating the message view.
        This is relatively harmless, since the only time we are called is
        when the user herself marks her message as unread.  But we
        do eventually want to be more surgical here, especially once we
        have a final scheme for how best to structure the HTML within
        the message to indicate read-vs.-unread.  Currently we use a
        green border, but that may change.
    */
    message_live_update.rerender_messages_view();

    if (
        !message_lists.current.can_mark_messages_read() &&
        message_lists.current.has_unread_messages()
    ) {
        unread_ui.notify_messages_remain_unread();
    }

    unread_ui.update_unread_counts();
}

// Takes a list of messages and marks them as read.
// Skips any messages that are already marked as read.
export function notify_server_messages_read(messages, options = {}) {
    messages = unread.get_unread_messages(messages);
    if (messages.length === 0) {
        return;
    }

    message_flags.send_read(messages);

    for (const message of messages) {
        if (message_lists.current === message_list.narrowed) {
            unread.set_messages_read_in_narrow(true);
        }

        unread.mark_as_read(message.id);
        process_newly_read_message(message, options);
    }

    unread_ui.update_unread_counts();
}

export function notify_server_message_read(message, options) {
    notify_server_messages_read([message], options);
}

export function process_scrolled_to_bottom() {
    if (recent_topics_util.is_visible()) {
        // First, verify the current message list is visible.
        return;
    }

    if (message_lists.current.can_mark_messages_read()) {
        mark_current_list_as_read();
        return;
    }

    // For message lists that don't support marking messages as read
    // automatically, we display a banner offering to let you mark
    // them as read manually, only if there are unreads present.
    if (message_lists.current.has_unread_messages()) {
        unread_ui.notify_messages_remain_unread();
    }
}

// If we ever materially change the algorithm for this function, we
// may need to update notifications.received_messages as well.
export function process_visible() {
    if (message_viewport.is_visible_and_focused() && message_viewport.bottom_message_visible()) {
        process_scrolled_to_bottom();
    }
}

export function mark_current_list_as_read(options) {
    notify_server_messages_read(message_lists.current.all_messages(), options);
}

export function mark_stream_as_read(stream_id, cont) {
    channel.post({
        url: "/json/mark_stream_as_read",
        data: {stream_id},
        success: cont,
    });
}

export function mark_topic_as_read(stream_id, topic, cont) {
    channel.post({
        url: "/json/mark_topic_as_read",
        data: {stream_id, topic_name: topic},
        success: cont,
    });
}

export function mark_pm_as_read(user_ids_string) {
    // user_ids_string is a stringified list of user ids which are
    // participants in the conversation other than the current
    // user. Eg: "123,124" or "123"
    const unread_msg_ids = unread.get_msg_ids_for_user_ids_string(user_ids_string);
    message_flags.mark_as_read(unread_msg_ids);
}
<|endoftext|>