<commit_before>import React from "react";
import {
  StyleSheet,
  Text,
  View,
  Image,
  ScrollView,
  TouchableOpacity,
  Button,
  StatusBar,
  Platform,
  Alert
} from "react-native";
import { Permissions } from "expo";
//import { MapView } from "expo";
import { NavigationActions } from "react-navigation";
import { lightpurple, darkpurple, pink } from "./colors.js";
import { Feather } from '@expo/vector-icons';
import MapViewDirections from 'react-native-maps-directions';

import  MapView, {Polyline} from 'react-native-maps';

// This triggers asking the user for location permissions.
// This won't do anything if the permission is already granted.
Permissions.askAsync(Permissions.LOCATION);
export default class ExplorePage extends React.Component {
    constructor(props) {
        super(props);
        self = this;
        initialLat = 42.518217;
        initialLong = -70.891919;
        initialDelta = 0.005;

        this.state = { markers : [],
                        };

      this.onRegionChange = this.onRegionChange.bind(this);
      this.tourNext = this.tourNext.bind(this);
 }

  getInitialState() {
    initialLat = 42.518217;
    initialLong = -70.891919;
    initialDelta = 0.005;
    return {

      region: {
        latitude: initialLat,
        longitude: initialLong ,
        latitudeDelta: initialDelta,
        longitudeDelta: initialDelta,
      },
    };
  }
    componentDidMount() {
        // if (Platform.OS === 'ios') this.watchID = navigator.geolocation.watchPosition();

    }

    componentWillUnmount() {
        // if (Platform.OS === 'ios') navigator.geolocation.clearWatch(this.watchID);

    }
    componentDidUpdate (){
      // if (this.props.screenProps.tourStarted){

      //        if(this.markers){
      //           if(this.markerID){
      //                 this.markers[this.markerID].showCallout();
      //               }
      //         }
      //         if( this.props.screenProps.currMarker == Object.keys(this.props.screenProps.murals).length){
      //             this.toggleTour();
      //           }
      //       }
    }
    onRegionChange(region) {
      this.setState({ region });
    }

  static navigationOptions = ({ navigation}) => {
    return Platform.OS === "ios"
      ? {
          headerLeft: (
            <TouchableOpacity
              style={{ top: 30, left: -25, padding: 40 }}
              onPress={() => {self.props.screenProps.falseFromGallery()
                              navigation.dispatch(NavigationActions.back())}}
            >
              <View
                style={{
                  position: "relative",
                  flexDirection: "row",
                  backgroundColor: 'white',
                  zIndex: 100,
                  marginTop: -15,
                  width: 120,
                  height: 40,
                  borderRadius: 100,
                  alignItems: 'center',
                  justifyContent: 'center',
                  paddingRight: 6,
                  shadowOffset: { width: 1, height: 1 },
                  shadowRadius: 2,
                  shadowOpacity: 0.6,
                }}
              >
                <Feather name="chevron-left" size={25} color={pink} style={{marginBottom: 1}}/>
                <Text style={{fontWeight: 'bold', fontSize: 17, color: pink}}>  Back </Text>
              </View>
            </TouchableOpacity>
          ),
          headerStyle: {
            position: "absolute",
            backgroundColor: "transparent",
            zIndex: 100,
            top: 0,
            left: 0,
            right: 0,
            borderBottomColor: "transparent"
          }
        }
      : {
          title: "Punto Urban Art",
          headerTintColor: "white",
          headerStyle: { backgroundColor: pink }
        };
  }

  renderImages() {
    const { navigate } = this.props.navigation;

    murals = this.props.screenProps.murals || {};
    artists = this.props.screenProps.artists || {};

    defaultMuralID = '';
    if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
      defaultMuralID = this.props.navigation.state.params.muralID;
    }

    return Object.keys(murals).map((key, i) => {
      lat = parseFloat(murals[key]["Lat"]);
      long = parseFloat(murals[key]["Long"]);
      title = murals[key]["Title"];
      artistName = artists[murals[key]["Artist"]]["name"];

      setRefLambda = (function (ref) {
        this.calloutToMakeVisible = ref
      }).bind(this);

      return (
        <MapView.Marker
          key={i}
          title={title}
          description={artistName}
          coordinate={{ latitude: lat, longitude: long }}
          pinColor={pink}
          ref = {(ref) => this.state.markers[key] = ref}
          //{key == defaultMuralID ? setRefLambda : null}

          onCalloutPress={() => {
            navigate("MuralInfoPage", {
              mural: murals[key],
              artist: artists[murals[key]["Artist"]]
            });
          }}
        />
      );
    });

  }

  goToMural() {

    // if (this.calloutToMakeVisible) {
    //   this.calloutToMakeVisible.showCallout();
    // }
    murals = this.props.screenProps.murals || {};
    if (this.props.screenProps.tourStarted) {
            // See if the currMarker corresponds to a mural
        if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
            this.toggleTour();
            this.props.screenProps.trueFromGallery();

            this.state.markers[this.props.navigation.state.params.muralID].showCallout();
            return;
            }

            Lat = 0
            Lon = 0
            markerKey =0
            Object.keys(murals).map((key,i) =>{
                    console.log("306")
                    if (murals[key]["Index"] == this.props.screenProps.currMarker){
                      Lat = parseFloat(murals[key]["Lat"]);
                      Lon = parseFloat(murals[key]["Long"]);
                      markerKey = key;
                      }

                  });
      if (this.state.markers) {
                  this.state.markers[markerKey].showCallout();
        }

  }
     if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
      this.state.markers[this.props.navigation.state.params.muralID].showCallout();

    }

  }

    toggleTour() {

      console.log("start button pressed");
      murals = this.props.screenProps.murals || {};
      if (this.props.screenProps.tourStarted){
        Object.keys(murals).map((key,i) =>{
          this.state.markers[key].hideCallout();
        });

      }

        this.props.screenProps.tourState()

    }

    tourNext () {

        this.props.screenProps.changeMarker();

        if( this.props.screenProps.currMarker == Object.keys(this.props.screenProps.murals).length - 1){
            this.toggleTour();
        }

    }

    getCurrCoordsLat(){
      murals = this.props.screenProps.murals || {}
      Lat = 42.518217

        Object.keys(murals).map((key,i) =>{

            if (murals[key]["Index"] == this.props.screenProps.currMarker ){
              Lat = parseFloat(murals[key]["Lat"]);
              return Lat;
            }

          })

      return Lat;

    }

    getCurrCoordsLong(){
      murals = this.props.screenProps.murals || {}
      Lon = -70.891919

      Object.keys(murals).map((key,i) =>{

          if (murals[key]["Index"] == this.props.screenProps.currMarker ){
            Lon = parseFloat(murals[key]["Long"]);
            return Lon;
          }

        })

      return Lon;

    }

    tourPrev() {
      if(this.props.screenProps.currMarker == 1){
        return;
      }
      else{
        this.props.screenProps.changeMarkerPrev();
      }
    }

    render() {
        const { navigate } = this.props.navigation;
        initialLat = 42.518217;
        initialLong = -70.891919;
        initialDelta = 0.005;

        initialRegion = {
            longitude: initialLong,
            latitude: initialLat,
            latitudeDelta: initialDelta,
            longitudeDelta: initialDelta
        };

        // Determine which region we WANT to go to.
        region = undefined;

        murals = this.props.screenProps.murals || {};

        // If we came from the MuralInfoPage
        if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
            key = this.props.navigation.state.params.muralID;

            region = {
              latitude: parseFloat(murals[key]["Lat"]),
              longitude: parseFloat(murals[key]["Long"]),
              latitudeDelta: .001,
              longitudeDelta: .001,
            }
        }

        // If we're on a tour
        else if (this.props.screenProps.tourStarted) {
            console.log("299", this.props.screenProps.currMarker)
            // See if the currMarker corresponds to a mural

            Lat = 0
            Lon = 0

            Object.keys(murals).map((key,i) =>{
                    console.log("306")
                    if (murals[key]["Index"] == this.props.screenProps.currMarker){
                      Lat = parseFloat(murals[key]["Lat"]);
                      Lon = parseFloat(murals[key]["Long"]);

                      }

                  });

            if (Lat != 0 && Lon != 0) {
                console.log("316")
                region = {
                   latitude: Lat,
                   longitude: Lon,
                   latitudeDelta: .001,
                   longitudeDelta: .001,
                 }

            }

        }

        else {
          region = initialRegion
        }

        console.log("326", region)

        return (
            <View style = {{flex: 1}}>
            <StatusBar barStyle = { Platform.OS === 'ios' ? "dark-content" : "light-content"}/>
            <AnimatedMapView
              style = {{flex: 1 }}
              showsPointsOfInterest={false}
              showsUserLocation={true}
              initialRegion = {initialRegion}
              region =  {region}
              onLayout = {this.goToMural.bind(this)}
               >
              {this.renderImages()}

            </AnimatedMapView>
            {console.log(this.props.screenProps.tourStarted)}
          {this.props.screenProps.tourStarted ?
            <View>
             <Button
            title="prev"
            onPress={()=>this.tourPrev()}
            >  </Button>
             <Button
            title="next"
            onPress = {()=>this.tourNext()} >
            </Button>
            <Button
            title="end tour"
            onPress={()=>this.toggleTour()}
            >  </Button>
            </View>
            : this.props.screenProps.fromGallery ?
            <View></View> :
            <Button
            title="start tour"
            onPress={()=>this.toggleTour()}>
            </Button>  }
          </View>
        );
    }

}

//console.log(this.props.screenProps.currMarker)

      //   Object.keys(murals).map((key,i) =>{

      //     if (murals[key]["Index"] == this.props.screenProps.currMarker){
      //       Lat = parseFloat(murals[key]["Lat"]);
      //       Lon = parseFloat(murals[key]["Long"]);
      //     }

      //   })

      // console.log(this.props.screenProps.currMarker)

      //    _mapView.animateToCoordinate({
      //       latitude: Lat,
      //       longitude: Lon,
      //     }, 1000)
// {{
//                 latitude: this.props.screenProps.tourStarted == false ? initialLat: this.getCurrCoordsLat() ,
//                 longitude: this.props.screenProps.tourStarted == false ? initialLong : this.getCurrCoordsLong() ,
//                 latitudeDelta: this.props.screenProps.tourStarted == false ? initialDelta : 0.0001,
//                 longitudeDelta: this.props.screenProps.tourStarted == false ? initialDelta : 0.0001,
//               }}

/*****************************************************************************/

// Just a MapView but it animates to region if the region prop changes!
class AnimatedMapView extends React.Component {

    shouldComponentUpdate(nextProps, nextState) {
        console.log("408")
        this.goToRegion(nextProps.region, nextProps.onLayout);
        return false;
    }

    // Note: onLayout (which gets passed in as a prop) is called afterwards so
    // that the parent component has a way to hook into onLayout.
    // But TBH im not sure if this is the right way to do this lol.
    goToRegion(region, onLayout) {
        if (region) {
            console.log("415")
            setTimeout(function () {
                this.map.animateToRegion(region, 1000);
            }.bind(this), 500);
        }

        if (onLayout) {
            onLayout();
        }
    }

    render() {
        var {initialRegion, region, children, onLayout, ...otherProps} = this.props;

        return (
            <MapView
                onLayout={this.goToRegion.bind(this, region, onLayout)}
                initialRegion =  {initialRegion}
                ref =  {r => {this.map = r}}
                {...otherProps}>
                {children}
            </MapView>
        )
    }

}

<commit_msg>remove unecessary new lines<commit_after>import React from "react";
import {
  StyleSheet,
  Text,
  View,
  Image,
  ScrollView,
  TouchableOpacity,
  Button,
  StatusBar,
  Platform,
  Alert
} from "react-native";
import { Permissions } from "expo";
//import { MapView } from "expo";
import { NavigationActions } from "react-navigation";
import { lightpurple, darkpurple, pink } from "./colors.js";
import { Feather } from '@expo/vector-icons';
import MapViewDirections from 'react-native-maps-directions';

import  MapView, {Polyline} from 'react-native-maps';

// This triggers asking the user for location permissions.
// This won't do anything if the permission is already granted.
Permissions.askAsync(Permissions.LOCATION);

export default class ExplorePage extends React.Component {
    constructor(props) {
        super(props);
        self = this;
        initialLat = 42.518217;
        initialLong = -70.891919;
        initialDelta = 0.005;

        this.state = { markers : [],
                        };

      this.onRegionChange = this.onRegionChange.bind(this);
      this.tourNext = this.tourNext.bind(this);
 }

  getInitialState() {
    initialLat = 42.518217;
    initialLong = -70.891919;
    initialDelta = 0.005;
    return {
      region: {
        latitude: initialLat,
        longitude: initialLong ,
        latitudeDelta: initialDelta,
        longitudeDelta: initialDelta,
      },
    };
  }

  onRegionChange(region) {
    this.setState({ region });
  }

  static navigationOptions = ({ navigation}) => {
    return Platform.OS === "ios"
      ? {
          headerLeft: (
            <TouchableOpacity
              style={{ top: 30, left: -25, padding: 40 }}
              onPress={() => {self.props.screenProps.falseFromGallery()
                              navigation.dispatch(NavigationActions.back())}}
            >
              <View
                style={{
                  position: "relative",
                  flexDirection: "row",
                  backgroundColor: 'white',
                  zIndex: 100,
                  marginTop: -15,
                  width: 120,
                  height: 40,
                  borderRadius: 100,
                  alignItems: 'center',
                  justifyContent: 'center',
                  paddingRight: 6,
                  shadowOffset: { width: 1, height: 1 },
                  shadowRadius: 2,
                  shadowOpacity: 0.6,
                }}
              >
                <Feather name="chevron-left" size={25} color={pink} style={{marginBottom: 1}}/>
                <Text style={{fontWeight: 'bold', fontSize: 17, color: pink}}>  Back </Text>
              </View>
            </TouchableOpacity>
          ),
          headerStyle: {
            position: "absolute",
            backgroundColor: "transparent",
            zIndex: 100,
            top: 0,
            left: 0,
            right: 0,
            borderBottomColor: "transparent"
          }
        }
      : {
          title: "Punto Urban Art",
          headerTintColor: "white",
          headerStyle: { backgroundColor: pink }
        };
  }

  renderImages() {
    const { navigate } = this.props.navigation;

    murals = this.props.screenProps.murals || {};
    artists = this.props.screenProps.artists || {};

    defaultMuralID = '';
    if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
      defaultMuralID = this.props.navigation.state.params.muralID;
    }

    return Object.keys(murals).map((key, i) => {
      lat = parseFloat(murals[key]["Lat"]);
      long = parseFloat(murals[key]["Long"]);
      title = murals[key]["Title"];
      artistName = artists[murals[key]["Artist"]]["name"];

      setRefLambda = (function (ref) {
        this.calloutToMakeVisible = ref
      }).bind(this);

      return (
        <MapView.Marker
          key={i}
          title={title}
          description={artistName}
          coordinate={{ latitude: lat, longitude: long }}
          pinColor={pink}
          ref = {(ref) => this.state.markers[key] = ref}
          //{key == defaultMuralID ? setRefLambda : null}

          onCalloutPress={() => {
            navigate("MuralInfoPage", {
              mural: murals[key],
              artist: artists[murals[key]["Artist"]]
            });
          }}
        />
      );
    });

  }

  goToMural() {
    murals = this.props.screenProps.murals || {};
    if (this.props.screenProps.tourStarted) {
            // See if the currMarker corresponds to a mural
        if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
            this.toggleTour();
            this.props.screenProps.trueFromGallery();

            this.state.markers[this.props.navigation.state.params.muralID].showCallout();
            return;
            }

            Lat = 0
            Lon = 0
            markerKey =0
            Object.keys(murals).map((key,i) =>{
                    console.log("306")
                    if (murals[key]["Index"] == this.props.screenProps.currMarker){
                      Lat = parseFloat(murals[key]["Lat"]);
                      Lon = parseFloat(murals[key]["Long"]);
                      markerKey = key;
                      }

                  });
      if (this.state.markers) {
                  this.state.markers[markerKey].showCallout();
        }

  }
     if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
      this.state.markers[this.props.navigation.state.params.muralID].showCallout();

    }

  }

    toggleTour() {

      console.log("start button pressed");
      murals = this.props.screenProps.murals || {};
      if (this.props.screenProps.tourStarted){
        Object.keys(murals).map((key,i) =>{
          this.state.markers[key].hideCallout();
        });

      }

        this.props.screenProps.tourState()

    }

    tourNext () {

        this.props.screenProps.changeMarker();

        if( this.props.screenProps.currMarker == Object.keys(this.props.screenProps.murals).length - 1){
            this.toggleTour();
        }

    }

    getCurrCoordsLat(){
      murals = this.props.screenProps.murals || {}
      Lat = 42.518217

        Object.keys(murals).map((key,i) =>{

            if (murals[key]["Index"] == this.props.screenProps.currMarker ){
              Lat = parseFloat(murals[key]["Lat"]);
              return Lat;
            }
          })

      return Lat;

    }

    getCurrCoordsLong(){
      murals = this.props.screenProps.murals || {}
      Lon = -70.891919

      Object.keys(murals).map((key,i) =>{

          if (murals[key]["Index"] == this.props.screenProps.currMarker ){
            Lon = parseFloat(murals[key]["Long"]);
            return Lon;
          }
        })
      return Lon;
    }

    tourPrev() {
      if(this.props.screenProps.currMarker == 1){
        return;
      }
      else{
        this.props.screenProps.changeMarkerPrev();
      }
    }

    render() {
        const { navigate } = this.props.navigation;
        initialLat = 42.518217;
        initialLong = -70.891919;
        initialDelta = 0.005;

        initialRegion = {
            longitude: initialLong,
            latitude: initialLat,
            latitudeDelta: initialDelta,
            longitudeDelta: initialDelta
        };

        // Determine which region we WANT to go to.
        region = undefined;

        murals = this.props.screenProps.murals || {};

        // If we came from the MuralInfoPage
        if (this.props.navigation.state.params && this.props.navigation.state.params.muralID) {
            key = this.props.navigation.state.params.muralID;

            region = {
              latitude: parseFloat(murals[key]["Lat"]),
              longitude: parseFloat(murals[key]["Long"]),
              latitudeDelta: .001,
              longitudeDelta: .001,
            }
        }

        // If we're on a tour
        else if (this.props.screenProps.tourStarted) {
            console.log("299", this.props.screenProps.currMarker)
            // See if the currMarker corresponds to a mural

            Lat = 0
            Lon = 0

            Object.keys(murals).map((key,i) =>{
                    console.log("306")
                    if (murals[key]["Index"] == this.props.screenProps.currMarker){
                      Lat = parseFloat(murals[key]["Lat"]);
                      Lon = parseFloat(murals[key]["Long"]);

                      }

                  });

            if (Lat != 0 && Lon != 0) {
                console.log("316")
                region = {
                   latitude: Lat,
                   longitude: Lon,
                   latitudeDelta: .001,
                   longitudeDelta: .001,
                 }

            }

        }

        else {
          region = initialRegion
        }

        console.log("326", region)

        return (
            <View style = {{flex: 1}}>
            <StatusBar barStyle = { Platform.OS === 'ios' ? "dark-content" : "light-content"}/>
            <AnimatedMapView
              style = {{flex: 1 }}
              showsPointsOfInterest={false}
              showsUserLocation={true}
              initialRegion = {initialRegion}
              region =  {region}
              onLayout = {this.goToMural.bind(this)}
               >
              {this.renderImages()}

            </AnimatedMapView>
            {console.log(this.props.screenProps.tourStarted)}
          {this.props.screenProps.tourStarted ?
            <View>
             <Button
            title="prev"
            onPress={()=>this.tourPrev()}
            >  </Button>
             <Button
            title="next"
            onPress = {()=>this.tourNext()} >
            </Button>
            <Button
            title="end tour"
            onPress={()=>this.toggleTour()}
            >  </Button>
            </View>
            : this.props.screenProps.fromGallery ?
            <View></View> :
            <Button
            title="start tour"
            onPress={()=>this.toggleTour()}>
            </Button>  }
          </View>
        );
    }

}

/*****************************************************************************/

// Just a MapView but it animates to region if the region prop changes!
class AnimatedMapView extends React.Component {

    shouldComponentUpdate(nextProps, nextState) {
        console.log("408")
        this.goToRegion(nextProps.region, nextProps.onLayout);
        return false;
    }

    // Note: onLayout (which gets passed in as a prop) is called afterwards so
    // that the parent component has a way to hook into onLayout.
    // But TBH im not sure if this is the right way to do this lol.
    goToRegion(region, onLayout) {
        if (region) {
            console.log("415")
            setTimeout(function () {
                this.map.animateToRegion(region, 1000);
            }.bind(this), 500);
        }

        if (onLayout) {
            onLayout();
        }
    }

    render() {
        var {initialRegion, region, children, onLayout, ...otherProps} = this.props;

        return (
            <MapView
                onLayout={this.goToRegion.bind(this, region, onLayout)}
                initialRegion =  {initialRegion}
                ref =  {r => {this.map = r}}
                {...otherProps}>
                {children}
            </MapView>
        )
    }

}

<|endoftext|>


<commit_before>/**
 * Similar to the Date (dd/mm/YY) data sorting plug-in, this plug-in offers
 * additional  flexibility with support for spaces between the values and
 * either . or / notation for the separators.
 *
 *  @name Date (dd . mm[ . YYYY])
 *  @summary Sort dates in the format `dd/mm/YY[YY]` (with optional spaces)
 *  @author [Robert Sedovšek](http://galjot.si/)
 *
 *  @example
 *    $('#example').dataTable( {
 *       columnDefs: [
 *         { type: 'date-eu', targets: 0 }
 *       ]
 *    } );
 */

jQuery.extend( jQuery.fn.dataTableExt.oSort, {
	"date-eu-pre": function ( date ) {
		date = date.replace(" ", "");
		var eu_date, year;

		if (date.indexOf('.') > 0) {
			/*date a, format dd.mn.(yyyy) ; (year is optional)*/
			eu_date = date.split('.');
		} else {
			/*date a, format dd/mn/(yyyy) ; (year is optional)*/
			eu_date = date.split('/');
		}

		/*year (optional)*/
		if (eu_date[2]) {
			year = eu_date[2];
		} else {
			year = 0;
		}

		/*month*/
		var month = eu_date[1];
		if (month.length == 1) {
			month = 0+month;
		}

		/*day*/
		var day = eu_date[0];
		if (day.length == 1) {
			day = 0+day;
		}

		return (year + month + day) * 1;
	},

	"date-eu-asc": function ( a, b ) {
		return ((a < b) ? -1 : ((a > b) ? 1 : 0));
	},

	"date-eu-desc": function ( a, b ) {
		return ((a < b) ? 1 : ((a > b) ? -1 : 0));
	}
} );
<commit_msg>Bug: Plugin used to break on empty strings.<commit_after>/**
 * Similar to the Date (dd/mm/YY) data sorting plug-in, this plug-in offers
 * additional  flexibility with support for spaces between the values and
 * either . or / notation for the separators.
 *
 *  @name Date (dd . mm[ . YYYY])
 *  @summary Sort dates in the format `dd/mm/YY[YY]` (with optional spaces)
 *  @author [Robert Sedovšek](http://galjot.si/)
 *
 *  @example
 *    $('#example').dataTable( {
 *       columnDefs: [
 *         { type: 'date-eu', targets: 0 }
 *       ]
 *    } );
 */

jQuery.extend( jQuery.fn.dataTableExt.oSort, {
	"date-eu-pre": function ( date ) {
		date = date.replace(" ", "");
		var eu_date, year;

		if (date == '') return;

		if (date.indexOf('.') > 0) {
			/*date a, format dd.mn.(yyyy) ; (year is optional)*/
			eu_date = date.split('.');
		} else {
			/*date a, format dd/mn/(yyyy) ; (year is optional)*/
			eu_date = date.split('/');
		}

		/*year (optional)*/
		if (eu_date[2]) {
			year = eu_date[2];
		} else {
			year = 0;
		}

		/*month*/
		var month = eu_date[1];
		if (month.length == 1) {
			month = 0+month;
		}

		/*day*/
		var day = eu_date[0];
		if (day.length == 1) {
			day = 0+day;
		}

		return (year + month + day) * 1;
	},

	"date-eu-asc": function ( a, b ) {
		return ((a < b) ? -1 : ((a > b) ? 1 : 0));
	},

	"date-eu-desc": function ( a, b ) {
		return ((a < b) ? 1 : ((a > b) ? -1 : 0));
	}
} );
<|endoftext|>


<commit_before>const electron = require('electron')
var remote = require('electron').remote
const app = remote.app
const path = require('path')

var dbFile = path.join(app.getPath('userData'), 'easy-store-db.json')
var Datastore = require('nedb'),
    DB = new Datastore({ filename: dbFile, autoload: true });

const TransferProtocols = ["ftp", "rsync", "s3", "sftp", "scp"];
const SerializationFormats = ["gzip", "tar", "zip"];

class AppSetting {
    constructor(name, value) {
        this.name = name;
        this.value = value;
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
}

class BagItProfile {
    constructor() {
        // name and description are not part of BagItProfile standard
        this.name = "";
        this.description = "";
        this.acceptBagItVersion = [];
        this.acceptSerialization = [];
        this.allowFetchTxt = false;
        this.allowMiscTopLevelFiles = false;
        this.allowMiscDirectories = false;
        this.bagItProfileInfo = new BagItProfileInfo();
        this.manifestsRequired = [];
        this.serialization = "optional";
        // In BagItProfile format, this is a dictionary,
        // not an array. Format is
        // Key = name of tag file, Value = TagDefinition
        // The fact that key names have dots in them prevents
        // us from using nedb datastore.
        this.tagFilesRequired = [];
        this.tagManifestsRequired = [];
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
    toBagItProfileJson() {
        // Return a string of JSON in BagItProfile format,
        // with all the bad keys they use.
    }
    static fromBagItProfileJson(jsonString) {
        // Parse JSON from BagItProfile format, with the bad
        // keys they use. Return a BagItProfile object.
        var obj = JSON.parse(jsonString)
        return BagItProfile.fromBagItProfileObject(obj)
    }
    static fromBagItProfileObject(obj) {
        var p = new BagItProfile();
        p.acceptBagItVersion = obj["Accept-BagIt-Version"];
        p.acceptSerialization = obj["Accept-Serialization"];
        p.allowFetchTxt = obj["Allow-Fetch.txt"];
        p.allowMiscTopLevelFiles = obj["Allow-Misc-Top-Level-Files"];
        p.allowMiscDirectories = obj["Allow-Misc-Directories"];
        p.manifestsRequired = obj["Manifests-Required"];
        p.serialization = obj["Serialization"];
        p.tagManifestsRequired = obj["Tag-Manifests-Required"];

        p.bagItProfileInfo = new BagItProfileInfo();
        p.bagItProfileInfo.bagItProfileIdentifier = obj["BagIt-Profile-Info"]["BagIt-Profile-Identifier"];
        p.bagItProfileInfo.contactEmail = obj["BagIt-Profile-Info"]["Contact-Email"];
        p.bagItProfileInfo.contactName = obj["BagIt-Profile-Info"]["Contact-Name"];
        p.bagItProfileInfo.externalDescription = obj["BagIt-Profile-Info"]["External-Description"];
        p.bagItProfileInfo.sourceOrganization = obj["BagIt-Profile-Info"]["Source-Organization"];
        p.bagItProfileInfo.version = obj["BagIt-Profile-Info"]["Version"];

        // Copy required tag definitions to our preferred structure.
        // The BagIt profiles we're transforming don't have default values for tags.
        for (var fileName in obj["Tag-Files-Required"]) {
            for (var tagName in obj["Tag-Files-Required"][fileName]) {
                var originalDef = obj["Tag-Files-Required"][fileName][tagName];
                var tagDef = new TagDefinition(fileName, tagName);
                tagDef.required = originalDef["required"] || false;
                tagDef.emptyOk = originalDef["emptyOk"] || false;
                tagDef.values = originalDef["values"] || [];
                p.tagFilesRequired.push(tagDef);
            }
        }
        return p;
    }
}

class BagItProfileInfo {
    constructor() {
        this.bagItProfileIdentifier = "";
        this.contactEmail = "";
        this.contactName = "";
        this.externalDescription = "";
        this.sourceOrganization = "";
        this.version = "";
    }
}

class Choice {
    constructor(value, label) {
        this.value = value;
        this.label = label;
        this.selected = false;
    }
    static makeList(items, selected) {
        // return a list of choices
    }
}

class Field {
    constructor(id, name, label, value) {
        this.id = id;
        this.name = name;
        this.label = label;
        this.value = value;
        this.choices = [];
        this.attrs = {}
    }
}

class Form {
    constructor() {
        this.field = [];
    }
    validate() {
        // Convert the form to the underlying object,
        // validate that, then set the errors here.
    }
}

class StorageService {
    constructor(name) {
        this.name = name;
        this.description = "";
        this.protocol = "";
        this.url = "";
        this.bucket = "";
        this.loginName = "";
        this.loginPassword = "";
        this.loginExtra = "";
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
}

class TagDefinition {
    constructor(tagFile, tagName) {
        this.tagFile = tagFile;
        this.tagName = tagName;
        this.required = false;
        this.emptyOk = true;
        this.values = [];
        this.defaultValue = "";
    }
}

class Util {
    // Thanks https://gist.github.com/kaizhu256/4482069
    static uuid4() {
        var uuid = '', ii;
        for (ii = 0; ii < 32; ii += 1) {
            switch (ii) {
            case 8:
            case 20:
                uuid += '-';
                uuid += (Math.random() * 16 | 0).toString(16);
                break;
            case 12:
                uuid += '-';
                uuid += '4';
                break;
            case 16:
                uuid += '-';
                uuid += (Math.random() * 4 | 8).toString(16);
                break;
            default:
                uuid += (Math.random() * 16 | 0).toString(16);
            }
        }
        return uuid;
    };
}

module.exports.AppSetting = AppSetting;
module.exports.BagItProfile = BagItProfile;
module.exports.BagItProfileInfo = BagItProfileInfo;
module.exports.Choice = Choice;
module.exports.DB = DB;
module.exports.Field = Field;
module.exports.Form = Form;
module.exports.SerializationFormats = SerializationFormats
module.exports.StorageService = StorageService;
module.exports.TagDefinition = TagDefinition;
module.exports.TransferProtocols = TransferProtocols
module.exports.Util = Util
<commit_msg>Built-in profiles are now accessible within easy_store.js<commit_after>const electron = require('electron')
var remote = require('electron').remote
const app = remote.app
const path = require('path')
const builtin_profiles = require(path.resolve('electron/easy/builtin_profiles'))

var dbFile = path.join(app.getPath('userData'), 'easy-store-db.json')
var Datastore = require('nedb'),
    DB = new Datastore({ filename: dbFile, autoload: true });

const TransferProtocols = ["ftp", "rsync", "s3", "sftp", "scp"];
const SerializationFormats = ["gzip", "tar", "zip"];

class AppSetting {
    constructor(name, value) {
        this.name = name;
        this.value = value;
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
}

class BagItProfile {
    constructor() {
        // name and description are not part of BagItProfile standard
        this.name = "";
        this.description = "";
        this.acceptBagItVersion = [];
        this.acceptSerialization = [];
        this.allowFetchTxt = false;
        this.allowMiscTopLevelFiles = false;
        this.allowMiscDirectories = false;
        this.bagItProfileInfo = new BagItProfileInfo();
        this.manifestsRequired = [];
        this.serialization = "optional";
        // In BagItProfile format, this is a dictionary,
        // not an array. Format is
        // Key = name of tag file, Value = TagDefinition
        // The fact that key names have dots in them prevents
        // us from using nedb datastore.
        this.tagFilesRequired = [];
        this.tagManifestsRequired = [];
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
    toBagItProfileJson() {
        // Return a string of JSON in BagItProfile format,
        // with all the bad keys they use.
    }
    static fromBagItProfileJson(jsonString) {
        // Parse JSON from BagItProfile format, with the bad
        // keys they use. Return a BagItProfile object.
        var obj = JSON.parse(jsonString)
        return BagItProfile.fromBagItProfileObject(obj)
    }
    static fromBagItProfileObject(obj) {
        var p = new BagItProfile();
        p.acceptBagItVersion = obj["Accept-BagIt-Version"];
        p.acceptSerialization = obj["Accept-Serialization"];
        p.allowFetchTxt = obj["Allow-Fetch.txt"];
        p.allowMiscTopLevelFiles = obj["Allow-Misc-Top-Level-Files"];
        p.allowMiscDirectories = obj["Allow-Misc-Directories"];
        p.manifestsRequired = obj["Manifests-Required"];
        p.serialization = obj["Serialization"];
        p.tagManifestsRequired = obj["Tag-Manifests-Required"];

        p.bagItProfileInfo = new BagItProfileInfo();
        p.bagItProfileInfo.bagItProfileIdentifier = obj["BagIt-Profile-Info"]["BagIt-Profile-Identifier"];
        p.bagItProfileInfo.contactEmail = obj["BagIt-Profile-Info"]["Contact-Email"];
        p.bagItProfileInfo.contactName = obj["BagIt-Profile-Info"]["Contact-Name"];
        p.bagItProfileInfo.externalDescription = obj["BagIt-Profile-Info"]["External-Description"];
        p.bagItProfileInfo.sourceOrganization = obj["BagIt-Profile-Info"]["Source-Organization"];
        p.bagItProfileInfo.version = obj["BagIt-Profile-Info"]["Version"];

        // Copy required tag definitions to our preferred structure.
        // The BagIt profiles we're transforming don't have default values for tags.
        for (var fileName in obj["Tag-Files-Required"]) {
            for (var tagName in obj["Tag-Files-Required"][fileName]) {
                var originalDef = obj["Tag-Files-Required"][fileName][tagName];
                var tagDef = new TagDefinition(fileName, tagName);
                tagDef.required = originalDef["required"] || false;
                tagDef.emptyOk = originalDef["emptyOk"] || false;
                tagDef.values = originalDef["values"] || [];
                p.tagFilesRequired.push(tagDef);
            }
        }
        return p;
    }
}

class BagItProfileInfo {
    constructor() {
        this.bagItProfileIdentifier = "";
        this.contactEmail = "";
        this.contactName = "";
        this.externalDescription = "";
        this.sourceOrganization = "";
        this.version = "";
    }
}

class Choice {
    constructor(value, label) {
        this.value = value;
        this.label = label;
        this.selected = false;
    }
    static makeList(items, selected) {
        // return a list of choices
    }
}

class Field {
    constructor(id, name, label, value) {
        this.id = id;
        this.name = name;
        this.label = label;
        this.value = value;
        this.choices = [];
        this.attrs = {}
    }
}

class Form {
    constructor() {
        this.field = [];
    }
    validate() {
        // Convert the form to the underlying object,
        // validate that, then set the errors here.
    }
}

class StorageService {
    constructor(name) {
        this.name = name;
        this.description = "";
        this.protocol = "";
        this.url = "";
        this.bucket = "";
        this.loginName = "";
        this.loginPassword = "";
        this.loginExtra = "";
    }
    validate() {
        // Return ValidationResult w/ isValid and errors
    }
    toForm() {
        // Return a form object that can be passed to a template
    }
    static fromForm() {
        // Parses a form and returns an AppSetting object
    }
}

class TagDefinition {
    constructor(tagFile, tagName) {
        this.tagFile = tagFile;
        this.tagName = tagName;
        this.required = false;
        this.emptyOk = true;
        this.values = [];
        this.defaultValue = "";
    }
}

class Util {
    // Thanks https://gist.github.com/kaizhu256/4482069
    static uuid4() {
        var uuid = '', ii;
        for (ii = 0; ii < 32; ii += 1) {
            switch (ii) {
            case 8:
            case 20:
                uuid += '-';
                uuid += (Math.random() * 16 | 0).toString(16);
                break;
            case 12:
                uuid += '-';
                uuid += '4';
                break;
            case 16:
                uuid += '-';
                uuid += (Math.random() * 4 | 8).toString(16);
                break;
            default:
                uuid += (Math.random() * 16 | 0).toString(16);
            }
        }
        return uuid;
    };
}

module.exports.AppSetting = AppSetting;
module.exports.BagItProfile = BagItProfile;
module.exports.BagItProfileInfo = BagItProfileInfo;
module.exports.Choice = Choice;
module.exports.DB = DB;
module.exports.Field = Field;
module.exports.Form = Form;
module.exports.SerializationFormats = SerializationFormats
module.exports.StorageService = StorageService;
module.exports.TagDefinition = TagDefinition;
module.exports.TransferProtocols = TransferProtocols
module.exports.Util = Util
<|endoftext|>


<commit_before>/**
 * Created by suman on 08/05/16.
 */

var core = require('chanakya');
var _ = require('lodash');
var Q = require('q'),
  http = require('http');
var rp = require('request-promise');

core.response('fail', function (to) {
  return {
    text: `I am sorry ${to.first_name}, I am unable to understand what you mean.`
  };
});

core.response('balance', function (to) {

  console.log(to);

  var deferred = Q.defer();

  var options = {
    uri: `https://polar-atoll-33216.herokuapp.com/users/1`,
    headers: {
      'Authorization': 'Bearer LUPCP5OOAFQXURYOH7I7YVU4FGBGVAG3',
      'Accept': 'application/vnd.wit.20141022+json'
    },
    json: true // Automatically parses the JSON string in the response
  };

  rp(options)
    .then(function (res) {
      deferred.resolve({
        text: `Your balance is ${res.currency}${res.balance}`
      });
    })
    .catch(function (err) {
      console.error(err);
    });
  return deferred.promise;
}, 'statement');
<commit_msg>new deploy<commit_after>/**
 * Created by suman on 08/05/16.
 */

var core = require('chanakya');
var _ = require('lodash');
var Q = require('q'),
  http = require('http');
var rp = require('request-promise');

core.response('fail', function (to) {
  return {
    text: `I am sorry ${to.first_name}, I am unable to understand what you mean. Please rephrase and send back.`
  };
});

core.response('balance', function (to) {

  console.log(to);

  var deferred = Q.defer();

  var options = {
    uri: `https://polar-atoll-33216.herokuapp.com/users/1`,
    headers: {
      'Authorization': 'Bearer LUPCP5OOAFQXURYOH7I7YVU4FGBGVAG3',
      'Accept': 'application/vnd.wit.20141022+json'
    },
    json: true // Automatically parses the JSON string in the response
  };

  rp(options)
    .then(function (res) {
      deferred.resolve({
        text: `Your balance is =${res.currency}${res.balance}`
      });
    })
    .catch(function (err) {
      console.error(err);
    });
  return deferred.promise;
}, 'statement');
<|endoftext|>


<commit_before><commit_msg>Touched webpack sass global config<commit_after><|endoftext|>


<commit_before>'use strict';

/*!
 * bufferutil: WebSocket buffer utils
 * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
 * MIT Licensed
 */

module.exports.BufferUtil = {
  merge: function(mergedBuffer, buffers) {
    for (var i = 0, offset = 0, l = buffers.length; i < l; ++i) {
      var buf = buffers[i];

      buf.copy(mergedBuffer, offset);
      offset += buf.length;
    }
  },

  mask: function(source, mask, output, offset, length) {
    var maskNum = mask.readUInt32LE(0, true)
      , i = 0
      , num;

    for (; i < length - 3; i += 4) {
      num = maskNum ^ source.readUInt32LE(i, true);

      if (num < 0) num = 4294967296 + num;
      output.writeUInt32LE(num, offset + i, true);
    }

    switch (length % 4) {
      case 3: output[offset + i + 2] = source[i + 2] ^ mask[2];
      case 2: output[offset + i + 1] = source[i + 1] ^ mask[1];
      case 1: output[offset + i] = source[i] ^ mask[0];
    }
  },

  unmask: function(data, mask) {
    var maskNum = mask.readUInt32LE(0, true)
      , length = data.length
      , i = 0
      , num;

    for (; i < length - 3; i += 4) {
      num = maskNum ^ data.readUInt32LE(i, true);

      if (num < 0) num = 4294967296 + num;
      data.writeUInt32LE(num, i, true);
    }

    switch (length % 4) {
      case 3: data[i + 2] = data[i + 2] ^ mask[2];
      case 2: data[i + 1] = data[i + 1] ^ mask[1];
      case 1: data[i] = data[i] ^ mask[0];
    }
  }
};
<commit_msg>Sync fallback code with ws<commit_after>/*!
 * bufferutil: WebSocket buffer utils
 * Copyright(c) 2015 Einar Otto Stangvik <einaros@gmail.com>
 * MIT Licensed
 */

'use strict';

exports.BufferUtil = {
  merge: function (mergedBuffer, buffers) {
    var offset = 0;
    for (var i = 0, l = buffers.length; i < l; ++i) {
      var buf = buffers[i];
      buf.copy(mergedBuffer, offset);
      offset += buf.length;
    }
  },
  mask: function (source, mask, output, offset, length) {
    for (var i = 0; i < length; i++) {
      output[offset + i] = source[i] ^ mask[i & 3];
    }
  },
  unmask: function (data, mask) {
    // required until https://github.com/nodejs/node/issues/9006 is resolved
    var length = data.length;
    for (var i = 0; i < length; i++) {
      data[i] ^= mask[i & 3];
    }
  }
};
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var Game = function(goal) {

    var scoreBulls = function(guess, goal) {
	var bulls = 0;
	for (var i=0;i<guess.length;++i) {
	    if (guess[i] === goal[i])
		bulls++;
	}
	return bulls;
    };

    var scoreCows = function(guess, goal) {
	var cows = 0;
	for (var i=0;i<goal.length;++i) {
	    var desiredChar = goal[i];
	    for (var j=0;j<goal.length;++j) {
		if (j === i) continue;

		if (guess[j] === desiredChar) {
		    cows++;
		}
	    }
	}
	return cows;
    };

    this.score = function(guess) {
	assert(goal.length === guess.length, 'Lengths must be equivalent');

        return {
	    cows: scoreCows(guess,goal),
	    bulls: scoreBulls(guess,goal)
	};
    };

    var finishingScore = function(score) {
	return score.bulls === 4;
    };

    this.play = function(strategy) {
	var turns = 0;

	do {
	    turns++;
	    var guess = strategy.guess();
	    var score = this.score(guess);
	    strategy.update(score);
	} while (!finishingScore(score));

	return turns;
    };

    return this;
};

var Naive = function() {
    this.guess = function() {
	return '5555';
    };

    this.update = function(guess, score) {

    };

    return this;
};

var Strategy = {
    Naive: new Naive()
};

var createGame = function(goal) {
    return new Game(goal);
};

describe("cows and bulls", function() {

    describe('playing naive', function() {
	it('should solve it within 9999 turns', function() {
	    var game = createGame('5555');
	    var turns = game.play(Strategy.Naive);

	    assert.equal(4444, turns);
	});
    });

    describe('scoring', function() {
	it('should match the example', function() {
	    var game = createGame('8045');
	    var result = game.score('0865');

	    assert.equal(2, result.cows);
	    assert.equal(1, result.bulls);
	});

	it('no matches scores no cows or bulls', function() {
            var game = createGame('1234');

            var r = game.score('5678');
            assert.equal(0,r.cows);
	    assert.equal(0,r.bulls);
	});

	it('all correct is all bulls', function() {
	    var game = createGame('1234');

	    var r = game.score('1234');
	    assert.equal(4, r.bulls);
	    assert.equal(0, r.cows);
	});

	it('all in wrong order is all cows', function() {
	    var game = createGame('1234');

	    var r = game.score('4321');
	    assert.equal(4, r.cows);
	    assert.equal(0, r.bulls);
	});
    });
});
<commit_msg>refactor<commit_after>"use strict";

var assert = require('assert');

var Game = function(goal) {

    var scoreBulls = function(guess, goal) {
	var bulls = 0;
	for (var i=0;i<guess.length;++i) {
	    if (guess[i] === goal[i])
		bulls++;
	}
	return bulls;
    };

    var scoreCows = function(guess, goal) {
	var cows = 0;
	for (var i=0;i<goal.length;++i) {
	    var desiredChar = goal[i];
	    for (var j=0;j<goal.length;++j) {
		if (j === i) continue;

		if (guess[j] === desiredChar) {
		    cows++;
		}
	    }
	}
	return cows;
    };

    this.score = function(guess) {
	assert(goal.length === guess.length, 'Lengths must be equivalent');

        return {
	    cows: scoreCows(guess,goal),
	    bulls: scoreBulls(guess,goal)
	};
    };

    var finishingScore = function(score) {
	return score.bulls === 4;
    };

    this.play = function(strategy) {
	var turns = 0;

	do {
	    turns++;
	    var guess = strategy.guess();
	    var score = this.score(guess);
	    strategy.update(score);
	} while (!finishingScore(score));

	return turns;
    };

    return this;
};

var Naive = function() {

    this.currentGuess = '5555';

    this.guess = function() {
	return this.currentGuess;
    };

    this.update = function(guess, score) {

    };

    return this;
};

var Strategy = {
    Naive: new Naive()
};

var createGame = function(goal) {
    return new Game(goal);
};

describe("cows and bulls", function() {

    describe('playing naive', function() {
	it('should solve it within 9999 turns', function() {
	    var game = createGame('5555');
	    var turns = game.play(Strategy.Naive);

	    assert.equal(4444, turns);
	});
    });

    describe('scoring', function() {
	it('should match the example', function() {
	    var game = createGame('8045');
	    var result = game.score('0865');

	    assert.equal(2, result.cows);
	    assert.equal(1, result.bulls);
	});

	it('no matches scores no cows or bulls', function() {
            var game = createGame('1234');

            var r = game.score('5678');
            assert.equal(0,r.cows);
	    assert.equal(0,r.bulls);
	});

	it('all correct is all bulls', function() {
	    var game = createGame('1234');

	    var r = game.score('1234');
	    assert.equal(4, r.bulls);
	    assert.equal(0, r.cows);
	});

	it('all in wrong order is all cows', function() {
	    var game = createGame('1234');

	    var r = game.score('4321');
	    assert.equal(4, r.cows);
	    assert.equal(0, r.bulls);
	});
    });
});
<|endoftext|>


<commit_before>"use strict";

var canvasId         = 'gl-canvas';
var vertexSourceId   = 'shader-vertex';
var fragmentSourceId = 'shader-fragment';

// Shader attributes/uniforms
var attrPosition           = 'vPosition';
var attrNormal             = 'vNormal';
var attrTexCoord           = 'texCoord';
var attrTangent            = 'objTangent';
var uniformModelMatrix     = 'modelMatrix';
var uniformProjViewMatrix  = 'projViewMatrix';
var uniformAmbientProduct  = 'ambientProduct';
var uniformDiffuseProduct  = 'diffuseProduct';
var uniformNormalMat       = 'normalMat';
var uniformLightPosition   = 'lightPosition';
var uniformTexSampler      = 'uSampler';
var uniformBumpTexSampler  = 'nSampler';
var uniformEnableLighting  = 'enableLighting';
var uniformUniformLighting = 'uniformLighting';
var uniformEnableBumpingV   = 'enableBumpingV';
var uniformEnableBumpingF   = 'enableBumpingF';

var shapes = [];
var campRocks = [];
var fire;
var bumpCube;
var sun;

var gl;	     // WebGL object for the canvas
var canvas;  // HTML canvas element that we are drawing in
var program; // The WebGL linked program
var camera;  // Camera used for navigating the scene
var player;

var timer = new Timer();

var cutscene=false;

// Steps in for moving camera
var rotateDegree = 1;
var moveUnit = 0.125;
var mouseSensitivity = 0.1;
var dayDuration = 1000;

// Helper to set shader attributes/uniforms
var glHelper = (function() {
	var helper = {};
	function setAttrib(name, vbo) {
		var loc = gl.getAttribLocation(program, name);
		gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
		gl.enableVertexAttribArray(loc);
		gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
	}

	function setUniformMat(name, mat) {
		var loc = gl.getUniformLocation(program, name);
		gl.uniformMatrix4fv(loc, false, flatten(mat));
	}

	function setUniformVec4(name, vec) {
		var loc = gl.getUniformLocation(program, name);
		gl.uniform4fv(loc, flatten(vec));
	}

	helper.setPositionAttrib = function(vbo) {
		setAttrib(attrPosition, vbo);
	}

	helper.setNormalAttrib = function(vbo) {
		setAttrib(attrNormal, vbo);
	}

	helper.setTangentAttrib = function(vbo) {
		setAttrib(attrTangent, vbo);
	}

	helper.setTexCoordAttrib = function(vbo) {
		var loc = gl.getAttribLocation(program, attrTexCoord);
		gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
		gl.enableVertexAttribArray(loc);
		gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
	}

	helper.setNormalModelMatrix = function(mat) {
		setUniformMat(uniformNormalMat, mat);
	}

	helper.setModelMatrix = function(mat) {
		setUniformMat(uniformModelMatrix, mat);
	}

	helper.setProjViewMatrix = function(mat) {
		setUniformMat(uniformProjViewMatrix, mat);
	}

	helper.setTexSampler = function(arg) {
		var loc = gl.getUniformLocation(program, uniformTexSampler);
		gl.uniform1i(loc, arg);
	}

	helper.setBumpTexSampler = function(arg) {
		var loc = gl.getUniformLocation(program, uniformBumpTexSampler);
		gl.uniform1i(loc, arg);
	}

	helper.uniformLighting = function(arg) {
		var loc = gl.getUniformLocation(program, uniformUniformLighting);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	//enable lighting will only work as expected when the object has a texture
	//it is intended only for the fire so that it is always full lit.
	helper.enableLighting = function(arg) {
		var loc = gl.getUniformLocation(program, uniformEnableLighting);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	helper.enableBumping = function(arg) {
		var loc = gl.getUniformLocation(program, uniformEnableBumpingF);
		gl.uniform1i(loc, (arg ? 1 : 0));
		loc = gl.getUniformLocation(program, uniformEnableBumpingV);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	helper.setAmbientProduct = function(vec) {
		setUniformVec4(uniformAmbientProduct, mult(sun.lightMaterial.ambient, vec));
	}

	helper.setDiffuseProduct = function(vec) {
		setUniformVec4(uniformDiffuseProduct, mult(sun.lightMaterial.diffuse, vec));
	}

	helper.setLightPosition = function(vec) {
		var loc = gl.getUniformLocation(program, uniformLightPosition);
		gl.uniform3fv(loc, flatten(vec));
	}

	return helper;
})();

// Init function to start GL and draw everything
window.onload = function() {
	canvas = document.getElementById(canvasId);
	gl = WebGLUtils.setupWebGL(canvas);

	if(!gl) {
		var msg = 'Unable to start WebGL!';
		alert(msg);
		throw msg;
	}

	// Compile and load the gl program
	try {
		program = initShaders(gl, vertexSourceId, fragmentSourceId);
		gl.useProgram(program);
		gl.viewport(0, 0, canvas.width, canvas.height);
	} catch(e) {
		alert(e);
		throw e;
	}

	// Initialize the player
	player = new Player(canvas, vec3(quarterSize, 0, -quarterSize+20), moveUnit);
    player.camera.yawBy(-45);
    player.camera.rollBy(-80);

	var waterMaterial = new Material(
		vec4(0.2, 0.2, 0.5, 0.8),
		vec4(0.2, 0.2, 0.7, 0.8)
	);

	var rockMaterial = new Material(
		vec4(0.9, 0.9, 0.9, 1.0),
		vec4(0.9, 0.9, 0.9, 1.0)
	);

	var water = new Cube(waterMaterial, null, true, false);
	water.position = vec3(islandSize/2, 0.0, islandSize/2);
	water.scale = vec3(islandSize*10, 0.1, islandSize*10);

    var theIsland = new Island();

	sun = new Sun(300, 1/dayDuration);

	shapes = [water, theIsland];

	for (var x=1; x<quarterSize; x+=2)
	{
        for(var z=1; z<quarterSize; z+=2)
        {
            var kXZ = 2.5 * (Math.random() + 1.5);
            var kY = 4.0 * (Math.random() * 0.3 +1.0);
            var age = Math.random();
            var rand = Math.random();
            if(heights[x][z]>0.21 && rand<=0.04 && (x < 49 || x > 51 || z < 29 || z > 31)) {
                new Tree(
                    vec3(x, heights[x][z]-0.5, z),
				    kXZ, kY,
                    age);
            }
        }
	}

	//This object is created as a test object
	var bumpMap = new Texture.fromImageSrc('./images/balls.png',gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR);
	bumpCube = new Cube(null, null, true, false, bumpMap);
	bumpCube.position = vec3(20.0, 0.8, 70.0);

	//create rocks in a circle to signify campsite
	for(var i = 0; i < 10; i++){
		campRocks.push(new CampRock(rockMaterial, new Texture.fromImageSrc('./images/rockTex.png'), gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.NEAREST, gl.NEAREST));
		campRocks[i].position = vec3(50.0 + Math.cos(i*Math.PI/5), heights[50][30] + 0.1, 30.0 + Math.sin(i*Math.PI/5));
		campRocks[i].scale = vec3(0.5, 0.5, 0.5);
		}

	fire = new Campfire(vec3(50.0, heights[50][30]+0.1, 30.0));
	fire.numSticks = 0.0;

	// Attach our keyboard listener to the canvas
	var playerHandleKeyDown = function(e){ return player.handleKeyDown(e); }
	var playerHandleKeyUp = function(e){ return player.handleKeyUp(e); }
	window.addEventListener('keydown', playerHandleKeyDown);
	window.addEventListener('keyup', playerHandleKeyUp);

	// Set off the draw loop
	draw();

    setTimeout(function() {
        // Attach our keyboard listener to the canvas
        cutscene=true;
    }, 2000);

    setTimeout(function() {
        // Attach our keyboard and mouse listeners to the canvas
	pointerLock(canvas, function(x, y) {
		player.camera.yawBy(-x * mouseSensitivity);
		player.camera.pitchBy(-y * mouseSensitivity);
	}, null);

        var playerHandleKeyDown = function(e){ return player.handleKeyDown(e); }
        var playerHandleKeyUp = function(e){ return player.handleKeyUp(e); }
        window.addEventListener('keydown', playerHandleKeyDown);
        window.addEventListener('keyup', playerHandleKeyUp);
    }, 2500);
}

// Draws the data in the vertex buffer on the canvas repeatedly
function draw() {
	var skyColor = sun.skyColor;
	gl.clearColor(skyColor[0], skyColor[1], skyColor[2], 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
	gl.enable(gl.DEPTH_TEST);

	glHelper.uniformLighting(true);
	glHelper.enableLighting(true);
	glHelper.enableBumping(false);
	player.move(); // This will set our camera in the world
	glHelper.setProjViewMatrix(player.camera.getProjViewMatrix());

	var identMat = mat4();
	var dt = timer.getElapsedTime();

	sun.draw(dt);  // This will set our light position and material
	Tree.drawTrees(dt);

	fire.draw(dt, identMat);

	shapes.forEach(function(e) {
		dt += timer.getElapsedTime();
		e.draw(dt, identMat);
	});

	campRocks.forEach(function(e) {
		dt += timer.getElapsedTime();
		e.draw(dt, identMat);
	});

//This commented cube draws a test cube that clearly shows the sucesfull
//implemintation of bump mapping
//	glHelper.enableBumping(true);
//	dt += timer.getElapsedTime();
//	bumpCube.draw(dt, identMat);
//	glHelper.enableBumping(false);

	player.draw(); // This will draw the crosshairs and arms on the screen
    if(cutscene) {
        if(player.camera.getRoll()!=0) {
            player.camera.rollBy(1);
        }
    }
	window.requestAnimFrame(draw);
}
<commit_msg>Attach handlers only once, fixing a botched merge<commit_after>"use strict";

var canvasId         = 'gl-canvas';
var vertexSourceId   = 'shader-vertex';
var fragmentSourceId = 'shader-fragment';

// Shader attributes/uniforms
var attrPosition           = 'vPosition';
var attrNormal             = 'vNormal';
var attrTexCoord           = 'texCoord';
var attrTangent            = 'objTangent';
var uniformModelMatrix     = 'modelMatrix';
var uniformProjViewMatrix  = 'projViewMatrix';
var uniformAmbientProduct  = 'ambientProduct';
var uniformDiffuseProduct  = 'diffuseProduct';
var uniformNormalMat       = 'normalMat';
var uniformLightPosition   = 'lightPosition';
var uniformTexSampler      = 'uSampler';
var uniformBumpTexSampler  = 'nSampler';
var uniformEnableLighting  = 'enableLighting';
var uniformUniformLighting = 'uniformLighting';
var uniformEnableBumpingV   = 'enableBumpingV';
var uniformEnableBumpingF   = 'enableBumpingF';

var shapes = [];
var campRocks = [];
var fire;
var bumpCube;
var sun;

var gl;	     // WebGL object for the canvas
var canvas;  // HTML canvas element that we are drawing in
var program; // The WebGL linked program
var camera;  // Camera used for navigating the scene
var player;

var timer = new Timer();

var cutscene=false;

// Steps in for moving camera
var rotateDegree = 1;
var moveUnit = 0.125;
var mouseSensitivity = 0.1;
var dayDuration = 1000;

// Helper to set shader attributes/uniforms
var glHelper = (function() {
	var helper = {};
	function setAttrib(name, vbo) {
		var loc = gl.getAttribLocation(program, name);
		gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
		gl.enableVertexAttribArray(loc);
		gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
	}

	function setUniformMat(name, mat) {
		var loc = gl.getUniformLocation(program, name);
		gl.uniformMatrix4fv(loc, false, flatten(mat));
	}

	function setUniformVec4(name, vec) {
		var loc = gl.getUniformLocation(program, name);
		gl.uniform4fv(loc, flatten(vec));
	}

	helper.setPositionAttrib = function(vbo) {
		setAttrib(attrPosition, vbo);
	}

	helper.setNormalAttrib = function(vbo) {
		setAttrib(attrNormal, vbo);
	}

	helper.setTangentAttrib = function(vbo) {
		setAttrib(attrTangent, vbo);
	}

	helper.setTexCoordAttrib = function(vbo) {
		var loc = gl.getAttribLocation(program, attrTexCoord);
		gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
		gl.enableVertexAttribArray(loc);
		gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
	}

	helper.setNormalModelMatrix = function(mat) {
		setUniformMat(uniformNormalMat, mat);
	}

	helper.setModelMatrix = function(mat) {
		setUniformMat(uniformModelMatrix, mat);
	}

	helper.setProjViewMatrix = function(mat) {
		setUniformMat(uniformProjViewMatrix, mat);
	}

	helper.setTexSampler = function(arg) {
		var loc = gl.getUniformLocation(program, uniformTexSampler);
		gl.uniform1i(loc, arg);
	}

	helper.setBumpTexSampler = function(arg) {
		var loc = gl.getUniformLocation(program, uniformBumpTexSampler);
		gl.uniform1i(loc, arg);
	}

	helper.uniformLighting = function(arg) {
		var loc = gl.getUniformLocation(program, uniformUniformLighting);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	//enable lighting will only work as expected when the object has a texture
	//it is intended only for the fire so that it is always full lit.
	helper.enableLighting = function(arg) {
		var loc = gl.getUniformLocation(program, uniformEnableLighting);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	helper.enableBumping = function(arg) {
		var loc = gl.getUniformLocation(program, uniformEnableBumpingF);
		gl.uniform1i(loc, (arg ? 1 : 0));
		loc = gl.getUniformLocation(program, uniformEnableBumpingV);
		gl.uniform1i(loc, (arg ? 1 : 0));
	}

	helper.setAmbientProduct = function(vec) {
		setUniformVec4(uniformAmbientProduct, mult(sun.lightMaterial.ambient, vec));
	}

	helper.setDiffuseProduct = function(vec) {
		setUniformVec4(uniformDiffuseProduct, mult(sun.lightMaterial.diffuse, vec));
	}

	helper.setLightPosition = function(vec) {
		var loc = gl.getUniformLocation(program, uniformLightPosition);
		gl.uniform3fv(loc, flatten(vec));
	}

	return helper;
})();

// Init function to start GL and draw everything
window.onload = function() {
	canvas = document.getElementById(canvasId);
	gl = WebGLUtils.setupWebGL(canvas);

	if(!gl) {
		var msg = 'Unable to start WebGL!';
		alert(msg);
		throw msg;
	}

	// Compile and load the gl program
	try {
		program = initShaders(gl, vertexSourceId, fragmentSourceId);
		gl.useProgram(program);
		gl.viewport(0, 0, canvas.width, canvas.height);
	} catch(e) {
		alert(e);
		throw e;
	}

	// Initialize the player
	player = new Player(canvas, vec3(quarterSize, 0, -quarterSize+20), moveUnit);
    player.camera.yawBy(-45);
    player.camera.rollBy(-80);

	var waterMaterial = new Material(
		vec4(0.2, 0.2, 0.5, 0.8),
		vec4(0.2, 0.2, 0.7, 0.8)
	);

	var rockMaterial = new Material(
		vec4(0.9, 0.9, 0.9, 1.0),
		vec4(0.9, 0.9, 0.9, 1.0)
	);

	var water = new Cube(waterMaterial, null, true, false);
	water.position = vec3(islandSize/2, 0.0, islandSize/2);
	water.scale = vec3(islandSize*10, 0.1, islandSize*10);

    var theIsland = new Island();

	sun = new Sun(300, 1/dayDuration);

	shapes = [water, theIsland];

	for (var x=1; x<quarterSize; x+=2)
	{
        for(var z=1; z<quarterSize; z+=2)
        {
            var kXZ = 2.5 * (Math.random() + 1.5);
            var kY = 4.0 * (Math.random() * 0.3 +1.0);
            var age = Math.random();
            var rand = Math.random();
            if(heights[x][z]>0.21 && rand<=0.04 && (x < 49 || x > 51 || z < 29 || z > 31)) {
                new Tree(
                    vec3(x, heights[x][z]-0.5, z),
				    kXZ, kY,
                    age);
            }
        }
	}

	//This object is created as a test object
	var bumpMap = new Texture.fromImageSrc('./images/balls.png',gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR);
	bumpCube = new Cube(null, null, true, false, bumpMap);
	bumpCube.position = vec3(20.0, 0.8, 70.0);

	//create rocks in a circle to signify campsite
	for(var i = 0; i < 10; i++){
		campRocks.push(new CampRock(rockMaterial, new Texture.fromImageSrc('./images/rockTex.png'), gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE, gl.NEAREST, gl.NEAREST));
		campRocks[i].position = vec3(50.0 + Math.cos(i*Math.PI/5), heights[50][30] + 0.1, 30.0 + Math.sin(i*Math.PI/5));
		campRocks[i].scale = vec3(0.5, 0.5, 0.5);
		}

	fire = new Campfire(vec3(50.0, heights[50][30]+0.1, 30.0));
	fire.numSticks = 0.0;

	// Set off the draw loop
	draw();

    setTimeout(function() {
        // Attach our keyboard listener to the canvas
        cutscene=true;
    }, 2000);

    setTimeout(function() {
        // Attach our keyboard and mouse listeners to the canvas
	pointerLock(canvas, function(x, y) {
		player.camera.yawBy(-x * mouseSensitivity);
		player.camera.pitchBy(-y * mouseSensitivity);
	}, null);

	// Attach our keyboard listener to the canvas
        var playerHandleKeyDown = function(e){ return player.handleKeyDown(e); }
        var playerHandleKeyUp = function(e){ return player.handleKeyUp(e); }
        window.addEventListener('keydown', playerHandleKeyDown);
        window.addEventListener('keyup', playerHandleKeyUp);
    }, 3000);
}

// Draws the data in the vertex buffer on the canvas repeatedly
function draw() {
	var skyColor = sun.skyColor;
	gl.clearColor(skyColor[0], skyColor[1], skyColor[2], 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
	gl.enable(gl.DEPTH_TEST);

	glHelper.uniformLighting(true);
	glHelper.enableLighting(true);
	glHelper.enableBumping(false);
	player.move(); // This will set our camera in the world
	glHelper.setProjViewMatrix(player.camera.getProjViewMatrix());

	var identMat = mat4();
	var dt = timer.getElapsedTime();

	sun.draw(dt);  // This will set our light position and material
	Tree.drawTrees(dt);

	fire.draw(dt, identMat);

	shapes.forEach(function(e) {
		dt += timer.getElapsedTime();
		e.draw(dt, identMat);
	});

	campRocks.forEach(function(e) {
		dt += timer.getElapsedTime();
		e.draw(dt, identMat);
	});

//This commented cube draws a test cube that clearly shows the sucesfull
//implemintation of bump mapping
//	glHelper.enableBumping(true);
//	dt += timer.getElapsedTime();
//	bumpCube.draw(dt, identMat);
//	glHelper.enableBumping(false);

	player.draw(); // This will draw the crosshairs and arms on the screen
    if(cutscene) {
        if(player.camera.getRoll()!=0) {
            player.camera.rollBy(1);
        }
    }
	window.requestAnimFrame(draw);
}
<|endoftext|>


<commit_before>import { c, field, fieldError, selectField } from '../support/utils.js';

describe('Create event', () => {
  beforeEach(() => {
    cy.resetDb();
    cy.cachedLogin();
  });

  const uploadHeader = () => {
    // Upload file
    cy.upload_file(
      c('ImageUploadField__coverImage') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );
    cy.get('.cropper-move').click();
    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();
  };

  it('should fill required fields before being allowed to submit', () => {
    cy.visit('/events/create');
    // Check that validation errors show only after we click "OPPRETT"
    fieldError('cover').should('not.exist');
    fieldError('title').should('not.exist');
    fieldError('description').should('not.exist');
    fieldError('eventType').should('not.exist');

    cy.contains('button', 'OPPRETT').should('be.disabled');
    // click editor to initialize form and enable OPPRETT button
    cy.get('div[name="text"]').click();

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    fieldError('cover').should('be.visible');
    fieldError('title').should('be.visible');
    fieldError('description').should('be.visible');
    fieldError('eventType').should('be.visible');

    // Upload file
    uploadHeader();
    fieldError('cover').should('not.exist');

    field('title')
      .type('Testevent')
      .blur();
    fieldError('title').should('not.exist');

    field('description')
      .type('blir fett')
      .blur();
    fieldError('description').should('not.exist');

    // TODO: Make the suggestion box open if you click the label, not only when you click the input field
    selectField('eventType').click();
    /* selectField('eventType')
      .find('.Select-menu-outer')
      .should(results => {
        expect(results).to.contain('Bedriftspresentasjon');
        expect(results).to.contain('Sosialt');
        expect(results).to.contain('Annet');
      }); */
    cy.focused().type('sos', { force: true });
    /* selectField('eventType')
      .find('.Select-menu-outer')
      .should(results => {
        expect(results).to.not.contain('Bedriftspresentasjon');
        expect(results).to.contain('Sosialt');
        expect(results).to.not.contain('Annet');
      }); */
    cy.focused().type('{enter}', { force: true });
    fieldError('eventType').should('not.exist');

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');

    // Verify that created event looks good..
    cy.contains('Testevent');
    cy.contains('Sosialt');
  });

  it('should be possible to use the editor', () => {
    cy.visit('/events/create');

    // Click editor
    cy.get('div[name="text"]').click();
    // Sidebar is visible
    cy.get('.md-side-toolbar').should('be.visible');
    cy.focused().type('{enter}hello{uparrow}lol');
    // Sidebar not visible because there is text on current line
    cy.get('.md-side-toolbar').should('not.exist');

    // toolbar becomes visible only when text is selected
    cy.get('.md-editor-toolbar').should('not.be.visible');
    cy.focused().type('{selectall}');
    cy.get('.md-editor-toolbar').should('be.visible');
    cy.focused().type('test article{enter}');
    cy.get('.md-editor-toolbar').should('not.be.visible');

    // Sidebar buttons are only visible when the sidebar is opened
    cy.get('button[title="Add an Image"]').should('not.exist');
    cy.get('button[title="Show editor info"]').should('not.exist');

    // Open, close and reopen sidebar
    cy.get('.md-side-toolbar')
      .should('be.visible')
      .click();
    cy.get('.md-open-button')
      .should('be.visible')
      .click();
    cy.get('.md-open-button').should('not.exist');
    cy.get('.md-side-toolbar')
      .should('be.visible')
      .click();
    cy.get('button[title="Add an Image"]').should('be.visible');
    cy.get('button[title="Show editor info"]').should('be.visible');

    // No image in article before adding it
    cy.get('.md-block-image').should('not.exist');

    // Open file upload modal
    cy.get(c('Modal__content')).should('not.exist');
    cy.get('button[title="Add an Image"]').click();
    cy.get(c('Modal__content')).should('be.visible');

    // TODO: Upload button should be disabled when no image is uploaded
    // cy.get(c('Modal__content')).contains('Last opp').should('be.disabled');

    // Upload file
    cy.upload_file(
      c('Modal__content') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );

    // This is needed so that the crop module is activated because of how we mock upload files in these tests
    cy.get('.cropper-move').click();

    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();

    // Image is inside article
    cy.get('.md-block-image').should('be.visible');

    // navigate past image with arrow keys and add text on bottom
    cy.get('div[name="text"]').click();
    cy.focused().type('{downarrow}');
    cy.get('.md-side-toolbar').should('not.exist');
    cy.focused().type('{enter}EOF{enter}');
    cy.get('.md-side-toolbar').should('be.visible');

    // Fill rest of form
    cy.upload_file(
      c('ImageUploadField__coverImage') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );
    cy.get('.cropper-move').click();
    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();
    field('title')
      .type('Pils på Webkomkontoret!')
      .blur();
    field('description')
      .type('blir fett')
      .blur();
    cy.contains('Type arrangement')
      .find('.Select')
      .click();
    cy.focused().type('sos{enter}', { force: true });

    // Create event
    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');

    // Verify that created event looks good..
    cy.contains('Pils på Webkomkontoret!');
    cy.contains('Sosialt');
    cy.contains('test article');
    cy.get('.md-block-image').should('be.visible');
    cy.contains('EOF');
  });

  it('should be able so set the standard fields', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Standard event')
      .blur();
    field('description')
      .type('standard event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('standard event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select company
    selectField('company').click();
    cy.focused().type('BEKK', { force: true });
    selectField('company')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'BEKK');
    cy.focused().type('{enter}', { force: true });

    // Select group
    selectField('responsibleGroup').click();
    cy.focused().type('bedk', { force: true });
    selectField('responsibleGroup')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Bedkom');
    cy.focused().type('{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Standard event');
    cy.contains('Bedriftspresentasjon');
    cy.contains('BEKK');
    cy.contains('TBA');
    cy.contains('webkom webkom');
  });

  it('should be possible to create TBA event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Ubestemt event')
      .blur();
    field('description')
      .type('mer info kommer')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('mer info kommer');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('TBA{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Ubestemt event');
    cy.contains('mer info kommer');
    cy.contains('TBA');
  });

  it('should be possible to create NORMAL event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Normal event')
      .blur();
    field('description')
      .type('normal event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('normal event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Vanlig{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('R4');

    // Set the first pool
    field('pools[0].name')
      .clear()
      .type('WebkomPool')
      .blur();
    field('pools[0].capacity')
      .type('20')
      .blur();
    selectField('pools[0].permissionGroups').click();
    cy.focused().type('Webkom', { force: true });
    selectField('pools[0].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Webkom');
    cy.focused().type('{enter}', { force: true });

    // Create new pool
    cy.contains('button', 'Legg til ny pool')
      .should('not.be.disabled')
      .click();
    field('pools[1].name')
      .clear()
      .type('BedkomPool')
      .blur();
    field('pools[1].capacity')
      .type('30')
      .blur();
    selectField('pools[1].permissionGroups').click();
    cy.focused().type('Bedkom', { force: true });
    selectField('pools[1].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Bedkom');
    cy.focused().type('{enter}', { force: true });
    selectField('pools[1].permissionGroups').click();
    cy.focused().type('Abakus', { force: true });
    selectField('pools[1].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Abakus');
    cy.focused().type('{enter}', { force: true });

    field('mergeTime').click();
    cy.get(c('DatePicker__selectedDate'))
      .next()
      .click();

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('0/20');
    cy.contains('0/30');
    cy.contains('Bedriftspresentasjon');
    cy.contains('webkom webkom');
    cy.contains('WebkomPool');
    cy.contains('BedkomPool');
    cy.contains('R4');
    cy.contains('Påmelding åpner');
  });

  it('should be possible to create OPEN event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Open event')
      .blur();
    field('description')
      .type('open event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('open event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('fes{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Uten{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('Kjellern');

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Fest');
    cy.contains('Open event');
    cy.contains('Kjellern');
  });

  it('should be possible to create INFINITE event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Infinite event')
      .blur();
    field('description')
      .type('infinite event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('intifite event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('anne{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Med på{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('EL6');

    // Images
    field('useConsent').check();

    // Question
    field('feedbackRequired').check();
    field('feedbackDescription').type('Burger eller sushi');

    // Set the first pool
    field('pools[0].name')
      .clear()
      .type('Mange')
      .blur();
    selectField('pools[0].permissionGroups').click();
    cy.focused().type('Abaku', { force: true });
    selectField('pools[0].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Abakus');
    cy.focused().type('{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Annet');
    cy.contains('Mange');
    cy.contains('0/∞');
  });
});
<commit_msg>Fix bug in datepicker integration test. Select 15th of next month instead of tomorrow as date.<commit_after>import { c, field, fieldError, selectField } from '../support/utils.js';

describe('Create event', () => {
  beforeEach(() => {
    cy.resetDb();
    cy.cachedLogin();
  });

  const uploadHeader = () => {
    // Upload file
    cy.upload_file(
      c('ImageUploadField__coverImage') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );
    cy.get('.cropper-move').click();
    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();
  };

  it('should fill required fields before being allowed to submit', () => {
    cy.visit('/events/create');
    // Check that validation errors show only after we click "OPPRETT"
    fieldError('cover').should('not.exist');
    fieldError('title').should('not.exist');
    fieldError('description').should('not.exist');
    fieldError('eventType').should('not.exist');

    cy.contains('button', 'OPPRETT').should('be.disabled');
    // click editor to initialize form and enable OPPRETT button
    cy.get('div[name="text"]').click();

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    fieldError('cover').should('be.visible');
    fieldError('title').should('be.visible');
    fieldError('description').should('be.visible');
    fieldError('eventType').should('be.visible');

    // Upload file
    uploadHeader();
    fieldError('cover').should('not.exist');

    field('title')
      .type('Testevent')
      .blur();
    fieldError('title').should('not.exist');

    field('description')
      .type('blir fett')
      .blur();
    fieldError('description').should('not.exist');

    // TODO: Make the suggestion box open if you click the label, not only when you click the input field
    selectField('eventType').click();
    /* selectField('eventType')
      .find('.Select-menu-outer')
      .should(results => {
        expect(results).to.contain('Bedriftspresentasjon');
        expect(results).to.contain('Sosialt');
        expect(results).to.contain('Annet');
      }); */
    cy.focused().type('sos', { force: true });
    /* selectField('eventType')
      .find('.Select-menu-outer')
      .should(results => {
        expect(results).to.not.contain('Bedriftspresentasjon');
        expect(results).to.contain('Sosialt');
        expect(results).to.not.contain('Annet');
      }); */
    cy.focused().type('{enter}', { force: true });
    fieldError('eventType').should('not.exist');

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');

    // Verify that created event looks good..
    cy.contains('Testevent');
    cy.contains('Sosialt');
  });

  it('should be possible to use the editor', () => {
    cy.visit('/events/create');

    // Click editor
    cy.get('div[name="text"]').click();
    // Sidebar is visible
    cy.get('.md-side-toolbar').should('be.visible');
    cy.focused().type('{enter}hello{uparrow}lol');
    // Sidebar not visible because there is text on current line
    cy.get('.md-side-toolbar').should('not.exist');

    // toolbar becomes visible only when text is selected
    cy.get('.md-editor-toolbar').should('not.be.visible');
    cy.focused().type('{selectall}');
    cy.get('.md-editor-toolbar').should('be.visible');
    cy.focused().type('test article{enter}');
    cy.get('.md-editor-toolbar').should('not.be.visible');

    // Sidebar buttons are only visible when the sidebar is opened
    cy.get('button[title="Add an Image"]').should('not.exist');
    cy.get('button[title="Show editor info"]').should('not.exist');

    // Open, close and reopen sidebar
    cy.get('.md-side-toolbar')
      .should('be.visible')
      .click();
    cy.get('.md-open-button')
      .should('be.visible')
      .click();
    cy.get('.md-open-button').should('not.exist');
    cy.get('.md-side-toolbar')
      .should('be.visible')
      .click();
    cy.get('button[title="Add an Image"]').should('be.visible');
    cy.get('button[title="Show editor info"]').should('be.visible');

    // No image in article before adding it
    cy.get('.md-block-image').should('not.exist');

    // Open file upload modal
    cy.get(c('Modal__content')).should('not.exist');
    cy.get('button[title="Add an Image"]').click();
    cy.get(c('Modal__content')).should('be.visible');

    // TODO: Upload button should be disabled when no image is uploaded
    // cy.get(c('Modal__content')).contains('Last opp').should('be.disabled');

    // Upload file
    cy.upload_file(
      c('Modal__content') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );

    // This is needed so that the crop module is activated because of how we mock upload files in these tests
    cy.get('.cropper-move').click();

    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();

    // Image is inside article
    cy.get('.md-block-image').should('be.visible');

    // navigate past image with arrow keys and add text on bottom
    cy.get('div[name="text"]').click();
    cy.focused().type('{downarrow}');
    cy.get('.md-side-toolbar').should('not.exist');
    cy.focused().type('{enter}EOF{enter}');
    cy.get('.md-side-toolbar').should('be.visible');

    // Fill rest of form
    cy.upload_file(
      c('ImageUploadField__coverImage') + ' ' + c('UploadImage__dropArea'),
      'images/screenshot.png'
    );
    cy.get('.cropper-move').click();
    cy.get(c('Modal__content'))
      .contains('Last opp')
      .should('not.be.disabled')
      .click();
    field('title')
      .type('Pils på Webkomkontoret!')
      .blur();
    field('description')
      .type('blir fett')
      .blur();
    cy.contains('Type arrangement')
      .find('.Select')
      .click();
    cy.focused().type('sos{enter}', { force: true });

    // Create event
    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');

    // Verify that created event looks good..
    cy.contains('Pils på Webkomkontoret!');
    cy.contains('Sosialt');
    cy.contains('test article');
    cy.get('.md-block-image').should('be.visible');
    cy.contains('EOF');
  });

  it('should be able so set the standard fields', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Standard event')
      .blur();
    field('description')
      .type('standard event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('standard event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select company
    selectField('company').click();
    cy.focused().type('BEKK', { force: true });
    selectField('company')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'BEKK');
    cy.focused().type('{enter}', { force: true });

    // Select group
    selectField('responsibleGroup').click();
    cy.focused().type('bedk', { force: true });
    selectField('responsibleGroup')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Bedkom');
    cy.focused().type('{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Standard event');
    cy.contains('Bedriftspresentasjon');
    cy.contains('BEKK');
    cy.contains('TBA');
    cy.contains('webkom webkom');
  });

  it('should be possible to create TBA event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Ubestemt event')
      .blur();
    field('description')
      .type('mer info kommer')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('mer info kommer');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('TBA{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Ubestemt event');
    cy.contains('mer info kommer');
    cy.contains('TBA');
  });

  it('should be possible to create NORMAL event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Normal event')
      .blur();
    field('description')
      .type('normal event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('normal event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('be{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Vanlig{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('R4');

    // Set the first pool
    field('pools[0].name')
      .clear()
      .type('WebkomPool')
      .blur();
    field('pools[0].capacity')
      .type('20')
      .blur();
    selectField('pools[0].permissionGroups').click();
    cy.focused().type('Webkom', { force: true });
    selectField('pools[0].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Webkom');
    cy.focused().type('{enter}', { force: true });

    // Create new pool
    cy.contains('button', 'Legg til ny pool')
      .should('not.be.disabled')
      .click();
    field('pools[1].name')
      .clear()
      .type('BedkomPool')
      .blur();
    field('pools[1].capacity')
      .type('30')
      .blur();
    selectField('pools[1].permissionGroups').click();
    cy.focused().type('Bedkom', { force: true });
    selectField('pools[1].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Bedkom');
    cy.focused().type('{enter}', { force: true });
    selectField('pools[1].permissionGroups').click();
    cy.focused().type('Abakus', { force: true });
    selectField('pools[1].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Abakus');
    cy.focused().type('{enter}', { force: true });

    field('mergeTime').click();
    cy.get(c('DatePicker__header'))
      .find('button:last-child')
      .click();
    cy.contains(c('DatePicker__calendarItem'), '15').click();

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('0/20');
    cy.contains('0/30');
    cy.contains('Bedriftspresentasjon');
    cy.contains('webkom webkom');
    cy.contains('WebkomPool');
    cy.contains('BedkomPool');
    cy.contains('R4');
    cy.contains('Påmelding åpner');
  });

  it('should be possible to create OPEN event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Open event')
      .blur();
    field('description')
      .type('open event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('open event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('fes{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Uten{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('Kjellern');

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Fest');
    cy.contains('Open event');
    cy.contains('Kjellern');
  });

  it('should be possible to create INFINITE event', () => {
    cy.visit('/events/create');
    uploadHeader();

    // Set title, description and text
    field('title')
      .type('Infinite event')
      .blur();
    field('description')
      .type('infinite event')
      .blur();
    cy.get('div[name="text"]').click();
    cy.focused().type('intifite event');

    // Select type
    selectField('eventType').click();
    cy.focused().type('anne{enter}', { force: true });

    // Select regitrationType
    selectField('eventStatusType').click();
    cy.focused().type('Med på{enter}', { force: true });

    // Set location
    cy.contains('Sted').click();
    cy.focused().type('EL6');

    // Images
    field('useConsent').check();

    // Question
    field('feedbackRequired').check();
    field('feedbackDescription').type('Burger eller sushi');

    // Set the first pool
    field('pools[0].name')
      .clear()
      .type('Mange')
      .blur();
    selectField('pools[0].permissionGroups').click();
    cy.focused().type('Abaku', { force: true });
    selectField('pools[0].permissionGroups')
      .find('.Select-menu-outer')
      .should('not.contain', 'No results')
      .and('contain', 'Abakus');
    cy.focused().type('{enter}', { force: true });

    cy.contains('button', 'OPPRETT')
      .should('not.be.disabled')
      .click();

    // Verify that created event looks good..
    cy.url().should('not.contain', '/events/create');
    cy.url().should('contain', '/events/');
    cy.contains('Annet');
    cy.contains('Mange');
    cy.contains('0/∞');
  });
});
<|endoftext|>