<commit_before>/*
 * Changes to this file committed after and not including commit-id: ccc0d2c5f9a5ac661e60e6eaf138de7889928b8b
 * are released under the following license:
 *
 * This file is part of Hopsworks
 * Copyright (C) 2018, Logical Clocks AB. All rights reserved
 *
 * Hopsworks is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Hopsworks is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 *
 * Changes to this file committed before and including commit-id: ccc0d2c5f9a5ac661e60e6eaf138de7889928b8b
 * are released under the following license:
 *
 * Copyright (C) 2013 - 2018, Logical Clocks AB and RISE SICS AB. All rights reserved
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

'use strict';

angular.module('hopsWorksApp')
        .controller('HomeCtrl', ['ProjectService', 'UserService',
        'ModalService', 'growl', 'ActivityService', '$q', 'TourService',
        'StorageService', '$location', '$scope',
          function (ProjectService, UserService, ModalService, growl,
          ActivityService, $q, TourService, StorageService, $location, $scope) {

            var self = this;

            self.histories = [];
            self.loadedView = false;
            self.loadedZeppelin = false;
            self.tourService = TourService;
            self.projects = [];
            self.currentPage = 1;
            self.showTours = false;
            $scope.creating = {"spark" : false, "zeppelin" : false};
            self.exampleProjectID;
            self.tours = [];
            self.tutorials = [];
            self.working = [];
            self.user = {};
            self.showTourTips = true;
            self.sortBy='-project.created';
            self.getTours = function () {
              self.tours = [
                {'name': 'Deep Learning', 'tip': 'Take a tour by creating a project and running a Deep Learning notebook!'},
                {'name': 'Spark', 'tip': 'Take a tour of Hopsworks by creating a project and running a Spark job!'},
                {'name': 'Kafka', 'tip': 'Take a tour of Hopsworks by creating a project and running a Kafka job!'},
                {'name': 'Feature Store', 'tip': 'Take a tour of Hopsworks by creating a project and creating/reading features from your own Feature Store!'}
              ];
            };

            $scope.$on('$viewContentLoaded', function () {
              self.loadedView = true;
            });

            self.getTutorials = function () {
              self.tutorials = [
                {'url': 'spark.apache.org/docs/latest/running-on-yarn.html', 'description': 'Spark on YARN'},
                {'url': 'ci.apache.org/projects/flink/flink-docs-master/setup/yarn_setup.html', 'description': 'Flink on YARN'}
              ];
            };

            $scope.isCreating = function (tourName) {
              if ($scope.creating[tourName] === true) {
                return true;
              }
              return false;
            };

            // Load all projects
            var loadProjects = function (success) {
              self.projects = success;
              self.pageSizeProjects = 10;
              self.totalPagesProjects = Math.ceil(self.projects.length / self.pageSizeProjects);
              self.totalItemsProjects = self.projects.length;
              self.currentPageProjects = 1;
            };

            var updateUIAfterChange = function (exampleProject) {
              ProjectService.query().$promise.then(function (result) {
                  if (exampleProject) {
                    self.tourService.currentStep_TourOne = 0;
                    self.tourService.KillTourOneSoon();
                  }
                  loadProjects(result);
                },
                function (error) {
                  growl.info(error, {title: 'Info', ttl: 2000});
                });
            };

            updateUIAfterChange(false);

            self.initCheckBox = function () {
              self.loadToursState().then(
                function(success) {
                  if (self.tourService.informAndTips || self.tourService.tipsOnly) {
                    self.showTourTips = true;
                  } else {
                    self.showTourTips = false;
                  }
                  StorageService.store("hopsworks-showtourtips",self.showTourTips);
                }, function(error) {
                  console.log("error");
                }
              );
            };

            self.loadToursState = function () {
                return UserService.profile().then(
                  function (success) {
                    self.user = success.data;
                    var tourState = self.user.toursState;
                    if (tourState === 0) {
                      self.tourService.setInformAndTipsState();
                    } else if (tourState === 1) {
                      self.tourService.setTipsOnlyState();
                    } else if (tourState === 2) {
                      self.tourService.setInformOnly();
                    } else if (tourState === 3) {
                      self.tourService.setShowNothingState();
                    } else {
                      self.tourService.setDefaultTourState();
                    }
                  }, function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                  });
            };

            self.disableInformBalloon = function () {
              if (self.tourService.informAndTips) {
                self.user.toursState = 1;
                self.updateProfile(self.tourService.setTipsOnlyState);
              } else if (self.tourService.informOnly) {
                self.user.toursState = 3;
                self.updateProfile(self.tourService.setShowNothingState);
              }
            };

            self.toggleTourTips = function () {
              if (self.showTourTips) {
                self.enableTourTips();
              } else {
                self.disableTourTips();
              }
              StorageService.store("hopsworks-showtourtips",self.showTourTips);
            };

            self.disableTourTips = function () {
              if (self.tourService.informAndTips) {
                self.user.toursState = 2;
                self.updateProfile(self.tourService.setInformOnly);
              } else if (self.tourService.tipsOnly) {
                self.user.toursState = 3;
                self.updateProfile(self.tourService.setShowNothingState);
              }
            };

            self.enableTourTips = function () {
              if (self.tourService.informOnly) {
                self.user.toursState = 0;
                self.updateProfile(self.tourService.setInformAndTipsState);
              } else if (self.tourService.showNothing) {
                self.user.toursState = 1;
                self.updateProfile(self.tourService.setTipsOnlyState);
              }
            };

            self.updateProfile = function (fun) {
              UserService.updateProfile(self.user).then (
                function (success) {
                  fun();
                }, function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                }
              );
            };

            self.showGettingStarted = function () {
              if (self.projects === undefined || self.projects === null || self.projects.length === 0) {
                return true;
              }
              return false;
            };

            // Create a new project
            self.newProject = function () {
              ModalService.createProject('lg').then(
                function (success) {
                  updateUIAfterChange(false);
                }, function (error) {
                  if (typeof error.data !== 'undefined' && typeof error.data.usrMsg !== 'undefined') {
                    growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                  }
              });
            };

            self.createExampleProject = function (uiTourName) {

              $scope.creating[uiTourName] = true;

              var internalTourName = '';
              if(uiTourName === 'Deep Learning') {
                internalTourName = 'Deep_Learning';
              } else {
                internalTourName = uiTourName;
              }
              if(uiTourName === 'Feature Store') {
                internalTourName = 'featurestore';
              } else {
                internalTourName = uiTourName;
              }

              if (self.showTourTips === false) {
                self.toggleTourTips();
              }

              ProjectService.example({type: internalTourName}).$promise.then(
                      function (success) {
                        $scope.creating[uiTourName] = false;
                        self.tourService.setActiveTour(internalTourName);
                        growl.success("Created Tour Project", {title: 'Success', ttl: 5000});
                        self.exampleProjectID = success.id;
                        updateUIAfterChange(true);
                        // To make sure the new project is refreshed
//                        self.showTours = false;
                        if (success.errorMsg) {
                          $scope.creating[uiTourName] = false;
                          growl.warning("some problem", {title: 'Error', ttl: 10000});
                        }
                      },
                      function (error) {
                        $scope.creating[uiTourName] = false;
                          if (typeof error.data.usrMsg !== 'undefined') {
                              growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                          } else {
                              growl.error("", {title: error.data.errorMsg, ttl: 8000});
                          }
                      }
              );
            };

            self.deleteProjectAndDatasets = function (projectId) {
              self.working[projectId] = true;
              //Clear project StorageService state
              StorageService.remove(projectId+"-tftour-finished");

              ProjectService.delete({id: projectId}).$promise.then(
                      function (success) {
                        growl.success(success.successMessage, {title: 'Success', ttl: 5000});
                        updateUIAfterChange(false);
                        if (self.tourService.currentStep_TourOne > -1) {
                          self.tourService.resetTours();
                        }
                        self.working[projectId] = false;
                      },function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                        self.working[projectId] = false;
                      }
              );
            };

            self.EnterExampleProject = function (id) {
              $location.path('/project/' + id);
              $location.replace();
              self.tourService.resetTours();
            };
          }]);
<commit_msg>[HOPSWORKS-899] Fix if clause for tours (#116)<commit_after>/*
 * Changes to this file committed after and not including commit-id: ccc0d2c5f9a5ac661e60e6eaf138de7889928b8b
 * are released under the following license:
 *
 * This file is part of Hopsworks
 * Copyright (C) 2018, Logical Clocks AB. All rights reserved
 *
 * Hopsworks is free software: you can redistribute it and/or modify it under the terms of
 * the GNU Affero General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Hopsworks is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 *
 * Changes to this file committed before and including commit-id: ccc0d2c5f9a5ac661e60e6eaf138de7889928b8b
 * are released under the following license:
 *
 * Copyright (C) 2013 - 2018, Logical Clocks AB and RISE SICS AB. All rights reserved
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

'use strict';

angular.module('hopsWorksApp')
        .controller('HomeCtrl', ['ProjectService', 'UserService',
        'ModalService', 'growl', 'ActivityService', '$q', 'TourService',
        'StorageService', '$location', '$scope',
          function (ProjectService, UserService, ModalService, growl,
          ActivityService, $q, TourService, StorageService, $location, $scope) {

            var self = this;

            self.histories = [];
            self.loadedView = false;
            self.loadedZeppelin = false;
            self.tourService = TourService;
            self.projects = [];
            self.currentPage = 1;
            self.showTours = false;
            $scope.creating = {"spark" : false, "zeppelin" : false};
            self.exampleProjectID;
            self.tours = [];
            self.tutorials = [];
            self.working = [];
            self.user = {};
            self.showTourTips = true;
            self.sortBy='-project.created';
            self.getTours = function () {
              self.tours = [
                {'name': 'Deep Learning', 'tip': 'Take a tour by creating a project and running a Deep Learning notebook!'},
                {'name': 'Spark', 'tip': 'Take a tour of Hopsworks by creating a project and running a Spark job!'},
                {'name': 'Kafka', 'tip': 'Take a tour of Hopsworks by creating a project and running a Kafka job!'},
                {'name': 'Feature Store', 'tip': 'Take a tour of Hopsworks by creating a project and creating/reading features from your own Feature Store!'}
              ];
            };

            $scope.$on('$viewContentLoaded', function () {
              self.loadedView = true;
            });

            self.getTutorials = function () {
              self.tutorials = [
                {'url': 'spark.apache.org/docs/latest/running-on-yarn.html', 'description': 'Spark on YARN'},
                {'url': 'ci.apache.org/projects/flink/flink-docs-master/setup/yarn_setup.html', 'description': 'Flink on YARN'}
              ];
            };

            $scope.isCreating = function (tourName) {
              if ($scope.creating[tourName] === true) {
                return true;
              }
              return false;
            };

            // Load all projects
            var loadProjects = function (success) {
              self.projects = success;
              self.pageSizeProjects = 10;
              self.totalPagesProjects = Math.ceil(self.projects.length / self.pageSizeProjects);
              self.totalItemsProjects = self.projects.length;
              self.currentPageProjects = 1;
            };

            var updateUIAfterChange = function (exampleProject) {
              ProjectService.query().$promise.then(function (result) {
                  if (exampleProject) {
                    self.tourService.currentStep_TourOne = 0;
                    self.tourService.KillTourOneSoon();
                  }
                  loadProjects(result);
                },
                function (error) {
                  growl.info(error, {title: 'Info', ttl: 2000});
                });
            };

            updateUIAfterChange(false);

            self.initCheckBox = function () {
              self.loadToursState().then(
                function(success) {
                  if (self.tourService.informAndTips || self.tourService.tipsOnly) {
                    self.showTourTips = true;
                  } else {
                    self.showTourTips = false;
                  }
                  StorageService.store("hopsworks-showtourtips",self.showTourTips);
                }, function(error) {
                  console.log("error");
                }
              );
            };

            self.loadToursState = function () {
                return UserService.profile().then(
                  function (success) {
                    self.user = success.data;
                    var tourState = self.user.toursState;
                    if (tourState === 0) {
                      self.tourService.setInformAndTipsState();
                    } else if (tourState === 1) {
                      self.tourService.setTipsOnlyState();
                    } else if (tourState === 2) {
                      self.tourService.setInformOnly();
                    } else if (tourState === 3) {
                      self.tourService.setShowNothingState();
                    } else {
                      self.tourService.setDefaultTourState();
                    }
                  }, function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                  });
            };

            self.disableInformBalloon = function () {
              if (self.tourService.informAndTips) {
                self.user.toursState = 1;
                self.updateProfile(self.tourService.setTipsOnlyState);
              } else if (self.tourService.informOnly) {
                self.user.toursState = 3;
                self.updateProfile(self.tourService.setShowNothingState);
              }
            };

            self.toggleTourTips = function () {
              if (self.showTourTips) {
                self.enableTourTips();
              } else {
                self.disableTourTips();
              }
              StorageService.store("hopsworks-showtourtips",self.showTourTips);
            };

            self.disableTourTips = function () {
              if (self.tourService.informAndTips) {
                self.user.toursState = 2;
                self.updateProfile(self.tourService.setInformOnly);
              } else if (self.tourService.tipsOnly) {
                self.user.toursState = 3;
                self.updateProfile(self.tourService.setShowNothingState);
              }
            };

            self.enableTourTips = function () {
              if (self.tourService.informOnly) {
                self.user.toursState = 0;
                self.updateProfile(self.tourService.setInformAndTipsState);
              } else if (self.tourService.showNothing) {
                self.user.toursState = 1;
                self.updateProfile(self.tourService.setTipsOnlyState);
              }
            };

            self.updateProfile = function (fun) {
              UserService.updateProfile(self.user).then (
                function (success) {
                  fun();
                }, function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                }
              );
            };

            self.showGettingStarted = function () {
              if (self.projects === undefined || self.projects === null || self.projects.length === 0) {
                return true;
              }
              return false;
            };

            // Create a new project
            self.newProject = function () {
              ModalService.createProject('lg').then(
                function (success) {
                  updateUIAfterChange(false);
                }, function (error) {
                  if (typeof error.data !== 'undefined' && typeof error.data.usrMsg !== 'undefined') {
                    growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                  }
              });
            };

            self.createExampleProject = function (uiTourName) {

              $scope.creating[uiTourName] = true;

              var internalTourName = '';
              if(uiTourName === 'Deep Learning') {
                internalTourName = 'Deep_Learning';
              } else if(uiTourName === 'Feature Store') {
                internalTourName = 'featurestore';
              } else {
                internalTourName = uiTourName;
              }

              if (self.showTourTips === false) {
                self.toggleTourTips();
              }

              ProjectService.example({type: internalTourName}).$promise.then(
                      function (success) {
                        $scope.creating[uiTourName] = false;
                        self.tourService.setActiveTour(internalTourName);
                        growl.success("Created Tour Project", {title: 'Success', ttl: 5000});
                        self.exampleProjectID = success.id;
                        updateUIAfterChange(true);
                        // To make sure the new project is refreshed
//                        self.showTours = false;
                        if (success.errorMsg) {
                          $scope.creating[uiTourName] = false;
                          growl.warning("some problem", {title: 'Error', ttl: 10000});
                        }
                      },
                      function (error) {
                        $scope.creating[uiTourName] = false;
                          if (typeof error.data.usrMsg !== 'undefined') {
                              growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                          } else {
                              growl.error("", {title: error.data.errorMsg, ttl: 8000});
                          }
                      }
              );
            };

            self.deleteProjectAndDatasets = function (projectId) {
              self.working[projectId] = true;
              //Clear project StorageService state
              StorageService.remove(projectId+"-tftour-finished");

              ProjectService.delete({id: projectId}).$promise.then(
                      function (success) {
                        growl.success(success.successMessage, {title: 'Success', ttl: 5000});
                        updateUIAfterChange(false);
                        if (self.tourService.currentStep_TourOne > -1) {
                          self.tourService.resetTours();
                        }
                        self.working[projectId] = false;
                      },function (error) {
                      if (typeof error.data.usrMsg !== 'undefined') {
                          growl.error(error.data.usrMsg, {title: error.data.errorMsg, ttl: 8000});
                      } else {
                          growl.error("", {title: error.data.errorMsg, ttl: 8000});
                      }
                        self.working[projectId] = false;
                      }
              );
            };

            self.EnterExampleProject = function (id) {
              $location.path('/project/' + id);
              $location.replace();
              self.tourService.resetTours();
            };
          }]);
<|endoftext|>


<commit_before>function getDataFromGithub(username) {
    var url = "https://api.github.com/search/issues?q=author:" + username + "+type:pr+created:2016-10-01T00:00:00-12:00..2016-10-31T23:59:59-12:00";

    var results = $("#results");
    results.html("");

    var loading = $("#loading");
    loading.css("display", "block");

    $.ajax(url, {
        success: function (data, status, jqxhr) {
            if (status == "success") {
                var total = $("#total");

                total.html("Total PR's: " + data.items.length);

                $.each(data.items, function (ix, item) {
                    $.ajax(item.repository_url, {
                        success: function (data2, status2, jqxhr2) {
                            results.append("
" +
                                "" + data2.name + "	" +
                                "" + item.number + "	" +
                                "" + item.title + "	" +
                                "" + item.created_at + "	" +
                                "" + (item.closed_at == null ? "open" : item.closed_at) + "	" +
                                "
");
                            loading.css("display", "none");
                        }
                    });
                });
            } else {
                results.html("
No data to show
");
                loading.css("display", "none");
            }
        },
        error: function(jqXHR, status, errorThrown){
            results.html("
No data to show
");
            loading.css("display", "none");
        }

    });
}

$(function () {
    $("#checkbutton").click(function () {
        var ghuser = $("#ghuser").val();
        if (ghuser != "") {
            getDataFromGithub(ghuser);
        }
    });
});<commit_msg>Update scripts.js<commit_after>function getDataFromGithub(username) {
    var url = "https://api.github.com/search/issues?q=author:" + username + "+type:pr+created:2016-10-01..2016-10-31";

    var results = $("#results");
    results.html("");

    var loading = $("#loading");
    loading.css("display", "block");

    $.ajax(url, {
        success: function (data, status, jqxhr) {
            if (status == "success") {
                var total = $("#total");

                total.html("Total PR's: " + data.items.length);

                $.each(data.items, function (ix, item) {
                    $.ajax(item.repository_url, {
                        success: function (data2, status2, jqxhr2) {
                            results.append("
" +
                                "" + data2.name + "	" +
                                "" + item.number + "	" +
                                "" + item.title + "	" +
                                "" + item.created_at + "	" +
                                "" + (item.closed_at == null ? "open" : item.closed_at) + "	" +
                                "
");
                            loading.css("display", "none");
                        }
                    });
                });
            } else {
                results.html("
No data to show
");
                loading.css("display", "none");
            }
        },
        error: function(jqXHR, status, errorThrown){
            results.html("
No data to show
");
            loading.css("display", "none");
        }

    });
}

$(function () {
    $("#checkbutton").click(function () {
        var ghuser = $("#ghuser").val();
        if (ghuser != "") {
            getDataFromGithub(ghuser);
        }
    });
});
<|endoftext|>


<commit_before>odoo.define('jim_telesale.new_order_widgets2', function (require) {
"use strict";
var Model = require('web.DataModel');
var NewOrderWidgets = require('telesale.new_order_widgets');
var core = require('web.core');
var _t = core._t;

var OrderWidget = NewOrderWidgets.OrderWidget.include({
    create_line_from_vals: function(product_id, line_vals){
        var added_line = this.create_line_empty(product_id);
        added_line.set('qty', line_vals.qty || 1.0);
        added_line.set('pvp', line_vals.price || 0.0);
        added_line.set('discount', line_vals.discount || 0.0);
        added_line.set('taxes_ids', line_vals.tax_ids || []);
        added_line.update_line_values();
        return added_line;
    },

    // Creates a line with product and unit seted
    create_line_empty: function(product_id){
        var added_line = this._super(product_id);
        var product_obj = this.ts_model.db.get_product_by_id(product_id);
        var description = product_obj.display_name;
        if (product_obj.description_sale){
            description = description + '\n' + product.description_sale
        }
        added_line.set('description', description);
        return added_line;
    },

});

var OrderlineWidget = NewOrderWidgets.OrderlineWidget.include({

    // Link change chained discount to method
    set_input_handlers: function() {
        this._super();
        this.$('.col-chained_discount').change(_.bind(this.set_value, this, 'chained_discount'));
        this.$('.col-chained_discount').focus(_.bind(this.click_handler, this, 'chained_discount'));

        this.$('.col-description').blur(_.bind(this.set_value, this, 'description'));
        this.$('.col-description').focus(_.bind(this.click_handler, this, 'description'));

        this.$('.col-note').blur(_.bind(this.set_value, this, 'note'));
        this.$('.col-note').focus(_.bind(this.click_handler, this, 'note'));
    },

    // Convert a chained discout like (10.5+20) in a float (20.5)
    // or returns false if something wrong.
    chained_discount2float: function(value){
        if (!value){
            return 0.0
        }
        var split_disc = value.split('+')
        var discount = 0.0
        var disc = 0
        for (var i in split_disc){
            disc = split_disc[i]
            if (isNaN(disc) || disc == "") {
               return false // Break
            }
            else{
              discount = discount + parseFloat(disc);
            }
        }
        return discount;

    },

    // Manage chained_discount
    set_value: function(key) {
        this._super(key)
        if (key == 'chained_discount'){
            var value = this.$('.col-chained_discount').val();

            var discount = this.chained_discount2float(value);
            if (!discount){
                alert(value + _t("is not a valid format for chained discount. It must be something like 23+5.2+1"));
                this.model.set('discount', 0.0);
                this.model.set('chained_discount', 0.0);
            }
            else{
                this.model.set('discount', discount);
            }
            this.refresh('chained_discount');
        }
    },

    perform_onchange: function(key){
        if (key == 'pvp'){
            this.refresh('chained_discount');
        }

        this._super(key);

        if (key == 'template'){
            var value = this.$('.col-'+key).val();
            // Case name not valid
            var template_obj = this.get_template();

            // Get product from model
            if (template_obj){
                var description = template_obj.display_name;
                this.model.set('description', description);
            }

        }

    },

    // OVERWRITED Get global stock available in product_id change
    call_product_id_change: function(product_id, add_qty){
        var self = this;

        if (!add_qty){
            add_qty = 1.0
        }

        var customer_id = self.ts_model.db.partner_name_id[self.order.get('partner')];
        var pricelist_id = self.ts_model.db.pricelist_name_id[self.order.get('pricelist')];
        var model = new Model("sale.order.line");
        return model.call("ts_product_id_change", [product_id, customer_id, pricelist_id])
        .then(function(result){
            var product_obj = self.ts_model.db.get_product_by_id(product_id);
            var uom_obj = self.ts_model.db.get_unit_by_id(product_obj.uom_id)
            var description = product_obj.display_name;
            if (product_obj.description_sale){
                description = description + '\n' + product.description_sale
            }
            self.model.set('description', description);
            self.model.set('code', product_obj.default_code || "");
            self.model.set('product', product_obj.display_name || "");
            self.model.set('taxes_ids', result.tax_id || []); //TODO poner impuestos de producto o vacio
            self.model.set('unit', self.model.ts_model.db.unit_by_id[result.product_uom].name);
            self.model.set('qty', add_qty);
            self.model.set('discount', 0.0);
            self.model.set('standard_price', result.standard_price, 0.0);
            self.model.set('pvp', self.ts_model.my_round( result.price_unit));

            var subtotal = self.model.get('pvp') * self.model.get('qty') * (1 - self.model.get('discount') / 100.0)
            self.model.set('total', self.ts_model.my_round(subtotal || 0,2));

            // ADDED
            self.model.set('global_available_stock', result.global_available_stock || 0.0)

            self.refresh('qty');
            self.$('.col-qty').select();
        });
    },

    renderElement: function() {
        // Set lqdr route_name and global_available_stock
        var prod_name = this.model.get("product");
        // var prod_name = this.$('.col-product').val();
        var product_id = this.ts_model.db.product_name_id[prod_name];
        var product_obj = false
        if (product_id){
            product_obj = this.ts_model.db.get_product_by_id(product_id);
        }
        // Get first vatiant related
        else{
            var template_obj = this.get_template();
            if (template_obj){
                product_id = template_obj.product_variant_ids[0];
                product_obj = this.ts_model.db.get_product_by_id(product_id)
            }
        }

        // Always set lqdr route name and description.
        if (product_obj){
            var lqdr = (product_obj.lqdr)  ? _t("Yes") : _t("No")

            this.model.set('lqdr', lqdr);
            this.model.set('route_name', product_obj.route_name);
        }

        //set handler for fiscount plus field.
        this._super();
    },
    control_arrow_keys: function(){
        var self=this;
        this._super()
        this.$('.col-chained_discount').keydown(function(event){
          var keyCode = event.keyCode || event.which;
          if (keyCode == 40) {  // KEY DOWWN (40)
                event.preventDefault();
                $(this).parent().parent().next().find('.col-chained_discount').select();

            }
            else if (keyCode == 38){  //KEY UP
                event.preventDefault();
                $(this).parent().parent().prev().find('.col-chained_discount').select();
            }
        });
    },
});

var DataOrderWidget = NewOrderWidgets.DataOrderWidget.include({
    // fUllOverwrited to show warning  orblocking menssage menssagge and neutral documente
    // Maybe an improvement geting warning mode and message from the customer
    // and calling super after do the warning checks
    renderElement: function () {
        var self=this;
        this._super();
        this.$('#neutral').blur(_.bind(this.set_neutral_value, this, 'neutral'))
        var current_order = this.ts_model.get('selectedOrder')
        var neutral_document = current_order.get('neutral');
        if (neutral_document) {
            this.$('#neutral').prop('checked', true);
        }
        this.$('#epd').blur(_.bind(this.set_epd_value, this, 'epd'))
        var early_payment_discount = current_order.get('epd');
    },
    set_neutral_value: function(key) {
        var value = this.$('#' + key).is(':checked');
        this.order_model.set(key, value);
    },
    set_epd_value: function(key) {
        var value = this.$('#' + key).val();
        this.order_model.set(key, value);
    },

    perform_onchange: function(key, value) {
        var self=this;
        if (!value) {return;}
        if (key == "partner"){
            var partner_id = self.ts_model.db.partner_name_id[value];

            // Not partner found in backbone model
            if (value && !partner_id){
                var alert_msg = _t("Customer name '" + value + "' does not exist");
                alert(alert_msg);
                self.order_model.set('partner', "");
                self.refresh();
                self.$('#partner').focus();
            }
            else {
                var partner_obj = self.ts_model.db.get_partner_by_id(partner_id);
                var model = new Model("sale.order");
                model.call("ts_onchange_partner_id", [partner_id])
                .then(function(result){
                    var cus_name = self.ts_model.getComplexName(partner_obj);
                    self.order_model.set('partner', cus_name);
                    self.order_model.set('partner_code', partner_obj.ref ? partner_obj.ref : "");

                    self.order_model.set('customer_comment', partner_obj.comment);
                    // TODO nan_partner_risk migrar a la 10
                    // self.order_model.set('limit_credit', self.ts_model.my_round(partner_obj.credit_limit,2));
                    // self.order_model.set('customer_debt', self.ts_model.my_round(partner_obj.credit,2));

                    self.order_model.set('comercial', partner_obj.user_id ? partner_obj.user_id[1] : "");
                    var partner_shipp_obj = self.ts_model.db.get_partner_by_id(result.partner_shipping_id);
                    var shipp_addr =self.ts_model.getComplexName(partner_shipp_obj);
                    self.order_model.set('shipp_addr', shipp_addr);
                    var pricelist_obj = self.ts_model.db.pricelist_by_id[result.pricelist_id];
                    if (pricelist_obj){
                        self.order_model.set('pricelist', pricelist_obj.name);
                    }
                    self.order_model.set('epd', result.early_payment_discount);
                    // Get alert if warning is not false
                    if (result.warning){
                        alert(result.warning);
                        if (result.mode == 'block'){
                            self.order_model.set('partner', "");
                        }

                    }
                    self.refresh();
                    // New line and VUA button when chang
                    // Only do it when partner is setted
                    // if (self.order_model.get('partner')){
                    //     $('#vua-button').click();
                    // }
                    if(self.order_model.get('orderLines').length == 0 && self.order_model.get('partner')){
                        $('.add-line-button').click()
                    }
                    else{
                        self.$('#date_order').focus();
                    }

                });
            }
        }
        else if (key == "pricelist"){
            var pricelist_id = self.ts_model.db.pricelist_name_id[value];

            // Not partner found in backbone model
            if (!pricelist_id){
                var alert_msg = _t("Pricelist name '" + value + "' does not exist");
                alert(alert_msg);
                self.order_model.set('pricelist', "");
                self.refresh();
                self.$('#pricelist').focus();
            }
        }
    },
});

var TotalsOrderWidget = NewOrderWidgets.TotalsOrderWidget.include({
    renderElement: function(){
        var self=this;
        this._super();
        this.$('.proforma-button').click(function (){ self.promoCurrentOrder() });
        this.$('.print-alm-button').click(function (){ self.printAlmOrder() });
    },
     doPrintAlm: function(erp_id){
            this.do_action({
                model: 'sale.order',
                context: {'active_ids': [erp_id]},
                data: null,
                name: 'Quotation / Order',
                report_file: 'custom_documents.custom_sale_order_report_warehouse',
                report_name: 'custom_documents.custom_sale_order_report_warehouse',
                report_type: 'qweb-pdf',
                type: 'ir.actions.report.xml'
            });
        },
    printAlmOrder: function() {
        var self = this;
        self.ts_model.ready3 = $.Deferred();
        self.print_id = false
        var current_order = this.ts_model.get('selectedOrder')
        if (current_order.get('erp_id')){
            // if (current_order.get('state') != 'draft'){
            //     self.doPrintAlm(current_order.get('erp_id'));
            //     return;
            // }
            // else{
            //     self.print_id = current_order.get('erp_id')
            // }
            self.doPrintAlm(current_order.get('erp_id'));

        }
        else{
            this.ts_widget.new_order_screen.totals_order_widget.saveCurrentOrder()
            $.when( self.ts_model.ready3 )
            .done(function(){
                // var domain = [['chanel', '=', 'telesale']]
                // if (self.print_id){
                //     domain = [['id', '=', self.print_id]]
                // }
                // var loaded = self.ts_model.fetch('sale.order', ['id', 'name'], domain)
                //    .then(function(orders){
                //        if (orders[0]) {
                //        var my_id = orders[0].id
                //        $.when( self.ts_widget.new_order_screen.order_widget.load_order_from_server(my_id) )
                //        .done(function(){
                //             var currentOrder = self.ts_model.get('selectedOrder')
                //             self.doPrint(currentOrder.get('erp_id'));
                //        });

                //      }
                //    });
                var currentOrder = self.ts_model.get('selectedOrder')
                self.doPrint(currentOrder.get('erp_id'));
            });
        }
    },

    promoCurrentOrder: function() {
        var self = this;
        var currentOrder = this.order_model;
        if ( (currentOrder.get('erp_state')) && (currentOrder.get('erp_state') != 'draft') ){
            alert(_t('You cant set proform state to an order which state is diferent than draft.'));
            return;
        }
        self.saveCurrentOrder(true)
        $.when( self.ts_model.ready2 )
        .done(function(){
            if (self.ts_model.last_sale_id){
                var domain = [['id', '=', self.ts_model.last_sale_id]]
            }
            else{
                var domain = [['chanel', '=', 'telesale'], ['user_id', '=', self.ts_model.get('user').id]]
            }
            var loaded = self.ts_model.fetch('sale.order', ['id', 'name'], domain)
                .then(function(orders){
                    if (orders[0]) {
                      (new Model('sale.order')).call('ts_action_proforma',[orders[0].id])
                          .fail(function(unused, event){
                              //don't show error popup if it fails
                              console.error('Failed confirm order: ',orders[0].name);
                          })
                          .done(function(){
                            var my_id = orders[0].id
                            $.when( self.ts_widget.new_order_screen.order_widget.load_order_from_server(my_id) )
                            .done(function(){
                                self.ts_model.last_sale_id = false
                            })
                            .fail(function(){
                                self.ts_model.last_sale_id = false
                            });
                          });

                    }
                });
         });
    },
    // Allways apply promotion when apply to server
    saveCurrentOrder: function(avoid_load) {
        var current_order = this.ts_model.get('selectedOrder')
        current_order.set('set_promotion', true)
        this._super(avoid_load);
    },

});

});
<commit_msg>[FIX]jim_telesale: Guardar siempre para imprimir<commit_after>odoo.define('jim_telesale.new_order_widgets2', function (require) {
"use strict";
var Model = require('web.DataModel');
var NewOrderWidgets = require('telesale.new_order_widgets');
var core = require('web.core');
var _t = core._t;

var OrderWidget = NewOrderWidgets.OrderWidget.include({
    create_line_from_vals: function(product_id, line_vals){
        var added_line = this.create_line_empty(product_id);
        added_line.set('qty', line_vals.qty || 1.0);
        added_line.set('pvp', line_vals.price || 0.0);
        added_line.set('discount', line_vals.discount || 0.0);
        added_line.set('taxes_ids', line_vals.tax_ids || []);
        added_line.update_line_values();
        return added_line;
    },

    // Creates a line with product and unit seted
    create_line_empty: function(product_id){
        var added_line = this._super(product_id);
        var product_obj = this.ts_model.db.get_product_by_id(product_id);
        var description = product_obj.display_name;
        if (product_obj.description_sale){
            description = description + '\n' + product.description_sale
        }
        added_line.set('description', description);
        return added_line;
    },

});

var OrderlineWidget = NewOrderWidgets.OrderlineWidget.include({

    // Link change chained discount to method
    set_input_handlers: function() {
        this._super();
        this.$('.col-chained_discount').change(_.bind(this.set_value, this, 'chained_discount'));
        this.$('.col-chained_discount').focus(_.bind(this.click_handler, this, 'chained_discount'));

        this.$('.col-description').blur(_.bind(this.set_value, this, 'description'));
        this.$('.col-description').focus(_.bind(this.click_handler, this, 'description'));

        this.$('.col-note').blur(_.bind(this.set_value, this, 'note'));
        this.$('.col-note').focus(_.bind(this.click_handler, this, 'note'));
    },

    // Convert a chained discout like (10.5+20) in a float (20.5)
    // or returns false if something wrong.
    chained_discount2float: function(value){
        if (!value){
            return 0.0
        }
        var split_disc = value.split('+')
        var discount = 0.0
        var disc = 0
        for (var i in split_disc){
            disc = split_disc[i]
            if (isNaN(disc) || disc == "") {
               return false // Break
            }
            else{
              discount = discount + parseFloat(disc);
            }
        }
        return discount;

    },

    // Manage chained_discount
    set_value: function(key) {
        this._super(key)
        if (key == 'chained_discount'){
            var value = this.$('.col-chained_discount').val();

            var discount = this.chained_discount2float(value);
            if (!discount){
                alert(value + _t("is not a valid format for chained discount. It must be something like 23+5.2+1"));
                this.model.set('discount', 0.0);
                this.model.set('chained_discount', 0.0);
            }
            else{
                this.model.set('discount', discount);
            }
            this.refresh('chained_discount');
        }
    },

    perform_onchange: function(key){
        if (key == 'pvp'){
            this.refresh('chained_discount');
        }

        this._super(key);

        if (key == 'template'){
            var value = this.$('.col-'+key).val();
            // Case name not valid
            var template_obj = this.get_template();

            // Get product from model
            if (template_obj){
                var description = template_obj.display_name;
                this.model.set('description', description);
            }

        }

    },

    // OVERWRITED Get global stock available in product_id change
    call_product_id_change: function(product_id, add_qty){
        var self = this;

        if (!add_qty){
            add_qty = 1.0
        }

        var customer_id = self.ts_model.db.partner_name_id[self.order.get('partner')];
        var pricelist_id = self.ts_model.db.pricelist_name_id[self.order.get('pricelist')];
        var model = new Model("sale.order.line");
        return model.call("ts_product_id_change", [product_id, customer_id, pricelist_id])
        .then(function(result){
            var product_obj = self.ts_model.db.get_product_by_id(product_id);
            var uom_obj = self.ts_model.db.get_unit_by_id(product_obj.uom_id)
            var description = product_obj.display_name;
            if (product_obj.description_sale){
                description = description + '\n' + product.description_sale
            }
            self.model.set('description', description);
            self.model.set('code', product_obj.default_code || "");
            self.model.set('product', product_obj.display_name || "");
            self.model.set('taxes_ids', result.tax_id || []); //TODO poner impuestos de producto o vacio
            self.model.set('unit', self.model.ts_model.db.unit_by_id[result.product_uom].name);
            self.model.set('qty', add_qty);
            self.model.set('discount', 0.0);
            self.model.set('standard_price', result.standard_price, 0.0);
            self.model.set('pvp', self.ts_model.my_round( result.price_unit));

            var subtotal = self.model.get('pvp') * self.model.get('qty') * (1 - self.model.get('discount') / 100.0)
            self.model.set('total', self.ts_model.my_round(subtotal || 0,2));

            // ADDED
            self.model.set('global_available_stock', result.global_available_stock || 0.0)

            self.refresh('qty');
            self.$('.col-qty').select();
        });
    },

    renderElement: function() {
        // Set lqdr route_name and global_available_stock
        var prod_name = this.model.get("product");
        // var prod_name = this.$('.col-product').val();
        var product_id = this.ts_model.db.product_name_id[prod_name];
        var product_obj = false
        if (product_id){
            product_obj = this.ts_model.db.get_product_by_id(product_id);
        }
        // Get first vatiant related
        else{
            var template_obj = this.get_template();
            if (template_obj){
                product_id = template_obj.product_variant_ids[0];
                product_obj = this.ts_model.db.get_product_by_id(product_id)
            }
        }

        // Always set lqdr route name and description.
        if (product_obj){
            var lqdr = (product_obj.lqdr)  ? _t("Yes") : _t("No")

            this.model.set('lqdr', lqdr);
            this.model.set('route_name', product_obj.route_name);
        }

        //set handler for fiscount plus field.
        this._super();
    },
    control_arrow_keys: function(){
        var self=this;
        this._super()
        this.$('.col-chained_discount').keydown(function(event){
          var keyCode = event.keyCode || event.which;
          if (keyCode == 40) {  // KEY DOWWN (40)
                event.preventDefault();
                $(this).parent().parent().next().find('.col-chained_discount').select();

            }
            else if (keyCode == 38){  //KEY UP
                event.preventDefault();
                $(this).parent().parent().prev().find('.col-chained_discount').select();
            }
        });
    },
});

var DataOrderWidget = NewOrderWidgets.DataOrderWidget.include({
    // fUllOverwrited to show warning  orblocking menssage menssagge and neutral documente
    // Maybe an improvement geting warning mode and message from the customer
    // and calling super after do the warning checks
    renderElement: function () {
        var self=this;
        this._super();
        this.$('#neutral').blur(_.bind(this.set_neutral_value, this, 'neutral'))
        var current_order = this.ts_model.get('selectedOrder')
        var neutral_document = current_order.get('neutral');
        if (neutral_document) {
            this.$('#neutral').prop('checked', true);
        }
        this.$('#epd').blur(_.bind(this.set_epd_value, this, 'epd'))
        var early_payment_discount = current_order.get('epd');
    },
    set_neutral_value: function(key) {
        var value = this.$('#' + key).is(':checked');
        this.order_model.set(key, value);
    },
    set_epd_value: function(key) {
        var value = this.$('#' + key).val();
        this.order_model.set(key, value);
    },

    perform_onchange: function(key, value) {
        var self=this;
        if (!value) {return;}
        if (key == "partner"){
            var partner_id = self.ts_model.db.partner_name_id[value];

            // Not partner found in backbone model
            if (value && !partner_id){
                var alert_msg = _t("Customer name '" + value + "' does not exist");
                alert(alert_msg);
                self.order_model.set('partner', "");
                self.refresh();
                self.$('#partner').focus();
            }
            else {
                var partner_obj = self.ts_model.db.get_partner_by_id(partner_id);
                var model = new Model("sale.order");
                model.call("ts_onchange_partner_id", [partner_id])
                .then(function(result){
                    var cus_name = self.ts_model.getComplexName(partner_obj);
                    self.order_model.set('partner', cus_name);
                    self.order_model.set('partner_code', partner_obj.ref ? partner_obj.ref : "");

                    self.order_model.set('customer_comment', partner_obj.comment);
                    // TODO nan_partner_risk migrar a la 10
                    // self.order_model.set('limit_credit', self.ts_model.my_round(partner_obj.credit_limit,2));
                    // self.order_model.set('customer_debt', self.ts_model.my_round(partner_obj.credit,2));

                    self.order_model.set('comercial', partner_obj.user_id ? partner_obj.user_id[1] : "");
                    var partner_shipp_obj = self.ts_model.db.get_partner_by_id(result.partner_shipping_id);
                    var shipp_addr =self.ts_model.getComplexName(partner_shipp_obj);
                    self.order_model.set('shipp_addr', shipp_addr);
                    var pricelist_obj = self.ts_model.db.pricelist_by_id[result.pricelist_id];
                    if (pricelist_obj){
                        self.order_model.set('pricelist', pricelist_obj.name);
                    }
                    self.order_model.set('epd', result.early_payment_discount);
                    // Get alert if warning is not false
                    if (result.warning){
                        alert(result.warning);
                        if (result.mode == 'block'){
                            self.order_model.set('partner', "");
                        }

                    }
                    self.refresh();
                    // New line and VUA button when chang
                    // Only do it when partner is setted
                    // if (self.order_model.get('partner')){
                    //     $('#vua-button').click();
                    // }
                    if(self.order_model.get('orderLines').length == 0 && self.order_model.get('partner')){
                        $('.add-line-button').click()
                    }
                    else{
                        self.$('#date_order').focus();
                    }

                });
            }
        }
        else if (key == "pricelist"){
            var pricelist_id = self.ts_model.db.pricelist_name_id[value];

            // Not partner found in backbone model
            if (!pricelist_id){
                var alert_msg = _t("Pricelist name '" + value + "' does not exist");
                alert(alert_msg);
                self.order_model.set('pricelist', "");
                self.refresh();
                self.$('#pricelist').focus();
            }
        }
    },
});

var TotalsOrderWidget = NewOrderWidgets.TotalsOrderWidget.include({
    renderElement: function(){
        var self=this;
        this._super();
        this.$('.proforma-button').click(function (){ self.promoCurrentOrder() });
        this.$('.print-alm-button').click(function (){ self.printAlmOrder() });
    },
     doPrintAlm: function(erp_id){
            this.do_action({
                model: 'sale.order',
                context: {'active_ids': [erp_id]},
                data: null,
                name: 'Quotation / Order',
                report_file: 'custom_documents.custom_sale_order_report_warehouse',
                report_name: 'custom_documents.custom_sale_order_report_warehouse',
                report_type: 'qweb-pdf',
                type: 'ir.actions.report.xml'
            });
        },
    printAlmOrder: function() {
        var self = this;
        self.ts_model.ready3 = $.Deferred();
        self.print_id = false
        var current_order = this.ts_model.get('selectedOrder')
        if (current_order.get('erp_id') && false){ // No hacerlo nunca por si se modifica un presupuesto
            self.doPrintAlm(current_order.get('erp_id'));

        }
        else{
            this.ts_widget.new_order_screen.totals_order_widget.saveCurrentOrder()
            $.when( self.ts_model.ready3 )
            .done(function(){
                var currentOrder = self.ts_model.get('selectedOrder')
                self.doPrint(currentOrder.get('erp_id'));
            });
        }
    },

    promoCurrentOrder: function() {
        var self = this;
        var currentOrder = this.order_model;
        if ( (currentOrder.get('erp_state')) && (currentOrder.get('erp_state') != 'draft') ){
            alert(_t('You cant set proform state to an order which state is diferent than draft.'));
            return;
        }
        self.saveCurrentOrder(true)
        $.when( self.ts_model.ready2 )
        .done(function(){
            if (self.ts_model.last_sale_id){
                var domain = [['id', '=', self.ts_model.last_sale_id]]
            }
            else{
                var domain = [['chanel', '=', 'telesale'], ['user_id', '=', self.ts_model.get('user').id]]
            }
            var loaded = self.ts_model.fetch('sale.order', ['id', 'name'], domain)
                .then(function(orders){
                    if (orders[0]) {
                      (new Model('sale.order')).call('ts_action_proforma',[orders[0].id])
                          .fail(function(unused, event){
                              //don't show error popup if it fails
                              console.error('Failed confirm order: ',orders[0].name);
                          })
                          .done(function(){
                            var my_id = orders[0].id
                            $.when( self.ts_widget.new_order_screen.order_widget.load_order_from_server(my_id) )
                            .done(function(){
                                self.ts_model.last_sale_id = false
                            })
                            .fail(function(){
                                self.ts_model.last_sale_id = false
                            });
                          });

                    }
                });
         });
    },
    // Allways apply promotion when apply to server
    saveCurrentOrder: function(avoid_load) {
        var current_order = this.ts_model.get('selectedOrder')
        current_order.set('set_promotion', true)
        this._super(avoid_load);
    },

});

});
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert'),
    api = require('../api').create(),
    BaseHttpClient = require('./baseHttpClient'),
    promiseIt = require('../../testHelpers').promiseIt,
    port = api.port + 1,
    timeout = parseInt(process.env.MB_SLOW_TEST_TIMEOUT || 4000);

['http', 'https'].forEach(protocol => {
    const client = BaseHttpClient.create(protocol);

    describe(`${protocol} imposter`, function () {
        this.timeout(timeout);

        describe('POST /imposters with injections', function () {
            promiseIt('should allow javascript predicate for matching', function () {
                // note the lower-case keys for headers!!!
                const fn = request => request.path === '/test',
                    stub = {
                        predicates: [{ inject: fn.toString() }],
                        responses: [{ is: { body: 'MATCHED' } }]
                    },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                    const spec = {
                        path: '/test?key=value',
                        port,
                        method: 'POST',
                        headers: {
                            'X-Test': 'test header',
                            'Content-Type': 'text/plain'
                        },
                        body: 'BODY'
                    };
                    return client.responseFor(spec);
                }).then(response => {
                    assert.strictEqual(response.body, 'MATCHED');
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should not validate a bad predicate injection', function () {
                const stub = {
                        predicates: [{ inject: 'return true;' }],
                        responses: [{ is: { body: 'MATCHED' } }]
                    },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow synchronous javascript injection for responses', function () {
                const fn = request => ({ body: `${request.method} INJECTED` }),
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request)
                    .then(() => client.get('/', port))
                    .then(response => {
                        assert.strictEqual(response.body, 'GET INJECTED');
                        assert.strictEqual(response.statusCode, 200);
                        assert.strictEqual(response.headers.connection, 'close');
                    })
                    .finally(() => api.del('/imposters'));
            });

            promiseIt('should not validate a bad response injection', function () {
                const fn = () => { throw new Error('BOOM'); },
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow javascript injection to keep state between requests', function () {
                const fn = (request, state) => {
                        if (!state.calls) { state.calls = 0; }
                        state.calls += 1;
                        return { body: state.calls.toString() };
                    },
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, '1');

                    return client.get('/', port);
                }).then(response => {
                    assert.deepEqual(response.body, '2');
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow access to the global process object', function () {
                // https://github.com/bbyars/mountebank/issues/134
                const fn = () => ({ body: process.env.USER || 'test' }),
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, process.env.USER || 'test');
                }).finally(() => api.del('/imposters'));
            });

            if (process.env.MB_AIRPLANE_MODE !== 'true') {
                promiseIt('should allow asynchronous injection', function () {
                    const fn = (request, state, logger, callback) => {
                            const http = require('http'),
                                options = {
                                    method: request.method,
                                    hostname: 'www.google.com',
                                    port: 80,
                                    path: request.path,
                                    headers: request.headers
                                };

                            options.headers.host = options.hostname;
                            const httpRequest = http.request(options, response => {
                                response.body = '';
                                response.setEncoding('utf8');
                                response.on('data', chunk => {
                                    response.body += chunk;
                                });
                                response.on('end', () => {
                                    callback({
                                        statusCode: response.statusCode,
                                        headers: response.headers,
                                        body: response.body
                                    });
                                });
                            });
                            httpRequest.end();
                            // No return value!!!
                        },
                        stub = { responses: [{ inject: fn.toString() }] },
                        request = { protocol, port, stubs: [stub] };

                    return api.post('/imposters', request).then(response => {
                        assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                        return client.get('/', port);
                    }).then(response => {
                        // sometimes 301, sometimes 302
                        // 200 on new Mac with El Capitan?
                        assert.ok(response.statusCode <= 302, response.statusCode);
                        if (response.statusCode === 200) {
                            assert.ok(response.body.indexOf('google') >= 0, response.body);
                        }
                        else {
                            // google.com.br in Brasil, google.ca in Canada, etc
                            assert.ok(response.headers.location.indexOf('google.') >= 0, response.headers.location);
                        }
                    }).finally(() => api.del('/imposters'));
                });
            }
        });
    });
});
<commit_msg>Testing shared state between response and predicate injection<commit_after>'use strict';

const assert = require('assert'),
    api = require('../api').create(),
    BaseHttpClient = require('./baseHttpClient'),
    promiseIt = require('../../testHelpers').promiseIt,
    port = api.port + 1,
    timeout = parseInt(process.env.MB_SLOW_TEST_TIMEOUT || 4000);

['http', 'https'].forEach(protocol => {
    const client = BaseHttpClient.create(protocol);

    describe(`${protocol} imposter`, function () {
        this.timeout(timeout);

        describe('POST /imposters with injections', function () {
            promiseIt('should allow javascript predicate for matching', function () {
                // note the lower-case keys for headers!!!
                const fn = request => request.path === '/test',
                    stub = {
                        predicates: [{ inject: fn.toString() }],
                        responses: [{ is: { body: 'MATCHED' } }]
                    },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                    const spec = {
                        path: '/test?key=value',
                        port,
                        method: 'POST',
                        headers: {
                            'X-Test': 'test header',
                            'Content-Type': 'text/plain'
                        },
                        body: 'BODY'
                    };
                    return client.responseFor(spec);
                }).then(response => {
                    assert.strictEqual(response.body, 'MATCHED');
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should not validate a bad predicate injection', function () {
                const stub = {
                        predicates: [{ inject: 'return true;' }],
                        responses: [{ is: { body: 'MATCHED' } }]
                    },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow synchronous javascript injection for responses', function () {
                const fn = request => ({ body: `${request.method} INJECTED` }),
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request)
                    .then(() => client.get('/', port))
                    .then(response => {
                        assert.strictEqual(response.body, 'GET INJECTED');
                        assert.strictEqual(response.statusCode, 200);
                        assert.strictEqual(response.headers.connection, 'close');
                    })
                    .finally(() => api.del('/imposters'));
            });

            promiseIt('should not validate a bad response injection', function () {
                const fn = () => { throw new Error('BOOM'); },
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow javascript injection to keep state between requests', function () {
                const fn = (request, state) => {
                        if (!state.calls) { state.calls = 0; }
                        state.calls += 1;
                        return { body: state.calls.toString() };
                    },
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, '1');

                    return client.get('/', port);
                }).then(response => {
                    assert.deepEqual(response.body, '2');
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should share state with predicate and response injection', function () {
                const responseFn = (request, injectState, logger, callback, imposterState) => {
                        imposterState.calls = imposterState.calls || 0;
                        imposterState.calls += 1;
                        return { body: 'INJECT' };
                    },
                    predicateFn = (request, logger, state) => {
                        const numCalls = state.calls || 0;
                        return numCalls > 1;
                    },
                    stubs = [
                        {
                            predicates: [{ // Compound predicate because previous bug didn't pass state in and/or
                                and: [
                                    { inject: predicateFn.toString() },
                                    { equals: { path: '/' } }
                                ]
                            }],
                            responses: [{ is: { body: 'IS' } }]
                        },
                        {
                            responses: [{ inject: responseFn.toString() }]
                        }
                    ],
                    request = { protocol, port, stubs };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, 'INJECT');
                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, 'INJECT');
                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, 'IS');
                }).finally(() => api.del('/imposters'));
            });

            promiseIt('should allow access to the global process object', function () {
                // https://github.com/bbyars/mountebank/issues/134
                const fn = () => ({ body: process.env.USER || 'test' }),
                    stub = { responses: [{ inject: fn.toString() }] },
                    request = { protocol, port, stubs: [stub] };

                return api.post('/imposters', request).then(response => {
                    assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));
                    return client.get('/', port);
                }).then(response => {
                    assert.strictEqual(response.body, process.env.USER || 'test');
                }).finally(() => api.del('/imposters'));
            });

            if (process.env.MB_AIRPLANE_MODE !== 'true') {
                promiseIt('should allow asynchronous injection', function () {
                    const fn = (request, state, logger, callback) => {
                            const http = require('http'),
                                options = {
                                    method: request.method,
                                    hostname: 'www.google.com',
                                    port: 80,
                                    path: request.path,
                                    headers: request.headers
                                };

                            options.headers.host = options.hostname;
                            const httpRequest = http.request(options, response => {
                                response.body = '';
                                response.setEncoding('utf8');
                                response.on('data', chunk => {
                                    response.body += chunk;
                                });
                                response.on('end', () => {
                                    callback({
                                        statusCode: response.statusCode,
                                        headers: response.headers,
                                        body: response.body
                                    });
                                });
                            });
                            httpRequest.end();
                            // No return value!!!
                        },
                        stub = { responses: [{ inject: fn.toString() }] },
                        request = { protocol, port, stubs: [stub] };

                    return api.post('/imposters', request).then(response => {
                        assert.strictEqual(response.statusCode, 201, JSON.stringify(response.body));

                        return client.get('/', port);
                    }).then(response => {
                        // sometimes 301, sometimes 302
                        // 200 on new Mac with El Capitan?
                        assert.ok(response.statusCode <= 302, response.statusCode);
                        if (response.statusCode === 200) {
                            assert.ok(response.body.indexOf('google') >= 0, response.body);
                        }
                        else {
                            // google.com.br in Brasil, google.ca in Canada, etc
                            assert.ok(response.headers.location.indexOf('google.') >= 0, response.headers.location);
                        }
                    }).finally(() => api.del('/imposters'));
                });
            }
        });
    });
});
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 */

Viewport.Info = function ( editor ) {

	var signals = editor.signals;

	var container = new UI.Panel();
	container.setId( 'info' );
	container.setPosition( 'absolute' );
	container.setLeft( '10px' );
	container.setBottom( '10px' );
	container.setFontSize( '12px' );
	container.setColor( '#fff' );

        var smallerDim = Math.min(window.innerHeight, window.innerWidth);
        var imgDim = Math.max(smallerDim / 15, 30);
        var logo = new UI.Image('imgs/OpenSimApplicationIcon.png', imgDim, imgDim, 0.5,
                                function(img) {
                                    var smallerDim = Math.min(window.innerHeight, window.innerWidth);
                                    var imgDim = Math.max(smallerDim / 15, 30);
                                    img.dom.width = imgDim;
                                    img.dom.height = imgDim;
                                });
        var div = new UI.Div();
        div.add( logo );
        container.add( div );

	var objectsText = new UI.Text( '0' ).setMarginLeft( '6px' );
	var verticesText = new UI.Text( '0' ).setMarginLeft( '6px' );
	var trianglesText = new UI.Text( '0' ).setMarginLeft( '6px' );

	container.add( new UI.Text( 'objects' ), objectsText, new UI.Break() );
	container.add( new UI.Text( 'vertices' ), verticesText, new UI.Break() );
	container.add( new UI.Text( 'triangles' ), trianglesText, new UI.Break() );

	signals.objectAdded.add( update );
	signals.objectRemoved.add( update );
	signals.geometryChanged.add( update );

	//

	function update() {

		var scene = editor.scene;

		var objects = 0, vertices = 0, triangles = 0;

		for ( var i = 0, l = scene.children.length; i < l; i ++ ) {

			var object = scene.children[ i ];

			object.traverseVisible( function ( object ) {

				objects ++;

				if ( object instanceof THREE.Mesh ) {

					var geometry = object.geometry;

					if ( geometry instanceof THREE.Geometry ) {

						vertices += geometry.vertices.length;
						triangles += geometry.faces.length;

					} else if ( geometry instanceof THREE.BufferGeometry ) {

						if ( geometry.index !== null ) {

							vertices += geometry.index.count * 3;
							triangles += geometry.index.count;

						} else {

							vertices += geometry.attributes.position.count;
							triangles += geometry.attributes.position.count / 3;

						}

					}

				}

			} );

		}

		objectsText.setValue( objects.format() );
		verticesText.setValue( vertices.format() );
		trianglesText.setValue( triangles.format() );

	}

	return container;

}
<commit_msg>Fix path to logo file.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 */

Viewport.Info = function ( editor ) {

	var signals = editor.signals;

	var container = new UI.Panel();
	container.setId( 'info' );
	container.setPosition( 'absolute' );
	container.setLeft( '10px' );
	container.setBottom( '10px' );
	container.setFontSize( '12px' );
	container.setColor( '#fff' );

        var smallerDim = Math.min(window.innerHeight, window.innerWidth);
        var imgDim = Math.max(smallerDim / 15, 30);
        var logo = new UI.Image('icons/OpenSimApplicationIcon.png', imgDim, imgDim, 0.5,
                                function(img) {
                                    var smallerDim = Math.min(window.innerHeight, window.innerWidth);
                                    var imgDim = Math.max(smallerDim / 15, 30);
                                    img.dom.width = imgDim;
                                    img.dom.height = imgDim;
                                });
        var div = new UI.Div();
        div.add( logo );
        container.add( div );

	var objectsText = new UI.Text( '0' ).setMarginLeft( '6px' );
	var verticesText = new UI.Text( '0' ).setMarginLeft( '6px' );
	var trianglesText = new UI.Text( '0' ).setMarginLeft( '6px' );

	container.add( new UI.Text( 'objects' ), objectsText, new UI.Break() );
	container.add( new UI.Text( 'vertices' ), verticesText, new UI.Break() );
	container.add( new UI.Text( 'triangles' ), trianglesText, new UI.Break() );

	signals.objectAdded.add( update );
	signals.objectRemoved.add( update );
	signals.geometryChanged.add( update );

	//

	function update() {

		var scene = editor.scene;

		var objects = 0, vertices = 0, triangles = 0;

		for ( var i = 0, l = scene.children.length; i < l; i ++ ) {

			var object = scene.children[ i ];

			object.traverseVisible( function ( object ) {

				objects ++;

				if ( object instanceof THREE.Mesh ) {

					var geometry = object.geometry;

					if ( geometry instanceof THREE.Geometry ) {

						vertices += geometry.vertices.length;
						triangles += geometry.faces.length;

					} else if ( geometry instanceof THREE.BufferGeometry ) {

						if ( geometry.index !== null ) {

							vertices += geometry.index.count * 3;
							triangles += geometry.index.count;

						} else {

							vertices += geometry.attributes.position.count;
							triangles += geometry.attributes.position.count / 3;

						}

					}

				}

			} );

		}

		objectsText.setValue( objects.format() );
		verticesText.setValue( vertices.format() );
		trianglesText.setValue( triangles.format() );

	}

	return container;

}
<|endoftext|>


<commit_before>var db = require('config').db,
    DataAdapter = require('rendr/server/data_adapter'),
    _ = require('underscore'),
    debug = require('debug')('rendr:MongodbAdapter'),
    util = require('util'),
    mongoose = require('mongoose');

module.exports.initDB = initDB;
module.exports.MongodbAdapter = MongodbAdapter;
module.exports.get = get;
module.exports.fork = fork;
module.exports.query = query;

//
// Initialize DB connection.
//
function initDB() {
  var uri = 'mongodb://'
    + (db.user && db.password ? db.user + ':' + db.password + '@' : '')
    + db.host + (db.port ? ':' + db.port : '')
    + '/' + db.name;

  mongoose.connect(uri, db.options);

  var connection = mongoose.connection;

  connection.once('open', function () {
    console.log('Connected to ' + uri);
  });

  connection.on('error', console.error.bind(console, 'Connection Error:'));

  connection.on('disconnected', function () {
    mongoose.connect(uri, db.options);
    console.log('Reconnected to ' + uri);
  });
}

function MongodbAdapter(options) {
  DataAdapter.call(this, options);

  if (!options.mapper) {
    throw 'mapper must be defined';
  }

  this.mapper = options.mapper;

  /**
   * Default options.
   */
  _.defaults(this.options, {
    userAgent: 'Rendr MongodbAdapter; Node.js'
  });
}

util.inherits(MongodbAdapter, DataAdapter);

/**
 * `request`
 *
 * This is method that Rendr calls to ask for data.
 *
 * `req`: Actual request object from Express/Connect.
 * `api`: Object describing API call; properties including 'path', 'query', etc.
 *        Passed to `url.format()`.
 * `options`: (optional) Options.
 * `callback`: Callback.
 */
MongodbAdapter.prototype.request = function(req, api, options, callback) {
  /**
   * Allow for either 3 or 4 arguments; `options` is optional.
   */
  if (arguments.length === 3) {
    callback = options;
    options = {};
  }

  this.mapper(api.path, options, function (err, f, model, criteria) {
    if (err) {
      return callback(err);
    }

    /**
     * Request timing.
     */
    var start = new Date().getTime();

    f(model, criteria, function (err, body) {
      debug('Query %s %s %sms', model.modelName, criteria, new Date().getTime() - start);

      // prepare response object
      var response = {
        statusCode: err ? 500 : 200
      };

      callback(err, response, body);
    });
  });
};

//
// Find one document matching criteria.
//
function get(Model, criteria, callback) {
  Model.findOne(criteria).exec(function(err, body) {
    callback(err, body);
  });
}

function fork(Project, criteria, callback) {
  Project.findOne({id: criteria.originId, owner: criteria.originOwner}).exec(function(err, body) {
    if (err) {
      callback(err);
    } else {
      var originId = criteria.originId;
      var originOwner = criteria.originOwner;
      var newId = criteria.originId + '-from-' + criteria.originOwner;
      var newOwner = criteria.forkedBy;
      var doc = new Project({
        id: newId,
        name: body.name,
        type: body.type,
        owner: newOwner,
        organization: null,
        origin: {user: originOwner, proj: originId},
        description : body.description += ('(the project forked from ' + originOwner + '.)'),
        tags: body.tags,
        forks: [],
        starred: [],
        tracks: body.tracks,
        contributors: body.contributors
      });
      doc.save(function (err) {
        callback(err);
      });
    }
  });
}
//
// Query documents by criteria.
// Query all documents if criteria is empty.
//
function query(Model, criteria, callback) {
  Model.find(criteria).exec(function(err, body) {
    callback(err, body);
  });
}
<commit_msg>Changed to copy resouces on fork.<commit_after>var db = require('config').db,
    DataAdapter = require('rendr/server/data_adapter'),
    _ = require('underscore'),
    debug = require('debug')('rendr:MongodbAdapter'),
    util = require('util'),
    mongoose = require('mongoose'),
    fs = require('fs');

module.exports.initDB = initDB;
module.exports.MongodbAdapter = MongodbAdapter;
module.exports.get = get;
module.exports.fork = fork;
module.exports.query = query;

//
// Initialize DB connection.
//
function initDB() {
  var uri = 'mongodb://'
    + (db.user && db.password ? db.user + ':' + db.password + '@' : '')
    + db.host + (db.port ? ':' + db.port : '')
    + '/' + db.name;

  mongoose.connect(uri, db.options);

  var connection = mongoose.connection;

  connection.once('open', function () {
    console.log('Connected to ' + uri);
  });

  connection.on('error', console.error.bind(console, 'Connection Error:'));

  connection.on('disconnected', function () {
    mongoose.connect(uri, db.options);
    console.log('Reconnected to ' + uri);
  });
}

function MongodbAdapter(options) {
  DataAdapter.call(this, options);

  if (!options.mapper) {
    throw 'mapper must be defined';
  }

  this.mapper = options.mapper;

  /**
   * Default options.
   */
  _.defaults(this.options, {
    userAgent: 'Rendr MongodbAdapter; Node.js'
  });
}

util.inherits(MongodbAdapter, DataAdapter);

/**
 * `request`
 *
 * This is method that Rendr calls to ask for data.
 *
 * `req`: Actual request object from Express/Connect.
 * `api`: Object describing API call; properties including 'path', 'query', etc.
 *        Passed to `url.format()`.
 * `options`: (optional) Options.
 * `callback`: Callback.
 */
MongodbAdapter.prototype.request = function(req, api, options, callback) {
  /**
   * Allow for either 3 or 4 arguments; `options` is optional.
   */
  if (arguments.length === 3) {
    callback = options;
    options = {};
  }

  this.mapper(api.path, options, function (err, f, model, criteria) {
    if (err) {
      return callback(err);
    }

    /**
     * Request timing.
     */
    var start = new Date().getTime();

    f(model, criteria, function (err, body) {
      debug('Query %s %s %sms', model.modelName, criteria, new Date().getTime() - start);

      // prepare response object
      var response = {
        statusCode: err ? 500 : 200
      };

      callback(err, response, body);
    });
  });
};

//
// Find one document matching criteria.
//
function get(Model, criteria, callback) {
  Model.findOne(criteria).exec(function(err, body) {
    callback(err, body);
  });
}

function fork(Project, criteria, callback) {
  Project.findOne({id: criteria.originId, owner: criteria.originOwner}).exec(function(err, body) {
    if (err) {
      callback(err);
    } else {
      var originId = criteria.originId;
      var originOwner = criteria.originOwner;
      var newId = criteria.originId + '-from-' + criteria.originOwner;
      var newOwner = criteria.forkedBy;
      var doc = new Project({
        id: newId,
        name: body.name,
        type: body.type,
        owner: newOwner,
        organization: null,
        origin: {user: originOwner, proj: originId},
        description : body.description += ('(the project forked from ' + originOwner + '.)'),
        tags: body.tags,
        forks: [],
        starred: [],
        tracks: body.tracks,
        contributors: body.contributors
      });
      doc.save(function (err) {
        var prefix = './public/assets/';
        var srcDir = '/projects/' + originOwner + '/';
        var dstDir = '/projects/' + newOwner + '/';
        var srcImage = prefix + 'images' + srcDir + originId + '-l.png';
        var srcMedia = prefix + 'media' + srcDir + originId + '.mp3';
        var dstImageDir = prefix + 'images' + dstDir;
        var dstImageFile = dstImageDir + newId + '-l.png';
        var dstMediaDir = prefix + 'media' + dstDir;
        var dstMediaFile = dstMediaDir + newId + '.mp3';

        if (fs.existsSync(srcImage)) {
          if (!fs.existsSync(dstImageDir)) {
            fs.mkdirSync(dstImageDir);
          }
          fs.writeFileSync(dstImageFile, fs.readFileSync(srcImage));
        }
        if (fs.existsSync(srcMedia)) {
          if (!fs.existsSync(dstMediaDir)) {
            fs.mkdirSync(dstMediaDir);
          }
          fs.writeFileSync(dstMediaFile, fs.readFileSync(srcMedia));
        }
        callback(err);
      });
    }
  });
}
//
// Query documents by criteria.
// Query all documents if criteria is empty.
//
function query(Model, criteria, callback) {
  Model.find(criteria).exec(function(err, body) {
    callback(err, body);
  });
}
<|endoftext|>