<commit_before>(function() {
  'use strict';

  angular
    .module('esim-app')
    .run(runFn);

  runFn.$inject = ['$ionicPlatform', '$ionicAnalytics', '$cordovaSplashscreen', '$rootScope', '$log', '$state', '$ionicPopup', 'Toast'];

  /* @ngInject */
  function runFn($ionicPlatform, $ionicAnalytics, $cordovaSplashscreen, $rootScope, $log, $state, $ionicPopup, Toast) {
    $ionicPlatform.ready(function (){

        /*----- Toast i ver<4  -----*/
        if (ionic.Platform.isAndroid()){
        var currentPlatformVersion = ionic.Platform.version();
          if(currentPlatformVersion < 14 && localStorage.getItem("alreadyLogged")){ //android 4.0
            $state.go('login');
          }else{
          if(confirm('e-Sim Application can work wrong on Android less than Android 4.0.')){
            localStorage.setItem("alreadyLogged","true"); // zapisz do storage
            }
          }
        }else{}

    $ionicPlatform.ready(function() {
        /*----- Analytics  -----*/

        // $ionicAnalytics.register({silent: true});

        /*----- AdMob inicjalizacja -----*/
        if (window.plugins) {
          var admobid = {};
          if (/(android)/i.test(navigator.userAgent)) { // for android
            admobid = {
              banner: 'ca-app-pub-7561623930514913/9310831791', // or DFP format "/6253334/dfp_example_ad"
            };
          } else if (/(ipod|iphone|ipad)/i.test(navigator.userAgent)) { // for ios
            admobid = {
              banner: 'ca-app-pub-7561623930514913/1196758192', // or DFP format "/6253334/dfp_example_ad"
            };
          } else { // for windows phone
            admobid = {
              banner: 'ca-app-pub-xxx/zzz', // or DFP format "/6253334/dfp_example_ad"
            };
          }
          if (!AdMob) {
            console.log('admob plugin not ready');
            return;
          }
          /*----- AdMob Dodanie reklam  -----*/
          AdMob.createBanner({
            adId: admobid.banner,
            isTesting: false,
            overlap: false,
            offsetTopBar: false,
            position: AdMob.AD_POSITION.BOTTOM_CENTER,
            bgColor: 'black'
          });

        }
      })
      .then(function GeneralConfig() {

        $log.debug("GeneralConfig fired");
        $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
          Toast(error);
        });
        //$cordovaSplashscreen.hide(); wywala error - trzeba zbadac
      })
      .then(function() {
        $log.debug("BackButtonConfig fired");
        $ionicPlatform.registerBackButtonAction(function() {
          //Wylaczamy standardowe zachowanie przycisku zeby kontrolowac go troche precyzyjniej
        }, 100);
        $ionicPlatform.onHardwareBackButton(function() {
          $log.debug("Back button: currentState: " + $state.current.name);
          $log.debug("Back button: $state.includes('login'): " + $state.includes('login'));
          $log.debug("Back button: $state.includes('main.main'): " + $state.includes('main.main'));
          if ($state.includes('login') || $state.includes('main.main')) {
            $ionicPopup.confirm({
              title: 'Quit e-Sim?'
            }).then(function(res) {
              if (res) {
                ionic.Platform.exitApp();
              }
            });
          } else {
            $state.go('main.main');
          }
        });
      });
  }

})();
<commit_msg>little change<commit_after>(function() {
    'use strict';

    angular
      .module('esim-app')
      .run(runFn);

    runFn.$inject = ['$ionicPlatform', '$ionicAnalytics', '$cordovaSplashscreen', '$rootScope', '$log', '$state', '$ionicPopup', 'Toast'];

    /* @ngInject */
    function runFn($ionicPlatform, $ionicAnalytics, $cordovaSplashscreen, $rootScope, $log, $state, $ionicPopup, Toast) {
      $ionicPlatform.ready(function() {

          /*----- Toast i ver<4  -----*/
          if (ionic.Platform.isAndroid()) {
            var currentPlatformVersion = ionic.Platform.version();
            if (currentPlatformVersion < 14 && localStorage.getItem("alreadyLogged")) { //android 4.0
              $state.go('login');
            } else {
              if (confirm('e-Sim Application can work wrong on Android less than Android 4.0.')) {
                localStorage.setItem("alreadyLogged", "true"); // zapisz do storage
              }
            }
          } else {}

          $ionicPlatform.ready(function() {
              /*----- Analytics  -----*/

              // $ionicAnalytics.register({silent: true});

              /*----- AdMob inicjalizacja -----*/
              if (window.plugins) {
                var admobid = {};
                if (/(android)/i.test(navigator.userAgent)) { // for android
                  admobid = {
                    banner: 'ca-app-pub-7561623930514913/9310831791', // or DFP format "/6253334/dfp_example_ad"
                  };
                } else if (/(ipod|iphone|ipad)/i.test(navigator.userAgent)) { // for ios
                  admobid = {
                    banner: 'ca-app-pub-7561623930514913/1196758192', // or DFP format "/6253334/dfp_example_ad"
                  };
                } else { // for windows phone
                  admobid = {
                    banner: 'ca-app-pub-xxx/zzz', // or DFP format "/6253334/dfp_example_ad"
                  };
                }
                if (!AdMob) {
                  console.log('admob plugin not ready');
                  return;
                }
                /*----- AdMob Dodanie reklam  -----*/
                AdMob.createBanner({
                  adId: admobid.banner,
                  isTesting: false,
                  overlap: false,
                  offsetTopBar: false,
                  position: AdMob.AD_POSITION.BOTTOM_CENTER,
                  bgColor: 'black'
                });

              }
            })
            .then(function GeneralConfig() {

              $log.debug("GeneralConfig fired");
              $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
                Toast(error);
              });
              //$cordovaSplashscreen.hide(); wywala error - trzeba zbadac
            })
            .then(function() {
              $log.debug("BackButtonConfig fired");
              $ionicPlatform.registerBackButtonAction(function() {
                //Wylaczamy standardowe zachowanie przycisku zeby kontrolowac go troche precyzyjniej
              }, 100);
              $ionicPlatform.onHardwareBackButton(function() {
                $log.debug("Back button: currentState: " + $state.current.name);
                $log.debug("Back button: $state.includes('login'): " + $state.includes('login'));
                $log.debug("Back button: $state.includes('main.main'): " + $state.includes('main.main'));
                if ($state.includes('login') || $state.includes('main.main')) {
                  $ionicPopup.confirm({
                    title: 'Quit e-Sim?'
                  }).then(function(res) {
                    if (res) {
                      ionic.Platform.exitApp();
                    }
                  });
                } else {
                  $state.go('main.main');
                }
              });
            });
        });
      }

      })();
<|endoftext|>


<commit_before>define(["webL10n",
        "sugar-web/activity/shortcut",
        "sugar-web/bus",
        "sugar-web/env",
        "sugar-web/datastore",
        "sugar-web/graphics/icon",
        "sugar-web/graphics/activitypalette"], function (
    l10n, shortcut, bus, env, datastore, icon, activitypalette) {

    var datastoreObject = null;

    var activity = {};

    activity.setup = function () {
        bus.listen();

        l10n.start();

        datastoreObject = new datastore.DatastoreObject();

        var activityButton = document.getElementById("activity-button");

        var activityPalette = new activitypalette.ActivityPalette(
            activityButton, datastoreObject);

        // Colorize the activity icon.
        activity.getXOColor(function (error, colors) {
            icon.colorize(activityButton, colors);
            invokerElem =
                document.querySelector("#activity-palette .palette-invoker");
            icon.colorize(invokerElem, colors);
        });

        // Make the activity stop with the stop button.
        var stopButton = document.getElementById("stop-button");
        stopButton.addEventListener('click', function (e) {
            activity.close();
        });

        shortcut.add("Ctrl", "Q", this.close);

        env.getEnvironment(function (error, environment) {
            if (!environment.objectId) {
                datastoreObject.setMetadata({
                    "title": environment.activityName + " Activity",
                    "title_set_by_user": "0",
                    "activity": environment.bundleId,
                    "activity_id": environment.activityId
                });
            }
            datastoreObject.save(function () {
                datastoreObject.getMetadata(function (error, metadata) {
                    activityPalette.setTitleDescription(metadata);
                });
            });
        });
    };

    activity.getDatastoreObject = function () {
        return datastoreObject;
    };

    activity.getXOColor = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null, {
                    stroke: result[0][0],
                    fill: result[0][1]
                });
            } else {
                callback(null, {
                    stroke: "#00A0FF",
                    fill: "#8BFF7A"
                });
            }
        }

        bus.sendMessage("activity.get_xo_color", [], onResponseReceived);
    };

    activity.close = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null);
            } else {
                console.log("activity.close called");
            }
        }

        bus.sendMessage("activity.close", [], onResponseReceived);
    };

    activity.showObjectChooser = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null, result[0]);
            } else {
                console.log("activity.show_object_chooser called");
            }
        }

        bus.sendMessage("activity.show_object_chooser", [], onResponseReceived);
    };

    return activity;
});
<commit_msg>Send an error to the callback<commit_after>define(["webL10n",
        "sugar-web/activity/shortcut",
        "sugar-web/bus",
        "sugar-web/env",
        "sugar-web/datastore",
        "sugar-web/graphics/icon",
        "sugar-web/graphics/activitypalette"], function (
    l10n, shortcut, bus, env, datastore, icon, activitypalette) {

    var datastoreObject = null;

    var activity = {};

    activity.setup = function () {
        bus.listen();

        l10n.start();

        datastoreObject = new datastore.DatastoreObject();

        var activityButton = document.getElementById("activity-button");

        var activityPalette = new activitypalette.ActivityPalette(
            activityButton, datastoreObject);

        // Colorize the activity icon.
        activity.getXOColor(function (error, colors) {
            icon.colorize(activityButton, colors);
            invokerElem =
                document.querySelector("#activity-palette .palette-invoker");
            icon.colorize(invokerElem, colors);
        });

        // Make the activity stop with the stop button.
        var stopButton = document.getElementById("stop-button");
        stopButton.addEventListener('click', function (e) {
            activity.close();
        });

        shortcut.add("Ctrl", "Q", this.close);

        env.getEnvironment(function (error, environment) {
            if (!environment.objectId) {
                datastoreObject.setMetadata({
                    "title": environment.activityName + " Activity",
                    "title_set_by_user": "0",
                    "activity": environment.bundleId,
                    "activity_id": environment.activityId
                });
            }
            datastoreObject.save(function () {
                datastoreObject.getMetadata(function (error, metadata) {
                    activityPalette.setTitleDescription(metadata);
                });
            });
        });
    };

    activity.getDatastoreObject = function () {
        return datastoreObject;
    };

    activity.getXOColor = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null, {
                    stroke: result[0][0],
                    fill: result[0][1]
                });
            } else {
                callback(null, {
                    stroke: "#00A0FF",
                    fill: "#8BFF7A"
                });
            }
        }

        bus.sendMessage("activity.get_xo_color", [], onResponseReceived);
    };

    activity.close = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null);
            } else {
                callback(error, null);
            }
        }

        bus.sendMessage("activity.close", [], onResponseReceived);
    };

    activity.showObjectChooser = function (callback) {
        function onResponseReceived(error, result) {
            if (error === null) {
                callback(null, result[0]);
            } else {
                callback(error, null);
            }
        }

        bus.sendMessage("activity.show_object_chooser", [], onResponseReceived);
    };

    return activity;
});
<|endoftext|>


<commit_before>app.controller('MainController', ['$scope', '$http', function($scope, $http) {

	$scope.locale = "enUS"; //This is the language. Use these: enUS frFR

	$scope.person = {
		"name": "Martin Verdier", //That's your name!
		"birthdate": new Date(1994, 10, 27), //Here is your birthdate
		"role": "Backend software developer", //The role you're probably looking for
		"phone": "0033624726458", //Your phone (This is the version that's going to be called, put it in a single block!)
		"phoneDisplay": "(+33) 6 24 72 64 58", //Your phone for the display, the one that a human can easily read!
		"email": "mart.verdier@gmail.com", //Your email
		"picture": "resources/profile.png", //The relative path to your picture in the project's folder (relative to resume.html)
		"github": "mverdier" //Your GitHub link, if you have one
	};

	/*
	This is your school data. In there you'll put the several degrees you've earned,
	as well as your certifications or stuff like that.

	The format is pretty straight-forward, each element has a title, dates, and a location:
	{
		"title": "Your degree, like Bachelor Degree in Computer Science",
		"dates": "The dates between which you workd on that degree, like 2010-2013",
		"location": "Which establishment gave it to you, for example Massachusetts Institute of Technology, Boston, MA"
	}

	I strongly recommend putting them in anti-chronological order (more recent first, older last).
	That's it. You can fill those and put as many as you like.
	*/
	$scope.school = [{
		"title": "APSIO Professional Bachelor",
		"dates": "2014 - 2015",
		"location": "Blagnac IUT, France"
	},
	{
		"title": "DUT in Computer Science (2-year diploma)",
		"dates": "2012 - 2014",
		"location": "Rodez IUT, France"
	},
	{
		"title": "Baccalauréat Scientifique (Engineer Science Option), mention AB",
		"dates": "2012",
		"location": "Antoine Bourdelle High School, Montauban, France"
	}]

	/*
	This is a tad more complete than the school part.
	Basically in there you'll put every work experience you've had.
	Each of them will have information available as such:

	{
		"type": "Type of contract, like an Internship",
		"dates": "Same as for school, the dates between which you've worked under this contract, like 2012-2013",
		"role": "Your role in the company during this contract, Web Developer for example",
		"company": "The company you worked in, might be Microsoft",
		"location": "Where you worked, as in a city, state format, for example in Denver, CO",
		"techs": "Which techs you used. This is a bit developer-specific and might not apply to you, don't bother putting it if you don't feel like it helps. Otherwise, for example PHP, HTML5, CSS3",
		"url": "The website of the company you worked in, or of the project you worked on. http://microsoft.com/",
		"displayUrl": "A nice, clean version of the website URL, easily readable by humans, like microsoft.com",
		"tasks": [{
			"content": "Content of the task you worked on"
		},
		{
			"content": "Content of another task"
		}]
	}

	I strongly recommend putting them in anti-chronological order (more recent first, older last).
	*/
	$scope.work = [{
		"type": "Permanent contract",
		"dates": "2018 - Current",
		"role": "Software Engineer",
		"company": "Adyen",
		"location": "Amsterdam, The Netherlands",
		"techs": "Java, PostgreSQL, XML",
		"url": "https://www.adyen.com/",
		"displayUrl": "www.adyen.com",
		"tasks": [{
			"content": "Working on the onboarding team: writing software for checking new merchants' information."
		}]
	},
	{
		"type": "Permanent contract",
		"dates": "2015 - 2018",
		"role": "Lead Java developer",
		"company": "Telegrafik",
		"location": "Toulouse, France",
		"techs": "Java, MongoDB, AngularJS, HTML5, CSS3, Python",
		"url": "http://www.telegrafik.eu/",
		"displayUrl": "www.telegrafik.eu",
		"tasks": [{
			"content": "Improving the software by developing new features"
		},
		{
			"content": "Created a rule engine allowing helpers to set personal alarms according to their close one's behavior"
		},
		{
			"content": "Tons of bug fixing and software optimization"
		},
		{
			"content": "Work distribution to other developers"
		},
		{
			"content": "Supervision and validation of other developers' work"
		},
		{
			"content": "Managing software deployment process, branch merging, production pushes"
		},
		{
			"content": "Managing the evolutions and optimizations of the database"
		}]
	},
	{
		"type": "One-year Apprenticeship",
		"dates": "2014 - 2015",
		"role": "Software developer",
		"company": "Telegrafik",
		"location": "Toulouse, France",
		"techs": "Java, MongoDB, AngularJS, HTML5, CSS3",
		"url": "http://www.telegrafik.eu/",
		"displayUrl": "www.telegrafik.eu",
		"tasks": [{
			"content": "Updated software features"
		},
		{
			"content": "Developed an artificial intelligence and machine learning engine"
		},
		{
			"content": "Maintained and adapted pre-existing features"
		},
		{
			"content": "Updated the dynamic web dashboards"
		},
		{
			"content": "Updated the MongoDB database"
		},
		{
			"content": "Worked with a Python developer for intelligence metrics"
		}]

	},
	{
		"type": "Ten-week internship",
		"dates": "2014",
		"role": "Full-stack web and Android developer",
		"company": "Visual-2000",
		"location": "Montréal, Canada",
		"techs": "HTML5, CSS3, JS, PHP, SQL, Android",
		"url": "http://qeepr.com/",
		"displayUrl": "www.qeepr.com",
		"tasks": [{
			"content": "Entirely remade signup, login, and genealogy tree pages"
		},
		{
			"content": "Added picture uploading feature to the signup page"
		},
		{
			"content": "Added a QR code selling feature in the website"
		},
		{
			"content": "Updated and developed several features"
		},
		{
			"content": "Developed an Android application using geolocation, QR code scanning, and website data access features"
		}]
	}]

	/*
	Skills are a complex yet simple type of data here
	What you want to do is separate your skills in categories (Web development, Microsoft Suite, Personal skills, ...)
	and fill it as such. Here is the format:

	{
		"category": "The category of skills, such as Web Development",
		"more": [{
			"name": "A skill you're good at, like PHP"
		},
		{
			"name": "Another skill you're good at, like HTML5"
		}],
		"less": [{
			"name": "A skill you know but you haven't yet practiced enough"
		}]
	}

	You can put in as many categories as you like, with as many skills as you like.
	Neither more or less are mandatory. You can have both, or only one, the webpage will adapt consequently.
	You should still put at least one "more" or one "less". You don't /have to/ but otherwise you'll have
	an empty card with just a title. But if that's your kind of stuff, go for it, who am I to stop you.
	Be crative, that's the important stuff!
	*/
	$scope.skills = [{
		"category": "Object-Oriented Programming",
		"more": [{
			"name": "Java 8"
		},
		{
			"name": "PHP"
		},
		{
			"name": "Android"
		},
		{
			"name": "C#"
		},
		],
		"less": [{
			"name": "C++"
		},
		{
			"name": "Ruby"
		}]

	},
	{
		"category": "Web Development",
		"more": [{
			"name": "HTML5"
		},
		{
			"name": "CSS3"
		},
		{
			"name": "JavaScript"
		}],
		"less": [{
			"name": "AngularJS"
		},
		{
			"name": "Node.JS"
		},
		{
			"name": "Ruby on Rails"
		}]
	},
	{
		"category": "Databases",
		"more": [{
			"name": "MongoDB"
		},
		{
			"name": "SQL"
		}]
	},
	{
		"category": "Systems",
		"less": [{
			"name": "Linux"
		}],
		"more": [{
			"name": "Bash"
		}]
	}];

	/*
	This is one of the two "misc" parts!
	This thing right here is about *you*. Not what you can do, not what you know, who you are. What you like!
	Basically if you're into say, hockey, you can put that here. Drawing? Yeah, sure, go ahead!
	Keep in mind that you might get questions about this stuff because it can be considered things you /really/ like.
	So, dont just put "movies" if you watch one every month or so, except if it's really out of real interest in specific movies!

	Well I'm not your mother, do what you want here. Just do it like so:
	{
		"title": "Your interest"
	}

	Here too, put in as many as you want. If I were to say, I would advise about 5 should be a ceiling.
	But again, I'm not your mother.
	*/
	$scope.likes = [{
		"title": "Traveling"
	},
	{
		"title": "Cartography"
	},
	{
		"title": "Photography"
	}];

	/*
	The second misc part!
	This is the classic "which languages can I speak, and how good?" part of a resume.

	The format comes in its classic way as well:
	{
		"name": "The language you know, like Spanish",
		"level": "How well you master it, like School Level or Native or Bilingual or Professional. This is not exhaustive."
	}

	Here again, put as many as you like. Depending on your job you might want 2 or 10 of those.
	*/
	$scope.languages = [{
		"name": "French",
		"level": "Native"
	},
	{
		"name": "English",
		"level": "Bilingual"
	}];

	// Function calculating the age, courtesy of user pxixelbits on StackOverflow
	// http://stackoverflow.com/a/24883386/4197752
	$scope.calculateAge = function calculateAge(birthday) { // birthday is a date
		var ageDifMs = Date.now() - birthday.getTime();
		var ageDate = new Date(ageDifMs); // miliseconds from epoch
		return Math.abs(ageDate.getUTCFullYear() - 1970);
	}

}]);
<commit_msg>Updated phone number<commit_after>app.controller('MainController', ['$scope', '$http', function($scope, $http) {

	$scope.locale = "enUS"; //This is the language. Use these: enUS frFR

	$scope.person = {
		"name": "Martin Verdier", //That's your name!
		"birthdate": new Date(1994, 10, 27), //Here is your birthdate
		"role": "Backend software developer", //The role you're probably looking for
		"phone": "0031683811277", //Your phone (This is the version that's going to be called, put it in a single block!)
		"phoneDisplay": "(+31) 6 83 81 12 77", //Your phone for the display, the one that a human can easily read!
		"email": "mart.verdier@gmail.com", //Your email
		"picture": "resources/profile.png", //The relative path to your picture in the project's folder (relative to resume.html)
		"github": "mverdier" //Your GitHub link, if you have one
	};

	/*
	This is your school data. In there you'll put the several degrees you've earned,
	as well as your certifications or stuff like that.

	The format is pretty straight-forward, each element has a title, dates, and a location:
	{
		"title": "Your degree, like Bachelor Degree in Computer Science",
		"dates": "The dates between which you workd on that degree, like 2010-2013",
		"location": "Which establishment gave it to you, for example Massachusetts Institute of Technology, Boston, MA"
	}

	I strongly recommend putting them in anti-chronological order (more recent first, older last).
	That's it. You can fill those and put as many as you like.
	*/
	$scope.school = [{
		"title": "APSIO Professional Bachelor",
		"dates": "2014 - 2015",
		"location": "Blagnac IUT, France"
	},
	{
		"title": "DUT in Computer Science (2-year diploma)",
		"dates": "2012 - 2014",
		"location": "Rodez IUT, France"
	},
	{
		"title": "Baccalauréat Scientifique (Engineer Science Option), mention AB",
		"dates": "2012",
		"location": "Antoine Bourdelle High School, Montauban, France"
	}]

	/*
	This is a tad more complete than the school part.
	Basically in there you'll put every work experience you've had.
	Each of them will have information available as such:

	{
		"type": "Type of contract, like an Internship",
		"dates": "Same as for school, the dates between which you've worked under this contract, like 2012-2013",
		"role": "Your role in the company during this contract, Web Developer for example",
		"company": "The company you worked in, might be Microsoft",
		"location": "Where you worked, as in a city, state format, for example in Denver, CO",
		"techs": "Which techs you used. This is a bit developer-specific and might not apply to you, don't bother putting it if you don't feel like it helps. Otherwise, for example PHP, HTML5, CSS3",
		"url": "The website of the company you worked in, or of the project you worked on. http://microsoft.com/",
		"displayUrl": "A nice, clean version of the website URL, easily readable by humans, like microsoft.com",
		"tasks": [{
			"content": "Content of the task you worked on"
		},
		{
			"content": "Content of another task"
		}]
	}

	I strongly recommend putting them in anti-chronological order (more recent first, older last).
	*/
	$scope.work = [{
		"type": "Permanent contract",
		"dates": "2018 - Current",
		"role": "Software Engineer",
		"company": "Adyen",
		"location": "Amsterdam, The Netherlands",
		"techs": "Java, PostgreSQL, XML",
		"url": "https://www.adyen.com/",
		"displayUrl": "www.adyen.com",
		"tasks": [{
			"content": "Working on the onboarding team: writing software for checking new merchants' information."
		}]
	},
	{
		"type": "Permanent contract",
		"dates": "2015 - 2018",
		"role": "Lead Java developer",
		"company": "Telegrafik",
		"location": "Toulouse, France",
		"techs": "Java, MongoDB, AngularJS, HTML5, CSS3, Python",
		"url": "http://www.telegrafik.eu/",
		"displayUrl": "www.telegrafik.eu",
		"tasks": [{
			"content": "Improving the software by developing new features"
		},
		{
			"content": "Created a rule engine allowing helpers to set personal alarms according to their close one's behavior"
		},
		{
			"content": "Tons of bug fixing and software optimization"
		},
		{
			"content": "Work distribution to other developers"
		},
		{
			"content": "Supervision and validation of other developers' work"
		},
		{
			"content": "Managing software deployment process, branch merging, production pushes"
		},
		{
			"content": "Managing the evolutions and optimizations of the database"
		}]
	},
	{
		"type": "One-year Apprenticeship",
		"dates": "2014 - 2015",
		"role": "Software developer",
		"company": "Telegrafik",
		"location": "Toulouse, France",
		"techs": "Java, MongoDB, AngularJS, HTML5, CSS3",
		"url": "http://www.telegrafik.eu/",
		"displayUrl": "www.telegrafik.eu",
		"tasks": [{
			"content": "Updated software features"
		},
		{
			"content": "Developed an artificial intelligence and machine learning engine"
		},
		{
			"content": "Maintained and adapted pre-existing features"
		},
		{
			"content": "Updated the dynamic web dashboards"
		},
		{
			"content": "Updated the MongoDB database"
		},
		{
			"content": "Worked with a Python developer for intelligence metrics"
		}]

	},
	{
		"type": "Ten-week internship",
		"dates": "2014",
		"role": "Full-stack web and Android developer",
		"company": "Visual-2000",
		"location": "Montréal, Canada",
		"techs": "HTML5, CSS3, JS, PHP, SQL, Android",
		"url": "http://qeepr.com/",
		"displayUrl": "www.qeepr.com",
		"tasks": [{
			"content": "Entirely remade signup, login, and genealogy tree pages"
		},
		{
			"content": "Added picture uploading feature to the signup page"
		},
		{
			"content": "Added a QR code selling feature in the website"
		},
		{
			"content": "Updated and developed several features"
		},
		{
			"content": "Developed an Android application using geolocation, QR code scanning, and website data access features"
		}]
	}]

	/*
	Skills are a complex yet simple type of data here
	What you want to do is separate your skills in categories (Web development, Microsoft Suite, Personal skills, ...)
	and fill it as such. Here is the format:

	{
		"category": "The category of skills, such as Web Development",
		"more": [{
			"name": "A skill you're good at, like PHP"
		},
		{
			"name": "Another skill you're good at, like HTML5"
		}],
		"less": [{
			"name": "A skill you know but you haven't yet practiced enough"
		}]
	}

	You can put in as many categories as you like, with as many skills as you like.
	Neither more or less are mandatory. You can have both, or only one, the webpage will adapt consequently.
	You should still put at least one "more" or one "less". You don't /have to/ but otherwise you'll have
	an empty card with just a title. But if that's your kind of stuff, go for it, who am I to stop you.
	Be crative, that's the important stuff!
	*/
	$scope.skills = [{
		"category": "Object-Oriented Programming",
		"more": [{
			"name": "Java 8"
		},
		{
			"name": "PHP"
		},
		{
			"name": "Android"
		},
		{
			"name": "C#"
		},
		],
		"less": [{
			"name": "C++"
		},
		{
			"name": "Ruby"
		}]

	},
	{
		"category": "Web Development",
		"more": [{
			"name": "HTML5"
		},
		{
			"name": "CSS3"
		},
		{
			"name": "JavaScript"
		}],
		"less": [{
			"name": "AngularJS"
		},
		{
			"name": "Node.JS"
		},
		{
			"name": "Ruby on Rails"
		}]
	},
	{
		"category": "Databases",
		"more": [{
			"name": "MongoDB"
		},
		{
			"name": "SQL"
		}]
	},
	{
		"category": "Systems",
		"less": [{
			"name": "Linux"
		}],
		"more": [{
			"name": "Bash"
		}]
	}];

	/*
	This is one of the two "misc" parts!
	This thing right here is about *you*. Not what you can do, not what you know, who you are. What you like!
	Basically if you're into say, hockey, you can put that here. Drawing? Yeah, sure, go ahead!
	Keep in mind that you might get questions about this stuff because it can be considered things you /really/ like.
	So, dont just put "movies" if you watch one every month or so, except if it's really out of real interest in specific movies!

	Well I'm not your mother, do what you want here. Just do it like so:
	{
		"title": "Your interest"
	}

	Here too, put in as many as you want. If I were to say, I would advise about 5 should be a ceiling.
	But again, I'm not your mother.
	*/
	$scope.likes = [{
		"title": "Traveling"
	},
	{
		"title": "Cartography"
	},
	{
		"title": "Photography"
	}];

	/*
	The second misc part!
	This is the classic "which languages can I speak, and how good?" part of a resume.

	The format comes in its classic way as well:
	{
		"name": "The language you know, like Spanish",
		"level": "How well you master it, like School Level or Native or Bilingual or Professional. This is not exhaustive."
	}

	Here again, put as many as you like. Depending on your job you might want 2 or 10 of those.
	*/
	$scope.languages = [{
		"name": "French",
		"level": "Native"
	},
	{
		"name": "English",
		"level": "Bilingual"
	}];

	// Function calculating the age, courtesy of user pxixelbits on StackOverflow
	// http://stackoverflow.com/a/24883386/4197752
	$scope.calculateAge = function calculateAge(birthday) { // birthday is a date
		var ageDifMs = Date.now() - birthday.getTime();
		var ageDate = new Date(ageDifMs); // miliseconds from epoch
		return Math.abs(ageDate.getUTCFullYear() - 1970);
	}

}]);
<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2014 Richard Casar <caricsvk@gmail.com>.
 *
 * 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.
 */
APP.directive('miloTable', function() {
	var tplUrl = 'tpl/directives/table.html';
	return {
		transclude: true,
		templateUrl: window.SETTINGS && window.SETTINGS.libPrefix ? window.SETTINGS.libPrefix + tplUrl : tplUrl,
		scope: {init: '=miloTable'},
		controller: ['$scope', '$rootScope', '$filter', '$location', '$q', '$sce', '$timeout',
			function($scope, $rootScope, $filter, $location, $q, $sce, $timeout) {

				// console.log('controller', $scope);
				if ($scope.init) {
					$scope.service = $scope.init.service;
					for (var i = 0; $scope.init.actions && i < $scope.init.actions.length; i ++) {
						$scope.init.actions[i].name = $sce.trustAsHtml($scope.init.actions[i].name);
					}
				}
				$scope.filter = function () {

					if (! $scope.state.limit) {
						$scope.state.limit = $scope.limits[0];
					}
					if (! $scope.state.offset) {
						$scope.state.offset = 0;
					}
					if (! $scope.state.page) {
						$scope.state.page = 1;
					}

					// console.log('filtering', $scope.state);
					$scope.loadings.filtering = true;
					$scope.state.offset = ($scope.state.page - 1) * $scope.state.limit;
					$scope.state.param = null;
					if ($scope.data.length) {
						$scope.data = new Array(parseInt($scope.state.limit));
					}
					$scope.service.query($scope.state, function (data) {
						$scope.loadings.filtering = false;
						$scope.showData(data, $scope.data.length ? 0 : 5);
					});
					$scope.changeCount(true);
				};

				$scope.changeCount = function (isFilterCall) {
					$scope.state.param = 'count';
					$scope.service.get($scope.state, function (count) {
						if (isFilterCall && $scope.state.page > Math.ceil(parseInt(count.count) / $scope.state.limit)) {
							$scope.updateRoute("page", 1);
						}
						$scope.dataCount = count.count;
					});
				};

				$scope.showData = function (data, initPause) {
					for (var i = 0; i < data.length; i ++) {
						(function (i) {
							$timeout(function () {
								var row = data[i];
								for (var key in row) {
									row[key + "_filtered"] = applyNgFilter(row[key], key);
									for (var j = 0; j < $scope.columns.length; j ++) {
										if ($scope.columns[j].filter) {
											try {
												row[$scope.columns[j].name + "_filtered"] = $sce.trustAsHtml(
													'' + $scope.columns[j].filter(row)
												);
											} catch (e) {
												row[$scope.columns[j].name + "_filtered"] = $sce.trustAsHtml('');
											}
										}
									}
								}
								if ($scope.data.length != $scope.state.limit) {
									$scope.data.push(data[i]);
								} else {
									$scope.data[i] = data[i];
								}
								if (i + 1 == data.length) {
									$scope.rendered = true;
								}
							}, (i + initPause) * 90);
						} (i));
					}
				};

				$scope.updateOrder = function (columnName) {
					var oppositeOrderType = $scope.state.orderType === 'DESC' ? 'ASC' : 'DESC';
					var orderType = $scope.state.order === columnName ? oppositeOrderType : 'DESC';
					$scope.updateRoute({'order': columnName, 'orderType': orderType});
				};

				$scope.getPagesCount = function () {
					return Math.ceil(parseInt($scope.dataCount) / $scope.state.limit);
				};

				$scope.onDateFilterChange = function (stateKey) {
					$scope.show.date = null;
					$scope.state[stateKey] = $scope.stateDate[stateKey] ? new Date(parseInt($scope.stateDate[stateKey])).getTime() : null;
					$scope.changeCount();
				};

				$scope.initDate = function (stateKey) {
					return $scope.state[stateKey] ? new Date($scope.state[stateKey]) : null;
				}

				$scope.clearDateFilter = function (stateKey) {
					$scope.stateDate[stateKey + '_min']=null;
					$scope.stateDate[stateKey + '_max']=null;
					$scope.onDateFilterChange(stateKey + '_max');
					$scope.onDateFilterChange(stateKey + '_min');
				};

				$scope.setEmptyState = function (stateKey, value) {
					$scope.state[stateKey + '_max'] = $scope.state[stateKey + '_min'] = $scope.state[stateKey + '_wild'] = null;
					$scope.state[stateKey + "_empty"] = $scope.state[stateKey + "_empty"] == value ? null : value;
					$scope.changeCount();
				};

				//private
				var self = this;
				var applyNgFilter = function (value, key) {
					for (var i = 0; i < $scope.columns.length; i ++) {
						if (key === $scope.columns[i].name) {
							switch ($scope.columns[i].type) {
								case 'long':
								case 'integer':
								case 'int':
									return $filter('number')(value);
									break;
								case 'bigdecimal':
								case 'double':
								case 'float':
									return $filter('currency')(value, '');
									break;
								case 'localdatetime':
									if (value) {
										while(value.length < 6) {
											value.push(0);
										}
										value = new Date(value[0], value[1] - 1, value[2], value[3], value[4], value[5]).getTime();
									}
								case 'timestamp':
								case 'date':
								case 'calendar':
									return $filter('date')(value, 'medium');
									break;
								default:
									return value;
							}
						}
					}

					return value;
				};

				//public
				self.getFilterType = function (type) {
					switch (type) {
						case 'long':
						case 'integer':
						case 'int':
						case 'bigdecimal':
						case 'double':
						case 'float':
							return 'number';
							break;
						case 'timestamp':
						case 'date':
						case 'calendar':
							return 'date';
							break;
						default:
							return 'string';
					}
				};

				$scope.$on('$routeUpdate', function() {
					$scope.state = jQuery.extend({}, $location.search());
					$scope.filter();
				});

				$scope.state = $location.search();

			}
		], link: function($scope, $element, attr, ctrl, transclude) {

			if (! $scope.init) {
				return;
			}

			//inherit parent scope methods
			var parentScope = $element.scope();
			for (var key in parentScope) {
				if (! $scope[key] && typeof parentScope[key] === 'function' && key.substr(0, 1) != '$') {
					$scope[key] = parentScope[key];
				}
			}

			//set defaults
			$scope.state = jQuery.extend({}, $scope.state);
			$scope.stateDate = {};
			$scope.loadings = {};
			$scope.limits = $scope.init.limits ? $scope.init.limits : [5, 10, 20, 50, 100];
			$scope.actions = $scope.init.actions ? $scope.init.actions : [];
			$scope.show = {};
			$scope.columns = [];
			$scope.data = [];
			var columns = $scope.init.columns ? $scope.init.columns : []; //dont want to pre-render them - cause DOM lag
			var knownState = ['limit', 'offset', 'page', 'order', 'orderType', 'param'];

			$scope.showFilters = false;
			for (var key in $scope.state) {
				if (knownState.indexOf(key) == -1) {
					$scope.showFilters = true;
				}
			}

			$scope.filter();

			//setup column types and filter for columns by them
			$scope.service.get({param: "entity-field-types"}, function (entityFieldTypes) {
				var allEntityColumns = {};
				for (var key in entityFieldTypes) {
					if (typeof entityFieldTypes[key] !== 'object' && typeof entityFieldTypes[key] !== 'function'
						&& key.indexOf("_") === -1 && key.substr(0, 1) !== "$" && key !== "serialVersionUID")
					{
						var type = entityFieldTypes[key].split(".");
						allEntityColumns[key] = {
							name: key,
							originalType: entityFieldTypes[key].split(' ')[1],
							type: type[type.length - 1].toLowerCase(),
							filterType: ctrl.getFilterType(type),
							isSortable: true,
							isFilterable: key
						};
					}
				}
				// update table defined columns to fully set objects
				for (var i = 0; i < columns.length; i ++) {
					var defaultColumn = allEntityColumns[columns[i]];
					if (defaultColumn) {
						columns[i] = defaultColumn;
						// put defaults to column-object from table definition
					} else if (columns[i] !== 'string' && allEntityColumns[columns[i].name]) {
						defaultColumn = allEntityColumns[columns[i].name];
						for (var key in defaultColumn) {
							if (typeof columns[i][key] === 'undefined') {
								columns[i][key] = defaultColumn[key];
							}
						}
					}
					if (columns[i].filterType == 'string') {
						(function (column) {
							$scope.service.get({param: 'is-enum', fullClassName: column.originalType}, function (isEnum) {
								column.isEnum = isEnum && isEnum.value;
							});
						} (columns[i]));
					}
				}
				$scope.columns = columns;
			});

			//just because HTML 5 input:number does not show number when they are as strings in angular
			$scope.$watch('state', function (newState) {
				for (var key in newState) {
					if (key.substr(key.length - 4) === '_min'
						|| key.substr(key.length - 4) === '_max') {
						newState[key] = parseFloat(newState[key]);
					}
				}
			});

			transclude($scope, function(clone) {
				$element.prepend(clone);
			});
			// console.log('peTable', $scope);
		}
	};
});<commit_msg>change default order type order<commit_after>/*
 * The MIT License
 *
 * Copyright 2014 Richard Casar <caricsvk@gmail.com>.
 *
 * 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.
 */
APP.directive('miloTable', function() {
	var tplUrl = 'tpl/directives/table.html';
	return {
		transclude: true,
		templateUrl: window.SETTINGS && window.SETTINGS.libPrefix ? window.SETTINGS.libPrefix + tplUrl : tplUrl,
		scope: {init: '=miloTable'},
		controller: ['$scope', '$rootScope', '$filter', '$location', '$q', '$sce', '$timeout',
			function($scope, $rootScope, $filter, $location, $q, $sce, $timeout) {

				// console.log('controller', $scope);
				if ($scope.init) {
					$scope.service = $scope.init.service;
					for (var i = 0; $scope.init.actions && i < $scope.init.actions.length; i ++) {
						$scope.init.actions[i].name = $sce.trustAsHtml($scope.init.actions[i].name);
					}
				}
				$scope.filter = function () {

					if (! $scope.state.limit) {
						$scope.state.limit = $scope.limits[0];
					}
					if (! $scope.state.offset) {
						$scope.state.offset = 0;
					}
					if (! $scope.state.page) {
						$scope.state.page = 1;
					}

					// console.log('filtering', $scope.state);
					$scope.loadings.filtering = true;
					$scope.state.offset = ($scope.state.page - 1) * $scope.state.limit;
					$scope.state.param = null;
					if ($scope.data.length) {
						$scope.data = new Array(parseInt($scope.state.limit));
					}
					$scope.service.query($scope.state, function (data) {
						$scope.loadings.filtering = false;
						$scope.showData(data, $scope.data.length ? 0 : 5);
					});
					$scope.changeCount(true);
				};

				$scope.changeCount = function (isFilterCall) {
					$scope.state.param = 'count';
					$scope.service.get($scope.state, function (count) {
						if (isFilterCall && $scope.state.page > Math.ceil(parseInt(count.count) / $scope.state.limit)) {
							$scope.updateRoute("page", 1);
						}
						$scope.dataCount = count.count;
					});
				};

				$scope.showData = function (data, initPause) {
					for (var i = 0; i < data.length; i ++) {
						(function (i) {
							$timeout(function () {
								var row = data[i];
								for (var key in row) {
									row[key + "_filtered"] = applyNgFilter(row[key], key);
									for (var j = 0; j < $scope.columns.length; j ++) {
										if ($scope.columns[j].filter) {
											try {
												row[$scope.columns[j].name + "_filtered"] = $sce.trustAsHtml(
													'' + $scope.columns[j].filter(row)
												);
											} catch (e) {
												row[$scope.columns[j].name + "_filtered"] = $sce.trustAsHtml('');
											}
										}
									}
								}
								if ($scope.data.length != $scope.state.limit) {
									$scope.data.push(data[i]);
								} else {
									$scope.data[i] = data[i];
								}
								if (i + 1 == data.length) {
									$scope.rendered = true;
								}
							}, (i + initPause) * 90);
						} (i));
					}
				};

				$scope.updateOrder = function (columnName) {
					var oppositeOrderType = $scope.state.orderType === 'DESC' ? 'ASC' : 'DESC';
					var orderType = $scope.state.order === columnName ? oppositeOrderType : 'ASC';
					$scope.updateRoute({'order': columnName, 'orderType': orderType});
				};

				$scope.getPagesCount = function () {
					return Math.ceil(parseInt($scope.dataCount) / $scope.state.limit);
				};

				$scope.onDateFilterChange = function (stateKey) {
					$scope.show.date = null;
					$scope.state[stateKey] = $scope.stateDate[stateKey] ? new Date(parseInt($scope.stateDate[stateKey])).getTime() : null;
					$scope.changeCount();
				};

				$scope.initDate = function (stateKey) {
					return $scope.state[stateKey] ? new Date($scope.state[stateKey]) : null;
				}

				$scope.clearDateFilter = function (stateKey) {
					$scope.stateDate[stateKey + '_min']=null;
					$scope.stateDate[stateKey + '_max']=null;
					$scope.onDateFilterChange(stateKey + '_max');
					$scope.onDateFilterChange(stateKey + '_min');
				};

				$scope.setEmptyState = function (stateKey, value) {
					$scope.state[stateKey + '_max'] = $scope.state[stateKey + '_min'] = $scope.state[stateKey + '_wild'] = null;
					$scope.state[stateKey + "_empty"] = $scope.state[stateKey + "_empty"] == value ? null : value;
					$scope.changeCount();
				};

				//private
				var self = this;
				var applyNgFilter = function (value, key) {
					for (var i = 0; i < $scope.columns.length; i ++) {
						if (key === $scope.columns[i].name) {
							switch ($scope.columns[i].type) {
								case 'long':
								case 'integer':
								case 'int':
									return $filter('number')(value);
									break;
								case 'bigdecimal':
								case 'double':
								case 'float':
									return $filter('currency')(value, '');
									break;
								case 'localdatetime':
									if (value) {
										while(value.length < 6) {
											value.push(0);
										}
										value = new Date(value[0], value[1] - 1, value[2], value[3], value[4], value[5]).getTime();
									}
								case 'timestamp':
								case 'date':
								case 'calendar':
									return $filter('date')(value, 'medium');
									break;
								default:
									return value;
							}
						}
					}

					return value;
				};

				//public
				self.getFilterType = function (type) {
					switch (type) {
						case 'long':
						case 'integer':
						case 'int':
						case 'bigdecimal':
						case 'double':
						case 'float':
							return 'number';
							break;
						case 'timestamp':
						case 'date':
						case 'calendar':
							return 'date';
							break;
						default:
							return 'string';
					}
				};

				$scope.$on('$routeUpdate', function() {
					$scope.state = jQuery.extend({}, $location.search());
					$scope.filter();
				});

				$scope.state = $location.search();

			}
		], link: function($scope, $element, attr, ctrl, transclude) {

			if (! $scope.init) {
				return;
			}

			//inherit parent scope methods
			var parentScope = $element.scope();
			for (var key in parentScope) {
				if (! $scope[key] && typeof parentScope[key] === 'function' && key.substr(0, 1) != '$') {
					$scope[key] = parentScope[key];
				}
			}

			//set defaults
			$scope.state = jQuery.extend({}, $scope.state);
			$scope.stateDate = {};
			$scope.loadings = {};
			$scope.limits = $scope.init.limits ? $scope.init.limits : [5, 10, 20, 50, 100];
			$scope.actions = $scope.init.actions ? $scope.init.actions : [];
			$scope.show = {};
			$scope.columns = [];
			$scope.data = [];
			var columns = $scope.init.columns ? $scope.init.columns : []; //dont want to pre-render them - cause DOM lag
			var knownState = ['limit', 'offset', 'page', 'order', 'orderType', 'param'];

			$scope.showFilters = false;
			for (var key in $scope.state) {
				if (knownState.indexOf(key) == -1) {
					$scope.showFilters = true;
				}
			}

			$scope.filter();

			//setup column types and filter for columns by them
			$scope.service.get({param: "entity-field-types"}, function (entityFieldTypes) {
				var allEntityColumns = {};
				for (var key in entityFieldTypes) {
					if (typeof entityFieldTypes[key] !== 'object' && typeof entityFieldTypes[key] !== 'function'
						&& key.indexOf("_") === -1 && key.substr(0, 1) !== "$" && key !== "serialVersionUID")
					{
						var type = entityFieldTypes[key].split(".");
						allEntityColumns[key] = {
							name: key,
							originalType: entityFieldTypes[key].split(' ')[1],
							type: type[type.length - 1].toLowerCase(),
							filterType: ctrl.getFilterType(type),
							isSortable: true,
							isFilterable: key
						};
					}
				}
				// update table defined columns to fully set objects
				for (var i = 0; i < columns.length; i ++) {
					var defaultColumn = allEntityColumns[columns[i]];
					if (defaultColumn) {
						columns[i] = defaultColumn;
						// put defaults to column-object from table definition
					} else if (columns[i] !== 'string' && allEntityColumns[columns[i].name]) {
						defaultColumn = allEntityColumns[columns[i].name];
						for (var key in defaultColumn) {
							if (typeof columns[i][key] === 'undefined') {
								columns[i][key] = defaultColumn[key];
							}
						}
					}
					if (columns[i].filterType == 'string') {
						(function (column) {
							$scope.service.get({param: 'is-enum', fullClassName: column.originalType}, function (isEnum) {
								column.isEnum = isEnum && isEnum.value;
							});
						} (columns[i]));
					}
				}
				$scope.columns = columns;
			});

			//just because HTML 5 input:number does not show number when they are as strings in angular
			$scope.$watch('state', function (newState) {
				for (var key in newState) {
					if (key.substr(key.length - 4) === '_min'
						|| key.substr(key.length - 4) === '_max') {
						newState[key] = parseFloat(newState[key]);
					}
				}
			});

			transclude($scope, function(clone) {
				$element.prepend(clone);
			});
			// console.log('peTable', $scope);
		}
	};
});<|endoftext|>


<commit_before>import Ember from 'ember';
import moment from 'moment';

export default Ember.Mixin.create({

  DAYS: {
    sunday: 0,
    saturday: 6
  },

  CHECKS: {
    same: '===',
    notSame: '!==',
    before: '<', // before
    after: '>', // after
    beforeSame: '<=', // before or same
    afterSame: '>=' // after or same
  },

  compare: function(source, target, operator) {
    switch (operator) {
      case '===':
        return source.isSame(target);
      case '!==':
        return !source.isSame(target);
      case '>=':
        return source.isAfter(target) || source.isSame(target);
      case '<=':
        return source.isBefore(target) || source.isSame(target);
      case '>':
        return source.isAfter(target);
      case '<':
        return source.isBefore(target);
      default:
        return false;
    }
  },

  perform: function() {
    var value = this.model.get(this.property);
    var option;
    var target;

    var transform = function(value, format) {
      var date;
      if (typeof(value) === 'string') {
        if (format) {
          date = moment(value, format, true);
        } else {
          date = moment(new Date(value));
        }
      } else {
        date = moment(value);
      }
      return date;
    };

    var setTime = function(date, hours, minutes, seconds, milliseconds) {
      date.hours(hours);
      date.minutes(minutes);
      date.seconds(seconds);
      date.milliseconds(milliseconds);
      return date;
    };

    if (!Ember.isEmpty(value)) {
      value = transform(value, this.options.format);

      if (!this.options.time) {
        value = setTime(value, 0, 0, 0, 0);
      }

      if (!value.isValid()) {
        this.pushResult(this.options.messages.date);
      } else {
        if (this.options.weekend && [this.DAYS.sunday, this.DAYS.saturday].indexOf(value.day()) !== -1) {
          this.pushResult(this.options.messages.weekend);
        } else if (this.options.onlyWeekend && [this.DAYS.sunday, this.DAYS.saturday].indexOf(value.day()) === -1) {
          this.pushResult(this.options.messages.onlyWeekend);
        } else {
          for (var key in this.CHECKS) {
            option = this.options[key];
            if (!option) {
              continue;
            }

            target = transform(option.target, option.format);

            if (!this.options.time) {
              target = setTime(target, 0, 0, 0, 0);
            }

            if (!target.isValid()) {
              continue;
            }

            if (!this.compare(value, target, this.CHECKS[key])) {
              this.pushResult(this.options.messages[key], { date: target.format(option.format) });
            }
          }
        }
      }
    }
  }
});
<commit_msg>Removed moment import<commit_after>import Ember from 'ember';

export default Ember.Mixin.create({

  DAYS: {
    sunday: 0,
    saturday: 6
  },

  CHECKS: {
    same: '===',
    notSame: '!==',
    before: '<', // before
    after: '>', // after
    beforeSame: '<=', // before or same
    afterSame: '>=' // after or same
  },

  compare: function(source, target, operator) {
    switch (operator) {
      case '===':
        return source.isSame(target);
      case '!==':
        return !source.isSame(target);
      case '>=':
        return source.isAfter(target) || source.isSame(target);
      case '<=':
        return source.isBefore(target) || source.isSame(target);
      case '>':
        return source.isAfter(target);
      case '<':
        return source.isBefore(target);
      default:
        return false;
    }
  },

  perform: function() {
    var value = this.model.get(this.property);
    var option;
    var target;

    var transform = function(value, format) {
      var date;
      if (typeof(value) === 'string') {
        if (format) {
          date = moment(value, format, true);
        } else {
          date = moment(new Date(value));
        }
      } else {
        date = moment(value);
      }
      return date;
    };

    var setTime = function(date, hours, minutes, seconds, milliseconds) {
      date.hours(hours);
      date.minutes(minutes);
      date.seconds(seconds);
      date.milliseconds(milliseconds);
      return date;
    };

    if (!Ember.isEmpty(value)) {
      value = transform(value, this.options.format);

      if (!this.options.time) {
        value = setTime(value, 0, 0, 0, 0);
      }

      if (!value.isValid()) {
        this.pushResult(this.options.messages.date);
      } else {
        if (this.options.weekend && [this.DAYS.sunday, this.DAYS.saturday].indexOf(value.day()) !== -1) {
          this.pushResult(this.options.messages.weekend);
        } else if (this.options.onlyWeekend && [this.DAYS.sunday, this.DAYS.saturday].indexOf(value.day()) === -1) {
          this.pushResult(this.options.messages.onlyWeekend);
        } else {
          for (var key in this.CHECKS) {
            option = this.options[key];
            if (!option) {
              continue;
            }

            target = transform(option.target, option.format);

            if (!this.options.time) {
              target = setTime(target, 0, 0, 0, 0);
            }

            if (!target.isValid()) {
              continue;
            }

            if (!this.compare(value, target, this.CHECKS[key])) {
              this.pushResult(this.options.messages[key], { date: target.format(option.format) });
            }
          }
        }
      }
    }
  }
});
<|endoftext|>


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

function jsonp(obj) {
  T(jsonp_flag == 0);
  T(obj.results.length == 1 && obj.last_seq==1, "jsonp")
  jsonp_flag = 1;
}

couchTests.changes = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  var req = CouchDB.request("GET", "/test_suite_db/_changes");
  var resp = JSON.parse(req.responseText);

  T(resp.results.length == 0 && resp.last_seq==0, "empty db")
  var docFoo = {_id:"foo", bar:1};
  T(db.save(docFoo).ok);
  T(db.ensureFullCommit().ok);

  req = CouchDB.request("GET", "/test_suite_db/_changes");
  var resp = JSON.parse(req.responseText);

  T(resp.results.length == 1 && resp.last_seq==1, "one doc db")
  T(resp.results[0].changes[0].rev == docFoo._rev)

  // test with callback
  var xhr = CouchDB.request("GET", "/test_suite_db/_changes?callback=jsonp");
  T(xhr.status == 200);
  jsonp_flag = 0;
  eval(xhr.responseText);
  T(jsonp_flag == 1);

  req = CouchDB.request("GET", "/test_suite_db/_changes?feed=continuous&timeout=10");
  var lines = req.responseText.split("\n");
  T(JSON.parse(lines[0]).changes[0].rev == docFoo._rev);
  T(JSON.parse(lines[1]).last_seq == 1);

  var xhr;

  try {
    xhr = CouchDB.newXhr();
  } catch (err) {
  }

  // poor man's browser detection
  var is_safari = false;
  if(typeof(navigator) == "undefined") {
    is_safari = true; // For CouchHTTP based runners
  } else if(navigator.userAgent.match(/AppleWebKit/)) {
    is_safari = true;
  };
  if (!is_safari && xhr) {
    // Only test the continuous stuff if we have a real XHR object
    // with real async support.

    // WebKit (last checked on nightly #47686) does fail on processing
    // the async-request properly while javascript is executed.

    var sleep = function(msecs) {
      // by making a slow sync request, we allow the waiting XHR request data
      // to be received.
      var req = CouchDB.request("GET", "/_sleep?time=" + msecs);
      T(JSON.parse(req.responseText).ok == true);
    }

    xhr.open("GET", "/test_suite_db/_changes?feed=continuous", true);
    xhr.send("");

    var docBar = {_id:"bar", bar:1};
    db.save(docBar);

    sleep(100);
    var lines = xhr.responseText.split("\n");

    var change = JSON.parse(lines[0]);

    T(change.seq == 1)
    T(change.id == "foo")

    change = JSON.parse(lines[1]);

    T(change.seq == 2)
    T(change.id == "bar")
    T(change.changes[0].rev == docBar._rev)

    var docBaz = {_id:"baz", baz:1};
    db.save(docBaz);

    sleep(100);
    var lines = xhr.responseText.split("\n");

    change = JSON.parse(lines[2]);

    T(change.seq == 3);
    T(change.id == "baz");
    T(change.changes[0].rev == docBaz._rev);

    xhr = CouchDB.newXhr();

    //verify the hearbeat newlines are sent
    xhr.open("GET", "/test_suite_db/_changes?feed=continuous&heartbeat=10", true);
    xhr.send("");

    sleep(100);

    var str = xhr.responseText;

    T(str.charAt(str.length - 1) == "\n")
    T(str.charAt(str.length - 2) == "\n")

    // test longpolling
    xhr = CouchDB.newXhr();

    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll", true);
    xhr.send("");

    sleep(100);
    var lines = xhr.responseText.split("\n");
    T(lines[5]=='"last_seq":3}');

    xhr = CouchDB.newXhr();

    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&since=3", true);
    xhr.send("");

    sleep(100);

    var docBarz = {_id:"barz", bar:1};
    db.save(docBarz);

    sleep(100);

    var lines = xhr.responseText.split("\n");

    var parse_changes_line = function(line) {
      if (line.charAt(line.length-1) == ",") {
        line = line.substring(0, line.length-1);
      }
      return JSON.parse(line);
    }

    change = parse_changes_line(lines[1]);

    T(change.seq == 4);
    T(change.id == "barz");
    T(change.changes[0].rev == docBarz._rev);
    T(lines[3]=='"last_seq":4}');

  }

  // test the filtered changes
  var ddoc = {
    _id : "_design/changes_filter",
    "filters" : {
      "bop" : "function(doc, req) { return (doc.bop);}",
      "dynamic" : stringFun(function(doc, req) {
        var field = req.query.field;
        return doc[field];
      }),
      "userCtx" : stringFun(function(doc, req) {
        return doc.user && (doc.user == req.userCtx.name);
      })
    }
  }

  db.save(ddoc);

  var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop");
  var resp = JSON.parse(req.responseText);
  T(resp.results.length == 0);

  db.save({"bop" : "foom"});
  db.save({"bop" : false});

  var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop");
  var resp = JSON.parse(req.responseText);
  T(resp.results.length == 1);

  req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=woox");
  resp = JSON.parse(req.responseText);
  T(resp.results.length == 0);

  req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=bop");
  resp = JSON.parse(req.responseText);
  T(resp.results.length == 1);

  if (!is_safari && xhr) { // full test requires parallel connections
    // filter with longpoll
    // longpoll filters full history when run without a since seq
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&filter=changes_filter/bop", true);
    xhr.send("");
    sleep(100);
    var resp = JSON.parse(xhr.responseText);
    T(resp.last_seq == 7);
    // longpoll waits until a matching change before returning
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&since=7&filter=changes_filter/bop", true);
    xhr.send("");
    db.save({"_id":"falsy", "bop" : ""}); // empty string is falsy
    db.save({"_id":"bingo","bop" : "bingo"});
    sleep(100);
    var resp = JSON.parse(xhr.responseText);
    T(resp.last_seq == 9);
    T(resp.results && resp.results.length > 0 && resp.results[0]["id"] == "bingo", "filter the correct update");

    // filter with continuous
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=continuous&filter=changes_filter/bop&timeout=200", true);
    xhr.send("");
    db.save({"_id":"rusty", "bop" : "plankton"});
    T(db.ensureFullCommit().ok);
    sleep(300);
    var lines = xhr.responseText.split("\n");
    T(JSON.parse(lines[1]).id == "bingo", lines[1]);
    T(JSON.parse(lines[2]).id == "rusty", lines[2]);
    T(JSON.parse(lines[3]).last_seq == 10, lines[3]);
  }
  // error conditions

  // non-existing design doc
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=nothingtosee/bop");
  TEquals(404, req.status, "should return 404 for non existant design doc");

  // non-existing filter
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=changes_filter/movealong");
  TEquals(404, req.status, "should return 404 for non existant filter fun");

  // both
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=nothingtosee/movealong");
  TEquals(404, req.status,
    "should return 404 for non existant design doc and filter fun");

  // changes get all_docs style with deleted docs
  var doc = {a:1};
  db.save(doc);
  db.deleteDoc(doc);
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=changes_filter/bop&style=all_docs");
  var resp = JSON.parse(req.responseText);
  TEquals(3, resp.results.length, "should return matching rows");

  // test for userCtx
  run_on_modified_server(
    [{section: "httpd",
      key: "authentication_handlers",
      value: "{couch_httpd_auth, special_test_authentication_handler}"},
     {section:"httpd",
      key: "WWW-Authenticate",
      value:  "X-Couch-Test-Auth"}],

    function() {
      var authOpts = {"headers":{"WWW-Authenticate": "X-Couch-Test-Auth Chris Anderson:mp3"}};

      var req = CouchDB.request("GET", "/_session", authOpts);
      var resp = JSON.parse(req.responseText);

      T(db.save({"user" : "Noah Slater"}).ok);
      var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts);
      var resp = JSON.parse(req.responseText);
      T(resp.results.length == 0);

      var docResp = db.save({"user" : "Chris Anderson"});
      T(docResp.ok);
      T(db.ensureFullCommit().ok);
      req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts);
      resp = JSON.parse(req.responseText);
      T(resp.results.length == 1, "userCtx");
      T(resp.results[0].id == docResp.id);
    });

  req = CouchDB.request("GET", "/test_suite_db/_changes?limit=1");
  resp = JSON.parse(req.responseText);
  TEquals(1, resp.results.length);

};
<commit_msg>show conflicts in changes filters. Patch by Lena Herrmann. Closes COUCHDB-630<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

function jsonp(obj) {
  T(jsonp_flag == 0);
  T(obj.results.length == 1 && obj.last_seq==1, "jsonp")
  jsonp_flag = 1;
}

couchTests.changes = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;

  var req = CouchDB.request("GET", "/test_suite_db/_changes");
  var resp = JSON.parse(req.responseText);

  T(resp.results.length == 0 && resp.last_seq==0, "empty db")
  var docFoo = {_id:"foo", bar:1};
  T(db.save(docFoo).ok);
  T(db.ensureFullCommit().ok);

  req = CouchDB.request("GET", "/test_suite_db/_changes");
  var resp = JSON.parse(req.responseText);

  T(resp.results.length == 1 && resp.last_seq==1, "one doc db")
  T(resp.results[0].changes[0].rev == docFoo._rev)

  // test with callback
  var xhr = CouchDB.request("GET", "/test_suite_db/_changes?callback=jsonp");
  T(xhr.status == 200);
  jsonp_flag = 0;
  eval(xhr.responseText);
  T(jsonp_flag == 1);

  req = CouchDB.request("GET", "/test_suite_db/_changes?feed=continuous&timeout=10");
  var lines = req.responseText.split("\n");
  T(JSON.parse(lines[0]).changes[0].rev == docFoo._rev);
  T(JSON.parse(lines[1]).last_seq == 1);

  var xhr;

  try {
    xhr = CouchDB.newXhr();
  } catch (err) {
  }

  // poor man's browser detection
  var is_safari = false;
  if(typeof(navigator) == "undefined") {
    is_safari = true; // For CouchHTTP based runners
  } else if(navigator.userAgent.match(/AppleWebKit/)) {
    is_safari = true;
  };
  if (!is_safari && xhr) {
    // Only test the continuous stuff if we have a real XHR object
    // with real async support.

    // WebKit (last checked on nightly #47686) does fail on processing
    // the async-request properly while javascript is executed.

    var sleep = function(msecs) {
      // by making a slow sync request, we allow the waiting XHR request data
      // to be received.
      var req = CouchDB.request("GET", "/_sleep?time=" + msecs);
      T(JSON.parse(req.responseText).ok == true);
    }

    xhr.open("GET", "/test_suite_db/_changes?feed=continuous", true);
    xhr.send("");

    var docBar = {_id:"bar", bar:1};
    db.save(docBar);

    sleep(100);
    var lines = xhr.responseText.split("\n");

    var change = JSON.parse(lines[0]);

    T(change.seq == 1)
    T(change.id == "foo")

    change = JSON.parse(lines[1]);

    T(change.seq == 2)
    T(change.id == "bar")
    T(change.changes[0].rev == docBar._rev)

    var docBaz = {_id:"baz", baz:1};
    db.save(docBaz);

    sleep(100);
    var lines = xhr.responseText.split("\n");

    change = JSON.parse(lines[2]);

    T(change.seq == 3);
    T(change.id == "baz");
    T(change.changes[0].rev == docBaz._rev);

    xhr = CouchDB.newXhr();

    //verify the hearbeat newlines are sent
    xhr.open("GET", "/test_suite_db/_changes?feed=continuous&heartbeat=10", true);
    xhr.send("");

    sleep(100);

    var str = xhr.responseText;

    T(str.charAt(str.length - 1) == "\n")
    T(str.charAt(str.length - 2) == "\n")

    // test longpolling
    xhr = CouchDB.newXhr();

    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll", true);
    xhr.send("");

    sleep(100);
    var lines = xhr.responseText.split("\n");
    T(lines[5]=='"last_seq":3}');

    xhr = CouchDB.newXhr();

    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&since=3", true);
    xhr.send("");

    sleep(100);

    var docBarz = {_id:"barz", bar:1};
    db.save(docBarz);

    sleep(100);

    var lines = xhr.responseText.split("\n");

    var parse_changes_line = function(line) {
      if (line.charAt(line.length-1) == ",") {
        line = line.substring(0, line.length-1);
      }
      return JSON.parse(line);
    }

    change = parse_changes_line(lines[1]);

    T(change.seq == 4);
    T(change.id == "barz");
    T(change.changes[0].rev == docBarz._rev);
    T(lines[3]=='"last_seq":4}');

  }

  // test the filtered changes
  var ddoc = {
    _id : "_design/changes_filter",
    "filters" : {
      "bop" : "function(doc, req) { return (doc.bop);}",
      "dynamic" : stringFun(function(doc, req) {
        var field = req.query.field;
        return doc[field];
      }),
      "userCtx" : stringFun(function(doc, req) {
        return doc.user && (doc.user == req.userCtx.name);
      }),
      "conflicted" : "function(doc, req) { return (doc._conflicts);}",
    }
  }

  db.save(ddoc);

  var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop");
  var resp = JSON.parse(req.responseText);
  T(resp.results.length == 0);

  db.save({"bop" : "foom"});
  db.save({"bop" : false});

  var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/bop");
  var resp = JSON.parse(req.responseText);
  T(resp.results.length == 1);

  req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=woox");
  resp = JSON.parse(req.responseText);
  T(resp.results.length == 0);

  req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/dynamic&field=bop");
  resp = JSON.parse(req.responseText);
  T(resp.results.length == 1);

  if (!is_safari && xhr) { // full test requires parallel connections
    // filter with longpoll
    // longpoll filters full history when run without a since seq
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&filter=changes_filter/bop", true);
    xhr.send("");
    sleep(100);
    var resp = JSON.parse(xhr.responseText);
    T(resp.last_seq == 7);
    // longpoll waits until a matching change before returning
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&since=7&filter=changes_filter/bop", true);
    xhr.send("");
    db.save({"_id":"falsy", "bop" : ""}); // empty string is falsy
    db.save({"_id":"bingo","bop" : "bingo"});
    sleep(100);
    var resp = JSON.parse(xhr.responseText);
    T(resp.last_seq == 9);
    T(resp.results && resp.results.length > 0 && resp.results[0]["id"] == "bingo", "filter the correct update");

    // filter with continuous
    xhr = CouchDB.newXhr();
    xhr.open("GET", "/test_suite_db/_changes?feed=continuous&filter=changes_filter/bop&timeout=200", true);
    xhr.send("");
    db.save({"_id":"rusty", "bop" : "plankton"});
    T(db.ensureFullCommit().ok);
    sleep(300);
    var lines = xhr.responseText.split("\n");
    T(JSON.parse(lines[1]).id == "bingo", lines[1]);
    T(JSON.parse(lines[2]).id == "rusty", lines[2]);
    T(JSON.parse(lines[3]).last_seq == 10, lines[3]);
  }
  // error conditions

  // non-existing design doc
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=nothingtosee/bop");
  TEquals(404, req.status, "should return 404 for non existant design doc");

  // non-existing filter
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=changes_filter/movealong");
  TEquals(404, req.status, "should return 404 for non existant filter fun");

  // both
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=nothingtosee/movealong");
  TEquals(404, req.status,
    "should return 404 for non existant design doc and filter fun");

  // changes get all_docs style with deleted docs
  var doc = {a:1};
  db.save(doc);
  db.deleteDoc(doc);
  var req = CouchDB.request("GET",
    "/test_suite_db/_changes?filter=changes_filter/bop&style=all_docs");
  var resp = JSON.parse(req.responseText);
  TEquals(3, resp.results.length, "should return matching rows");

  // test for userCtx
  run_on_modified_server(
    [{section: "httpd",
      key: "authentication_handlers",
      value: "{couch_httpd_auth, special_test_authentication_handler}"},
     {section:"httpd",
      key: "WWW-Authenticate",
      value:  "X-Couch-Test-Auth"}],

    function() {
      var authOpts = {"headers":{"WWW-Authenticate": "X-Couch-Test-Auth Chris Anderson:mp3"}};

      var req = CouchDB.request("GET", "/_session", authOpts);
      var resp = JSON.parse(req.responseText);

      T(db.save({"user" : "Noah Slater"}).ok);
      var req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts);
      var resp = JSON.parse(req.responseText);
      T(resp.results.length == 0);

      var docResp = db.save({"user" : "Chris Anderson"});
      T(docResp.ok);
      T(db.ensureFullCommit().ok);
      req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/userCtx", authOpts);
      resp = JSON.parse(req.responseText);
      T(resp.results.length == 1, "userCtx");
      T(resp.results[0].id == docResp.id);
    }
  );

  req = CouchDB.request("GET", "/test_suite_db/_changes?limit=1");
  resp = JSON.parse(req.responseText);
  TEquals(1, resp.results.length)

  //filter includes _conflicts
  var id = db.save({'food' : 'pizza'}).id;
  db.bulkSave([{_id: id, 'food' : 'pasta'}], {all_or_nothing:true});

  req = CouchDB.request("GET", "/test_suite_db/_changes?filter=changes_filter/conflicted");
  resp = JSON.parse(req.responseText);
  T(resp.results.length == 1);
};

<|endoftext|>


<commit_before>'use strict';

/**
 * Dependencies
 */
var assert = require('assert')
  , fs = require('fs')
  , wrench = require('wrench')
  , _ = require('lodash')
  , path = require('path')
  , exec = require('child_process').exec;

describe('Generate', function(){
  describe('New application', function(){
    var bin = './bin/koan.js';
    var appName = 'testApp';

    before(function(done) {
      fs.exists(appName, function(exists) {
        if (exists) {
          wrench.rmdirSyncRecursive(appName);
        }
        done();
      });
    });

    after(function(done) {
      fs.exists(appName, function(exists) {
        if (exists) {
          wrench.rmdirSyncRecursive(appName);
        }
        done();
      });
    });

    it('should create a new application', function(done) {
      exec(bin + ' new ' + appName, function(err) {
        if (err)
          return done(new Error(err));

        var nodeModulesPath = path.join(appName, 'node_modules');
        if (fs.existsSync(nodeModulesPath))
          wrench.rmdirSyncRecursive(nodeModulesPath);

        assert(checkGeneratedFiles(appName), 'generated files don\'t match expected files');
        done();
      });
    });

    it('should test the new application successfully', function(done) {
      exec('cd ' + appName + ' && npm install && npm test', function(err) {
        if (err)
          return done(new Error(err));

        assert(!err, 'an error occurred while trying to test a newly created application');
        done();
      });
    });
  });
});

function checkGeneratedFiles(appName) {
  var expectedFiles = [
          '.gitignore',
          'index.js',
          'public',
          'config',
          'package.json',
          'README.md',
          'views',
          'views/home.ejs',
          'public/images',
          'public/js',
          'public/robots.txt',
          'public/css',
          'public/images/.gitkeep',
          'public/images/define_koan.png',
          'public/js/.gitkeep',
          'public/css/.gitkeep',
          'config/routes.js',
          'config/options.js',
          'config/index.js',
          'config/environments',
          'config/environments/development.js',
          'config/environments/production.js',
          'test',
          'test/index.test.js',
          'test/mocha.opts'
  ];

  // Read actual generated files from disk
  var files = wrench.readdirSyncRecursive(appName);

  // Disregard stupid files
  // (fs-specific, OS-specific, editor-specific, yada yada)
  files = _.reject(files, function(f) {
    return f.match(/^node_modules/) || f.match(/.DS_Store/gi) || f.match(/\*~$/);
  });

  // Generate diff
  var diff = _.difference(files, expectedFiles);

  // Uneven # of files
  if (files.length !== expectedFiles.length) {
    return false;
  }

  // Files don't match
  if (diff.length !== 0) {
    return false;
  }

  // Everything's ok!
  return true;
}
<commit_msg>Bringing tests up to date.<commit_after>'use strict';

/**
 * Dependencies
 */
var assert = require('assert')
  , fs = require('fs')
  , wrench = require('wrench')
  , _ = require('lodash')
  , path = require('path')
  , exec = require('child_process').exec;

describe('Generate', function(){
  describe('New application', function(){
    var bin = './bin/koan.js';
    var appName = 'testApp';

    before(function(done) {
      fs.exists(appName, function(exists) {
        if (exists) {
          wrench.rmdirSyncRecursive(appName);
        }
        done();
      });
    });

    after(function(done) {
      fs.exists(appName, function(exists) {
        if (exists) {
          wrench.rmdirSyncRecursive(appName);
        }
        done();
      });
    });

    it('should create a new application', function(done) {
      exec(bin + ' new ' + appName, function(err) {
        if (err)
          return done(new Error(err));

        var nodeModulesPath = path.join(appName, 'node_modules');
        if (fs.existsSync(nodeModulesPath))
          wrench.rmdirSyncRecursive(nodeModulesPath);

        assert(checkGeneratedFiles(appName), 'generated files don\'t match expected files');
        done();
      });
    });

    it('should test the new application successfully', function(done) {
      exec('cd ' + appName + ' && npm install && npm test', function(err) {
        if (err)
          return done(new Error(err));

        assert(!err, 'an error occurred while trying to test a newly created application');
        done();
      });
    });
  });
});

function checkGeneratedFiles(appName) {
  var expectedFiles = [
          '.gitignore',
          'index.js',
          'public',
          'config',
          'package.json',
          'README.md',
          'controllers',
          'controllers/index.js',
          'controllers/pages.js',
          'views',
          'views/home.ejs',
          'views/pages',
          'views/pages/about.ejs',
          'public/images',
          'public/js',
          'public/robots.txt',
          'public/css',
          'public/images/.gitkeep',
          'public/images/define_koan.png',
          'public/js/.gitkeep',
          'public/css/.gitkeep',
          'config/routes.js',
          'config/options.js',
          'config/index.js',
          'config/environments',
          'config/environments/development.js',
          'config/environments/production.js',
          'test',
          'test/index.test.js',
          'test/mocha.opts'
  ];

  // Read actual generated files from disk
  var files = wrench.readdirSyncRecursive(appName);

  // Disregard stupid files
  // (fs-specific, OS-specific, editor-specific, yada yada)
  files = _.reject(files, function(f) {
    return f.match(/^node_modules/) || f.match(/.DS_Store/gi) || f.match(/\*~$/);
  });

  // Generate diff
  var diff = _.difference(files, expectedFiles);

  // Uneven # of files
  if (files.length !== expectedFiles.length) {
    return false;
  }

  // Files don't match
  if (diff.length !== 0) {
    return false;
  }

  // Everything's ok!
  return true;
}
<|endoftext|>


<commit_before>dojo.provide("org.ppwcode.dojo.dijit.form.PpwCrudFormContainer");

dojo.require("dijit.layout.StackContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("org.ppwcode.dojo.util.JavaScriptHelpers");

dojo.declare(
	"org.ppwcode.dojo.dijit.form.PpwCrudFormContainer",
	dijit.layout.StackContainer,
	{
		_formIdMap: null,
		// we use a map from the constructor function NAME to the formid
		// instead of from the constructor FUNCTION, because it is not possible
		// to use a function object as a value in a ComboBox (it is possible
		// but it acts funnily).  We need the ComboBox in the PpwMasterView.
		// when adding new Objects.
		_constructorNameMap: null,
		_displayingformid: null,

//		constructorMap: null,

		postMixInProperties: function() {
			this.inherited(arguments);
//			if (this.constructorMap) {
//				this.setConstructorMap(this.constructorMap);
//			}
		},

		startup: function() {
			this.inherited(arguments);
			// we assume that our children are content panes that contain
			// exactly one form.
			this._formIdMap = new Object();
			this._constructorNameMap = new Object();
			var children = this.getChildren();
			for (var i = 0; i < children.length; i++) {
				var contentpane = children[i];
				var list = dojo.query("form[widgetId]", contentpane.containerNode);
				dojo.forEach(list, function(theform) {
						//console.log("child: " + theform + " with id " + dojo.attr(theform, "id") + " and constructor " + dijit.byNode(theform).getConstructorFunction().name);
						var mapproperties = new Object();
						mapproperties.pane = contentpane;
						mapproperties.form = dijit.byNode(theform);
						this._formIdMap[dojo.attr(theform, "id")] = mapproperties;
						this._constructorNameMap[org.ppwcode.dojo.util.JavaScriptHelpers.getFunctionName(mapproperties.form.getConstructorFunction())] = dojo.attr(theform, "id");
					}, this);
			}
			// add an empty pane
			var tmpnode = dojo.doc.createElement('div');
			var emptypage = new dijit.layout.ContentPane(null, tmpnode);
			emptypage.setAttribute("title", "emptyPane");
			// obey the rules
			emptypage.startup();
			//add it to the list
			this._formIdMap["__empty"] = emptypage;
			this.addChild(emptypage);
			//set it as active page. (apparently this does not happen when
			//the child is added, this is a bug in the stack container.
			this.clear();
		},

//		setConstructorMap: function(/*Array*/map) {
//			if (map.length != 0) {
//				this._formCreatorFunctionMap = new Object();
//				for (var i = 0; i < map.length; i++) {
//					this._constructorMap[map[i].constructor] = map[i].formid;
//				}
//			}
//		},

		displayForm: function(/*String*/formid) {
			var formdata = this._formIdMap[formid];
			if (formdata) {
				this.selectChild(formdata.pane);
				this._displayedformid = formid;
			}
		},

		clear: function() {
			if (this._displayedformid && this._displayedformid != "__empty") {
				this.resetCurrentForm();
			}
			this.selectChild(this._formIdMap["__empty"]);
			this._displayedformid = "__empty";
		},

		resetCurrentForm: function() {
			if (this._displayingformid) {
				this.resetForm(this._displayingformid);
			}
		},

		resetForm: function(formid) {
			this._formIdMap[formid].form.reset();
		},

		getFormForConstructor: function(/*String*/constructorname) {
			var formid = this._constructorNameMap[constructorname];
			if (formid && this._formIdMap[formid]) {
				return this._formIdMap[formid].form;
			} else {
				return null;
			}
		},

		getFormsList: function() {
			var result = new Array();
			for (var formid in this._formIdMap) {
				if (formid != "__empty") {
					var item = new Object();
					var form = this._formIdMap[formid].form;
					item.constructorFunction = form.getConstructorFunction();
					item.objectName = form.getObjectName();
					result.push(item);
				}
			}
			return result;
		},

		displayObject: function(/*Object*/obj) {
			var theformid = this._constructorNameMap[org.ppwcode.dojo.util.JavaScriptHelpers.getFunctionName(obj.constructor)];
			//constructor is defined in the map
			if (theformid) {
				this.displayForm(theformid);
				this._formIdMap[theformid].form.displayObject(obj);
			} else {
				this.displayForm("__empty");
			}
		},

		createObject: function(/*String*/constructorname) {
			var formid = this._constructorNameMap[constructorname];
			if (formid && this._formIdMap[formid]) {
				this.displayForm(formid);
				this._formIdMap[formid].form.createObject();
			} else {
				this.displayForm("__empty");
			}
		}
	}
);<commit_msg>Changed FormContainer so a user can add a user specific empty page<commit_after>dojo.provide("org.ppwcode.dojo.dijit.form.PpwCrudFormContainer");

dojo.require("dijit.layout.StackContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("org.ppwcode.dojo.util.JavaScriptHelpers");

dojo.declare(
	"org.ppwcode.dojo.dijit.form.PpwCrudFormContainer",
	dijit.layout.StackContainer,
	{
		_formIdMap: null,
		// we use a map from the constructor function NAME to the formid
		// instead of from the constructor FUNCTION, because it is not possible
		// to use a function object as a value in a ComboBox (it is possible
		// but it acts funnily).  We need the ComboBox in the PpwMasterView.
		// when adding new Objects.
		_constructorNameMap: null,
		_displayingformid: null,

//		constructorMap: null,

		postMixInProperties: function() {
			this.inherited(arguments);
//			if (this.constructorMap) {
//				this.setConstructorMap(this.constructorMap);
//			}
		},

		startup: function() {
			this.inherited(arguments);
			// we assume that our children are content panes that contain
			// exactly one form.
			this._formIdMap = new Object();
			this._constructorNameMap = new Object();
			var children = this.getChildren();
			for (var i = 0; i < children.length; i++) {
				var contentpane = children[i];
				if (dojo.attr(contentpane.domNode, 'emptyPane') == "true") {
					this._formIdMap["__empty"] = contentpane;
				} else {
					var list = dojo.query("form[widgetId]", contentpane.containerNode);
					dojo.forEach(list, function(theform) {
							//console.log("child: " + theform + " with id " + dojo.attr(theform, "id") + " and constructor " + dijit.byNode(theform).getConstructorFunction().name);
							var mapproperties = new Object();
							mapproperties.pane = contentpane;
							mapproperties.form = dijit.byNode(theform);
							this._formIdMap[dojo.attr(theform, "id")] = mapproperties;
							this._constructorNameMap[org.ppwcode.dojo.util.JavaScriptHelpers.getFunctionName(mapproperties.form.getConstructorFunction())] = dojo.attr(theform, "id");
						}, this);
				}
			}
			if (!this._formIdMap["__empty"]) {
				// add an empty pane
				var tmpnode = dojo.doc.createElement('div');
				var emptypage = new dijit.layout.ContentPane(null, tmpnode);
				emptypage.setAttribute("title", "emptyPane");
				// obey the rules
				emptypage.startup();
				//add it to the list
				this._formIdMap["__empty"] = emptypage;
				this.addChild(emptypage);
			}
			//set the empty as active page. (apparently this does not happen when
			//the child is added, this is a bug in the stack container.
			this.clear();
		},

//		setConstructorMap: function(/*Array*/map) {
//			if (map.length != 0) {
//				this._formCreatorFunctionMap = new Object();
//				for (var i = 0; i < map.length; i++) {
//					this._constructorMap[map[i].constructor] = map[i].formid;
//				}
//			}
//		},

		displayForm: function(/*String*/formid) {
			var formdata = this._formIdMap[formid];
			if (formdata) {
				this.selectChild(formdata.pane);
				this._displayedformid = formid;
			}
		},

		clear: function() {
			if (this._displayedformid && this._displayedformid != "__empty") {
				this.resetCurrentForm();
			}
			this.selectChild(this._formIdMap["__empty"]);
			this._displayedformid = "__empty";
		},

		resetCurrentForm: function() {
			if (this._displayingformid) {
				this.resetForm(this._displayingformid);
			}
		},

		resetForm: function(formid) {
			this._formIdMap[formid].form.reset();
		},

		getFormForConstructor: function(/*String*/constructorname) {
			var formid = this._constructorNameMap[constructorname];
			if (formid && this._formIdMap[formid]) {
				return this._formIdMap[formid].form;
			} else {
				return null;
			}
		},

		getFormsList: function() {
			var result = new Array();
			for (var formid in this._formIdMap) {
				if (formid != "__empty") {
					var item = new Object();
					var form = this._formIdMap[formid].form;
					item.constructorFunction = form.getConstructorFunction();
					item.objectName = form.getObjectName();
					result.push(item);
				}
			}
			return result;
		},

		displayObject: function(/*Object*/obj) {
			var theformid = this._constructorNameMap[org.ppwcode.dojo.util.JavaScriptHelpers.getFunctionName(obj.constructor)];
			//constructor is defined in the map
			if (theformid) {
				this.displayForm(theformid);
				this._formIdMap[theformid].form.displayObject(obj);
			} else {
				this.displayForm("__empty");
			}
		},

		createObject: function(/*String*/constructorname) {
			var formid = this._constructorNameMap[constructorname];
			if (formid && this._formIdMap[formid]) {
				this.displayForm(formid);
				this._formIdMap[formid].form.createObject();
			} else {
				this.displayForm("__empty");
			}
		}
	}
);<|endoftext|>


<commit_before>import Ember from 'ember';
import Error  from './error';

const {
  typeOf
} = Ember;

export function assert(message, ok) {
  if(!ok) {
    let hash;
    if(typeOf(message) === 'object') {
      hash = message;
    } else {
      hash = { error: 'assertion', reason: message };
    }
    throw new Error(hash);
  }
}

export function notBlank_(message, value) {
  assert(message, typeOf(value) === 'string' && value.trim().length > 0);
}

export function notBlank(key, value) {
  notBlank_(`${key} must not be blank`, value);
}

export function isString_(message, value) {
  assert(message, typeOf(value) === 'string');
}

export function isString(key, value) {
  isString_(`${key} must be string`, value);
}

export function isObject_(message, value) {
  assert(message, typeOf(value) === 'object');
}

export function isObject(key, value) {
  isObject_(`${key} must be object`, value);
}

export function isClass_(message, value) {
  assert(message, typeOf(value) === 'class');
}

export function isClass(key, value) {
  isClass_(`${key} must be class`, value);
}

export function isFunction_(message, value) {
  assert(message, typeOf(value) === 'function');
}

export function isFunction(key, value) {
  isFunction_(`${key} must be function`, value);
}

export function isOneOf(key, value, values) {
  assert(`${key} must be one of [${values.join(', ')}]`, values.indexOf(value) !== -1);
}

export default assert;
<commit_msg>use couch base-assert<commit_after>import SofaError  from './error';
import Base from 'couch/util/assert-base';

let {
  assert,
  notBlank_,
  notBlank,
  isString_,
  isString,
  isObject_,
  isObject,
  isClass_,
  isClass,
  isFunction_,
  isFunction,
  isOneOf
} = Base(SofaError);

export {
  assert,
  notBlank_,
  notBlank,
  isString_,
  isString,
  isObject_,
  isObject,
  isClass_,
  isClass,
  isFunction_,
  isFunction,
  isOneOf
}

export default assert;
<|endoftext|>