瀏覽代碼

customer, lead and opportunity bugs fixed and opportunities views redesigned

robert 8 年之前
父節點
當前提交
547f04655b
共有 37 個文件被更改,包括 504 次插入678 次删除
  1. 2 2
      bower.json
  2. 2 1
      package.json
  3. 1 1
      scss/ionic.app.scss
  4. 16 33
      www/css/app.css
  5. 二進制
      www/img/empty.png
  6. 66 59
      www/index.html
  7. 3 3
      www/js/app.js
  8. 5 1
      www/js/controllers/configuration.controller.js
  9. 51 26
      www/js/controllers/customer.controller.js
  10. 66 43
      www/js/controllers/lead.controller.js
  11. 70 17
      www/js/controllers/opportunity.controller.js
  12. 1 1
      www/js/factories/database.factory.js
  13. 3 1
      www/js/factories/odoo.factory.js
  14. 6 7
      www/js/factories/sales/crm.stage.storage.factory.js
  15. 0 2
      www/js/factories/sales/customer.storage.factory.js
  16. 0 1
      www/js/factories/sales/lead.sync.factory.js
  17. 7 7
      www/js/factories/sales/opportunity.storage.factory.js
  18. 3 3
      www/js/factories/sales/opportunity.sync.factory.js
  19. 57 17
      www/js/factories/utils.factory.js
  20. 0 40
      www/lib/ionic-toast/.bower.json
  21. 0 131
      www/lib/ionic-toast/README.md
  22. 0 30
      www/lib/ionic-toast/bower.json
  23. 0 0
      www/lib/ionic-toast/dist/ionic-toast.bundle.min.js
  24. 0 34
      www/lib/ionic-toast/gulpfile.js
  25. 0 19
      www/lib/ionic-toast/package.json
  26. 0 58
      www/lib/ionic-toast/src/ionic-toast.css
  27. 0 4
      www/lib/ionic-toast/src/ionic-toast.module.js
  28. 0 90
      www/lib/ionic-toast/src/ionic-toast.provider.js
  29. 0 15
      www/lib/ionic-toast/src/ionic-toast.run.js
  30. 28 0
      www/lib/ti-segmented-control/.bower.json
  31. 6 5
      www/lib/ti-segmented-control/LICENSE
  32. 18 0
      www/lib/ti-segmented-control/bower.json
  33. 50 0
      www/lib/ti-segmented-control/dist/ti-segmented-control.js
  34. 4 0
      www/templates/sales/customer.html
  35. 3 3
      www/templates/sales/customers.html
  36. 10 10
      www/templates/sales/leads.html
  37. 26 14
      www/templates/sales/opportunities.html

+ 2 - 2
bower.json

@@ -8,9 +8,9 @@
     "angular-local-storage": "^0.2.7",
     "ngCordova": "^0.1.27-alpha",
     "ionic-filter-bar": "^1.1.1",
-    "ionic-toast": "^0.4.1",
     "angular-translate": "^2.11.1",
     "squel": "^5.3.3",
-    "ngstorage": "^0.3.11"
+    "ngstorage": "^0.3.11",
+    "ti-segmented-control": "^0.0.2"
   }
 }

+ 2 - 1
package.json

@@ -26,7 +26,8 @@
     "cordova-plugin-vibration",
     "cordova-plugin-geolocation",
     "cordova-plugin-device-motion",
-    "uk.co.workingedge.phonegap.plugin.launchnavigator"
+    "uk.co.workingedge.phonegap.plugin.launchnavigator",
+    "cordova-plugin-dialogs"
   ],
   "cordovaPlatforms": [
     "android"

+ 1 - 1
scss/ionic.app.scss

@@ -19,4 +19,4 @@ $ionicons-font-path: "../lib/ionic/fonts" !default;
 
 @import 'https://fonts.googleapis.com/css?family=Harmattan';
 // Include all of Ionic
-@import "www/lib/ionic/scss/ionic";
+@import "www/lib/ionic/scss/ionic";

+ 16 - 33
www/css/app.css

@@ -31,11 +31,13 @@
 }
 
 .empty-data {
+    width: 150px;
+    height: 142px;
     position: absolute;
     top: 50%;
     left: 50%;
-    margin-top: -87px;
-    margin-left: -100px;
+    margin-top: -71px;
+    margin-left: -75px;
 }
 
 .bar-icon {
@@ -46,12 +48,6 @@
 
 .holded {
     background-color: lightgray;
-    /*box-shadow:
-                1px 1px #387ef5,
-                2px 2px #387ef5,
-                3px 3px #387ef5;
-        -webkit-transform: translateX(-3px);
-        transform: translateX(-3px);*/
 }
 
 .centered-spinner {
@@ -63,34 +59,21 @@
 }
 
 .spinner svg {
-  width: 32px;
-  height: 32px;
-  stroke: #387ef5;
-  fill: #387ef5;
+    width: 32px;
+    height: 32px;
+    stroke: #387ef5;
+    fill: #387ef5;
 }
 
-.animate-repeat {
-  line-height:30px;
-  list-style:none;
-  box-sizing:border-box;
+.popover {
+    height: auto !important;
 }
-
-.animate-repeat.ng-move,
-.animate-repeat.ng-enter,
-.animate-repeat.ng-leave {
-  transition:all linear 0.1s;
+.popover ion-header-bar {
+    position: relative;
 }
-
-.animate-repeat.ng-leave.ng-leave-active,
-.animate-repeat.ng-move,
-.animate-repeat.ng-enter {
-  opacity:0;
-  max-height:0;
+.popover ion-content {
+    top: 0;
+    position: relative;
 }
 
-.animate-repeat.ng-leave,
-.animate-repeat.ng-move.ng-move-active,
-.animate-repeat.ng-enter.ng-enter-active {
-  opacity:1;
-  max-height:30px;
-}
+

二進制
www/img/empty.png


+ 66 - 59
www/index.html

@@ -1,61 +1,68 @@
 <!DOCTYPE html>
 <html>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
-     <!-- <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://127.0.0.1:8100"> -->
-    <title></title>
-
-    <link href="css/ionic.app.min.css" rel="stylesheet">
-    <link href="css/app.css" rel="stylesheet">
-    <link href="lib/ionic-filter-bar/dist/ionic.filter.bar.css" rel="stylesheet">
-
-    <!-- Libs -->
-    <script src="lib/ionic/js/ionic.bundle.js"></script>
-    <script src="lib/ionic-filter-bar/dist/ionic.filter.bar.js"></script>
-    <script src="lib/ngCordova/dist/ng-cordova.min.js"></script>
-    <script src="cordova.js"></script>
-    <script src="lib/angular-translate/angular-translate.js"></script>
-
-    <!-- Main -->
-    <script src="js/app.js"></script>
-
-    <!-- Directives -->
-    <script src="js/directives/onerrorsrc.directive.js"></script>
-
-    <!-- Providers -->
-    <!-- <script src="js/providers/user.config.provider.js"></script> -->
-
-    <!-- Controllers -->
-    <script src="js/controllers/main.controller.js"></script>
-    <script src="js/controllers/sale.controller.js"></script>
-    <script src="js/controllers/customer.controller.js"></script>
-    <script src="js/controllers/lead.controller.js"></script>
-    <script src="js/controllers/opportunity.controller.js"></script>
-    <script src="js/controllers/configuration.controller.js"></script>
-    <script src="js/controllers/preferences.controller.js"></script>
-
-    <!-- Factories -->
-    <script src="js/factories/utils.factory.js"></script>
-    <script src="js/factories/odoo.factory.js"></script>
-    <script src="js/factories/database.factory.js"></script>
-    <script src="js/factories/sales/customer.storage.factory.js"></script>
-    <script src="js/factories/sales/customer.sync.factory.js"></script>
-    <script src="js/factories/sales/lead.storage.factory.js"></script>
-    <script src="js/factories/sales/lead.sync.factory.js"></script>
-    <script src="js/factories/sales/crm.stage.storage.factory.js"></script>
-    <script src="js/factories/sales/crm.stage.sync.factory.js"></script>
-    <script src="js/factories/sales/opportunity.storage.factory.js"></script>
-    <script src="js/factories/sales/opportunity.sync.factory.js"></script>
-
-    <!-- 3rd Party -->
-    <!-- JS -->
-    <script src="lib/angular-xmlrpc/xmlrpc.js"></script>
-    <script src="lib/ionic-toast/dist/ionic-toast.bundle.min.js"></script>
-    <script src="lib/squel/dist/squel-basic.js"></script>
-    <script src="lib/ngstorage/ngStorage.js"></script>
-  </head>
-  <body ng-app="odoo">
-      <ion-nav-view animation="slide-left-right"></ion-nav-view>
-  </body>
-</html>
+
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
+  <!-- <meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://127.0.0.1:8100"> -->
+  <title></title>
+
+  <link href="css/ionic.app.min.css" rel="stylesheet">
+  <link href="css/app.css" rel="stylesheet">
+
+
+  <!-- Libs -->
+  <script src="lib/ionic/js/ionic.bundle.js"></script>
+  <script src="cordova.js"></script>
+
+  <!-- Main -->
+  <script src="js/app.js"></script>
+
+  <!-- Directives -->
+  <script src="js/directives/onerrorsrc.directive.js"></script>
+
+  <!-- Providers -->
+  <!-- <script src="js/providers/user.config.provider.js"></script> -->
+
+  <!-- Controllers -->
+  <script src="js/controllers/main.controller.js"></script>
+  <script src="js/controllers/sale.controller.js"></script>
+  <script src="js/controllers/customer.controller.js"></script>
+  <script src="js/controllers/lead.controller.js"></script>
+  <script src="js/controllers/opportunity.controller.js"></script>
+  <script src="js/controllers/configuration.controller.js"></script>
+  <script src="js/controllers/preferences.controller.js"></script>
+
+  <!-- Factories -->
+  <script src="js/factories/utils.factory.js"></script>
+  <script src="js/factories/odoo.factory.js"></script>
+  <script src="js/factories/database.factory.js"></script>
+  <script src="js/factories/sales/customer.storage.factory.js"></script>
+  <script src="js/factories/sales/customer.sync.factory.js"></script>
+  <script src="js/factories/sales/lead.storage.factory.js"></script>
+  <script src="js/factories/sales/lead.sync.factory.js"></script>
+  <script src="js/factories/sales/crm.stage.storage.factory.js"></script>
+  <script src="js/factories/sales/crm.stage.sync.factory.js"></script>
+  <script src="js/factories/sales/opportunity.storage.factory.js"></script>
+  <script src="js/factories/sales/opportunity.sync.factory.js"></script>
+
+  <!-- 3rd Party -->
+  <!-- CSS -->
+  <link href="lib/ionic-filter-bar/dist/ionic.filter.bar.css" rel="stylesheet">
+
+  <!-- JS -->
+  <script src="lib/ionic-filter-bar/dist/ionic.filter.bar.js"></script>
+  <script src="lib/ti-segmented-control/dist/ti-segmented-control.js"></script>
+  <script src="lib/ngCordova/dist/ng-cordova.min.js"></script>
+  <script src="lib/angular-translate/angular-translate.js"></script>
+  <script src="lib/angular-xmlrpc/xmlrpc.js"></script>
+  <script src="lib/squel/dist/squel-basic.js"></script>
+  <script src="lib/ngstorage/ngStorage.js"></script>
+
+</head>
+
+<body ng-app="odoo">
+  <ion-nav-view animation="slide-left-right"></ion-nav-view>
+</body>
+
+</html>

+ 3 - 3
www/js/app.js

@@ -2,10 +2,10 @@ angular.module(
     'odoo',
     [
         'ionic',
-        'ionic-toast',
+        'xml-rpc',
         'ngCordova',
         'ngStorage',
-        'xml-rpc',
+        'ti-segmented-control',
         'jett.ionic.filter.bar',
         'pascalprecht.translate'
     ]
@@ -135,7 +135,7 @@ angular.module(
             Lost: 'Perdido'
         });
 
-        $ionicConfigProvider.spinner.icon('ios');
+        $ionicConfigProvider.spinner.icon('lines');
 
         $ionicFilterBarConfigProvider.theme('positive');
         $ionicFilterBarConfigProvider.placeholder('Buscar');

+ 5 - 1
www/js/controllers/configuration.controller.js

@@ -1,7 +1,11 @@
 angular.module('odoo')
 
     /**
-     *
+     *    ___           __ _                    _   _             ___         _           _ _                                                                          
+     *   / __|___ _ _  / _(_)__ _ _  _ _ _ __ _| |_(_)___ _ _    / __|___ _ _| |_ _ _ ___| | |___ _ _                                                                  
+     *  | (__/ _ \ ' \|  _| / _` | || | '_/ _` |  _| / _ \ ' \  | (__/ _ \ ' \  _| '_/ _ \ | / -_) '_|                                                                 
+     *   \___\___/_||_|_| |_\__, |\_,_|_| \__,_|\__|_\___/_||_|  \___\___/_||_\__|_| \___/_|_\___|_|                                                                   
+     *                      |___/                                                                              
      */
     .controller('ConfigurationController', function (
         $scope,

+ 51 - 26
www/js/controllers/customer.controller.js

@@ -9,20 +9,22 @@ angular.module('odoo')
         $scope,
         $ionicModal,
         $ionicActionSheet,
-        $ionicPopup,
+        $ionicFilterBar,
         customersRemoteFactory,
         customersStorageFactory,
         sqlFactory,
         deviceFactory
     ) {
         $scope.loading = false;
+        $scope.selectedIndex = -1;
         $scope.customers = [];
         $scope.customer = {};
+        $scope.search = null;
 
         $ionicModal.fromTemplateUrl('templates/sales/customer.html', {
             scope: $scope
         }).then(function (modal) {
-            $scope.customerModal = modal;
+            $scope.modal = modal;
         });
 
         /**
@@ -36,7 +38,7 @@ angular.module('odoo')
          *
          */
         $scope.$on('$destroy', function () {
-            $scope.customerModal.remove();
+            $scope.modal.remove();
         });
 
         /**
@@ -50,12 +52,14 @@ angular.module('odoo')
          *
          */
         $scope.$on('device.shaked', function () {
-            if ($scope.customerModal.isShown()) {
+            if ($scope.modal.isShown()) {
 
                 deviceFactory.getCurrentPosition(function (position) {
+
                     $scope.customer.partner_latitude = position.coords.latitude;
                     $scope.customer.partner_longitude = position.coords.longitude;
                     $scope.customer.date_localization = new Date(position.timestamp).toLocaleString();
+
                 }, function (err) {
                     console.log(err);
                 });
@@ -65,6 +69,25 @@ angular.module('odoo')
             }
         });
 
+        /**
+         *
+         */
+        $scope.toogleNew = function () {
+            $scope.modal.show();
+        }
+
+        /**
+         *
+         */
+        $scope.toogleSearch = function () {
+            $scope.search = $ionicFilterBar.show({
+                items: $scope.customers,
+                update: function (filtered, text) {
+                    $scope.customers = filtered;
+                }
+            });
+        }
+
         /**
          *
          */
@@ -82,7 +105,7 @@ angular.module('odoo')
                     $scope.$broadcast('scroll.refreshComplete');
                     $scope.loading = false;
 
-                    $ionicPopup.alert({ title: 'No se pudo obtener los clientes' });
+                    deviceFactory.toast('No se ha podido cargar los datos');
                 });
             }, function (syncErr) {
 
@@ -94,7 +117,7 @@ angular.module('odoo')
                     $scope.$broadcast('scroll.refreshComplete');
                     $scope.loading = false;
 
-                    $ionicPopup.alert({ title: 'No se pudo obtener los clientes' });
+                    deviceFactory.toast('No se ha podido cargar los datos');
                 });
             });
         }
@@ -121,6 +144,10 @@ angular.module('odoo')
          *
          */
         $scope.openOptions = function (index) {
+            deviceFactory.vibrate();
+
+            $scope.selectedIndex = index;
+
             if (index == -1) {
                 $scope.customer = {};
             } else {
@@ -145,12 +172,14 @@ angular.module('odoo')
                 destructiveText: '<i class="icon ion-trash-a assertive"></i> Eliminar',
                 cancel: function () {
                     $scope.customer = {};
-                    console.log('ActionSheet canceled');
+                    $scope.selectedIndex = -1;
                 },
                 buttonClicked: function (index) {
+                    $scope.selectedIndex = -1;
+
                     switch (index) {
                         case 0:
-                            $scope.show();
+                            $scope.toogleNew();
                             break;
                         case 1:
                             $scope.addContact();
@@ -159,11 +188,14 @@ angular.module('odoo')
                             $scope.navigate();
                             break;
                         default:
-                            $scope.show();
+                            $scope.toogleNew();
                     }
+
                     return true;
                 },
                 destructiveButtonClicked: function () {
+                    $scope.selectedIndex = -1;
+                    
                     $scope.delete();
 
                     return true;
@@ -182,11 +214,11 @@ angular.module('odoo')
                 }
 
                 $scope.customer = {};
-                $scope.customerModal.hide();
+                $scope.modal.hide();
                 console.log('Customer saved');
             }, function (error) {
-                $ionicPopup.alert({ title: 'No se ha podido guardar el cliente', template: JSON.stringify(error) });
-                console.log(JSON.stringify(error));
+                console.log(error);
+                deviceFactory.toast('No se ha podido guardar el cliente');
             });
         }
 
@@ -194,11 +226,8 @@ angular.module('odoo')
          *
          */
         $scope.delete = function () {
-            $ionicPopup.confirm({
-                title: 'Confirmar',
-                template: 'Estás seguro que quieres eliminar este cliente?'
-            }).then(function (confirmation) {
-                if (confirmation) {
+            deviceFactory.confirm('Estás seguro que quieres eliminar este cliente?', 'Confirmar', function (index) {
+                if (index == 1) {
                     customersStorageFactory.remove($scope.customer, function (affected) {
                         if (affected != 0) {
                             var index = $scope.customers.indexOf($scope.customer);
@@ -208,20 +237,13 @@ angular.module('odoo')
                             $scope.$apply();
                         }
                     }, function (error) {
-                        $ionicPopup.alert({ title: 'No se puedo eliminar el cliente', template: JSON.stringify(error) });
-                        console.log(JSON.stringify(error));
+                        console.log(error);
+                        deviceFactory.toast('No se ha podido eliminar el cliente');
                     });
                 }
             });
         }
 
-        /**
-         *
-         */
-        $scope.show = function () {
-            $scope.customerModal.show();
-        }
-
         /**
          *
          */
@@ -231,6 +253,7 @@ angular.module('odoo')
                 $scope.customer.image_medium = imageData;
             }, function (error) {
                 console.log(error);
+                deviceFactory.toast('No se ha podido tomar la foto');
             });
         }
 
@@ -242,6 +265,7 @@ angular.module('odoo')
                 console.log(result);
             }, function (error) {
                 console.log(error);
+                deviceFactory.toast('Este cliente no tiene contactos que guardar');
             })
         }
 
@@ -256,6 +280,7 @@ angular.module('odoo')
                 console.log(message);
             }, function (err) {
                 console.log(err);
+                deviceFactory.toast('Este cliente no tiene ubicación que navegar');
             })
         }
     });

+ 66 - 43
www/js/controllers/lead.controller.js

@@ -8,15 +8,15 @@ angular.module('odoo')
         $ionicModal,
         $ionicActionSheet,
         $ionicFilterBar,
-        $ionicPopup,
-        $cordovaVibration,
         leadsRemoteFactory,
         leadsStorageFactory,
         opportunitiesStorageFactory,
-        sqlFactory
+        sqlFactory,
+        deviceFactory
     ) {
 
         $scope.loading = false;
+        $scope.selectedIndex = -1;
         $scope.leads = [];
         $scope.lead = {};
         $scope.conversion = {
@@ -38,23 +38,42 @@ angular.module('odoo')
             $scope.leadToOpportunityModal = modal;
         });
 
+        /**
+         *
+         */
         $scope.$on('$ionicView.enter', function () {
-            $scope.fill();
+            $scope.fill(false);
         });
 
+        /**
+         *
+         */
         $scope.$on('$destroy', function () {
             $scope.leadModal.remove();
             $scope.leadToOpportunityModal.remove();
         });
 
+        /**
+         *
+         */
         $scope.$on('modal.hidden', function () {
             $scope.lead = {};
         });
+  
+
+         /**
+         *
+         */
+        $scope.$on('device.shaked', function () { 
+            if (!$scope.leadModal.isShown()) {
+                $scope.fill(false);
+            }
+        });
 
         /**
          *
          */
-        $scope.fill = function (refresh = false) {
+        $scope.fill = function (refresh) {
             $scope.loading = !refresh;
 
             leadsRemoteFactory.sync(function (leads) {
@@ -67,7 +86,7 @@ angular.module('odoo')
                     $scope.$broadcast('scroll.refreshComplete');
                     $scope.loading = false;
 
-                    $ionicPopup.alert({ title: 'No se pudo obtener las iniciativas' });
+                    deviceFactory.toast('No se pudo obtener las iniciativas');
                 });
             }, function (syncErr) {
                 $scope.getLeads(function () {
@@ -77,7 +96,7 @@ angular.module('odoo')
                     $scope.$broadcast('scroll.refreshComplete');
                     $scope.loading = false;
 
-                    $ionicPopup.alert({ title: 'No se pudo obtener las iniciativas' });
+                    deviceFactory.toast('No se pudo obtener las iniciativas');
                 });
             });
         }
@@ -103,28 +122,39 @@ angular.module('odoo')
         /**
          *
          */
-        $scope.show = function (event) {
+        $scope.toogleNew = function () {
             $scope.leadModal.show();
         }
 
+        /**
+         *
+         */
+        $scope.toggleSearch = function () {
+            $scope.search = $ionicFilterBar.show({
+                items: $scope.leads,
+                update: function (filtered, text) {
+                    $scope.leads = filtered;
+                }
+            });
+        }
+
         /**
          *
          */
         $scope.save = function () {
             leadsStorageFactory.save($scope.lead, function (leadId) {
-        
+
                 if (!$scope.lead.id) {
                     $scope.lead.id = leadId;
                     $scope.leads.push($scope.lead);
                 }
 
                 $scope.lead = {};
-                $scope.loading = false;
+                $scope.leadModal.hide();
                 console.log('Lead saved');
-
             }, function (error) {
-                $ionicPopup.alert({ title: 'No se ha podido guardar la iniciativa', template: JSON.stringify(error) });
-                console.log(JSON.stringify(error));
+                console.log(error);
+                deviceFactory.toast('No se ha podido guardar la iniciativa');
             });
         }
 
@@ -132,11 +162,8 @@ angular.module('odoo')
          *
          */
         $scope.delete = function () {
-            $ionicPopup.confirm({
-                title: 'Confirmar',
-                template: 'Estás seguro que quieres eliminar esta iniciativa?'
-            }).then(function (confirmation) {
-                if (confirmation) {
+            deviceFactory.confirm('Estás seguro que quieres eliminar esta iniciativa?', 'Confirmar', function (index) {
+                if (index == 1) {
                     leadsStorageFactory.remove($scope.lead, function (affected) {
                         if (affected != 0) {
                             var index = $scope.leads.indexOf($scope.lead);
@@ -146,8 +173,8 @@ angular.module('odoo')
                             $scope.$apply();
                         }
                     }, function (error) {
-                        $ionicPopup.alert({ title: 'No se puedo eliminar la iniciativa', template: JSON.stringify(error) });
-                        console.log(JSON.stringify(error));
+                        console.log(error);
+                        deviceFactory.toast('No se ha podido eliminar la iniciativa');
                     });
                 }
             });
@@ -158,31 +185,20 @@ angular.module('odoo')
          */
         $scope.convertToOpportunity = function () {
             opportunitiesStorageFactory.save($scope.lead, function (opportunityId) {
-                $scope.leadToOpportunityModal.hide();
+                // $scope.leadToOpportunityModal.hide();
 
                 var index = $scope.leads.indexOf($scope.lead);
                 $scope.leads.splice(index, 1);
                 $scope.lead = {};
 
                 $scope.$apply();
+
+                deviceFactory.toast('Se convirtió la iniciativa');
             }, function (saveErr) {
-                $scope.leadToOpportunityModal.hide();
-                $ionicPopup.alert({
-                    title: 'No se puedo convertir la iniciativa',
-                    template: JSON.stringify(saveErr)
-                });
-            });
-        }
+                console.log(saveErr);
 
-        /**
-         *
-         */
-        $scope.toggleSearch = function () {
-            $scope.search = $ionicFilterBar.show({
-                items: $scope.leads,
-                update: function (filtered, text) {
-                    $scope.leads = filtered;
-                }
+                // $scope.leadToOpportunityModal.hide();
+                deviceFactory.toast('No se pudo convertir la iniciativa');
             });
         }
 
@@ -190,7 +206,9 @@ angular.module('odoo')
          *
          */
         $scope.openOptions = function (index) {
-            $cordovaVibration.vibrate(100);
+            deviceFactory.vibrate();
+
+            $scope.selectedIndex = index;
 
             if (index == -1) {
                 $scope.lead = {};
@@ -198,7 +216,7 @@ angular.module('odoo')
                 $scope.lead = $scope.leads[index];
             }
 
-            console.log('Customer selected => ' + JSON.stringify($scope.lead));
+            console.log($scope.lead);
 
             $ionicActionSheet.show({
                 titleText: 'Acciones',
@@ -213,22 +231,27 @@ angular.module('odoo')
                 destructiveText: '<i class="icon ion-trash-a assertive"></i> Eliminar',
                 cancel: function () {
                     $scope.lead = {};
-                    console.log('ActionSheet canceled');
+                    $scope.selectedIndex = -1;
                 },
                 buttonClicked: function (index) {
+                    $scope.selectedIndex = -1;
+
                     switch (index) {
                         case 0:
-                            $scope.show();
+                            $scope.toogleNew();
                             break;
                         case 1:
-                            $scope.leadToOpportunityModal.show();
+                            // $scope.leadToOpportunityModal.show();
+                            $scope.convertToOpportunity();
                             break;
                         default:
-                            $scope.show();
+                            $scope.toogleNew();
                     }
                     return true;
                 },
                 destructiveButtonClicked: function () {
+                    $scope.selectedIndex = -1;
+
                     $scope.delete();
 
                     return true;

+ 70 - 17
www/js/controllers/opportunity.controller.js

@@ -5,19 +5,26 @@ angular.module('odoo')
      */
     .controller('OpportunitiesController', function (
         $scope,
-        $ionicActionSheet,
         $ionicPopup,
+        $ionicFilterBar,
+        $ionicActionSheet,
+        deviceFactory,
         crmStagesDataFactory,
-        opportunitiesDataFactory,
-        ionicToast
+        opportunitiesDataFactory
     ) {
 
         $scope.loading = false;
+        $scope.selectedIndex = -1;
+        $scope.search = null;
         $scope.stages = [];
         $scope.opportunities = [];
-        $scope.currentStage = {};
+        $scope.groupedOpportunities = [];
+        $scope.stage = {
+            previous: null,
+            current: null,
+            next: null
+        };
         $scope.stageToMove = {};
-        $scope.selected = -1;
 
         /**
          *
@@ -26,10 +33,18 @@ angular.module('odoo')
             $scope.slider = data.slider;
         });
 
+        /**
+         * 
+         */
+        $scope.$on("$ionicSlides.slideChangeStart", function (event, data) {
+            $scope.loading = true;
+        });
+
         /**
          *
          */
         $scope.$on("$ionicSlides.slideChangeEnd", function (event, data) {
+            $scope.loading = false;
             $scope.stageChanged(data.slider.activeIndex);
         });
 
@@ -50,9 +65,10 @@ angular.module('odoo')
 
                 $scope.slider.updateLoop();
                 $scope.getOpportunities(function (opportunities) {
-                    console.log(opportunities);
 
                     $scope.loading = false;
+                    $scope.groupOpportunities();
+
                     $scope.$apply();
                 }, function (err) {
                     $scope.loading = false;
@@ -60,6 +76,7 @@ angular.module('odoo')
 
             }, function (err) {
                 $scope.loading = false;
+                deviceFactory.toast('No se ha podido cargar las oportunidades');
             });
         }
 
@@ -103,17 +120,42 @@ angular.module('odoo')
             });
         }
 
+        /**
+         * 
+         */
+        $scope.groupOpportunities = function () {
+            $scope.groupedOpportunities = $scope.opportunities.filter(function (item) {
+                return item.stage_id == $scope.stage.current.remote_id;
+            });
+        }
+
+        /**
+        *
+        */
+        $scope.toggleSearch = function () {
+            $scope.search = $ionicFilterBar.show({
+                items: $scope.groupedOpportunities,
+                update: function (filtered, text) {
+                    $scope.groupedOpportunities = filtered;
+                }
+            });
+        }
+
         /**
          * Change the state
          */
-        $scope.changeStage = function (mode) {
-            $scope.loading = true;
-            if (mode) {
-                $scope.slider.slideNext();
-            } else {
-                $scope.slider.slidePrev();
+        $scope.changeStage = function (index) {
+            switch (index) {
+                case 0:
+                    $scope.slider.slidePrev();
+                    break;
+                case 1:
+                    $scope.slider.slideTo(0);
+                    break;
+                case 2:
+                    $scope.slider.slideNext();
+                    break;
             }
-            $scope.loading = false;
         }
 
         /**
@@ -124,7 +166,11 @@ angular.module('odoo')
                 return;
             }
 
-            $scope.currentStage = $scope.stages[index];
+            $scope.stage.previous = index - 1 >= 0 ? $scope.stages[index - 1] : $scope.stages[index];
+            $scope.stage.current = $scope.stages[index];
+            $scope.stage.next = index + 1 <= $scope.stages.length ? $scope.stages[index + 1] : $scope.stages[index];
+
+            $scope.groupOpportunities();
 
             if (!$scope.$$phase) {
                 $scope.$apply();
@@ -171,14 +217,17 @@ angular.module('odoo')
          */
         $scope.moveOpportunity = function () {
             console.log($scope.stageToMove);
-            ionicToast.show('Se movió la oportunidad ', 'bottom', false, 1500);
+            deviceFactory.toast('Se movió la oportunidad a ' + $scope.stageToMove.name);
         }
 
         /**
          * Open the actionsheet action options
          */
         $scope.openOptions = function (index) {
-            $scope.selected = index;
+            deviceFactory.vibrate();
+
+            $scope.selectedIndex = index;
+            console.log($scope.opportunities[index]);
 
             $ionicActionSheet.show({
                 titleText: 'Acciones',
@@ -193,9 +242,11 @@ angular.module('odoo')
                 destructiveText: '<i class="icon ion-trash-a assertive"></i> Eliminar',
                 cancel: function () {
                     $scope.customer = {};
-                    $scope.selected = -1;
+                    $scope.selectedIndex = -1;
                 },
                 buttonClicked: function (index) {
+                    $scope.selectedIndex = -1;
+
                     switch (index) {
                         case 0:
                             $scope.show();
@@ -209,6 +260,8 @@ angular.module('odoo')
                     return true;
                 },
                 destructiveButtonClicked: function () {
+                    $scope.selectedIndex = -1;
+
                     $scope.delete();
 
                     return true;

+ 1 - 1
www/js/factories/database.factory.js

@@ -21,7 +21,7 @@ angular.module('odoo')
             },
             {
                 model: 'crm.case.stage',
-                table: 'stages'
+                table: 'crm_stage'
             }
         ];
 

+ 3 - 1
www/js/factories/odoo.factory.js

@@ -1,7 +1,9 @@
 angular.module('odoo')
 
     /**
-     *
+     * -----------------------------------------------------------------------------
+     *  Description:    Odoo connection manager
+     * -----------------------------------------------------------------------------
      */
     .factory('odooFactory', function (
         $localStorage,

+ 6 - 7
www/js/factories/sales/crm.stage.storage.factory.js

@@ -16,20 +16,19 @@ angular.module('odoo')
                     .table('crm_stage')
                     .set('remote_id', data.remote_id)
                     .set('modified', 1)
-                    .set('modified_date', 'CURRENT_TIMESTAMP', { dontQuote: true })
                     .set('name', data.name)
-                    .where('id', data.id);
+                    .where('id = ?', data.id)
+                    .toParam();
             } else {
                 query = squel.insert()
                     .into('crm_stage')
                     .set('remote_id', data.remote_id)
                     .set('modified', 0)
-                    .set('name', data.name);
+                    .set('name', data.name)
+                    .toParam();
             }
 
-            query = query.toParam();
-
-            db.executeSql(query.text(), query.values, function (result) {
+            db.executeSql(query.text, query.values, function (result) {
                 success(query.text.startsWith('INSERT') ? result.insertId : data.id);
             }, function (err) {
                 error(err);
@@ -47,7 +46,7 @@ angular.module('odoo')
 
             db.executeSql(query.text, query.values, function(result) {
                 success(result.rowsAffected);
-            }, function(err) {
+            }, function (err) {
                 error(err);
             });
         }

+ 0 - 2
www/js/factories/sales/customer.storage.factory.js

@@ -15,8 +15,6 @@ angular.module('odoo')
         var save = function (data, success, error) {
             var query = null;
 
-            console.log(data);
-
             if (data.id) {
                 query = squel.update()
                     .table('partner')

+ 0 - 1
www/js/factories/sales/lead.sync.factory.js

@@ -58,7 +58,6 @@ angular.module('odoo')
 
                             odooFactory.write('crm.lead', id, data, function (response) {
                                 console.log(response);
-                                success(response);
                             }, function (odooErr) {
                                 console.log(odooErr);
                                 error(odooErr);

+ 7 - 7
www/js/factories/sales/opportunity.storage.factory.js

@@ -28,17 +28,17 @@ angular.module('odoo')
 
             if (data.remote_id) {
                 query = squel.update()
-                    .table('lead')
+                    .table('crm_lead')
                     .set('modified', 2)
-                    .where('id', data.id);
+                    .where('id = ?', data.id)
+                    toParam();
             } else {
                 query = squel.delete()
                     .from('lead')
-                    .where('id', data.id);
+                    .where('id = ?', data.id)
+                    .toParam();
             }
 
-            query = query.toParam();
-
             db.executeSql(query.text, query.values, function (result) {
                 success(result.rowsAffected);
             }, function (err) {
@@ -51,8 +51,8 @@ angular.module('odoo')
          */
         var removeAll = function (success, error) {
             var query = squel.delete()
-                .from('lead')
-                .where('type', 'opportunity')
+                .from('crm_lead')
+                .where('type = ?', 'opportunity')
                 .toParam();
 
             db.executeSql(query.text, query.values, function (result) {

+ 3 - 3
www/js/factories/sales/opportunity.sync.factory.js

@@ -61,7 +61,7 @@ angular.module('odoo')
          *
          */
         var get = function (constraint, success, error) {
-            sqlFactory.selectByConstraint('lead', constraint, function (leads) {
+            sqlFactory.selectByConstraint('crm_lead', constraint, function (leads) {
                 success(leads);
             }, function (err) {
                 error(err);
@@ -161,7 +161,6 @@ angular.module('odoo')
          */
         var downloadSyncData = function (success, error) {
             pull(null, function (opportunities) {
-
                 opportunitiesStorageFactory.removeAll(function () {
                     asyncLoopFactory(opportunities.length, function (loop) {
                         var data = opportunities[loop.iteration()];
@@ -169,7 +168,7 @@ angular.module('odoo')
                         data.remote_id = data.id;
                         delete data.id;
 
-                        opportunitiesStorageFactory.save(data, function (opportunity) {
+                        opportunitiesStorageFactory.save(data, function (opportunityId) {
                             loop.next();
                         }, function (saveErr) {
                             loop.next();
@@ -179,6 +178,7 @@ angular.module('odoo')
                         success(opportunities);
                     });
                 }, function (removeAllErr) {
+                    console.log(removeAllErr);
                     error(removeAllErr);
                 });
 

+ 57 - 17
www/js/factories/utils.factory.js

@@ -134,15 +134,17 @@ angular.module('odoo')
     .factory('deviceFactory', function (
         $timeout,
         $rootScope,
+        $cordovaToast,
         $cordovaCamera,
+        $cordovaDialogs,
         $cordovaContacts,
+        $cordovaVibration,
         $cordovaGeolocation,
         $cordovaDeviceMotion,
-        $cordovaLaunchNavigator,
-        $cordovaToast,
-        $cordovaVibration
+        $cordovaLaunchNavigator
     ) {
-        var vibrateDuration = 100;
+
+        var vibrateDuration = 50;
 
         /**
          *
@@ -168,10 +170,12 @@ angular.module('odoo')
             });
         }
 
+        /**
+         *
+         */
         var saveContact = function (contact, success, error) {
             if (!contact.mobile && !contact.phone && !contact.email) {
-                error();
-                return;
+                return error('No hay nada que guardar');
             }
 
             var info = {
@@ -237,17 +241,15 @@ angular.module('odoo')
                 enableHighAccuracy: false
             }
 
-            $cordovaToast.showShortBottom('Obteniendo localización');
-            $cordovaVibration.vibrate(vibrateDuration);
+
+            notify('Obteniendo localización');
 
             $cordovaGeolocation.getCurrentPosition(options).then(function (position) {
-                $cordovaVibration.vibrate(vibrateDuration);
-                $cordovaToast.showShortBottom('Localización obtenida con éxito');
+                notify('Localización obtenida con éxito');
 
                 success(position);
             }, function (err) {
-                $cordovaVibration.vibrate(vibrateDuration);
-                $cordovaToast.showLongBottom('No se pudo obtener la localización, revise si su GPS está activo');
+                notify('No se pudo obtener la localización, revise si su GPS está activo', true);
 
                 error(err);
             });
@@ -257,17 +259,50 @@ angular.module('odoo')
          *
          */
         var navigate = function (destination, success, error) {
-            // if (!destination.latitude || !destination.longitude) {
-            //     return error('Invalid destination');
-            // }
+            if (!destination.partner_latitude || !destination.partner_longitude) {
+                return error('No hay destino');
+            }
 
-            $cordovaLaunchNavigator.navigate(destination).then(function () { 
+            $cordovaLaunchNavigator.navigate(destination).then(function () {
                 success('Navigator launched');
-            }, function (err) { 
+            }, function (err) {
                 error(err);
             });
         }
 
+        /**
+         *
+         */
+        var vibrate = function () {
+            $cordovaVibration.vibrate(vibrateDuration);
+        }
+
+        /**
+         *
+         */
+        var toast = function (message, long) {
+            long = long || false;
+
+            $cordovaToast.show(message, long ? 'long' : 'short', 'bottom');
+        }
+
+        /**
+         *
+         */
+        var confirm = function (message, title, success) {
+            $cordovaDialogs.confirm(message, title, ['Aceptar', 'Cancelar']).then(function (index) {
+                success(index);
+            });
+        }
+
+        /**
+         *
+         */
+        var notify = function (message, long) {
+            vibrate();
+            toast(message, long);
+        }
+
         /**
          *
          */
@@ -323,8 +358,13 @@ angular.module('odoo')
 
         return {
             takePicture: takePicture,
+            saveContact: saveContact,
             getCurrentPosition: getCurrentPosition,
             navigate: navigate,
+            vibrate: vibrate,
+            toast: toast,
+            confirm: confirm,
+            notify: notify,
             detectShake: detectShake
         }
     });

+ 0 - 40
www/lib/ionic-toast/.bower.json

@@ -1,40 +0,0 @@
-{
-  "name": "ionic-toast",
-  "version": "0.4.1",
-  "authors": [
-    "rajeshwarpatlolla <rajeshwar.patlolla@gmail.com>"
-  ],
-  "description": "'ionic-toast' bower component for ionic framework applications",
-  "main": [
-    "./dist/ionic-toast.bundle.min.js"
-  ],
-  "keywords": [
-    "ionic-toast",
-    "toast",
-    "ionic",
-    "toast for ionic",
-    "toast for ionic framework"
-  ],
-  "license": "MIT",
-  "homepage": "https://github.com/rajeshwarpatlolla/ionic-toast",
-  "ignore": [
-    "**/.*",
-    "node_modules",
-    "bower_components",
-    "test",
-    "tests"
-  ],
-  "dependencies": {
-    "ionic": ">=0.9.27"
-  },
-  "_release": "0.4.1",
-  "_resolution": {
-    "type": "version",
-    "tag": "v0.4.1",
-    "commit": "d2e9fcab0bf0527ceecfe3fb78f8d1f47fecb436"
-  },
-  "_source": "https://github.com/rajeshwarpatlolla/ionic-toast.git",
-  "_target": "^0.4.1",
-  "_originalSource": "ionic-toast",
-  "_direct": true
-}

+ 0 - 131
www/lib/ionic-toast/README.md

@@ -1,131 +0,0 @@
-[![bitHound Score](https://www.bithound.io/github/rajeshwarpatlolla/ionic-toast/badges/score.svg)](https://www.bithound.io/github/rajeshwarpatlolla/ionic-toast)
-
-##Introduction:
-
-This is an `ionic-toast` bower component which can be used with any Ionic framework's application.
-
-[View Demo](http://rajeshwarpatlolla.github.io/ionic-toast-demo/demo/ "Demo") 
-
-
-##Prerequisites.
-
-1) node.js, bower and gulp.
-
-##How to use:
-
-**1)** In your project repository install the ionic-toast using bower
-
-    bower install ionic-toast --save
-
-This will install the latest version released. If you wish to install a specific version please use `bower install ionic-toast#<version number>`
-    
-**2)** Give the path of `ionic-toast.bundle.min.js` in your `index.html` file.
-
-````html
-<!-- path to ionic / angularjs files-->
-<script src="lib/ionic-toast/dist/ionic-toast.bundle.min.js"></script>
-````
-    
-**3)** In your application module inject the dependency `ionic-toast`, in order to work with the ionic toast.
-
-````javascript
-angular.module('mainModuleName', ['ionic', 'ionic-toast']){
- //
-}
-````
-
-**4)** Inject 'ionicToast' in your controller.
-
-````javascript
-.controller('HomeCtrl', ['$scope', 'ionicToast', function($scope, ionicToast) {
-  //code here
-}])
-````
-
-**5)** In your template, you can use like below
-
-````html
-<button class="button button-block" ng-click="showToast()">Show Toast at top with close</button>
-````
-
-**6)** In your controller you have to define a function like below to show the toast
-
-````javascript
-$scope.showToast = function(){
-<!-- ionicToast.show(message, position, stick, time); -->
-  ionicToast.show('This is a toast at the top.', 'top', true, 2500);
-};
-````
-
-The arguments are as follows. The order of arguments should not be changed.
-
-a) `message` is the first argument, which takes any string message.
-
-b) `position`(Optional) is the second argument, which takes on of the three values(top, middle, bottom). default position is `top`. 
-
-c) `stick`(Optional) is the third argument, which takes either `true` or `false`. Default value is false.
-- If the value is true, the toast will not close automatically. It will be closed once you click on the close button.
-- If the value is false, the toast will close automatically, after the given time. 
-
-d) `timeout`(Optional) is the fourth argument, which takes time in milliseconds. If the value is greater than 5000, then it will be considered as 5000(5 seconds) only. The default value is 4000 milli seconds.
-
-**7)** In your controller you have to define a function like below to hide the toast
-
-````javascript
-$scope.hideToast = function(){
-  ionicToast.hide();
-};
-````
-
-
-##Screen Shots:
-
-Once you are successfully done with the above steps, you should be able to see the below screen shots.
-I have used three buttons here. 
-
-The first screen shot shows only the buttons before clicking on them.
-Once you click on the button you should see the remaining screen shots.
- 
-![ionic-toast buttons](https://lh3.googleusercontent.com/Fc4fUe9_k6DktTMoNrpih_z5sSNoZs9XHuiyn4AcClw=w320-h568-no "ionic-toast buttons") 
-![ionic-toast top](https://lh3.googleusercontent.com/VDO5p9Z9KH6tC7zpTTk6mbkchKKBA4VYWpZuqLp9Jzc=w320-h568-no "ionic-toast top")
-![ionic-toast middle](https://lh3.googleusercontent.com/J7n3YRhRx68hIQmKLRJEKq6QfkxkAD7y_Jqc9eFDOtk=w320-h568-no "ionic-toast middle")
-![ionic-toast bottom](https://lh3.googleusercontent.com/MQyAFN9S8d8Pd05XALFcuhPiY_LNlKEIS9yWh-WKTh0=w320-h568-no "ionic-toast bottom")
-
-##Versions:
-
-### 1) v0.1.0
-The whole `ionic-toast` component functionality has been implemented, and it can be installed with the command `bower install ionic-toast --save`
-
-### 2) v0.1.1
-Bug Fix
-
-### 3) v0.2.0
-Lint issues fixed, npm packages updated, main files added in the package.json, changes in the gulp tasks.
-
-### 4) v0.3.0
-Code modularity implemented, npm packages updated.
-
-JS and CSS file is combined into one `ionic-toast.bundle.min.js` file in the dist folder.
-
-### 5) v0.4.0
-Bug fix.
-
-### 6) v0.4.1
-[Issue#21](https://github.com/rajeshwarpatlolla/ionic-toast/issues/21)
-
-
-##License:
-[MIT](https://github.com/rajeshwarpatlolla/ionic-toast/blob/master/LICENSE.md "MIT")
-
-##Contact:
-gmail : rajeshwar.patlolla@gmail.com
-
-github : https://github.com/rajeshwarpatlolla
-
-twitter : https://twitter.com/rajeshwar_9032
-
-facebook : https://www.facebook.com/rajeshwarpatlolla
-
-paypal : rajeshwar.patlolla@gmail.com
-
-Rate / Comment : http://market.ionic.io/plugins/ionictoast

+ 0 - 30
www/lib/ionic-toast/bower.json

@@ -1,30 +0,0 @@
-{
-  "name": "ionic-toast",
-  "version": "0.4.1",
-  "authors": [
-    "rajeshwarpatlolla <rajeshwar.patlolla@gmail.com>"
-  ],
-  "description": "'ionic-toast' bower component for ionic framework applications",
-  "main": [
-    "./dist/ionic-toast.bundle.min.js"
-  ],
-  "keywords": [
-    "ionic-toast",
-    "toast",
-    "ionic",
-    "toast for ionic",
-    "toast for ionic framework"
-  ],
-  "license": "MIT",
-  "homepage": "https://github.com/rajeshwarpatlolla/ionic-toast",
-  "ignore": [
-    "**/.*",
-    "node_modules",
-    "bower_components",
-    "test",
-    "tests"
-  ],
-  "dependencies": {
-    "ionic": ">=0.9.27"
-  }
-}

文件差異過大導致無法顯示
+ 0 - 0
www/lib/ionic-toast/dist/ionic-toast.bundle.min.js


+ 0 - 34
www/lib/ionic-toast/gulpfile.js

@@ -1,34 +0,0 @@
-var gulp = require('gulp');
-var del = require('del');
-var concat = require('gulp-concat');
-var uglify = require('gulp-uglify');
-var css2js = require("gulp-css2js");
-
-gulp.task('build', ['cssminify'], function () {
-  gulp.src(['./src/ionic-toast.js'])
-    .pipe(uglify())
-    .pipe(gulp.dest("./dist"));
-});
-
-gulp.task('css2js', function () {
-  return gulp.src("./src/*.css")
-    .pipe(css2js())
-    .pipe(gulp.dest("./dist/"));
-});
-
-gulp.task('del', function () {
-  del(['./dist/*']);
-});
-
-gulp.task('make-bundle', ['del', 'css2js'], function () {
-  return gulp.src(['./dist/*', './src/*.js'])
-    .pipe(concat('ionic-toast.bundle.min.js'))
-    .pipe(uglify())
-    .pipe(gulp.dest('./dist/'));
-});
-
-gulp.task('del-temp-files', ['make-bundle'], function () {
-  del(['./dist/style.js', './dist/ionic-toast.js']);
-});
-
-gulp.task('build', ['del-temp-files']);

+ 0 - 19
www/lib/ionic-toast/package.json

@@ -1,19 +0,0 @@
-{
-  "name": "ionic-toast",
-  "version": "0.4.1",
-  "description": "A toast for IONIC framework",
-  "main": [
-    "./dist/ionic-toast.bundle.min.js",
-    "./dist/style.css"
-  ],
-  "scripts": {},
-  "author": "https://github.com/rajeshwarpatlolla, rajeshwar.patlolla@gmail.com",
-  "license": "MIT",
-  "dependencies": {},
-  "devDependencies": {
-    "del": "^2.2.0",
-    "gulp-concat": "^2.6.0",
-    "gulp-css2js": "^1.0.2",
-    "gulp-uglify": "^1.5.3"
-  }
-}

+ 0 - 58
www/lib/ionic-toast/src/ionic-toast.css

@@ -1,58 +0,0 @@
-
-.ionic_toast {
-  z-index: 9999;
-}
-
-.toast_section {
-  color: #FFF;
-  cursor: default;
-  font-size: 1em;
-  display: none;
-  border-radius: 5px;
-  opacity: 1;
-  padding: 10px 30px 10px 10px;
-  margin: 10px;
-  position: fixed;
-  left: 0;
-  right: 0;
-  text-align: center;
-  z-index: 9999;
-  background-color: rgba(0, 0, 0, 0.75);
-}
-
-.ionic_toast_top {
-  top: 10px;
-}
-
-.ionic_toast_middle {
-  top: 40%;
-}
-
-.ionic_toast_bottom {
-  bottom: 10px;
-}
-
-.ionic_toast_close {
-  border-radius: 2px;
-  color: #CCCCCC;
-  cursor: pointer;
-  display: none;
-  position: absolute;
-  right: 4px;
-  top: 4px;
-  width: 20px;
-  height: 20px;
-}
-
-.toast_close_icon {
-  position: relative;
-  top: 1px;
-}
-
-.ionic_toast_sticky .ionic_toast_close {
-  display: block;
-}
-
-.ionic_toast_close:active {
-
-}

+ 0 - 4
www/lib/ionic-toast/src/ionic-toast.module.js

@@ -1,4 +0,0 @@
-'use strict';
-angular.module('ionic-toast', [
-  'ionic-toast.provider'
-]);

+ 0 - 90
www/lib/ionic-toast/src/ionic-toast.provider.js

@@ -1,90 +0,0 @@
-'use strict';
-angular.module('ionic-toast.provider', [])
-
-  .provider('ionicToast', function () {
-
-    var defaultConfig = {
-      position: 'top',
-      showClose: false,
-      theme: 'dark',
-      timeOut: 4000
-    };
-
-    this.configure = function (inputObj) {
-      angular.extend(defaultConfig, inputObj);
-    };
-
-
-    this.$get = ['$compile', '$document', '$interval', '$rootScope', '$templateCache', '$timeout',
-      function ($compile, $document, $interval, $rootScope, $templateCache, $timeout) {
-
-        var provider = {};
-        var $scope = $rootScope.$new();
-        var toastTimer = defaultConfig.timeOut;
-
-        var defaultScope = {
-          toastClass: '',
-          toastMessage: '',
-          toastStyle: {
-            display: 'none',
-            opacity: 0
-          }
-        };
-
-        var toastPosition = {
-          top: 'ionic_toast_top',
-          middle: 'ionic_toast_middle',
-          bottom: 'ionic_toast_bottom'
-        };
-
-        var toastTemplate = $compile($templateCache.get('ionic-toast/templates/ionic-toast.html'))($scope);
-
-        $scope.ionicToast = defaultScope;
-
-        $document.find('body').append(toastTemplate);
-
-        var toggleDisplayOfToast = function (display, opacity, callback) {
-          $scope.ionicToast.toastStyle = {
-            display: display,
-            opacity: opacity
-          };
-          $scope.ionicToast.toastStyle.opacity = opacity;
-          callback();
-        };
-
-        $scope.hideToast = function () {
-          toggleDisplayOfToast('none', 0, function () {
-          });
-        };
-
-        provider.show = function (message, position, isSticky, duration) {
-
-          if (!message) return;
-          position = position || defaultConfig.position;
-          duration = duration || defaultConfig.timeOut;
-
-          if (duration > 10000) duration = 10000;
-
-          angular.extend($scope.ionicToast, {
-            toastClass: toastPosition[position] + ' ' + (isSticky ? 'ionic_toast_sticky' : ''),
-            toastMessage: message
-          });
-
-          toggleDisplayOfToast('block', 1, function () {
-            if (isSticky)  return;
-
-            toastTimer = $timeout(function () {
-              $scope.hideToast();
-            }, duration);
-          });
-        };
-
-        provider.hide = function () {
-          $scope.hideToast();
-        };
-
-        return provider;
-
-      }
-    ];
-  });

+ 0 - 15
www/lib/ionic-toast/src/ionic-toast.run.js

@@ -1,15 +0,0 @@
-'use strict';
-angular.module('ionic-toast')
-
-  .run(['$templateCache', function ($templateCache) {
-    var toastTemplate = '<div class="ionic_toast">' +
-      '<div class="toast_section" ng-class="ionicToast.toastClass" ng-style="ionicToast.toastStyle" ng-click="hideToast()">' +
-      '<span class="ionic_toast_close">' +
-      '<i class="ion-android-close toast_close_icon"></i>' +
-      '</span>' +
-      '<span ng-bind-html="ionicToast.toastMessage"></span>' +
-      '</div>' +
-      '</div>';
-
-    $templateCache.put('ionic-toast/templates/ionic-toast.html', toastTemplate);
-  }]);

+ 28 - 0
www/lib/ti-segmented-control/.bower.json

@@ -0,0 +1,28 @@
+{
+  "name": "ti-segmented-control",
+  "version": "0.0.2",
+  "main": "dist/ti-segmented-control.js",
+  "homepage": "https://github.com/tinga-dev/ti-ionic-segmented-control",
+  "authors": [
+    "Richard Larsson <ri.la@me.com>",
+    "Mikael Bolmstam <mikael.bolmstam@gmail.com>"
+  ],
+  "ignore": [
+    ".gitignore",
+    "bower.json",
+    "LICENCE",
+    "README.md"
+  ],
+  "description": "iOS segmented control directive for ionic apps",
+  "license": "MIT",
+  "_release": "0.0.2",
+  "_resolution": {
+    "type": "version",
+    "tag": "v0.0.2",
+    "commit": "bde8f38b035632906b451522f7a4295ffadad209"
+  },
+  "_source": "https://github.com/tinga-dev/ti-ionic-segmented-control.git",
+  "_target": "^0.0.2",
+  "_originalSource": "ti-segmented-control",
+  "_direct": true
+}

+ 6 - 5
www/lib/ionic-toast/LICENSE.md → www/lib/ti-segmented-control/LICENSE

@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2015 Rajeshwar Patlolla
+Copyright (c) 2015 tinga-dev
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -9,13 +9,14 @@ 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 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.
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+

+ 18 - 0
www/lib/ti-segmented-control/bower.json

@@ -0,0 +1,18 @@
+{
+  "name": "ti-segmented-control",
+  "version": "0.0.1",
+  "main": "dist/ti-segmented-control.js",
+  "homepage": "https://github.com/tinga-dev/ti-ionic-segmented-control",
+  "authors": [
+    "Richard Larsson <ri.la@me.com>",
+    "Mikael Bolmstam <mikael.bolmstam@gmail.com>"
+  ],
+  "ignore": [
+    ".gitignore",
+    "bower.json",
+    "LICENCE",
+    "README.md"
+  ],
+  "description": "iOS segmented control directive for ionic apps",
+  "license": "MIT"
+}

+ 50 - 0
www/lib/ti-segmented-control/dist/ti-segmented-control.js

@@ -0,0 +1,50 @@
+angular.module('ti-segmented-control', []
+).directive('tiSegmentedControl', function () {
+    return {
+        restrict: 'E',
+        transclude: true,
+        replace: true,
+        scope: {
+            onSelect: "&"
+        },
+        template: '<div class=\"buttons\"><div class=\"button-bar bar-light ti-segmented-control\" ng-transclude></div></div>',
+
+        controller: function($scope){
+            this.buttons = [];
+            this.setSelectedButton = function (title) {
+                $scope.onSelect({$index: this.buttons.indexOf(title)});
+            }
+            var style = window.document.createElement('style');
+            style.type = 'text/css';
+            style.innerHTML += '.button.button-outline.ti-segmented-control:first-child { border-top-left-radius: 5px;border-bottom-left-radius: 5px; }';
+            style.innerHTML += '.button.button-outline.ti-segmented-control { line-height: 23px;max-height: 25px;min-height: 25px; }';
+            style.innerHTML += '.button.button-outline.ti-segmented-control:last-child { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }';
+            style.innerHTML += '.button.button-outline.ti-segmented-control.activated { color: #fafafa;box-shadow: none; }';
+            window.document.getElementsByTagName('head')[0].appendChild(style);
+        },
+        link: function (scope) {
+        }
+    }
+}).directive('tiSegmentedControlButton', function () {
+    return {
+        replace: true,
+        require: '^tiSegmentedControl',
+        scope: {
+            title: '='
+        },
+        template: '<a class=\"button button-outline ti-segmented-control\">{{title}}</a>',
+        link: function(scope, element, attr, segmentedControlCtrl){
+            segmentedControlCtrl.buttons.push(scope.title);
+            if(attr.selected != undefined) element.addClass('active');
+
+            element.bind('click', function(){
+                segmentedControlCtrl.setSelectedButton(scope.title);
+                var buttons = angular.element(angular.element(element.parent()[0]).children());
+                for(var i = 0; i < buttons.length; i++){
+                    angular.element(buttons[i]).removeClass('active');
+                }
+                element.addClass('active');
+            });
+        }
+    }
+});

文件差異過大導致無法顯示
+ 4 - 0
www/templates/sales/customer.html


文件差異過大導致無法顯示
+ 3 - 3
www/templates/sales/customers.html


文件差異過大導致無法顯示
+ 10 - 10
www/templates/sales/leads.html


+ 26 - 14
www/templates/sales/opportunities.html

@@ -1,28 +1,40 @@
-<ion-view title="Oportunidades <small>[ {{ currentStage.name | translate }} ]</small>">
+<ion-view title="Oportunidades">
 
     <ion-nav-buttons side="right">
-        <button class="button button-clear ion-chevron-left bar-icon" ng-disabled="slider.isBeginning" ng-click="changeStage(0)"></i></button>
-        <button class="button button-clear ion-chevron-right bar-icon" ng-disabled="slider.isEnd" ng-click="changeStage(1)"></i></button>
+        <button class="button button-clear ion-search bar-icon" ng-click="toggleSearch()"></i></button>
+        <button class="button button-clear ion-plus-round bar-icon" ng-click="toogleNew()"></i></button>
     </ion-nav-buttons>
 
-    <ion-content delegate-handle="mainScroll">
+    <ion-content padding="true">
 
-        <ion-spinner class="centered-spinner" ng-show="loading"></ion-spinner>
+        <ti-segmented-control>
+            <ti-segmented-control-button class="button-stable" title="stage.previous.name | translate" ng-click="changeStage(0)" ng-show="!slider.isBeginning"></ti-segmented-control-button>
+            <ti-segmented-control-button class="button-positive" title="stage.current.name | translate" ng-click="changeStage(1)"></ti-segmented-control-button>
+            <ti-segmented-control-button class="button-stable" title="stage.next.name | translate" ng-click="changeStage(2)" ng-show="!slider.isEnd"></ti-segmented-control-button>
+        </ti-segmented-control>
 
-        <ion-slides ng-show="!loading" on-swipe-left="changeStage(0)" on-swipe-right="changeStage(1)" slider="data.slider">
+        <ion-slides on-swipe-left="changeStage(0)" on-swipe-right="changeStage(1)" slider="data.slider">
             <ion-slide-page ng-repeat="s in stages">
-                <ion-scroll style="height: 500px;">
-                    <ion-list type="card" style="height: 2000px;" ng-show="!opportunities || opportunities.length != 0">
-                        <ion-item ng-class="{'holded': selected == $index }" on-hold="openOptions($index)" ng-repeat="o in opportunities">
+
+                <ion-scroll style="height: 500px;" ng-show="!loading && (!groupedOpportunities || groupedOpportunities.length != 0)">
+
+                    <ion-list type="card" style="height: 2000px;">
+
+                        <ion-item on-hold="openOptions($index)" ng-class="{'holded': selectedIndex == $index }" ng-repeat="o in groupedOpportunities">
                             <h2><strong>{{ o.name | uppercase }}</strong></h2>
-                            <p><strong>Contacto:</strong> {{ o.contact_name }}</p>
-                            <p><strong>Teléfono:</strong> {{ o.phone }}</p>
-                            <p><strong>Móvil:</strong> {{ o.mobile }}</p>
-                            <ion-option-button class="button-positive" ng-click="share(item)">Share</ion-option-button>
+                            <p><strong>Contacto:</strong> {{ o.contact_name || '' }}</p>
+                            <p><strong>Teléfono:</strong> {{ o.phone || '' }}</p>
+                            <p><strong>Móvil:</strong> {{ o.mobile || '' }}</p>
                         </ion-item>
+
                     </ion-list>
                 </ion-scroll>
+
             </ion-slide-page>
         </ion-slides>
+
+        <ion-spinner class="centered-spinner" ng-show="loading"></ion-spinner>
+        <img class="empty-data" ng-src="img/empty.png" ng-show="!loading && (groupedOpportunities == undefined || groupedOpportunities.length == 0)">
+
     </ion-content>
-</ion-view>
+</ion-view>

部分文件因文件數量過多而無法顯示