<commit_before>frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({
	html_element: "input",
	input_type: "text",
	make_input: function() {
		if(this.$input) return;

		this.$input = $("<"+ this.html_element +">")
			.attr("type", this.input_type)
			.attr("autocomplete", "off")
			.addClass("input-with-feedback form-control")
			.prependTo(this.input_area);

		if (in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'],
			this.df.fieldtype)) {
			this.$input.attr("maxlength", this.df.length || 140);
		}

		this.set_input_attributes();
		this.input = this.$input.get(0);
		this.has_input = true;
		this.bind_change_event();
		this.bind_focusout();
		this.setup_autoname_check();

		// somehow this event does not bubble up to document
		// after v7, if you can debug, remove this
	},
	setup_autoname_check: function() {
		if (!this.df.parent) return;
		this.meta = frappe.get_meta(this.df.parent);
		if (this.meta && ((this.meta.autoname
			&& this.meta.autoname.substr(0, 6)==='field:'
			&& this.meta.autoname.substr(6) === this.df.fieldname) || this.df.fieldname==='__newname') ) {
			this.$input.on('keyup', () => {
				this.set_description('');
				if (this.doc && this.doc.__islocal) {
					// check after 1 sec
					let timeout = setTimeout(() => {
						// clear any pending calls
						if (this.last_check) clearTimeout(this.last_check);

						// check if name exists
						frappe.db.get_value(this.doctype, this.$input.val(),
							'name', (val) => {
								if (val) {
									this.set_description(__('{0} already exists. Select another name', [val.name]));
								}
							},
							this.doc.parenttype
						);
						this.last_check = null;
					}, 1000);
					this.last_check = timeout;
				}
			});
		}
	},
	set_input_attributes: function() {
		this.$input
			.attr("data-fieldtype", this.df.fieldtype)
			.attr("data-fieldname", this.df.fieldname)
			.attr("placeholder", this.df.placeholder || "");
		if(this.doctype) {
			this.$input.attr("data-doctype", this.doctype);
		}
		if(this.df.input_css) {
			this.$input.css(this.df.input_css);
		}
		if(this.df.input_class) {
			this.$input.addClass(this.df.input_class);
		}
	},
	set_input: function(value) {
		this.last_value = this.value;
		this.value = value;
		this.set_formatted_input(value);
		this.set_disp_area(value);
		this.set_mandatory && this.set_mandatory(value);
	},
	set_formatted_input: function(value) {
		this.$input && this.$input.val(this.format_for_input(value));
	},
	get_input_value: function() {
		return this.$input ? this.$input.val() : undefined;
	},
	format_for_input: function(val) {
		return val==null ? "" : val;
	},
	validate: function(v) {
		if(this.df.is_filter) {
			return v;
		}
		if(this.df.options == 'Phone') {
			if(v+''=='') {
				return '';
			}
			var v1 = '';
			// phone may start with + and must only have numbers later, '-' and ' ' are stripped
			v = v.replace(/ /g, '').replace(/-/g, '').replace(/\(/g, '').replace(/\)/g, '');

			// allow initial +,0,00
			if(v && v.substr(0,1)=='+') {
				v1 = '+'; v = v.substr(1);
			}
			if(v && v.substr(0,2)=='00') {
				v1 += '00'; v = v.substr(2);
			}
			if(v && v.substr(0,1)=='0') {
				v1 += '0'; v = v.substr(1);
			}
			v1 += cint(v) + '';
			return v1;
		} else if(this.df.options == 'Email') {
			if(v+''=='') {
				return '';
			}

			var email_list = frappe.utils.split_emails(v);
			if (!email_list) {
				// invalid email
				return '';
			} else {
				let email_invalid = false;
				email_list.forEach(function(email) {
					if (!validate_email(email)) {
						email_invalid = true;
					}
				});
				this.df.invalid = email_invalid;
				return v;
			}

		} else {
			return v;
		}
	}
});
<commit_msg>fix: Also check if name is set, since empty object is truthy<commit_after>frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({
	html_element: "input",
	input_type: "text",
	make_input: function() {
		if(this.$input) return;

		this.$input = $("<"+ this.html_element +">")
			.attr("type", this.input_type)
			.attr("autocomplete", "off")
			.addClass("input-with-feedback form-control")
			.prependTo(this.input_area);

		if (in_list(['Data', 'Link', 'Dynamic Link', 'Password', 'Select', 'Read Only', 'Attach', 'Attach Image'],
			this.df.fieldtype)) {
			this.$input.attr("maxlength", this.df.length || 140);
		}

		this.set_input_attributes();
		this.input = this.$input.get(0);
		this.has_input = true;
		this.bind_change_event();
		this.bind_focusout();
		this.setup_autoname_check();

		// somehow this event does not bubble up to document
		// after v7, if you can debug, remove this
	},
	setup_autoname_check: function() {
		if (!this.df.parent) return;
		this.meta = frappe.get_meta(this.df.parent);
		if (this.meta && ((this.meta.autoname
			&& this.meta.autoname.substr(0, 6)==='field:'
			&& this.meta.autoname.substr(6) === this.df.fieldname) || this.df.fieldname==='__newname') ) {
			this.$input.on('keyup', () => {
				this.set_description('');
				if (this.doc && this.doc.__islocal) {
					// check after 1 sec
					let timeout = setTimeout(() => {
						// clear any pending calls
						if (this.last_check) clearTimeout(this.last_check);

						// check if name exists
						frappe.db.get_value(this.doctype, this.$input.val(),
							'name', (val) => {
								if (val && val.name) {
									this.set_description(__('{0} already exists. Select another name', [val.name]));
								}
							},
							this.doc.parenttype
						);
						this.last_check = null;
					}, 1000);
					this.last_check = timeout;
				}
			});
		}
	},
	set_input_attributes: function() {
		this.$input
			.attr("data-fieldtype", this.df.fieldtype)
			.attr("data-fieldname", this.df.fieldname)
			.attr("placeholder", this.df.placeholder || "");
		if(this.doctype) {
			this.$input.attr("data-doctype", this.doctype);
		}
		if(this.df.input_css) {
			this.$input.css(this.df.input_css);
		}
		if(this.df.input_class) {
			this.$input.addClass(this.df.input_class);
		}
	},
	set_input: function(value) {
		this.last_value = this.value;
		this.value = value;
		this.set_formatted_input(value);
		this.set_disp_area(value);
		this.set_mandatory && this.set_mandatory(value);
	},
	set_formatted_input: function(value) {
		this.$input && this.$input.val(this.format_for_input(value));
	},
	get_input_value: function() {
		return this.$input ? this.$input.val() : undefined;
	},
	format_for_input: function(val) {
		return val==null ? "" : val;
	},
	validate: function(v) {
		if(this.df.is_filter) {
			return v;
		}
		if(this.df.options == 'Phone') {
			if(v+''=='') {
				return '';
			}
			var v1 = '';
			// phone may start with + and must only have numbers later, '-' and ' ' are stripped
			v = v.replace(/ /g, '').replace(/-/g, '').replace(/\(/g, '').replace(/\)/g, '');

			// allow initial +,0,00
			if(v && v.substr(0,1)=='+') {
				v1 = '+'; v = v.substr(1);
			}
			if(v && v.substr(0,2)=='00') {
				v1 += '00'; v = v.substr(2);
			}
			if(v && v.substr(0,1)=='0') {
				v1 += '0'; v = v.substr(1);
			}
			v1 += cint(v) + '';
			return v1;
		} else if(this.df.options == 'Email') {
			if(v+''=='') {
				return '';
			}

			var email_list = frappe.utils.split_emails(v);
			if (!email_list) {
				// invalid email
				return '';
			} else {
				let email_invalid = false;
				email_list.forEach(function(email) {
					if (!validate_email(email)) {
						email_invalid = true;
					}
				});
				this.df.invalid = email_invalid;
				return v;
			}

		} else {
			return v;
		}
	}
});
<|endoftext|>


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

app.controller('myController', ['$scope', '$log', '$http','$filter', function($scope, $log, $http,$filter) {

        $scope.sortType     = 'name'; // set the default sort type
        $scope.sortReverse  = false;  // set the default sort order
        $scope.searchFish   = '';     // set the default search/filter term

      $scope.buscar = function() {

            $http.get('/api/logconversation').success(function(data) {

               var retorno = [];
               console.log('data '+data);
                var pos = 0;

                angular.forEach(data.logs, function(item){

                     var jsonParam = {};
                      angular.forEach(item.response.entities, function(ent){
                           jsonParam.entidade = ent.entity;
                           jsonParam.confidenceEntidade = ent.confidence;
                      });
                      angular.forEach(item.response.intents, function(int){
                         jsonParam.intencao = int.intent;
                         jsonParam.confidenceIntencao = int.confidence;
                      });

                       angular.forEach(item.response.input, function(text){
                                 if(text.length!=0)jsonParam.msgUser = text;
                        });

                     if(!angular.equals(jsonParam, {})){
                        retorno.push(jsonParam);
                     }

                 });

                 console.log('size data '+retorno.length);

                  $scope.items = retorno;

             });
      }

   $scope.sort_by = function(newSortingOrder) {
      $scope.sortType = newSortingOrder; $scope.sortReverse = !$scope.sortReverse;
    };

    $scope.showDown = function(newSortingOrder) {
          return $scope.sortType == newSortingOrder && !$scope.sortReverse
     };

    $scope.showUp = function(newSortingOrder) {
          return $scope.sortType == newSortingOrder && $scope.sortReverse

     };

}]);

<commit_msg>comitando<commit_after>
var app = angular.module('MinhaApp', []);

app.controller('myController', ['$scope', '$log', '$http','$filter', function($scope, $log, $http,$filter) {

        $scope.sortType     = 'name'; // set the default sort type
        $scope.sortReverse  = false;  // set the default sort order
        $scope.searchFish   = '';     // set the default search/filter term

      $scope.buscar = function() {

            $http.get('/api/logconversation').success(function(data) {

               var retorno = [];
               console.log('data '+data);
                var pos = 0;

                angular.forEach(data.logs, function(item){

                     var jsonParam = {};
                      angular.forEach(item.response.entities, function(ent){
                           jsonParam.entidade = ent.entity;
                           jsonParam.confidenceEntidade = (ent.confidence*100).toFixed(1)+" %";
                      });
                      angular.forEach(item.response.intents, function(int){
                         jsonParam.intencao = int.intent;
                         jsonParam.confidenceIntencao = (int.confidence*100).toFixed(1) +" %";
                      });

                      angular.forEach(item.response.input, function(text){
                                 if(text.length!=0)jsonParam.msgUser = text;
                       });

                      if(item.response.context.conversation_id.length!=0){
                        jsonParam.conversation_id = item.response.context.conversation_id;
                        jsonParam.data = item.response_timestamp;
                      }

                     if(!angular.equals(jsonParam, {})){
                        retorno.push(jsonParam);
                     }

                 });

                 console.log('size data '+retorno.length);

                  $scope.items = retorno;

             });
      }

   $scope.sort_by = function(newSortingOrder) {
      $scope.sortType = newSortingOrder; $scope.sortReverse = !$scope.sortReverse;
    };

    $scope.showDown = function(newSortingOrder) {
          return $scope.sortType == newSortingOrder && !$scope.sortReverse
     };

    $scope.showUp = function(newSortingOrder) {
          return $scope.sortType == newSortingOrder && $scope.sortReverse

     };

}]);

<|endoftext|>


<commit_before>(function (badges, $, undefined) {
    "use strict";

    var options = {}, geocoder, map, marker;

    badges.options = function (o) {
        $.extend(options, o);
    };

    badges.init = function () {
        initializeTypeahead();
        initializeImagePreview();
        $(".datepicker").datepicker();
        initializeMap();
    };

    function initializeTypeahead() {
        $("#Experience_Name").typeahead({
            name: 'title',
            prefetch: options.TitlesUrl,
            limit: 10
        });

        $("#Experience_Organization").typeahead({
            name: 'orgs',
            prefetch: options.OrganizationsUrl,
            limit: 10
        });
    }

    function initializeImagePreview() {
        $("#cover-image").change(function () {
            var filesToUpload = this.files;
            if (filesToUpload.length !== 1) return;

            var file = filesToUpload[0];

            if (!file.type.match(/image.*/)) {
                alert("only images, please");
            }

            var img = document.getElementById("cover-preview");
            img.src = window.URL.createObjectURL(file);
            img.onload = function(e) {
                window.URL.revokeObjectURL(this.src);
            };
            //img.height = 500;
        });
    }

    function initializeMap() {
        var davisLatLng = new google.maps.LatLng(38.5449065, -121.7405167);
        geocoder = new google.maps.Geocoder();
        var mapOptions = {
            center: davisLatLng,
            zoom: 10,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        map = new google.maps.Map(document.getElementById("map-canvas"),
            mapOptions);
        marker = new google.maps.Marker({
            map: map,
            position: davisLatLng
        });

        $("#Experience_Location").blur(function () {
            var address = this.value;
            geocoder.geocode({ 'address': address }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    if (marker) marker.setMap(null); //clear existing marker
                    map.setCenter(results[0].geometry.location);
                    marker = new google.maps.Marker({
                        map: map,
                        position: results[0].geometry.location
                    });
                    if (results[0].geometry.viewport)
                        map.fitBounds(results[0].geometry.viewport);
                } else {
                    alert('Geocode was not successful for the following reason: ' + status);
                }
            });
        });
    }
}(window.Badges = window.Badges || {}, jQuery));<commit_msg>datepicker formats nicer & autoclose<commit_after>(function (badges, $, undefined) {
    "use strict";

    var options = {}, geocoder, map, marker;

    badges.options = function (o) {
        $.extend(options, o);
    };

    badges.init = function () {
        initializeTypeahead();
        initializeImagePreview();
        $(".datepicker").datepicker({ format: 'm/d/yyyy', autoclose: true });
        initializeMap();
    };

    function initializeTypeahead() {
        $("#Experience_Name").typeahead({
            name: 'title',
            prefetch: options.TitlesUrl,
            limit: 10
        });

        $("#Experience_Organization").typeahead({
            name: 'orgs',
            prefetch: options.OrganizationsUrl,
            limit: 10
        });
    }

    function initializeImagePreview() {
        $("#cover-image").change(function () {
            var filesToUpload = this.files;
            if (filesToUpload.length !== 1) return;

            var file = filesToUpload[0];

            if (!file.type.match(/image.*/)) {
                alert("only images, please");
            }

            var img = document.getElementById("cover-preview");
            img.src = window.URL.createObjectURL(file);
            img.onload = function(e) {
                window.URL.revokeObjectURL(this.src);
            };
            //img.height = 500;
        });
    }

    function initializeMap() {
        var davisLatLng = new google.maps.LatLng(38.5449065, -121.7405167);
        geocoder = new google.maps.Geocoder();
        var mapOptions = {
            center: davisLatLng,
            zoom: 10,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        map = new google.maps.Map(document.getElementById("map-canvas"),
            mapOptions);
        marker = new google.maps.Marker({
            map: map,
            position: davisLatLng
        });

        $("#Experience_Location").blur(function () {
            var address = this.value;
            geocoder.geocode({ 'address': address }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    if (marker) marker.setMap(null); //clear existing marker
                    map.setCenter(results[0].geometry.location);
                    marker = new google.maps.Marker({
                        map: map,
                        position: results[0].geometry.location
                    });
                    if (results[0].geometry.viewport)
                        map.fitBounds(results[0].geometry.viewport);
                } else {
                    alert('Geocode was not successful for the following reason: ' + status);
                }
            });
        });
    }
}(window.Badges = window.Badges || {}, jQuery));<|endoftext|>


<commit_before>const ip = require('ip');
const path = require('path');
const autoprefixer = require('autoprefixer');
const Dashboard = require('webpack-dashboard');
const DashboardPlugin = require('webpack-dashboard/plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');

const dashboard = new Dashboard();

const join = path.join.bind(path, __dirname, '..');

const sources = ['src', 'demo'].map(dir => join(dir));

module.exports = {
  devtool: 'inline-source-map',
  entry: {
    app: [
      `webpack-dev-server/client?http://${ip.address()}:3000`,
      join('demo/app/index.ts'),
    ],
    sw: [
      join('demo/sw/index.ts'),
    ],
  },
  output: {
    path: join('build/'),
    filename: '[name].js',
  },
  resolve: {
    extensions: ['', '.js', '.ts', '.scss'],
  },
  module: {
    preLoaders: [{
      test: /\.ts$/,
      loader: 'tslint',
      include: sources,
    }],
    loaders: [{
      test: /\.ts$/,
      loader: 'ts',
      include: sources,
    }, {
      test: /\.scss/,
      loader: [
        'style',
        'css',
        'postcss',
        'sass?sourceMap',
      ],
    }],
    noParse: [
      // remove "Critical dependency" warning
      require.resolve('localforage/dist/localforage.nopromises.js'),
    ],
  },
  postcss: [autoprefixer],
  tslint: {
    formatter: 'stylish',
  },
  ts: {
    silent: true,
  },
  plugins: [
    new CircularDependencyPlugin({
      // exclude detection of files based on a RegExp
      exclude: /node_modules/,
      failOnError: true,
    }),
    new DashboardPlugin(dashboard.setData),
  ],
};
<commit_msg>update(webpack): don't generate d.ts files in dev<commit_after>const ip = require('ip');
const path = require('path');
const autoprefixer = require('autoprefixer');
const Dashboard = require('webpack-dashboard');
const DashboardPlugin = require('webpack-dashboard/plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');

const dashboard = new Dashboard();

const join = path.join.bind(path, __dirname, '..');

const sources = ['src', 'demo'].map(dir => join(dir));

module.exports = {
  devtool: 'inline-source-map',
  entry: {
    app: [
      `webpack-dev-server/client?http://${ip.address()}:3000`,
      join('demo/app/index.ts'),
    ],
    sw: [
      join('demo/sw/index.ts'),
    ],
  },
  output: {
    path: join('build/'),
    filename: '[name].js',
  },
  resolve: {
    extensions: ['', '.js', '.ts', '.scss'],
  },
  module: {
    preLoaders: [{
      test: /\.ts$/,
      loader: 'tslint',
      include: sources,
    }],
    loaders: [{
      test: /\.ts$/,
      loader: 'ts',
      include: sources,
    }, {
      test: /\.scss/,
      loader: [
        'style',
        'css',
        'postcss',
        'sass?sourceMap',
      ],
    }],
    noParse: [
      // remove "Critical dependency" warning
      require.resolve('localforage/dist/localforage.nopromises.js'),
    ],
  },
  postcss: [autoprefixer],
  tslint: {
    formatter: 'stylish',
  },
  ts: {
    silent: true,
    compilerOptions: {
      declaration: false,
    },
  },
  plugins: [
    new CircularDependencyPlugin({
      // exclude detection of files based on a RegExp
      exclude: /node_modules/,
      failOnError: true,
    }),
    new DashboardPlugin(dashboard.setData),
  ],
};
<|endoftext|>


<commit_before>var univNames = [
  "Adelphi",
  "Boston University",
  "CMU",
  "Harvard",
  "New York University",
  "Singapore Management University",
  "Stanford",
  "UC Berkeley",
  "University of Delaware",
  "University of Manouba",
  "University of Tunis El Manar",
  "University of Tsukuba",
  "University of Tunis",
  "University of Rochester",
  "UT Rio Grande Valley",
  "University of Washington",
  "University of Waterloo",
  "William & Mary",
  "가야대",
  "가천대",
  "가톨릭대",
  "가톨릭관동대",
  "감리교신학대",
  "강남대",
  "강릉원주대",
  "강원대",
  "건국대",
  "건양대",
  "경기대",
  "경남과학기술대",
  "경남대",
  "경동대",
  "경북대",
  "경상대",
  "경성대",
  "경운대",
  "경일대",
  "경주대",
  "경희대",
  "계명대",
  "계명문화대",
  "고려대",
  "고신대",
  "공주대",
  "광신대",
  "광운대",
  "광주가톨릭대",
  "광주대",
  "광주여자대",
  "국민대",
  "군산대",
  "극동대",
  "금강대",
  "금오공대",
  "김천대",
  "꽃동네대",
  "나사렛대",
  "남부대",
  "남서울대",
  "단국대",
  "대구가톨릭대",
  "대구대",
  "대구예술대",
  "대구한의대",
  "대신대",
  "대전가톨릭대",
  "대전대",
  "대전신학대",
  "대진대",
  "덕성여대",
  "동국대",
  "동덕여대",
  "동명대",
  "동서대",
  "동신대",
  "동아대",
  "동양대",
  "동의대",
  "루터대",
  "명지대",
  "목원대",
  "목포가톨릭대",
  "목포대",
  "목포해양대",
  "배재대",
  "백석대",
  "부경대",
  "부산가톨릭대",
  "부산대",
  "부산외국어대",
  "부산장신대",
  "삼육대",
  "상명대",
  "서강대",
  "서경대",
  "서울대",
  "서울과학기술대",
  "서울시립대",
  "선문대",
  "성공회대",
  "성균관대","세명대",
  "세종대",
  "순천대",
  "순천향대",
  "숭실대",
  "숭의여대",
  "아주대",
  "연세대",
  "영남대",
  "인천대",
  "유니스트",
  "유한대",
  "인하대",
  "전남대",
  "전북대",
  "전주대",
  "중앙대",
  "충남대",
  "충북대",
  "카이스트",
  "포항공과대학교",
  "평택대",
  "한국기술교육대",
  "한국외국어대",
  "한국항공대",
  "한동대",
  "한밭대",
  "한성대",
  "한양대",
  "호서대",
  "홍익대"
];
<commit_msg>Adjust Index at Readme<commit_after>var univNames = [
  "Adelphi University",
  "Boston University",
  "Carnegie Mellon University",
  "College of William & Mary",
  "Ez-zitouna University",
  "Gabes University",
  "Gafsa University",
  "Havard University",
  "Manouba University",
  "Monastir University",
  "New York University",
  "Sfax University",
  "Singapore Management University",
  "Sousse University",
  "Stanford University",
  "Tunis El Manar University",
  "Tunis University",
  "UC Berkeley",
  "University of Carthage",
  "University of Delaware",
  "University of Rochester",
  "University of Jendouba",
  "University of Texas Rio Grande Valley",
  "University of Tsukuba",
  "University of Washington",
  "University of Waterloo",
  "가야대",
  "가천대",
  "가톨릭대",
  "가톨릭관동대",
  "감리교신학대",
  "강남대",
  "강릉원주대",
  "강원대",
  "건국대",
  "건양대",
  "경기대",
  "경남과학기술대",
  "경남대",
  "경동대",
  "경북대",
  "경상대",
  "경성대",
  "경운대",
  "경일대",
  "경주대",
  "경희대",
  "계명대",
  "계명문화대",
  "고려대",
  "고신대",
  "공주대",
  "광신대",
  "광운대",
  "광주가톨릭대",
  "광주대",
  "광주여자대",
  "국민대",
  "군산대",
  "극동대",
  "금강대",
  "금오공대",
  "김천대",
  "꽃동네대",
  "나사렛대",
  "남부대",
  "남서울대",
  "단국대",
  "대구가톨릭대",
  "대구대",
  "대구예술대",
  "대구한의대",
  "대신대",
  "대전가톨릭대",
  "대전대",
  "대전신학대",
  "대진대",
  "덕성여대",
  "동국대",
  "동덕여대",
  "동명대",
  "동서대",
  "동신대",
  "동아대",
  "동양대",
  "동의대",
  "루터대",
  "명지대",
  "목원대",
  "목포가톨릭대",
  "목포대",
  "목포해양대",
  "배재대",
  "백석대",
  "부경대",
  "부산가톨릭대",
  "부산대",
  "부산외국어대",
  "부산장신대",
  "삼육대",
  "상명대",
  "서강대",
  "서경대",
  "서울대",
  "서울과학기술대",
  "서울시립대",
  "선문대",
  "성공회대",
  "성균관대",
  "세명대",
  "세종대",
  "순천대",
  "순천향대",
  "숭실대",
  "숭의여대",
  "아주대",
  "연세대",
  "영남대",
  "인천대",
  "유니스트",
  "유한대",
  "인하대",
  "전남대",
  "전북대",
  "전주대",
  "중앙대",
  "충남대",
  "충북대",
  "카이스트",
  "포항공과대학교",
  "평택대",
  "한국기술교육대",
  "한동대",
  "한국외국어대",
  "한국항공대",
  "한밭대",
  "한성대",
  "한양대",
  "호서대",
  "홍익대"
];
<|endoftext|>


<commit_before>function strlen(string) {
    "use strict"; /*
    var i = 0;

    while (string[i]) {
        i += 1;
    }
    return (i); */
    return (string.length);
}
function strstr(haystack, needle) {
    "use strict"; /*
    var i = 0;
    var j = 0;
    var limit = strlen(haystack);
    var key_size = strlen(needle);

    while (i < limit) {
        if (haystack[i] === needle[j]) {
            j += 1;
        } else {
            j = 0;
        }

        if (j === key_size) {
            return true;
        }
        i += 1;
    } */
    if (haystack.search(needle) >= 0) {
        return true;
    }
    return false;
}

function parse_user_agent(agent) {
    "use strict";
    var fields = [];

    fields[0] = agent;
    fields[1] = "(unknown)";
    fields[2] = "UNICS-derived";
    if (fields[0] === "") {
        fields[0] = "(no browser identification sent)";
        return (fields);
    }

    if (strstr(agent, "Mobile")) {
        if (strstr(agent, "Win")) {
            fields[2] = "Windows Mobile";
        } else if (strstr(agent, "Android")) {
            fields[2] = "Google Android";
        } else {
            fields[2] = "Apple iOS";
        }
    } else if (strstr(agent, "Win")) {
        fields[2] = "Microsoft Windows";
    } else if (strstr(agent, "Mac")) {
        fields[2] = "Apple Macintosh";
    } else if (strstr(agent, "BSD")) {
        fields[2] = "BSD Unix family";
    } else if (strstr(agent, "Sun") || strstr(agent, "Solar")) {
        fields[2] = "Solaris";
    } else if (strstr(agent, "X11")) {
        fields[2] = "Unix-based, running X";
    }

    if (strstr(agent, "Lynx")) {
        fields[1] = "Lynx";
    } else if (strstr(agent, "Links")) {
        fields[1] = "Links";
    } else if (strstr(agent, "OPR") || strstr(agent, "Opera")) {
        fields[1] = "Opera";
    } else if (strstr(agent, "Netscape") || strstr(agent, "Navigator")) {
        fields[1] = "Netscape Navigator";
    } else if (strstr(agent, "Konqueror") || strstr(agent, "konqueror")) {
        fields[1] = "Konqueror";
    } else if (strstr(agent, "Safari")) {
        fields[1] = "Apple Safari";
    } else if (strstr(agent, "Chrome")) {
        fields[1] = "Google Chrome";
    } else if (strstr(agent, "MSIE")) {
        fields[1] = "Microsoft Internet Explorer";
    } else if (strstr(agent, "Mozilla")) {
        if (strstr(agent, "Fire") || strstr(agent, "Phoenix")) {
            fields[1] = "Mozilla Firefox";
        } else {
            fields[1] = "Mozilla-compatible";
        }
    }
    return (fields);
}
<commit_msg>moved browser detection to function get_browser_from_agent()<commit_after>function strlen(string) {
    "use strict"; /*
    var i = 0;

    while (string[i]) {
        i += 1;
    }
    return (i); */
    return (string.length);
}
function strstr(haystack, needle) {
    "use strict"; /*
    var i = 0;
    var j = 0;
    var limit = strlen(haystack);
    var key_size = strlen(needle);

    while (i < limit) {
        if (haystack[i] === needle[j]) {
            j += 1;
        } else {
            j = 0;
        }

        if (j === key_size) {
            return true;
        }
        i += 1;
    } */
    if (haystack.search(needle) >= 0) {
        return true;
    }
    return false;
}

function get_browser_from_agent(agent) {
    "use strict";
    if (strstr(agent, "Lynx")) {
        return "Lynx";
    }
    if (strstr(agent, "Links")) {
        return "Links";
    }
    if (strstr(agent, "OPR") || strstr(agent, "Opera")) {
        return "Opera";
    }
    if (strstr(agent, "Netscape") || strstr(agent, "Navigator")) {
        return "Netscape Navigator";
    }
    if (strstr(agent, "Konqueror") || strstr(agent, "konqueror")) {
        return "Konqueror";
    }
    if (strstr(agent, "Safari")) {
        return "Apple Safari";
    }
    if (strstr(agent, "Chrome")) {
        return "Google Chrome";
    }
    if (strstr(agent, "MSIE")) {
        return "Microsoft Internet Explorer";
    }
    if (strstr(agent, "Mozilla") && strstr(agent, "Fire")) {
        return "Mozilla Firefox";
    }
    return "Mozilla-compatible";
}

function parse_user_agent(agent) {
    "use strict";
    var fields = [];

    fields[2] = "UNICS-derived";
    if (agent === "") {
        fields[0] = "(no browser identification sent)";
        fields[1] = "(unknown)";
        return (fields);
    }
    fields[0] = agent;
    fields[1] = get_browser_from_agent(agent);

    if (strstr(agent, "Mobile")) {
        if (strstr(agent, "Win")) {
            fields[2] = "Windows Mobile";
        } else if (strstr(agent, "Android")) {
            fields[2] = "Google Android";
        } else {
            fields[2] = "Apple iOS";
        }
    } else if (strstr(agent, "Win")) {
        fields[2] = "Microsoft Windows";
    } else if (strstr(agent, "Mac")) {
        fields[2] = "Apple Macintosh";
    } else if (strstr(agent, "BSD")) {
        fields[2] = "BSD Unix family";
    } else if (strstr(agent, "Sun") || strstr(agent, "Solar")) {
        fields[2] = "Solaris";
    } else if (strstr(agent, "X11")) {
        fields[2] = "Unix-based, running X";
    }

    return (fields);
}
<|endoftext|>


<commit_before>(function () {
	'use strict';
	/**
	** DEPENDENCIES
	**  - moment
	**/
	var formatMoment = function (_moment, _format) { //expects a moment
		var m = moment(_moment);
		if (m.isValid()) {
			return m.format(_format);
		} else {
			return _moment;
		}
	};

	angular.module('lui.filters')
	.filter('luifFriendlyRange', function () {
		var traductions = {
			'en': {
				sameDay: 'start(LL)',
				sameMonth: 'start(MMMM Do) - end(Do\, YYYY)',
				sameYear: 'start(MMMM Do) - end(LL)',
				other: 'start(LL) - end(LL)'
			},
			'fr': {
				sameDay: 'le start(LL)',
				sameMonth: 'du start(Do) au end(LL)',
				sameYear: 'du start(Do MMMM) au end(LL)',
				other: 'du start(LL) au end(LL)'
			}
		};
		var currentYearTraductions = {
			'en': {
				sameDay: 'start(MMMM Do)',
				sameMonth: 'start(MMMM Do) - end(Do)',
				sameYear: 'start(MMMM Do) - end(MMMM Do)',
				other: 'start(LL) - end(LL)'
			},
			'fr': {
				sameDay: 'le start(Do MMMM)',
				sameMonth: 'du start(Do) au end(Do MMMM)',
				sameYear: 'du start(Do MMMM) au end(Do MMMM)',
				other: 'du start(LL) au end(LL)'
			}
		};
		return function (_block, _excludeEnd) {
			if(!_block){ return; }
			var start = moment(_block.startsAt || _block.startsOn || _block.startDate || _block.start);
			var end = moment(_block.endsAt || _block.endsOn || _block.endDate || _block.end);
			if(_excludeEnd){
				end.add(-1,'d');
			}
			var trads = traductions[moment.locale()] || traductions.en;
			if(moment().year() === start.year() && moment().year() === end.year()){
				trads = currentYearTraductions[moment.locale()] || currentYearTraductions.en;
			}
			var format = start.year() === end.year() ? start.month() === end.month() ? start.date() === end.date() ? 'sameDay' : 'sameMonth' : 'sameYear' : 'other';
			var regex = /(start\((.*?)\))(.*(end\((.*?)\))){0,1}/gi.exec(trads[format]);
			return trads[format].replace(regex[1], start.format(regex[2])).replace(regex[4], end.format(regex[5]));
		};
	})
	.filter('luifMoment', function () {
		return function (_moment, _format) {
			if (!_format) { _format = 'LLL'; } // default format
			return formatMoment(_moment, _format);
		};
	})
	.filter('luifCalendar', function () {
		return function (_moment, _refDate) {
			var m = moment(_moment);
			var refDate = (_refDate && moment(_refDate).isValid()) ? moment(_refDate) : moment();

			if (m.isValid()) {
				return m.calendar(_refDate);
			} else {
				return _moment;
			}
		};
	})
	// this filter is very ugly and i'm sorry - i'll add lots of comments
	.filter('luifDuration', ['$filter', function ($filter) {
		return function (_duration, _sign, _unit, _precision) {  //expects a duration, returns the duration in the given unit with the given precision
			var d = moment.duration(_duration);

			if(d.asMilliseconds() === 0){ return ''; }

			// parse duration
			var values = [Math.abs(d.days()), Math.abs(d.hours()), Math.abs(d.minutes()), Math.abs(d.seconds()), Math.abs(d.milliseconds())];
			var units = ['d ', 'h', 'm', 's', 'ms'];
			var unit;

			// First we get the floor part of the unit of the duration : 1d11h = 1.x day or 35 hours or 2100 minutes depending on your unit
			switch(_unit){
				case 'd':
				case 'day':
				case 'days':
					_precision = !!_precision ? _precision : 'h'; // if no precision is provided, we take the next unit

					if ((_precision === 'd' || _precision === 'day' || _precision === 'days') && d.asDays() > 0) {
						unit = 0;
						// Determine the number of decimals to display
						var decimals = 2;
						var days = d.asDays();
						if ( Math.floor((days * 10) % 10) === 0 && Math.floor((days * 100) % 10) === 0 ) {
							decimals = 0;
						} else if ( Math.floor((days * 100) % 10) === 0) {
							decimals = 1;
						}
						values[0] = $filter("number")(days, decimals);
					} else {
						// the first unit with a not nul member, if you want 15 minutes expressed in days it will respond 15m
						unit = values[0] !== 0 ? 0 : values[1] !== 0 ? 1 : values[2] !== 0 ? 2 : values[3] !== 0 ? 3 : 4;
						values[0] = Math.abs(d.asDays() >= 0 ? Math.floor(d.asDays()) : Math.ceil(d.asDays()));
					}
					break;
				case undefined:
				case '': // if no _unit is provided, use hour
				case 'h':
				case 'hour':
				case 'hours':
					_precision = _precision || 'm';
					unit = (values[0] !== 0 || values[1] !== 0) ? 1 : values[2] !== 0 ? 2 : values[3] !== 0 ? 3 : 4; // the first unit with a not nul member
					values[1] = Math.abs(d.asHours() >= 0 ? Math.floor(d.asHours()) : Math.ceil(d.asHours()));
					break;
				case 'm':
				case 'min':
				case 'mins':
				case 'minute':
				case 'minutes':
					_precision = _precision || 's';
					unit = (values[0] !== 0 || values[1] !== 0 || values[2] !== 0) ? 2 : values[3] !== 0 ? 3 : 4; // the first unit with a not nul member
					values[2] = Math.abs(d.asMinutes() >= 0 ? Math.floor(d.asMinutes()) : Math.ceil(d.asMinutes()));
					break;
				case 's':
				case 'sec':
				case 'second':
				case 'seconds':
					_precision = _precision || 's';
					unit = (values[0] !== 0 || values[1] !== 0 || values[2] !== 0 || values[3] !== 0) ? 3 : 4; // the first unit with a not nul member
					values[3] = Math.abs(d.asSeconds() >= 0 ? Math.floor(d.asSeconds()) : Math.ceil(d.asSeconds()));
					break;
				case 'ms':
				case 'millisec':
				case 'millisecond':
				case 'milliseconds':
					_precision = _precision || 'ms';
					unit = 4;
					values[4] = Math.abs(d.asMilliseconds() >= 0 ? Math.floor(d.asMilliseconds()) : Math.ceil(d.asMilliseconds()));
					break;
			}
			var precision; // if you want 1h as minutes, precision milliseconds you want the result to be 60m and not 60m 00.000s
			switch(_precision){
				case 'd':
				case 'day':
				case 'days':
					precision = 0;
					break;
				case 'h':
				case 'hour':
				case 'hours':
					precision = values[1] !== 0 ? 1 : 0;
					break;
				case 'm':
				case 'min':
				case 'mins':
				case 'minute':
				case 'minutes':
					precision = values[2] !== 0 ? 2 : values[1] !== 0 ? 1 : 0;
					break;
				case 's':
				case 'sec':
				case 'second':
				case 'seconds':
					precision = values[3] !== 0 ? 3 : values[2] !== 0 ? 2 : values[1] !== 0 ? 1 : 0;
					break;
				case 'ms':
				case 'millisec':
				case 'millisecond':
				case 'milliseconds':
					precision = values[4] !== 0 ? 4 : values[3] !== 0 ? 3 : values[2] !== 0 ? 2 : values[1] !== 0 ? 1 : 0;
					break;
			}
			// some localisation shenanigans
			switch(moment.locale()){
				case "fr": units[0] = 'j '; break;
			}

			// if precision = ms and unit bigger than s we want to display 12.525s and not 12s525ms
			if(unit <= 3 && precision === 4){ units[3] = '.'; units[4] = 's'; }
			if(unit <= 1 && precision === 2){ units[2] = ''; }
			if(unit === 2 && precision === 3){ units[3] = ''; }

			var format = function(value, u){
				if (u === unit){
					return value + units[u];
				}
				if (u === 2 || u === 3){
					return (value < 10 ? '0' + value : value) + units[u];
				}
				if (u === 4){
					return (value < 10 ? '00' + value : value < 100 ? '0' + value : value) + units[u];
				}
				return value + units[u];
			};
			var result = '';
			for(var i = unit; i <= precision; i++){
				result += format(values[i],i);
			}

			// add prefix
			var prefix = '';
			if (_sign && !!result) {
				if (d.asMilliseconds() > 0) {
					prefix = '+';
				} else if (d.asMilliseconds() < 0) {
					prefix = '-';
				}
			}

			return prefix + result;
		};
	}])
	.filter('luifHumanize', function () {
		return function (_duration, suffix) {
			suffix = !!suffix;
			var d = moment.duration(_duration);
			return d.humanize(suffix);
		};
	});
})();
<commit_msg>REF : timeFilters.js refactoring<commit_after>(function () {
	'use strict';
	/**
	** DEPENDENCIES
	**  - moment
	**/
	var formatMoment = function (_moment, _format) { //expects a moment
		var m = moment(_moment);
		return m.isValid() ? m.format(_format) : _moment;
	};

	angular.module('lui.filters')
	.filter('luifFriendlyRange', function () {
		var traductions = {
			'en': {
				sameDay: 'start(LL)',
				sameMonth: 'start(MMMM Do) - end(Do\, YYYY)',
				sameYear: 'start(MMMM Do) - end(LL)',
				other: 'start(LL) - end(LL)'
			},
			'fr': {
				sameDay: 'le start(LL)',
				sameMonth: 'du start(Do) au end(LL)',
				sameYear: 'du start(Do MMMM) au end(LL)',
				other: 'du start(LL) au end(LL)'
			}
		};
		var currentYearTraductions = {
			'en': {
				sameDay: 'start(MMMM Do)',
				sameMonth: 'start(MMMM Do) - end(Do)',
				sameYear: 'start(MMMM Do) - end(MMMM Do)',
				other: 'start(LL) - end(LL)'
			},
			'fr': {
				sameDay: 'le start(Do MMMM)',
				sameMonth: 'du start(Do) au end(Do MMMM)',
				sameYear: 'du start(Do MMMM) au end(Do MMMM)',
				other: 'du start(LL) au end(LL)'
			}
		};
		return function (_block, _excludeEnd) {
			if(!_block){ return; }
			var start = moment(_block.startsAt || _block.startsOn || _block.startDate || _block.start);
			var end = moment(_block.endsAt || _block.endsOn || _block.endDate || _block.end);
			if(_excludeEnd){
				end.add(-1,'d');
			}
			var trads = traductions[moment.locale()] || traductions.en;
			if(moment().year() === start.year() && moment().year() === end.year()){
				trads = currentYearTraductions[moment.locale()] || currentYearTraductions.en;
			}
			var format = start.year() === end.year() ? start.month() === end.month() ? start.date() === end.date() ? 'sameDay' : 'sameMonth' : 'sameYear' : 'other';
			var regex = /(start\((.*?)\))(.*(end\((.*?)\))){0,1}/gi.exec(trads[format]);
			return trads[format].replace(regex[1], start.format(regex[2])).replace(regex[4], end.format(regex[5]));
		};
	})
	.filter('luifMoment', function () {
		return function (_moment, _format) {
			if (!_format) { _format = 'LLL'; } // default format
			return formatMoment(_moment, _format);
		};
	})
	.filter('luifCalendar', function () {
		return function (_moment, _refDate) {
			var m = moment(_moment);
			var refDate = (_refDate && moment(_refDate).isValid()) ? moment(_refDate) : moment();

			return m.isValid() ? m.calendar(_refDate) : _moment;
		};
	})
	.filter('luifDuration', ['$filter', function ($filter) {
		//expects a duration, returns the duration in the given unit with the given precision
		return function (_duration, _sign, _unit, _precision) {
			function getConfigIndex(expectedUnit){
				switch(expectedUnit){
					case 'd':
					case 'day':
					case 'days': return 0;
					case undefined:
					case '':
					case 'h':
					case 'hour':
					case 'hours': return 1;// default
					case 'm':
					case 'min':
					case 'mins':
					case 'minute':
					case 'minutes': return 2;
					case 's':
					case 'sec':
					case 'second':
					case 'seconds': return 3;
					case 'ms':
					case 'millisec':
					case 'millisecond':
					case 'milliseconds': return 4;
				}
			}

			function getNextNotNull(array, startIndex){
				return startIndex === 4 ? 4 : array[startIndex] !== 0 ? startIndex : getNextNotNull(array, startIndex + 1);
			}

			function getPrevNotNull(array, startIndex){
				return startIndex === 0 ? 0 : array[startIndex] !== 0 ? startIndex : getPrevNotNull(array, startIndex - 1);
			}

			function getDecimalNumber(days){
				switch(true){
					case (Math.floor((days * 10) % 10) === 0 && Math.floor((days * 100) % 10) === 0):	return 0;
					case (Math.floor((days * 100) % 10) === 0):											return 1;
					default: 																			return 2;
				}
			}

			function formatValue (value, u, expectedUnit){
				switch(u){
					case expectedUnit :	return value;
					case 2 :
					case 3 : 			return (value < 10 ? '0' + value : value);
					case 4 : 			return (value < 10 ? '00' + value : value < 100 ? '0' + value : value);
					default : 			return value;
				}
			}

			function getPrefix(sign, duration){
				if (sign) {
					if (duration.asMilliseconds() > 0) { return '+'; }
					else if (duration.asMilliseconds() < 0) { return '-'; }
				}
				return '';
			}

			// some localisation shenanigans
			function getUnitSymbols(unit, precision){
				var result = ['d ', 'h', 'm', 's', 'ms'];
				switch(moment.locale()){
					case "fr": result[0] = 'j '; break;
				}

				// if precision = ms and unit bigger than s we want to display 12.525s and not 12s525ms
				if(unit <= 3 && precision === 4) { result[3] = '.'; result[4] = 's'; }
				if(unit <= 1 && precision === 2) { result[2] = ''; }
				if(unit === 2 && precision === 3) { result[3] = ''; }

				return result;
			}

			var unitConfigs = [
				{
					index: 0,
					unit: 'd',
					dateConversion : 'asDays',
					expectedPrecision : 'h'
				},
				{
					index: 1,
					unit: 'h',
					dateConversion : 'asHours',
					expectedPrecision :'m'
				},
				{
					index: 2,
					unit: 'm',
					dateConversion : 'asMinutes',
					expectedPrecision : 's'
				},
				{
					index: 3,
					unit: 's',
					dateConversion : 'asSeconds',
					expectedPrecision : 's'
				},
				{
					index: 4,
					unit: 'ms',
					dateConversion : 'asMilliseconds',
					expectedPrecision : 'ms'
				},
			];

			var d = moment.duration(_duration);

			if (d.asMilliseconds() === 0) { return ''; }

			var values = [Math.abs(d.days()), Math.abs(d.hours()), Math.abs(d.minutes()), Math.abs(d.seconds()), Math.abs(d.milliseconds())];
			var config = unitConfigs[getConfigIndex(_unit)];
			var minimumUnit = Math.max(config.index, getNextNotNull(values, 0));
			values[config.index] = Math.abs(d[config.dateConversion]() >= 0 ? Math.floor(d[config.dateConversion]()) : Math.ceil(d[config.dateConversion]()));

			if (config.index === 0 && getConfigIndex(_precision) === 0 && d.asDays() > 0){
				var myDays = d.asDays();
				var decimalNumber = getDecimalNumber(myDays);
				minimumUnit = 0;
				values[0] = $filter("number")(myDays, decimalNumber);
			}

			var precision = getPrevNotNull(values, getConfigIndex(_precision || config.expectedPrecision));
			var units = getUnitSymbols(minimumUnit, precision);

			var result = '';
			for(var i = minimumUnit; i <= precision; i++){
				result += formatValue(values[i], i, minimumUnit) + units[i];
			}

			var prefix = !!result ? getPrefix(_sign, d) : '';
			return prefix + result;
		};
	}])
	.filter('luifHumanize', function () {
		return function (_duration, suffix) {
			suffix = !!suffix;
			var d = moment.duration(_duration);
			return d.humanize(suffix);
		};
	});
})();<|endoftext|>


<commit_before>const { resolve } = require('path');
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');

const ext = ['.js', '.ts', '.jsx', '.tsx', '.scss', '.sass', '.css', '.sheet'];

module.exports = {
  server: {
    extensions: ext,
    modules: ['node_modules',resolve('src/server'), resolve('src/lib')],
    plugins: [ new TsConfigPathsPlugin() ],
    alias: {
      '~assets':'src/client/dungeon'
    }

  },
  client: {
    extensions: ext,
    modules: ['node_modules',resolve('src/client'), resolve('src/lib')],
    plugins: [ new TsConfigPathsPlugin() ],
    alias: {
      '~assets':'src/client/dungeon',
      'fs':'src/client/shims/fs.js',
      'path':'src/client/shims/path.js'
    }

  }
};

<commit_msg>finishing touches<commit_after>const { resolve } = require('path');
const { TsConfigPathsPlugin } = require('awesome-typescript-loader');

const ext = ['.js', '.ts', '.jsx', '.tsx', '.scss', '.sass', '.css', '.sheet'];

module.exports = {
  server: {
    extensions: ext,
    modules: ['node_modules',resolve('src/server'), resolve('src/lib')],
    plugins: [ new TsConfigPathsPlugin() ],
    alias: {
      '~assets':'src/client/dungeon'
    }

  },
  client: {
    extensions: ext,
    modules: ['node_modules',resolve('src/client'), resolve('src/lib')],
    plugins: [ new TsConfigPathsPlugin() ],
    alias: {
      '~assets':'src/client/dungeon',
      'fs':'src/client/shims/fs.js',
      'path':'src/client/shims/path.js'
    }
  }
};

<|endoftext|>


<commit_before>import React, { Component } from 'react';
// Gets weather from state.
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from '../actions';
import { saveState } from '../manageLocalStorage';
import moment from 'moment';
import Hammer from 'hammerjs';

import Chart from '../components/chart';
import GoogleMap from '../components/google-map';

class WeatherList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      itemsWithSwipe: []
    };
  }
  componentDidMount() {
    this.props.actions.fetchWeatherFromLocalStorage();
  }

  componentDidUpdate() {
    // Todo - add items to state, when component updates, skip
    // items that already have swipe.
    this.props.weather.map(city => {
      const swipeMap = document.getElementById(city.id);
      const mc = new Hammer.Manager(swipeMap);
      const Swipe = new Hammer.Swipe();
      mc.add(Swipe);
      mc.on('swipeleft', e => {
        // Todo - add confirmation and/or animation and then
        // actually delete the city, not just the element. Or
        // can I delete the city and not bother with deleting
        // the element?
        const elementToRemove = e.target.closest('.row-swipe');
        elementToRemove.parentNode.removeChild(elementToRemove);
      });
    });
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.weather[0]) {
      saveState(nextProps.weather);
    }

    const now = new Date().getTime();

    nextProps.weather.map(city => {
      const { timeFetched } = city;
      // Convert milliseconds to minutes.
      const timeDifference = (now - timeFetched) / 1000 / 60;

      // Request weather update if fetched over 30 minutes ago.
      if (timeDifference > 30 || timeFetched === undefined) {
        this.props.actions.fetchWeatherUpdate(city.id);
      }
    });
  }

  renderWeather(cityData) {
    const id = cityData.id;
    const name = cityData.name;
    const description = cityData.weather[0].description;
    const tempInC = Math.round(cityData.main.temp);
    const tempInF = Math.round((tempInC * 9) / 5 + 32);
    const humidity = cityData.main.humidity;
    const { lon, lat } = cityData.coord;
    const timeLastUpdated = moment.unix(cityData.dt).fromNow();
    const timeLastFetched = moment(cityData.timeFetched).fromNow();
    const rowClassName = `row row--with-border row-swipe`;

    return (

          <GoogleMap lat={lat} lon={lon} />
          {name}

          fetched {timeLastFetched}

            ({description})

            <Chart data={tempInC} units="C" />
            <Chart data={tempInF} units="F" />

            <Chart data={humidity} units="%" label="Humidity" />

            updated {timeLastUpdated}

    );
  }

  render() {
    if (this.props.weather.length === 0) {
      return (

          No cities here - search for one!

      );
    }

    return (

        {this.props.weather.map(function(city) {
          return this.renderWeather(city, this);
        }, this)}

    );
  }
}

// Gets weather from state.
function mapStateToProps({ weather }) {
  return { weather }; // same as { weather: weather}
}

function mapDispatchToProps(dispatch) {
  // Assign all actions (import * as actionCreators) to props.actions
  return {
    actions: bindActionCreators(actionCreators, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(WeatherList);
<commit_msg>set list of swipe-able cities in state<commit_after>import React, { Component } from 'react';
// Gets weather from state.
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from '../actions';
import { saveState } from '../manageLocalStorage';
import moment from 'moment';
import Hammer from 'hammerjs';

import Chart from '../components/chart';
import GoogleMap from '../components/google-map';

class WeatherList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      itemsWithSwipe: []
    };
  }
  componentDidMount() {
    this.props.actions.fetchWeatherFromLocalStorage();
  }

  componentDidUpdate() {
    this.props.weather.map(city => {
      if (!this.state.itemsWithSwipe.includes(city.id)) {
        this.setState(prevState => ({
          itemsWithSwipe: [...prevState.itemsWithSwipe, city.id]
        }));
      }
      const swipeMap = document.getElementById(city.id);
      const mc = new Hammer.Manager(swipeMap);
      const Swipe = new Hammer.Swipe();
      mc.add(Swipe);
      mc.on('swipeleft', e => {
        // Todo - add confirmation and/or animation and then
        // actually delete the city, not just the element. Or
        // can I delete the city and not bother with deleting
        // the element?
        const elementToRemove = e.target.closest('.row-swipe');
        elementToRemove.parentNode.removeChild(elementToRemove);
      });
    });
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.weather[0]) {
      saveState(nextProps.weather);
    }

    const now = new Date().getTime();

    nextProps.weather.map(city => {
      const { timeFetched } = city;
      // Convert milliseconds to minutes.
      const timeDifference = (now - timeFetched) / 1000 / 60;

      // Request weather update if fetched over 30 minutes ago.
      if (timeDifference > 30 || timeFetched === undefined) {
        this.props.actions.fetchWeatherUpdate(city.id);
      }
    });
  }

  renderWeather(cityData) {
    const id = cityData.id;
    const name = cityData.name;
    const description = cityData.weather[0].description;
    const tempInC = Math.round(cityData.main.temp);
    const tempInF = Math.round((tempInC * 9) / 5 + 32);
    const humidity = cityData.main.humidity;
    const { lon, lat } = cityData.coord;
    const timeLastUpdated = moment.unix(cityData.dt).fromNow();
    const timeLastFetched = moment(cityData.timeFetched).fromNow();
    const rowClassName = `row row--with-border row-swipe`;

    return (

          <GoogleMap lat={lat} lon={lon} />
          {name}

          fetched {timeLastFetched}

            ({description})

            <Chart data={tempInC} units="C" />
            <Chart data={tempInF} units="F" />

            <Chart data={humidity} units="%" label="Humidity" />

            updated {timeLastUpdated}

    );
  }

  render() {
    if (this.props.weather.length === 0) {
      return (

          No cities here - search for one!

      );
    }

    return (

        {this.props.weather.map(function(city) {
          return this.renderWeather(city, this);
        }, this)}

    );
  }
}

// Gets weather from state.
function mapStateToProps({ weather }) {
  return { weather }; // same as { weather: weather}
}

function mapDispatchToProps(dispatch) {
  // Assign all actions (import * as actionCreators) to props.actions
  return {
    actions: bindActionCreators(actionCreators, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(WeatherList);
<|endoftext|>


<commit_before>'use strict';

import $ from 'jquery';
import { GetYoDigits } from './foundation.util.core';
import { Plugin } from './foundation.plugin';
import { SmoothScroll } from './foundation.smoothScroll';

/**
 * Magellan module.
 * @module foundation.magellan
 * @requires foundation.smoothScroll
 */

class Magellan extends Plugin {
  /**
   * Creates a new instance of Magellan.
   * @class
   * @name Magellan
   * @fires Magellan#init
   * @param {Object} element - jQuery object to add the trigger to.
   * @param {Object} options - Overrides to the default plugin settings.
   */
  _setup(element, options) {
    this.$element = element;
    this.options  = $.extend({}, Magellan.defaults, this.$element.data(), options);
    this.className = 'Magellan'; // ie9 back compat

    this._init();
    this.calcPoints();
  }

  /**
   * Initializes the Magellan plugin and calls functions to get equalizer functioning on load.
   * @private
   */
  _init() {
    var id = this.$element[0].id || GetYoDigits(6, 'magellan');
    var _this = this;
    this.$targets = $('[data-magellan-target]');
    this.$links = this.$element.find('a');
    this.$element.attr({
      'data-resize': id,
      'data-scroll': id,
      'id': id
    });
    this.$active = $();
    this.scrollPos = parseInt(window.pageYOffset, 10);

    this._events();
  }

  /**
   * Calculates an array of pixel values that are the demarcation lines between locations on the page.
   * Can be invoked if new elements are added or the size of a location changes.
   * @function
   */
  calcPoints() {
    var _this = this,
        body = document.body,
        html = document.documentElement;

    this.points = [];
    this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight));
    this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight));

    this.$targets.each(function(){
      var $tar = $(this),
          pt = Math.round($tar.offset().top - _this.options.threshold);
      $tar.targetPoint = pt;
      _this.points.push(pt);
    });
  }

  /**
   * Initializes events for Magellan.
   * @private
   */
  _events() {
    var _this = this,
        $body = $('html, body'),
        opts = {
          duration: _this.options.animationDuration,
          easing:   _this.options.animationEasing
        };
    $(window).one('load', function(){
      if(_this.options.deepLinking){
        if(location.hash){
          _this.scrollToLoc(location.hash);
        }
      }
      _this.calcPoints();
      _this._updateActive();
    });

    this.$element.on({
      'resizeme.zf.trigger': this.reflow.bind(this),
      'scrollme.zf.trigger': this._updateActive.bind(this)
    }).on('click.zf.magellan', 'a[href^="#"]', function(e) {
        e.preventDefault();
        var arrival   = this.getAttribute('href');
        _this.scrollToLoc(arrival);
      });

    this._deepLinkScroll = function(e) {
      if(_this.options.deepLinking) {
        _this.scrollToLoc(window.location.hash);
      }
    };

    $(window).on('popstate', this._deepLinkScroll);
  }

  /**
   * Function to scroll to a given location on the page.
   * @param {String} loc - a properly formatted jQuery id selector. Example: '#foo'
   * @function
   */
  scrollToLoc(loc) {
    this._inTransition = true;
    var _this = this;

    var options = {
      animationEasing: this.options.animationEasing,
      animationDuration: this.options.animationDuration,
      threshold: this.options.threshold,
      offset: this.options.offset
    };

    SmoothScroll.scrollToLoc(loc, options, function() {
      _this._inTransition = false;
      _this._updateActive();
    })
  }

  /**
   * Calls necessary functions to update Magellan upon DOM change
   * @function
   */
  reflow() {
    this.calcPoints();
    this._updateActive();
  }

  /**
   * Updates the visibility of an active location link, and updates the url hash for the page, if deepLinking enabled.
   * @private
   * @function
   * @fires Magellan#update
   */
  _updateActive(/*evt, elem, scrollPos*/) {
    if(this._inTransition) {return;}
    var winPos = /*scrollPos ||*/ parseInt(window.pageYOffset, 10),
        curIdx;

    if(winPos + this.winHeight === this.docHeight){ curIdx = this.points.length - 1; }
    else if(winPos < this.points[0]){ curIdx = undefined; }
    else{
      var isDown = this.scrollPos < winPos,
          _this = this,
          curVisible = this.points.filter(function(p, i){
            return isDown ? p - _this.options.offset <= winPos : p - _this.options.offset - _this.options.threshold <= winPos;
          });
      curIdx = curVisible.length ? curVisible.length - 1 : 0;
    }

    this.$active.removeClass(this.options.activeClass);
    this.$active = this.$links.filter('[href="#' + this.$targets.eq(curIdx).data('magellan-target') + '"]').addClass(this.options.activeClass);

    if(this.options.deepLinking){
      var hash = "";
      if(curIdx != undefined){
        hash = this.$active[0].getAttribute('href');
      }
      if(hash !== window.location.hash) {
        if (window.history.pushState) {
          if (this.options.updateHistory) {
            window.history.pushState({}, '', hash);
          } else {
            window.history.replaceState({}, '', hash);
          }
        } else {
          window.location.hash = hash;
        }
      }
    }

    this.scrollPos = winPos;
    /**
     * Fires when magellan is finished updating to the new active element.
     * @event Magellan#update
     */
    this.$element.trigger('update.zf.magellan', [this.$active]);
  }

  /**
   * Destroys an instance of Magellan and resets the url of the window.
   * @function
   */
  _destroy() {
    this.$element.off('.zf.trigger .zf.magellan')
        .find(`.${this.options.activeClass}`).removeClass(this.options.activeClass);

    if(this.options.deepLinking){
      var hash = this.$active[0].getAttribute('href');
      window.location.hash.replace(hash, '');
    }
    $(window).off('popstate', this._deepLinkScroll);
  }
}

/**
 * Default settings for plugin
 */
Magellan.defaults = {
  /**
   * Amount of time, in ms, the animated scrolling should take between locations.
   * @option
   * @type {number}
   * @default 500
   */
  animationDuration: 500,
  /**
   * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
   * @option
   * @type {string}
   * @default 'linear'
   * @see {@link https://api.jquery.com/animate|Jquery animate}
   */
  animationEasing: 'linear',
  /**
   * Number of pixels to use as a marker for location changes.
   * @option
   * @type {number}
   * @default 50
   */
  threshold: 50,
  /**
   * Class applied to the active locations link on the magellan container.
   * @option
   * @type {string}
   * @default 'is-active'
   */
  activeClass: 'is-active',
  /**
   * Allows the script to manipulate the url of the current page, and if supported, alter the history.
   * @option
   * @type {boolean}
   * @default false
   */
  deepLinking: false,
  /**
   * Update the browser history with the active link, if deep linking is enabled.
   * @option
   * @type {boolean}
   * @default true
   */
  updateHistory: true,
  /**
   * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
   * @option
   * @type {number}
   * @default 0
   */
  offset: 0
}

export {Magellan};
<commit_msg>feat: disable updateHistory by default for Magellan<commit_after>'use strict';

import $ from 'jquery';
import { GetYoDigits } from './foundation.util.core';
import { Plugin } from './foundation.plugin';
import { SmoothScroll } from './foundation.smoothScroll';

/**
 * Magellan module.
 * @module foundation.magellan
 * @requires foundation.smoothScroll
 */

class Magellan extends Plugin {
  /**
   * Creates a new instance of Magellan.
   * @class
   * @name Magellan
   * @fires Magellan#init
   * @param {Object} element - jQuery object to add the trigger to.
   * @param {Object} options - Overrides to the default plugin settings.
   */
  _setup(element, options) {
    this.$element = element;
    this.options  = $.extend({}, Magellan.defaults, this.$element.data(), options);
    this.className = 'Magellan'; // ie9 back compat

    this._init();
    this.calcPoints();
  }

  /**
   * Initializes the Magellan plugin and calls functions to get equalizer functioning on load.
   * @private
   */
  _init() {
    var id = this.$element[0].id || GetYoDigits(6, 'magellan');
    var _this = this;
    this.$targets = $('[data-magellan-target]');
    this.$links = this.$element.find('a');
    this.$element.attr({
      'data-resize': id,
      'data-scroll': id,
      'id': id
    });
    this.$active = $();
    this.scrollPos = parseInt(window.pageYOffset, 10);

    this._events();
  }

  /**
   * Calculates an array of pixel values that are the demarcation lines between locations on the page.
   * Can be invoked if new elements are added or the size of a location changes.
   * @function
   */
  calcPoints() {
    var _this = this,
        body = document.body,
        html = document.documentElement;

    this.points = [];
    this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight));
    this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight));

    this.$targets.each(function(){
      var $tar = $(this),
          pt = Math.round($tar.offset().top - _this.options.threshold);
      $tar.targetPoint = pt;
      _this.points.push(pt);
    });
  }

  /**
   * Initializes events for Magellan.
   * @private
   */
  _events() {
    var _this = this,
        $body = $('html, body'),
        opts = {
          duration: _this.options.animationDuration,
          easing:   _this.options.animationEasing
        };
    $(window).one('load', function(){
      if(_this.options.deepLinking){
        if(location.hash){
          _this.scrollToLoc(location.hash);
        }
      }
      _this.calcPoints();
      _this._updateActive();
    });

    this.$element.on({
      'resizeme.zf.trigger': this.reflow.bind(this),
      'scrollme.zf.trigger': this._updateActive.bind(this)
    }).on('click.zf.magellan', 'a[href^="#"]', function(e) {
        e.preventDefault();
        var arrival   = this.getAttribute('href');
        _this.scrollToLoc(arrival);
      });

    this._deepLinkScroll = function(e) {
      if(_this.options.deepLinking) {
        _this.scrollToLoc(window.location.hash);
      }
    };

    $(window).on('popstate', this._deepLinkScroll);
  }

  /**
   * Function to scroll to a given location on the page.
   * @param {String} loc - a properly formatted jQuery id selector. Example: '#foo'
   * @function
   */
  scrollToLoc(loc) {
    this._inTransition = true;
    var _this = this;

    var options = {
      animationEasing: this.options.animationEasing,
      animationDuration: this.options.animationDuration,
      threshold: this.options.threshold,
      offset: this.options.offset
    };

    SmoothScroll.scrollToLoc(loc, options, function() {
      _this._inTransition = false;
      _this._updateActive();
    })
  }

  /**
   * Calls necessary functions to update Magellan upon DOM change
   * @function
   */
  reflow() {
    this.calcPoints();
    this._updateActive();
  }

  /**
   * Updates the visibility of an active location link, and updates the url hash for the page, if deepLinking enabled.
   * @private
   * @function
   * @fires Magellan#update
   */
  _updateActive(/*evt, elem, scrollPos*/) {
    if(this._inTransition) {return;}
    var winPos = /*scrollPos ||*/ parseInt(window.pageYOffset, 10),
        curIdx;

    if(winPos + this.winHeight === this.docHeight){ curIdx = this.points.length - 1; }
    else if(winPos < this.points[0]){ curIdx = undefined; }
    else{
      var isDown = this.scrollPos < winPos,
          _this = this,
          curVisible = this.points.filter(function(p, i){
            return isDown ? p - _this.options.offset <= winPos : p - _this.options.offset - _this.options.threshold <= winPos;
          });
      curIdx = curVisible.length ? curVisible.length - 1 : 0;
    }

    this.$active.removeClass(this.options.activeClass);
    this.$active = this.$links.filter('[href="#' + this.$targets.eq(curIdx).data('magellan-target') + '"]').addClass(this.options.activeClass);

    if(this.options.deepLinking){
      var hash = "";
      if(curIdx != undefined){
        hash = this.$active[0].getAttribute('href');
      }
      if(hash !== window.location.hash) {
        if (window.history.pushState) {
          if (this.options.updateHistory) {
            window.history.pushState({}, '', hash);
          } else {
            window.history.replaceState({}, '', hash);
          }
        } else {
          window.location.hash = hash;
        }
      }
    }

    this.scrollPos = winPos;
    /**
     * Fires when magellan is finished updating to the new active element.
     * @event Magellan#update
     */
    this.$element.trigger('update.zf.magellan', [this.$active]);
  }

  /**
   * Destroys an instance of Magellan and resets the url of the window.
   * @function
   */
  _destroy() {
    this.$element.off('.zf.trigger .zf.magellan')
        .find(`.${this.options.activeClass}`).removeClass(this.options.activeClass);

    if(this.options.deepLinking){
      var hash = this.$active[0].getAttribute('href');
      window.location.hash.replace(hash, '');
    }
    $(window).off('popstate', this._deepLinkScroll);
  }
}

/**
 * Default settings for plugin
 */
Magellan.defaults = {
  /**
   * Amount of time, in ms, the animated scrolling should take between locations.
   * @option
   * @type {number}
   * @default 500
   */
  animationDuration: 500,
  /**
   * Animation style to use when scrolling between locations. Can be `'swing'` or `'linear'`.
   * @option
   * @type {string}
   * @default 'linear'
   * @see {@link https://api.jquery.com/animate|Jquery animate}
   */
  animationEasing: 'linear',
  /**
   * Number of pixels to use as a marker for location changes.
   * @option
   * @type {number}
   * @default 50
   */
  threshold: 50,
  /**
   * Class applied to the active locations link on the magellan container.
   * @option
   * @type {string}
   * @default 'is-active'
   */
  activeClass: 'is-active',
  /**
   * Allows the script to manipulate the url of the current page, and if supported, alter the history.
   * @option
   * @type {boolean}
   * @default false
   */
  deepLinking: false,
  /**
   * Update the browser history with the active link, if deep linking is enabled.
   * @option
   * @type {boolean}
   * @default false
   */
  updateHistory: false,
  /**
   * Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
   * @option
   * @type {number}
   * @default 0
   */
  offset: 0
}

export {Magellan};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
// Gets weather from state.
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from '../actions';
import { saveState } from '../manageLocalStorage';
import moment from 'moment';
import Hammer from 'hammerjs';
import Modal from 'react-modal';

import Chart from '../components/chart';
import GoogleMap from '../components/google-map';

class WeatherList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      itemsWithSwipe: [],
      modalIsOpen: false,
      rowToDelete: ''
    };

    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
    this.deleteCity = this.deleteCity.bind(this);
  }

  openModal(city) {
    this.currentCity = city;
    this.setState({ modalIsOpen: true });
  }

  closeModal() {
    this.setState({ modalIsOpen: false });
  }

  deleteCity() {
    this.setState({ modalIsOpen: false });
    this.rowToDelete.classList.add('animated');
    this.rowToDelete.classList.add('faster');
    this.rowToDelete.classList.add('zoomOut');
    setTimeout(() => {
      this.props.actions.deleteCity(this.currentCity.id);
    }, 500);
  }

  componentDidMount() {
    this.props.actions.fetchWeatherFromLocalStorage();
    this.currentCity = {};
    this.rowToDelete;
  }

  componentDidUpdate() {
    this.props.weather.map(city => {
      if (!this.state.itemsWithSwipe.includes(city.id)) {
        this.setState(prevState => ({
          itemsWithSwipe: [...prevState.itemsWithSwipe, city.id]
        }));
      }
      const swipeMap = document.getElementById(city.id);
      const mc = new Hammer.Manager(swipeMap);
      const Swipe = new Hammer.Swipe();
      mc.add(Swipe);
      mc.on('swipeleft', e => {
        // If delete is confirmed, use css to animate-out this div.
        this.rowToDelete = e.target.closest('.row-swipe');
        // Open a confirmation asking to delete the city or cancel.
        this.openModal(city);
      });
    });
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.weather[0]) {
      saveState(nextProps.weather);
    }

    const now = new Date().getTime();

    nextProps.weather.map(city => {
      const { timeFetched } = city;
      // Convert milliseconds to minutes.
      const timeDifference = (now - timeFetched) / 1000 / 60;

      // Request weather update if fetched over 30 minutes ago.
      if (timeDifference > 30 || timeFetched === undefined) {
        this.props.actions.fetchWeatherUpdate(city.id);
      }
    });
  }

  renderWeather(cityData) {
    const id = cityData.id;
    const name = cityData.name;
    const description = cityData.weather[0].description;
    const tempInC = Math.round(cityData.main.temp);
    const tempInF = Math.round((tempInC * 9) / 5 + 32);
    const humidity = cityData.main.humidity;
    const { lon, lat } = cityData.coord;
    const timeLastUpdated = moment.unix(cityData.dt).fromNow();
    const timeLastFetched = moment(cityData.timeFetched).fromNow();
    const rowClassName = `row row--with-border row-swipe`;

    return (

          <GoogleMap lat={lat} lon={lon} />
          {name}

          fetched {timeLastFetched}

          ({description})
          <Chart data={tempInC} units="C" />
          <Chart data={tempInF} units="F" />

          <Chart data={humidity} units="%" label="Humidity" />

          updated {timeLastUpdated}

    );
  }

  render() {
    if (this.props.weather.length === 0) {
      return (

          No cities here - search for one!

      );
    }

    return (

        <Modal
          isOpen={this.state.modalIsOpen}
          onAfterOpen={this.afterOpenModal}
          onRequestClose={this.closeModal}
          contentLabel="Example Modal"
          appElement={document.getElementById('app')}
          className="modal--delete"
        >

Delete {this.currentCity.name}?

          <button className="btn btn-danger" onClick={this.deleteCity}>
            Delete
          </button>
          <button className="btn btn-light" onClick={this.closeModal}>
            Cancel
          </button>
        </Modal>
        {this.props.weather.map(function(city) {
          return this.renderWeather(city, this);
        }, this)}

    );
  }
}

// Gets weather from state.
function mapStateToProps({ weather }) {
  return { weather }; // same as { weather: weather}
}

function mapDispatchToProps(dispatch) {
  // Assign all actions (import * as actionCreators) to props.actions
  return {
    actions: bindActionCreators(actionCreators, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(WeatherList);
<commit_msg>better name for swipeMap -> swipeRow<commit_after>import React, { Component } from 'react';
// Gets weather from state.
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionCreators from '../actions';
import { saveState } from '../manageLocalStorage';
import moment from 'moment';
import Hammer from 'hammerjs';
import Modal from 'react-modal';

import Chart from '../components/chart';
import GoogleMap from '../components/google-map';

class WeatherList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      itemsWithSwipe: [],
      modalIsOpen: false,
      rowToDelete: ''
    };

    this.openModal = this.openModal.bind(this);
    this.closeModal = this.closeModal.bind(this);
    this.deleteCity = this.deleteCity.bind(this);
  }

  openModal(city) {
    this.currentCity = city;
    this.setState({ modalIsOpen: true });
  }

  closeModal() {
    this.setState({ modalIsOpen: false });
  }

  deleteCity() {
    this.setState({ modalIsOpen: false });
    this.rowToDelete.classList.add('animated');
    this.rowToDelete.classList.add('faster');
    this.rowToDelete.classList.add('zoomOut');
    setTimeout(() => {
      this.props.actions.deleteCity(this.currentCity.id);
    }, 500);
  }

  componentDidMount() {
    this.props.actions.fetchWeatherFromLocalStorage();
    this.currentCity = {};
    this.rowToDelete;
  }

  componentDidUpdate() {
    this.props.weather.map(city => {
      if (!this.state.itemsWithSwipe.includes(city.id)) {
        this.setState(prevState => ({
          itemsWithSwipe: [...prevState.itemsWithSwipe, city.id]
        }));
      }
      const swipeRow = document.getElementById(city.id);
      const mc = new Hammer.Manager(swipeRow);
      const Swipe = new Hammer.Swipe();
      mc.add(Swipe);
      mc.on('swipeleft', e => {
        // If delete is confirmed, use css to animate-out this div.
        this.rowToDelete = e.target.closest('.row-swipe');
        // Open a confirmation asking to delete the city or cancel.
        this.openModal(city);
      });
    });
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.weather[0]) {
      saveState(nextProps.weather);
    }

    const now = new Date().getTime();

    nextProps.weather.map(city => {
      const { timeFetched } = city;
      // Convert milliseconds to minutes.
      const timeDifference = (now - timeFetched) / 1000 / 60;

      // Request weather update if fetched over 30 minutes ago.
      if (timeDifference > 30 || timeFetched === undefined) {
        this.props.actions.fetchWeatherUpdate(city.id);
      }
    });
  }

  renderWeather(cityData) {
    const id = cityData.id;
    const name = cityData.name;
    const description = cityData.weather[0].description;
    const tempInC = Math.round(cityData.main.temp);
    const tempInF = Math.round((tempInC * 9) / 5 + 32);
    const humidity = cityData.main.humidity;
    const { lon, lat } = cityData.coord;
    const timeLastUpdated = moment.unix(cityData.dt).fromNow();
    const timeLastFetched = moment(cityData.timeFetched).fromNow();
    const rowClassName = `row row--with-border row-swipe`;

    return (

          <GoogleMap lat={lat} lon={lon} />
          {name}

          fetched {timeLastFetched}

          ({description})
          <Chart data={tempInC} units="C" />
          <Chart data={tempInF} units="F" />

          <Chart data={humidity} units="%" label="Humidity" />

          updated {timeLastUpdated}

    );
  }

  render() {
    if (this.props.weather.length === 0) {
      return (

          No cities here - search for one!

      );
    }

    return (

        <Modal
          isOpen={this.state.modalIsOpen}
          onAfterOpen={this.afterOpenModal}
          onRequestClose={this.closeModal}
          contentLabel="Example Modal"
          appElement={document.getElementById('app')}
          className="modal--delete"
        >

Delete {this.currentCity.name}?

          <button className="btn btn-danger" onClick={this.deleteCity}>
            Delete
          </button>
          <button className="btn btn-light" onClick={this.closeModal}>
            Cancel
          </button>
        </Modal>
        {this.props.weather.map(function(city) {
          return this.renderWeather(city, this);
        }, this)}

    );
  }
}

// Gets weather from state.
function mapStateToProps({ weather }) {
  return { weather }; // same as { weather: weather}
}

function mapDispatchToProps(dispatch) {
  // Assign all actions (import * as actionCreators) to props.actions
  return {
    actions: bindActionCreators(actionCreators, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(WeatherList);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import Button from 'components/Button/Button';
import { asyncConnect } from 'redux-async-connect';
import { loadSuccess } from 'redux-async-connect';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import StarRating from 'react-star-rating';
import Feedback from 'components/Feedback/Feedback';
import ColumnLayout from 'components/ColumnLayout/ColumnLayout';
import styles from './styles.scss';

@asyncConnect([
  {key: 'cooks', promise: ({helpers}) => {helpers.client.get('/cooks', {params: {page: 1, per_page: 12}});}}
])
@connect(null, { loadSuccess })
export default class Cooks extends Component {
  static propTypes = {
    cooks: PropTypes.object.isRequired,
    loadSuccess: PropTypes.func.isRequired
  }

  static contextTypes = {
    client: PropTypes.object.isRequired
  }

  state = {
    page: 1
  }

  loadMoreHandle = () => {
    const { cooks } = this.props;
    const { page } = this.state;
    const params = {
      'per_page': 12,
      'page': page
    };
    this.setState({
      isInfiniteLoading: true
    });
    this.context.client.get('/cooks', {params})
      .then(cooksFromServer => {
        const newCooks = {...cooks, resources: [...cooks.resources, ...cooksFromServer.resources]};
        this.props.loadSuccess('cooks', newCooks);
        this.setState({
          page: page,
          isInfiniteLoading: false
        });
      });
  };

  render() {
    const { cooks } = this.props;
    const { isInfiniteLoading } = this.state;
    return (
      <ColumnLayout className={styles.root}>

Наши кулинары и рестораны

          {cooks.resources.map((cook, idx) => {
            return (

                  <Link className={styles.cookLink} to={`/lunches?cook_id="${cook.id}"`}>

{cook.full_name_genitive}

                        <StarRating name="cook-rating" totalStars={5}
                                    editing={false} rating={cook.rating} size={12}/>

                      <Feedback reviewsCount={cook.reviews_count} className={styles.feedback}/>

                  </Link>

            );
          })}

        {cooks.resources.length < cooks.meta.total &&

            <Button flat accent onClick={::this.loadMoreHandle} disabled={isInfiniteLoading}
                    label={isInfiniteLoading ? 'Загрузка...' : 'Посмотреть еще'}/>

        }
      </ColumnLayout>
    );
  }
}
<commit_msg>cooks index fix<commit_after>import React, { Component, PropTypes } from 'react';
import Button from 'components/Button/Button';
import { asyncConnect } from 'redux-async-connect';
import { loadSuccess } from 'redux-async-connect';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import StarRating from 'react-star-rating';
import Feedback from 'components/Feedback/Feedback';
import ColumnLayout from 'components/ColumnLayout/ColumnLayout';
import styles from './styles.scss';

@asyncConnect([
  {key: 'cooks', promise: ({helpers}) => helpers.client.get('/cooks', {params: {page: 1, per_page: 12}})}
])
@connect(null, { loadSuccess })
export default class Cooks extends Component {
  static propTypes = {
    cooks: PropTypes.object.isRequired,
    loadSuccess: PropTypes.func.isRequired
  }

  static contextTypes = {
    client: PropTypes.object.isRequired
  }

  state = {
    page: 1
  }

  loadMoreHandle = () => {
    const { cooks } = this.props;
    const { page } = this.state;
    const params = {
      'per_page': 12,
      'page': page
    };
    this.setState({
      isInfiniteLoading: true
    });
    this.context.client.get('/cooks', {params})
      .then(cooksFromServer => {
        const newCooks = {...cooks, resources: [...cooks.resources, ...cooksFromServer.resources]};
        this.props.loadSuccess('cooks', newCooks);
        this.setState({
          page: page,
          isInfiniteLoading: false
        });
      });
  };

  render() {
    const { cooks } = this.props;
    const { isInfiniteLoading } = this.state;
    return (
      <ColumnLayout className={styles.root}>

Наши кулинары и рестораны

          {cooks.resources.map((cook, idx) => {
            return (

                  <Link className={styles.cookLink} to={`/lunches?cook_id="${cook.id}"`}>

{cook.full_name_genitive}

                        <StarRating name="cook-rating" totalStars={5}
                                    editing={false} rating={cook.rating} size={12}/>

                      <Feedback reviewsCount={cook.reviews_count} className={styles.feedback}/>

                  </Link>

            );
          })}

        {cooks.resources.length < cooks.meta.total &&

            <Button flat accent onClick={::this.loadMoreHandle} disabled={isInfiniteLoading}
                    label={isInfiniteLoading ? 'Загрузка...' : 'Посмотреть еще'}/>

        }
      </ColumnLayout>
    );
  }
}
<|endoftext|>


<commit_before>;(function($){
/**
 * jqGrid Spanish Translation
 * Traduccion jqGrid en Español por Yamil Bracho
 * Traduccion corregida y ampliada por Faserline, S.L.
 * http://www.faserline.com
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
**/
$.jgrid = {
	defaults : {
		recordtext: "Amosando {0} - {1} de {2}",
	    emptyrecords: "Sen rexistros que amosar",
		loadtext: "Cargando...",
		pgtext : "Páxina {0} de {1}"
	},
	search : {
	    caption: "Búsqueda...",
	    Find: "Buscar",
	    Reset: "Limpar",
	    odata : ['igual ', 'diferente a', 'menor que', 'menor ou igual que','maior que','maior ou igual a', 'empece por','non empece por','está en','non está en','termina por','non termina por','contén','non contén'],
	    groupOps: [	{ op: "AND", text: "todo" },	{ op: "OR",  text: "calquera" }	],
		matchText: " match",
		rulesText: " regras"
	},
	edit : {
	    addCaption: "Engadir rexistro",
	    editCaption: "Modificar rexistro",
	    bSubmit: "Gardar",
	    bCancel: "Cancelar",
		bClose: "Pechar",
		saveData: "Modificáronse os datos, quere gardar os cambios?",
		bYes : "Si",
		bNo : "Non",
		bExit : "Cancelar",
	    msg: {
	        required:"Campo obrigatorio",
	        number:"Introduza un número",
	        minValue:"O valor debe ser maior ou igual a ",
	        maxValue:"O valor debe ser menor ou igual a ",
	        email: "non é un enderezo de correo válido",
	        integer: "Introduza un valor enteiro",
			date: "Introduza unha data correcta ",
			url: "non é unha URL válida. Prefixo requerido ('http://' ou 'https://')",
			nodefined : " non está definido.",
			novalue : " o valor de retorno é obrigatorio.",
			customarray : "A función persoalizada debe devolver un array.",
			customfcheck : "A función persoalizada debe estar presente no caso de ter validación persoalizada."
		}
	},
	view : {
	    caption: "Consultar rexistro",
	    bClose: "Pechar"
	},
	del : {
	    caption: "Eliminar",
	    msg: "Desexa eliminar os rexistros seleccionados?",
	    bSubmit: "Eliminar",
	    bCancel: "Cancelar"
	},
	nav : {
		edittext: " ",
	    edittitle: "Modificar a fila seleccionada",
		addtext:" ",
	    addtitle: "Engadir unha nova fila",
	    deltext: " ",
	    deltitle: "Eliminar a fila seleccionada",
	    searchtext: " ",
	    searchtitle: "Buscar información",
	    refreshtext: "",
	    refreshtitle: "Recargar datos",
	    alertcap: "Aviso",
	    alerttext: "Seleccione unha fila",
		viewtext: "",
		viewtitle: "Ver fila seleccionada"
	},
	col : {
	    caption: "Mostrar/ocultar columnas",
	    bSubmit: "Enviar",
	    bCancel: "Cancelar"
	},
	errors : {
		errcap : "Erro",
		nourl : "Non especificou unha URL",
		norecords: "Non hai datos para procesar",
	    model : "As columnas de nomes son diferentes das columnas de modelo"
	},
	formatter : {
		integer : {thousandsSeparator: ".", defaultValue: '0'},
		number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'},
		currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'},
		date : {
			dayNames:   [
				"Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa",
				"Domingo", "Luns", "Martes", "Mércoles", "Xoves", "Vernes", "Sábado"
			],
			monthNames: [
				"Xan", "Feb", "Mar", "Abr", "Mai", "Xuñ", "Xul", "Ago", "Set", "Out", "Nov", "Dec",
				"Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"
			],
			AmPm : ["am","pm","AM","PM"],
			S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'},
			srcformat: 'Y-m-d',
			newformat: 'd-m-Y',
			masks : {
	            ISO8601Long:"Y-m-d H:i:s",
	            ISO8601Short:"Y-m-d",
	            ShortDate: "n/j/Y",
	            LongDate: "l, F d, Y",
	            FullDateTime: "l, F d, Y g:i:s A",
	            MonthDay: "F d",
	            ShortTime: "g:i A",
	            LongTime: "g:i:s A",
	            SortableDateTime: "Y-m-d\\TH:i:s",
	            UniversalSortableDateTime: "Y-m-d H:i:sO",
	            YearMonth: "F, Y"
	        },
	        reformatAfterEdit : false
		},
		baseLinkUrl: '',
		showAction: '',
	    target: '',
	    checkbox : {disabled:true},
		idName : 'id'
	}
};
})(jQuery);
<commit_msg>Modified header.<commit_after>;(function($){
/**
 * jqGrid Galician Translation
 * Translated by Jorge Barreiro <yortx.barry@gmail.com>
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
**/
$.jgrid = {
	defaults : {
		recordtext: "Amosando {0} - {1} de {2}",
	    emptyrecords: "Sen rexistros que amosar",
		loadtext: "Cargando...",
		pgtext : "Páxina {0} de {1}"
	},
	search : {
	    caption: "Búsqueda...",
	    Find: "Buscar",
	    Reset: "Limpar",
	    odata : ['igual ', 'diferente a', 'menor que', 'menor ou igual que','maior que','maior ou igual a', 'empece por','non empece por','está en','non está en','termina por','non termina por','contén','non contén'],
	    groupOps: [	{ op: "AND", text: "todo" },	{ op: "OR",  text: "calquera" }	],
		matchText: " match",
		rulesText: " regras"
	},
	edit : {
	    addCaption: "Engadir rexistro",
	    editCaption: "Modificar rexistro",
	    bSubmit: "Gardar",
	    bCancel: "Cancelar",
		bClose: "Pechar",
		saveData: "Modificáronse os datos, quere gardar os cambios?",
		bYes : "Si",
		bNo : "Non",
		bExit : "Cancelar",
	    msg: {
	        required:"Campo obrigatorio",
	        number:"Introduza un número",
	        minValue:"O valor debe ser maior ou igual a ",
	        maxValue:"O valor debe ser menor ou igual a ",
	        email: "non é un enderezo de correo válido",
	        integer: "Introduza un valor enteiro",
			date: "Introduza unha data correcta ",
			url: "non é unha URL válida. Prefixo requerido ('http://' ou 'https://')",
			nodefined : " non está definido.",
			novalue : " o valor de retorno é obrigatorio.",
			customarray : "A función persoalizada debe devolver un array.",
			customfcheck : "A función persoalizada debe estar presente no caso de ter validación persoalizada."
		}
	},
	view : {
	    caption: "Consultar rexistro",
	    bClose: "Pechar"
	},
	del : {
	    caption: "Eliminar",
	    msg: "Desexa eliminar os rexistros seleccionados?",
	    bSubmit: "Eliminar",
	    bCancel: "Cancelar"
	},
	nav : {
		edittext: " ",
	    edittitle: "Modificar a fila seleccionada",
		addtext:" ",
	    addtitle: "Engadir unha nova fila",
	    deltext: " ",
	    deltitle: "Eliminar a fila seleccionada",
	    searchtext: " ",
	    searchtitle: "Buscar información",
	    refreshtext: "",
	    refreshtitle: "Recargar datos",
	    alertcap: "Aviso",
	    alerttext: "Seleccione unha fila",
		viewtext: "",
		viewtitle: "Ver fila seleccionada"
	},
	col : {
	    caption: "Mostrar/ocultar columnas",
	    bSubmit: "Enviar",
	    bCancel: "Cancelar"
	},
	errors : {
		errcap : "Erro",
		nourl : "Non especificou unha URL",
		norecords: "Non hai datos para procesar",
	    model : "As columnas de nomes son diferentes das columnas de modelo"
	},
	formatter : {
		integer : {thousandsSeparator: ".", defaultValue: '0'},
		number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaultValue: '0,00'},
		currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0,00'},
		date : {
			dayNames:   [
				"Do", "Lu", "Ma", "Me", "Xo", "Ve", "Sa",
				"Domingo", "Luns", "Martes", "Mércoles", "Xoves", "Vernes", "Sábado"
			],
			monthNames: [
				"Xan", "Feb", "Mar", "Abr", "Mai", "Xuñ", "Xul", "Ago", "Set", "Out", "Nov", "Dec",
				"Xaneiro", "Febreiro", "Marzo", "Abril", "Maio", "Xuño", "Xullo", "Agosto", "Setembro", "Outubro", "Novembro", "Decembro"
			],
			AmPm : ["am","pm","AM","PM"],
			S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'},
			srcformat: 'Y-m-d',
			newformat: 'd-m-Y',
			masks : {
	            ISO8601Long:"Y-m-d H:i:s",
	            ISO8601Short:"Y-m-d",
	            ShortDate: "n/j/Y",
	            LongDate: "l, F d, Y",
	            FullDateTime: "l, F d, Y g:i:s A",
	            MonthDay: "F d",
	            ShortTime: "g:i A",
	            LongTime: "g:i:s A",
	            SortableDateTime: "Y-m-d\\TH:i:s",
	            UniversalSortableDateTime: "Y-m-d H:i:sO",
	            YearMonth: "F, Y"
	        },
	        reformatAfterEdit : false
		},
		baseLinkUrl: '',
		showAction: '',
	    target: '',
	    checkbox : {disabled:true},
		idName : 'id'
	}
};
})(jQuery);
<|endoftext|>


<commit_before>import React from 'react';
import Helmet from 'react-helmet';
import { withRouter } from 'react-router';
import { connect } from 'react-redux';
import { clearPetition, publishPetition } from 'actions/PetitionActions';
import { clearSuggestionInputValue } from 'actions/AutocompleteActions';
import settings from 'settings';
import NewPetition from 'components/NewPetition';
import PreviewPetition from 'components/PreviewPetition';
import getPetitionPath from 'selectors/petitionPath';
import getPetitionForm from 'selectors/petitionForm';
import petitionPublished from 'selectors/petitionPublished';

const NewPetitionContainer = withRouter(React.createClass({
  componentWillUpdate (nextProps) {
    if (petitionPublished(nextProps.petition)) {
      this.props.router.push(`${getPetitionPath(nextProps.petition)}/published`);
    }
  },

  componentWillUnmount () {
    this.props.clearPetition();
    this.props.clearSuggestionInputValue();
  },

  render () {
    const { petition, publishPetition } = this.props;

    return (

        <Helmet title={settings.newPetitionPage.title} />
        {petition.saved
          ? <PreviewPetition
            petition={petition}
            publishPetition={publishPetition}
            />
          : <NewPetition petition={petition} />
        }

    );
  }
}));

export const mapStateToProps = ({ petition }) => ({
  petition: getPetitionForm(petition)
});

const mapDispatchToProps = (dispatch) => ({
  clearPetition: () => dispatch(clearPetition()),
  clearSuggestionInputValue: () => dispatch(clearSuggestionInputValue()),
  publishPetition: (petition) => dispatch(publishPetition(petition))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(NewPetitionContainer);
<commit_msg>Fixed /new route not being accessible from the petition detail page<commit_after>import React from 'react';
import Helmet from 'react-helmet';
import { withRouter } from 'react-router';
import { connect } from 'react-redux';
import { clearPetition, publishPetition } from 'actions/PetitionActions';
import { clearSuggestionInputValue } from 'actions/AutocompleteActions';
import settings from 'settings';
import NewPetition from 'components/NewPetition';
import PreviewPetition from 'components/PreviewPetition';
import getPetitionPath from 'selectors/petitionPath';
import getPetitionForm from 'selectors/petitionForm';
import petitionPublished from 'selectors/petitionPublished';

const NewPetitionContainer = withRouter(React.createClass({
  componentWillMount () {
    this.props.clearPetition();
  },

  componentWillUpdate (nextProps) {
    if (petitionPublished(nextProps.petition)) {
      this.props.router.push(`${getPetitionPath(nextProps.petition)}/published`);
    }
  },

  componentWillUnmount () {
    this.props.clearPetition();
    this.props.clearSuggestionInputValue();
  },

  render () {
    const { petition, publishPetition } = this.props;

    return (

        <Helmet title={settings.newPetitionPage.title} />
        {petition.saved
          ? <PreviewPetition
            petition={petition}
            publishPetition={publishPetition}
            />
          : <NewPetition petition={petition} />
        }

    );
  }
}));

export const mapStateToProps = ({ petition }) => ({
  petition: getPetitionForm(petition)
});

const mapDispatchToProps = (dispatch) => ({
  clearPetition: () => dispatch(clearPetition()),
  clearSuggestionInputValue: () => dispatch(clearSuggestionInputValue()),
  publishPetition: (petition) => dispatch(publishPetition(petition))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(NewPetitionContainer);
<|endoftext|>