<commit_before>// story.js(StoryModule)
var StoryModule = (function() {

  // Variables for the module
  var story;
  var bookmark;
  var saveObject;

  // Load the story
  var getStory = function() {
    $.getJSON('story.json', function(data) {
      story = data;
      mediator.publish('story_num_levels', getNumLevels());
      mediator.publish('story_story_loaded');
    });
  }

  // Gets the total number of levels in the story
  var getNumLevels = function() {
    var c = 0;
    for(var i=0;i<story.length;++i) {
      if(story[i].type == 'level') {
        ++c;
      }
    }
    return c;
  }

  // Set the bookmark of the current level
  var setBookmark = function(val) {
    bookmark = val;

    //Render it, and save it if it's a playable item
    if(story[bookmark].type == 'instruction') {
      mediator.publish('overlay_render', story[bookmark]);
      saveObject.visited_instructions.push(bookmark);
      mediator.publish('cookie_data_save', saveObject);
    }
    else {
      mediator.publish('board_render', story[bookmark]);
      saveObject.level = story[bookmark].number;
      mediator.publish('cookie_data_save', saveObject);
    }
  }

  // Advances the story
  var advance = function() {
    if(bookmark < story.length - 1) {
      // Passes all the previously visited instruction pages
      while(visited(++bookmark)) { }
      setBookmark(bookmark);
    }
  }

  // Returns whether or not the instruction screen at the bookmark has
  // previously been visited
  var visited = function(bookmarkNo) {
    return (saveObject.visited_instructions.indexOf(bookmarkNo) >= 0);
  }

  // Sets the bookmark to the given point
  var setBookmarkAtLevel = function(so) {
    saveObject = so;
    if(saveObject.level < 0) {
      setBookmark(0);
      return;
    }

    for(var i=0;i<story.length;++i) {
      if(story[i].number == saveObject.level) {
        setBookmark(i);
        return;
      }
    }
  }

  // The publicly visible methods are available by this facade
  return {
    getStory: getStory,
    setBookmark: setBookmark,
    setBookmarkAtLevel: setBookmarkAtLevel,
    advance: advance
  }
}())

// Add the mediator to the module
mediator.installTo(StoryModule);

// Subscribe to messages

// Get the story, advance it, and set the bookmark when told
mediator.subscribe('story_get_story', StoryModule.getStory);
mediator.subscribe('story_set_bookmark_at_level',
  StoryModule.setBookmarkAtLevel);
mediator.subscribe('story_advance', StoryModule.advance);

// Advance the story when notified that the current level has been completed
mediator.subscribe('board_level_complete', StoryModule.advance);<commit_msg>fixed code so end screen shows<commit_after>// story.js(StoryModule)
var StoryModule = (function() {

  // Variables for the module
  var story;
  var bookmark;
  var saveObject;

  // Load the story
  var getStory = function() {
    $.getJSON('story.json', function(data) {
      story = data;
      mediator.publish('story_num_levels', getNumLevels());
      mediator.publish('story_story_loaded');
    });
  }

  // Gets the total number of levels in the story
  var getNumLevels = function() {
    var c = 0;
    for(var i=0;i<story.length;++i) {
      if(story[i].type == 'level') {
        ++c;
      }
    }
    return c;
  }

  // Set the bookmark of the current level
  var setBookmark = function(val) {
    bookmark = val;

    //Render it, and save it if it's a playable item
    if(story[bookmark].type == 'instruction') {
      mediator.publish('overlay_render', story[bookmark]);
      saveObject.visited_instructions.push(bookmark);
      mediator.publish('cookie_data_save', saveObject);
    }
    else {
      mediator.publish('board_render', story[bookmark]);
      saveObject.level = story[bookmark].number;
      mediator.publish('cookie_data_save', saveObject);
    }
  }

  // Advances the story
  var advance = function() {
    if(bookmark < story.length - 1) {
      // Passes all the previously visited instruction pages
      while(visited(++bookmark) && bookmark != story.length - 1) { }
      setBookmark(bookmark);
    }
  }

  // Returns whether or not the instruction screen at the bookmark has
  // previously been visited
  var visited = function(bookmarkNo) {
    return (saveObject.visited_instructions.indexOf(bookmarkNo) >= 0);
  }

  // Sets the bookmark to the given point
  var setBookmarkAtLevel = function(so) {
    saveObject = so;
    if(saveObject.level < 0) {
      setBookmark(0);
      return;
    }

    for(var i=0;i<story.length;++i) {
      if(story[i].number == saveObject.level) {
        setBookmark(i);
        return;
      }
    }
  }

  // The publicly visible methods are available by this facade
  return {
    getStory: getStory,
    setBookmark: setBookmark,
    setBookmarkAtLevel: setBookmarkAtLevel,
    advance: advance
  }
}())

// Add the mediator to the module
mediator.installTo(StoryModule);

// Subscribe to messages

// Get the story, advance it, and set the bookmark when told
mediator.subscribe('story_get_story', StoryModule.getStory);
mediator.subscribe('story_set_bookmark_at_level',
  StoryModule.setBookmarkAtLevel);
mediator.subscribe('story_advance', StoryModule.advance);

// Advance the story when notified that the current level has been completed
mediator.subscribe('board_level_complete', StoryModule.advance);<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  Text,
  View,
  TouchableOpacity,
} from 'react-native';

import {
  Icon,
  Row,
  Image,
  Tile,
  Title,
  Divider,
  Subtitle,
  ListView,
  TextInput
} from '@shoutem/ui';

import SearchResult from './SearchResult';
import RouteDetail from './RouteDetail';

import SearchBar from 'react-native-searchbar';

const items = [
{
  "title": "Street art",
  "subtitle": "A walk by the best graffiti spots of Lyon",
  "image": { "url": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTdTw0nPNXmis_5a0QZ1Hd3VhK2hPQYUDOALjqL70982qq2B-_N" }
},
{
  "title": "History",
  "subtitle": "See all the important historical sites of Lyon",
  "image": { "url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmypAfm3oVWNHtZ1GcRhpo6uu8psEn_pcrvApQGQ2jnjUT2NVA" }
},
{
  "title": "By the Rhone",
  "subtitle": "Refreshing walk next to the river",
  "image": { "url": "https://bonjourparis.com/wp-content/uploads/2015/05/cotes-du-rhone-nord.jmarnaud.flkr_.jpg" }
},
{
  "title": "INSA Campus",
  "subtitle": "See the campus area of INSA in its greatness",
  "image": { "url": "https://i.ytimg.com/vi/EvA2H9zf0Ls/maxresdefault.jpg" }
}
];

const tags = [
  {
    "name": "dsoksko",
  },
  {
    "name": "asasa",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  }
];

export default class SearchContainer extends Component {

  constructor(props) {
    super(props);
    this.state = {
      text: '',
      results: [],
      items,
      tags,
    };
    this._renderRow = this._renderRow.bind(this);
  }

  _renderRow(tags) {
    return (
      <TouchableOpacity
        onPress={()=>this.rowPressed(tags.name)}>

        <View>
          <Row>
            <Icon name="search"/>
            <Text>
              {tags.name}
            </Text>
          </Row>
        </View>
      </TouchableOpacity>
    );
  }

  rowPressed(name) {
      //this push sends all props in passProps to the view SearchResult
      this.props.navigator.push({
        title: 'Results',
        name: 'SearchResult',
        component: SearchResult,
        passProps: {text: name}
      });
  }

  onSubmitEditing(event){
    var textSearch = this.state.text;
    //this push sends all props in passProps to the view SearchResult
    this.props.navigator.push({
      title: 'Results',
      name: 'SearchResult',
      component: SearchResult,
      passProps: {text: this.state.text}
    });
  }

  render() {
    return (
      <View style={{marginTop: 50}}>
        <View style={{flexDirection: 'row', margin:25, height:25}}>
          <Icon name="search" style={{marginTop: 3}}/>
          <TextInput
              style={{flex: 1, height: 35, fontSize: 15, paddingBottom: 5}}
              ref= {(el) => { this.text = el; }}
              onChangeText={(text) => this.setState({text})}
              onSubmitEditing={this.onSubmitEditing.bind(this)}
              value={this.state.text}
          />
        </View>
        <View>
          <ListView
            data={tags}
            renderRow={this._renderRow}
          />

        </View>

      </View>
    );
  }
}
<commit_msg>Update to master commit<commit_after>import React, { Component } from 'react';
import {
  Text,
  View,
  TouchableOpacity,
} from 'react-native';

import {
  Icon,
  Row,
  Image,
  Tile,
  Title,
  Divider,
  Subtitle,
  ListView,
  TextInput
} from '@shoutem/ui';

import SearchResult from './SearchResult';
import RouteDetail from './RouteDetail';

import SearchBar from 'react-native-searchbar';

const items = [
{
  "title": "Street art",
  "subtitle": "A walk by the best graffiti spots of Lyon",
  "image": { "url": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTdTw0nPNXmis_5a0QZ1Hd3VhK2hPQYUDOALjqL70982qq2B-_N" }
},
{
  "title": "History",
  "subtitle": "See all the important historical sites of Lyon",
  "image": { "url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQmypAfm3oVWNHtZ1GcRhpo6uu8psEn_pcrvApQGQ2jnjUT2NVA" }
},
{
  "title": "By the Rhone",
  "subtitle": "Refreshing walk next to the river",
  "image": { "url": "https://bonjourparis.com/wp-content/uploads/2015/05/cotes-du-rhone-nord.jmarnaud.flkr_.jpg" }
},
{
  "title": "INSA Campus",
  "subtitle": "See the campus area of INSA in its greatness",
  "image": { "url": "https://i.ytimg.com/vi/EvA2H9zf0Ls/maxresdefault.jpg" }
}
];

const tags = [
  {
    "name": "dsoksko",
  },
  {
    "name": "asasa",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  },
  {
    "name": "dsoksko",
  }
];

export default class SearchContainer extends Component {

  constructor(props) {
    super(props);
    this.state = {
      text: '',
      results: [],
      items,
      tags,
    };
    this._renderRow = this._renderRow.bind(this);
  }

  _renderRow(tags) {
    return (
      <TouchableOpacity
        onPress={()=>this.rowPressed(tags.name)}>

        <View>
          <Row>
            <Icon name="search"/>
            <Text>
              {tags.name}
            </Text>
          </Row>
        </View>
      </TouchableOpacity>
    );
  }

  rowPressed(name) {
      //this push sends all props in passProps to the view SearchResult
      this.props.navigator.push({
        title: 'Results',
        name: 'SearchResult',
        component: SearchResult,
        passProps: {text: name}
      });
  }

  onSubmitEditing(event){
    var textSearch = this.state.text;
    //this push sends all props in passProps to the view SearchResult
    this.props.navigator.push({
      title: 'Results',
      name: 'SearchResult',
      component: SearchResult,
      passProps: {text: this.state.text}
    });
  }

  render() {
    return (
      <View style={{marginTop: 50}}>
      <View style={{marginBottom:5, marginTop: 15, height:35, borderColor: '#E0E0E0', backgroundColor: '#E0E0E0', borderWidth: 1, borderRadius: 5, flexDirection: 'row'}}>
        <Icon
          style={{height:32, color:'gray', paddingLeft:5, paddingTop:2}}
          name="search" />
        <TextInput
          returnKeyType = "search"
          underlineColorAndroid='transparent'
          style={{flex: 1, height: 30, fontSize: 15, paddingBottom: 5}}
          placeholder="Rechercher"
          value={this.state.text}
          onChangeText={(text) => this.setState({text})}
          onSubmitEditing={this.onSubmitEditing.bind(this)}

        />
      </View>
        <View>
          <ListView
            data={tags}
            renderRow={this._renderRow}
          />

        </View>

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


<commit_before>// app/actions/HistoryActionCreators.js

import {
	EDIT_HISTORY_SET,
	END_EDIT_HISTORY_SET,
	UPDATE_HISTORY_FILTER,
} from '../ActionTypes';

import { GoogleSignin } from 'react-native-google-signin';
import config from '../config.json';

export const editHistorySet = (setID) => ({ type: EDIT_HISTORY_SET, setID: setID });

export const endEditHistorySet = () => ({ type: END_EDIT_HISTORY_SET });

export const showRemovedData = () => ({ type: UPDATE_HISTORY_FILTER, showRemoved: true });

export const hideRemovedData = () => ({ type: UPDATE_HISTORY_FILTER, showRemoved: false });

export const exportHistoryCSV = () => (dispatch, getState) => {
	GoogleSignin.hasPlayServices({ autoResolve: true }).then(() => {
		GoogleSignin.configure({
				scopes: ["https://www.googleapis.com/auth/drive"],
				iosClientId: config.iOSGoogleClientID,
				webClientId: config.webGoogleClientID
		}).then(() => {
			GoogleSignin.currentUserAsync().then((user) => {
				console.log('USER', user);
				console.log('access token: ' + user.accessToken);
			}).catch((err) => {
				// according to the docs, this should be impossible to reach
				console.log("EXPORT HISTORY CURRENT USER ERROR " + err);
			}).done();
		}).catch((err) => {
			// according to the docs, this should be impossible to reach
			console.log("EXPORT HISTORY CONFIGURE ERROR " + err);
		})
	}).catch((err) => {
		// according to the docs, this should be impossible to reach
		console.log("EXPORT HISTORY PLAY SERVICES ERROR " + err);
	}).done();

};
<commit_msg>tweaked the christmas tree esque structure of the promise for export csv<commit_after>// app/actions/HistoryActionCreators.js

import {
	EDIT_HISTORY_SET,
	END_EDIT_HISTORY_SET,
	UPDATE_HISTORY_FILTER,
} from '../ActionTypes';

import { GoogleSignin } from 'react-native-google-signin';
import config from '../config.json';

export const editHistorySet = (setID) => ({ type: EDIT_HISTORY_SET, setID: setID });

export const endEditHistorySet = () => ({ type: END_EDIT_HISTORY_SET });

export const showRemovedData = () => ({ type: UPDATE_HISTORY_FILTER, showRemoved: true });

export const hideRemovedData = () => ({ type: UPDATE_HISTORY_FILTER, showRemoved: false });

export const exportHistoryCSV = () => (dispatch, getState) => {
	GoogleSignin.hasPlayServices({ autoResolve: true })
	.then(GoogleSignin.configure({
		scopes: ["https://www.googleapis.com/auth/drive"],
		iosClientId: config.iOSGoogleClientID,
		webClientId: config.webGoogleClientID
	}))
	.then(GoogleSignin.currentUserAsync().then((user) => {
		console.log('USER', user);
		console.log('access token: ' + user.accessToken);
	}))
	.catch((err) => {
		console.log("EXPORT HISTORY ERROR " + err);
	})
	.done();
};
<|endoftext|>


<commit_before>/*
Copyright 2019 New Vector Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';
import React from "react";
import dis from "../../../dispatcher";
import MatrixClientPeg from "../../../MatrixClientPeg";
import AccessibleButton from '../elements/AccessibleButton';
import RoomAvatar from '../avatars/RoomAvatar';
import classNames from 'classnames';

const MAX_ROOMS = 20;

export default class RoomBreadcrumbs extends React.Component {
    constructor(props) {
        super(props);
        this.state = {rooms: []};
        this.onAction = this.onAction.bind(this);
        this._previousRoomId = null;
        this._dispatcherRef = null;
    }

    componentWillMount() {
        this._dispatcherRef = dis.register(this.onAction);
    }

    componentWillUnmount() {
        dis.unregister(this._dispatcherRef);
    }

    componentDidUpdate() {
        const rooms = this.state.rooms.slice();
        if (rooms.length) {
            const {room, animated} = rooms[0];
            if (!animated) {
                rooms[0] = {room, animated: true};
                setTimeout(() => this.setState({rooms}), 0);
            }
        }
    }

    onAction(payload) {
        switch (payload.action) {
            case 'view_room':
                if (this._previousRoomId) {
                    this._appendRoomId(this._previousRoomId);
                }
                this._previousRoomId = payload.room_id;
        }
    }

    _appendRoomId(roomId) {
        const room = MatrixClientPeg.get().getRoom(roomId);
        if (!room) {
            return;
        }
        const rooms = this.state.rooms.slice();
        const existingIdx = rooms.findIndex((r) => r.room.roomId === room.roomId);
        if (existingIdx !== -1) {
            rooms.splice(existingIdx, 1);
        }
        rooms.splice(0, 0, {room, animated: false});
        if (rooms.length > MAX_ROOMS) {
            rooms.splice(MAX_ROOMS, rooms.length - MAX_ROOMS);
        }
        this.setState({rooms});
    }

    _viewRoom(room) {
        dis.dispatch({action: "view_room", room_id: room.roomId});
    }

    render() {
        // check for collapsed here and
        // not at parent so we keep
        // rooms in our state
        // when collapsing and expanding
        if (this.props.collapsed) {
            return null;
        }
        const rooms = this.state.rooms;
        const avatars = rooms.map(({room, animated}, i) => {
            const isFirst = i === 0;
            const classes = classNames({
                "mx_RoomBreadcrumbs_preAnimate": isFirst && !animated,
                "mx_RoomBreadcrumbs_animate": isFirst,
            });
            return (
                <AccessibleButton className={classes} key={room.roomId} title={room.name} onClick={() => this._viewRoom(room)}>
                    <RoomAvatar room={room} width={32} height={32} />
                </AccessibleButton>
            );
        });
        return (
{ avatars }
);
    }
}
<commit_msg>Use custom tooltips on breadcrumb icons<commit_after>/*
Copyright 2019 New Vector Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';
import React from "react";
import dis from "../../../dispatcher";
import MatrixClientPeg from "../../../MatrixClientPeg";
import AccessibleButton from '../elements/AccessibleButton';
import RoomAvatar from '../avatars/RoomAvatar';
import classNames from 'classnames';
import sdk from "../../../index";

const MAX_ROOMS = 20;

export default class RoomBreadcrumbs extends React.Component {
    constructor(props) {
        super(props);
        this.state = {rooms: []};
        this.onAction = this.onAction.bind(this);
        this._previousRoomId = null;
        this._dispatcherRef = null;
    }

    componentWillMount() {
        this._dispatcherRef = dis.register(this.onAction);
    }

    componentWillUnmount() {
        dis.unregister(this._dispatcherRef);
    }

    componentDidUpdate() {
        const rooms = this.state.rooms.slice();
        if (rooms.length) {
            const {room, animated} = rooms[0];
            if (!animated) {
                rooms[0] = {room, animated: true};
                setTimeout(() => this.setState({rooms}), 0);
            }
        }
    }

    onAction(payload) {
        switch (payload.action) {
            case 'view_room':
                if (this._previousRoomId) {
                    this._appendRoomId(this._previousRoomId);
                }
                this._previousRoomId = payload.room_id;
        }
    }

    _appendRoomId(roomId) {
        const room = MatrixClientPeg.get().getRoom(roomId);
        if (!room) {
            return;
        }
        const rooms = this.state.rooms.slice();
        const existingIdx = rooms.findIndex((r) => r.room.roomId === room.roomId);
        if (existingIdx !== -1) {
            rooms.splice(existingIdx, 1);
        }
        rooms.splice(0, 0, {room, animated: false});
        if (rooms.length > MAX_ROOMS) {
            rooms.splice(MAX_ROOMS, rooms.length - MAX_ROOMS);
        }
        this.setState({rooms});
    }

    _viewRoom(room) {
        dis.dispatch({action: "view_room", room_id: room.roomId});
    }

    _onMouseEnter(room) {
        this._onHover(room);
    }

    _onMouseLeave(room) {
        this._onHover(null); // clear hover states
    }

    _onHover(room) {
        const rooms = this.state.rooms.slice();
        for (const r of rooms) {
            r.hover = room && r.room.roomId === room.roomId;
        }
        this.setState({rooms});
    }

    render() {
        const Tooltip = sdk.getComponent('elements.Tooltip');
        // check for collapsed here and
        // not at parent so we keep
        // rooms in our state
        // when collapsing and expanding
        if (this.props.collapsed) {
            return null;
        }
        const rooms = this.state.rooms;
        const avatars = rooms.map(({room, animated, hover}, i) => {
            const isFirst = i === 0;
            const classes = classNames({
                "mx_RoomBreadcrumbs_preAnimate": isFirst && !animated,
                "mx_RoomBreadcrumbs_animate": isFirst,
            });

            let tooltip = null;
            if (hover) {
                tooltip = <Tooltip label={room.name} />;
            }

            return (
                <AccessibleButton className={classes} key={room.roomId} onClick={() => this._viewRoom(room)}
                    onMouseEnter={() => this._onMouseEnter(room)} onMouseLeave={() => this._onMouseLeave(room)}>
                    <RoomAvatar room={room} width={32} height={32} />
                    {tooltip}
                </AccessibleButton>
            );
        });
        return (
{ avatars }
);
    }
}
<|endoftext|>


<commit_before>MLS.miniCart = {
    started : false,

	callbacks :
	{
		addItem: function(e)
		{
			MLS.miniCart.addItem($jQ(e.target).parents("form").serialize());
        	return false;
        },

        removeItem: function(e)
		{
            if ($jQ(this).hasClass("data-confirm-removal"))
            {
                MLS.miniCart.confirmItemRemoval($jQ(this));
            }
			else
            {
                MLS.miniCart.removeItem($jQ(this).is("a") ? $jQ(this).attr("href").split("?")[1] : $jQ(e.target).parents("form").serialize());
            }

            return false;
        },

        updateItemSuccess : function (data) {
            if (data.hasOwnProperty('error') && data.error.responseHTML != "") {
	    	    // error, unable to add to cart
	            // display error response: .append(data.error.responseHTML);
	            return MLS.modal.open(data.error ? data.error.responseHTML : null);
	        }

            var $tabs = $jQ('#nav-cart, .mini-cart'),
                $form = $jQ('#minicart-form');

            $tabs.removeClass("empty").addClass(((MLS.miniCart.started && $jQ("#nav-cart").is(":visible"))? 'active' : '') + ((data.success.itemCount == 0) ? " empty" : ""));

            MLS.miniCart.started = true;

            // response needs to contain both elements and updated total
            $jQ("#nav-cart .count").html(data.success.itemCount);
            MLS.miniCart.init($form.hide().html(data.success.responseHTML));

            // initialize scroll buttons on the mini-cart
            if (data.success.itemCount > 0 && data.success.itemCount < 4 ) {
                $jQ('.minicart-next').hide();
            } else if (inMini > 3) {
                $jQ('.minicart-next').addClass('on');
            }

            if (MLS.miniCart.started && $jQ("#nav-cart").is(":visible"))
            {
                $form.fadeIn();
            }
	    },

        scrollPrevious: function(e){
            e.preventDefault();
            var type = "next";
            MLS.miniCart.callbacks.scroll(type);
        },

        scrollNext: function(e){
            e.preventDefault();
            var type = "prev";
            MLS.miniCart.callbacks.scroll(type);
        },

        scroll: function(type) { // MINICART  scroll minicart items .............................................................
            if (type == "next") { // if scroll up, calculate max scroll up
                var inMini = $jQ('#minicart-item-list').find('.minicart-item').length;
                var maxScrollTimes = inMini / 3;
                var maxScrollInt = parseInt(maxScrollTimes, 10);
                var maxScrollPos = maxScrollInt * -247;

                // get current position
                var curPos = $jQ('.minicart-item.one').attr('data-vpos');

                //calculate new offset before actually moving
                var newPos = curPos - 247;

                // check position, move and adjust options as required
                if (newPos > maxScrollPos) { // if beginning/middle
                    $jQ('.minicart-item').each(function(){ // move up
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.prev-items-link').addClass('on'); //turn on prev
                    $jQ('.next-items-link').removeClass('off'); //turn on next if needed

                } else if (newPos == maxScrollPos) { // if end
                    $jQ('.minicart-item').each(function(){ // move up
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.next-items-link').addClass('off'); //turn off next
                }

            } else { // if scroll down
                // get current position
                var curPos = $jQ('.minicart-item.one').attr('data-vpos');
                var curPosParse = parseInt(curPos, 10);

                //calculate new offset before actually moving
                var newPos = curPosParse + 247;

                // check position, move and adjust options as required
                if (newPos == 0) { // if beginning/middle
                    $jQ('.minicart-item').each(function(){ //move down
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.prev-items-link').removeClass('on'); //turn off prev
                    $jQ('.next-items-link').removeClass('off'); //turn on next

                } else { // if end
                    $jQ('.minicart-item').each(function(){ //move down
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.next-items-link').removeClass('off'); //turn on next
                }
            }
        },
	},

    options: {

    },

	init : function (d, opts)
	{
        var $d = $jQ(d || document);

        this.options = $jQ.extend({
            getCartEndpoint: MLS.ajax.endpoints.GET_MINICART,
            addToCartEndpoint: MLS.ajax.endpoints.ADD_TO_MINICART,
            updateCartEndpoint: MLS.ajax.endpoints.UPDATE_CART,
            removeFromCartEndpoint: MLS.ajax.endpoints.REMOVE_FROM_MINICART,
            successCallback: MLS.miniCart.callbacks.updateItemSuccess
        }, opts);

		$d.find('.data-cart-add').bind('click', this.callbacks.addItem);
        $d.find('.data-cart-remove').bind('click', this.callbacks.removeItem);

        // free shipping modal
        $d.find('.minicart-banner.ship').find('.minicart-cta').click(function() {
            $jQ('#minicart-shipping-modal').show();
        });

        // next 3 items
        $d.find('.prev-items-link').click(this.callbacks.scrollPrevious);
        $d.find('.next-items-link').click(this.callbacks.scrollNext);

        !this.started && this.update();
    },

    // previously called 'minicartEdit'
    confirmItemRemoval : function($btn) {
        var $block = $btn.parents('.minicart-item'),
            $editBox = $btn.parents('.minicart-edit'),
            removeCallback = function() {
                MLS.miniCart.removeItem($jQ(this).attr("href").split("?")[1]);
            };

        $block.css('background-color' , '#d6d9d9');
        $editBox.css('width', '120px').find('.edit').html('Cancel');
        $jQ('
Are you sure you want to remove this item?
').appendTo($block.find('.item-info-block'));
        $btn.addClass('yes-remove').click(removeCallback);

        $editBox.find('.minicart-cancel-remove').click(function(e) { // cancel remove
            e.preventDefault();
            $block.removeAttr("style").find('.remove-msg').remove();
            $editBox.css('width', '96px').find('.edit').html('Edit');
            $btn.removeClass('.yes-remove').removeClass('yes-remove').unbind('click', removeCallback);

            // avoid memory leak
            removeCallback = $block = $editBox = null;
        });
    },

    finalize: function()
    {
    	$jQ('[data-cart-add]').unbind('click', this.callbacks.addItem);
    	$jQ('[data-cart-remove]').unbind('click', this.callbacks.removeItem);
        $jQ('.next-items-link').unbind('click', this.callbacks.scrollUp);
        $jQ('.prev-items-link').unbind('click', this.callbacks.scrollNext);
    },

    update : function (params) {
        MLS.ajax.sendRequest(
            this.options.getCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    addItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.addToCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    updateItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.updateCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    removeItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.removeFromCartEndpoint,
            params,
            this.options.successCallback
        );
    }
};<commit_msg>layout update for mini-cart "checkout" button<commit_after>MLS.miniCart = {
    started : false,

	callbacks :
	{
		addItem: function(e)
		{
			MLS.miniCart.addItem($jQ(e.target).parents("form").serialize());
        	return false;
        },

        removeItem: function(e)
		{
            if ($jQ(this).hasClass("data-confirm-removal"))
            {
                MLS.miniCart.confirmItemRemoval($jQ(this));
            }
			else
            {
                MLS.miniCart.removeItem($jQ(this).is("a") ? $jQ(this).attr("href").split("?")[1] : $jQ(e.target).parents("form").serialize());
            }

            return false;
        },

        updateItemSuccess : function (data) {
            if (data.hasOwnProperty('error') && data.error.responseHTML != "") {
	    	    // error, unable to add to cart
	            // display error response: .append(data.error.responseHTML);
	            return MLS.modal.open(data.error ? data.error.responseHTML : null);
	        }

            var $tabs = $jQ('#nav-cart, .mini-cart'),
                $form = $jQ('#minicart-form');

            $tabs.removeClass("empty").addClass(((MLS.miniCart.started && $jQ("#nav-cart").is(":visible"))? 'active' : '') + ((data.success.itemCount == 0) ? " empty" : ""));

            MLS.miniCart.started = true;

            // response needs to contain both elements and updated total
            $jQ("#nav-cart .count").html(data.success.itemCount);
            MLS.miniCart.init($form.hide().html(data.success.responseHTML));
            $form.find("input:submit").uniform();

            // initialize scroll buttons on the mini-cart
            if (data.success.itemCount > 0 && data.success.itemCount < 4 ) {
                $jQ('.minicart-next').hide();
            } else if (inMini > 3) {
                $jQ('.minicart-next').addClass('on');
            }

            if (MLS.miniCart.started && $jQ("#nav-cart").is(":visible"))
            {
                $form.fadeIn();
            }
	    },

        scrollPrevious: function(e){
            e.preventDefault();
            var type = "next";
            MLS.miniCart.callbacks.scroll(type);
        },

        scrollNext: function(e){
            e.preventDefault();
            var type = "prev";
            MLS.miniCart.callbacks.scroll(type);
        },

        scroll: function(type) { // MINICART  scroll minicart items .............................................................
            if (type == "next") { // if scroll up, calculate max scroll up
                var inMini = $jQ('#minicart-item-list').find('.minicart-item').length;
                var maxScrollTimes = inMini / 3;
                var maxScrollInt = parseInt(maxScrollTimes, 10);
                var maxScrollPos = maxScrollInt * -247;

                // get current position
                var curPos = $jQ('.minicart-item.one').attr('data-vpos');

                //calculate new offset before actually moving
                var newPos = curPos - 247;

                // check position, move and adjust options as required
                if (newPos > maxScrollPos) { // if beginning/middle
                    $jQ('.minicart-item').each(function(){ // move up
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.prev-items-link').addClass('on'); //turn on prev
                    $jQ('.next-items-link').removeClass('off'); //turn on next if needed

                } else if (newPos == maxScrollPos) { // if end
                    $jQ('.minicart-item').each(function(){ // move up
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.next-items-link').addClass('off'); //turn off next
                }

            } else { // if scroll down
                // get current position
                var curPos = $jQ('.minicart-item.one').attr('data-vpos');
                var curPosParse = parseInt(curPos, 10);

                //calculate new offset before actually moving
                var newPos = curPosParse + 247;

                // check position, move and adjust options as required
                if (newPos == 0) { // if beginning/middle
                    $jQ('.minicart-item').each(function(){ //move down
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.prev-items-link').removeClass('on'); //turn off prev
                    $jQ('.next-items-link').removeClass('off'); //turn on next

                } else { // if end
                    $jQ('.minicart-item').each(function(){ //move down
                        MLS.ui.vScroll(this, newPos);
                    });
                    $jQ('.next-items-link').removeClass('off'); //turn on next
                }
            }
        },
	},

    options: {

    },

	init : function (d, opts)
	{
        var $d = $jQ(d || document);

        this.options = $jQ.extend({
            getCartEndpoint: MLS.ajax.endpoints.GET_MINICART,
            addToCartEndpoint: MLS.ajax.endpoints.ADD_TO_MINICART,
            updateCartEndpoint: MLS.ajax.endpoints.UPDATE_CART,
            removeFromCartEndpoint: MLS.ajax.endpoints.REMOVE_FROM_MINICART,
            successCallback: MLS.miniCart.callbacks.updateItemSuccess
        }, opts);

		$d.find('.data-cart-add').bind('click', this.callbacks.addItem);
        $d.find('.data-cart-remove').bind('click', this.callbacks.removeItem);

        // free shipping modal
        $d.find('.minicart-banner.ship').find('.minicart-cta').click(function() {
            $jQ('#minicart-shipping-modal').show();
        });

        // next 3 items
        $d.find('.prev-items-link').click(this.callbacks.scrollPrevious);
        $d.find('.next-items-link').click(this.callbacks.scrollNext);

        !this.started && this.update();
    },

    // previously called 'minicartEdit'
    confirmItemRemoval : function($btn) {
        var $block = $btn.parents('.minicart-item'),
            $editBox = $btn.parents('.minicart-edit'),
            removeCallback = function() {
                MLS.miniCart.removeItem($jQ(this).attr("href").split("?")[1]);
            };

        $block.css('background-color' , '#d6d9d9');
        $editBox.css('width', '120px').find('.edit').html('Cancel');
        $jQ('
Are you sure you want to remove this item?
').appendTo($block.find('.item-info-block'));
        $btn.addClass('yes-remove').click(removeCallback);

        $editBox.find('.minicart-cancel-remove').click(function(e) { // cancel remove
            e.preventDefault();
            $block.removeAttr("style").find('.remove-msg').remove();
            $editBox.css('width', '96px').find('.edit').html('Edit');
            $btn.removeClass('.yes-remove').removeClass('yes-remove').unbind('click', removeCallback);

            // avoid memory leak
            removeCallback = $block = $editBox = null;
        });
    },

    finalize: function()
    {
    	$jQ('[data-cart-add]').unbind('click', this.callbacks.addItem);
    	$jQ('[data-cart-remove]').unbind('click', this.callbacks.removeItem);
        $jQ('.next-items-link').unbind('click', this.callbacks.scrollUp);
        $jQ('.prev-items-link').unbind('click', this.callbacks.scrollNext);
    },

    update : function (params) {
        MLS.ajax.sendRequest(
            this.options.getCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    addItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.addToCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    updateItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.updateCartEndpoint,
            params,
            this.options.successCallback
        );
    },

    removeItem : function (params) {
    	MLS.ajax.sendRequest(
            this.options.removeFromCartEndpoint,
            params,
            this.options.successCallback
        );
    }
};<|endoftext|>


<commit_before>class AutoSave {
  constructor(onServerSync) {
    this.onServerSyncCallback = onServerSync;

    this.setSyncStatus();
  }

  static get POLLING_INTERVAL() {
    return 3000;
  }

  startPolling() {
    setInterval(this.syncToServer.bind(this), AutoSave.POLLING_INTERVAL);
  }

  setChange(note) {
    this.setSyncStatus(false);

    localStorage.setItem(
      'note-' + note.uid,
      note.toJson()
    );
  }

  syncToServer() {
    if (jQuery.active) {
      return;
    }

    var keys = this.getLocalStorageKeys();

    for (var key of keys) {
      const noteRaw = localStorage.getItem(key);
      const note = JSON.parse(noteRaw);
      const url = '/api/notes/' + note.uid;

      $.ajax({
        url: url,
        method: 'PUT',
        dataType: 'json',
        data: { note: note }
      })
      // `serverNote` is just a partial note, the response doesn't contain all
      // attributes
      .done((serverNote) => this.ajaxDone(key, noteRaw, Note.fromAttributes(serverNote)))
      .fail((xhr, status, error) => this.ajaxFail(xhr, status, error, url));
    }
  }

  setSyncStatus(isSynced, serverNote) {
    if (isSynced === undefined) {
      isSynced = this.getLocalStorageKeys().length === 0;
    }

    if (isSynced) {
      window.onbeforeunload = undefined;
    }
    else {
      window.onbeforeunload = function() {
        return "Behold! You have unsynchronized changes. " +
          "If you leave the page now, your changes won't be saved to the server.\n" +
          "(Your data won't be lost, but it will only remain locally in your browser)";
      };
    }
    this.onServerSyncCallback({ isSynced: isSynced, note: serverNote });
  }

  getLocalStorageKeys() {
    var keys = [];
    var length = localStorage.length;

    for (var i = 0; i < length; ++i) {
      var key = localStorage.key(i);

      if (key.startsWith('note-')) {
        keys.push(key);
      }
    }

    return keys;
  }

  ajaxDone(key, noteRaw, serverNote) {
    // if the content is still the same -> clear from localStorage
    if (noteRaw === localStorage.getItem(key)) {
      localStorage.removeItem(key);
    }

    this.setSyncStatus(undefined, serverNote);
  }

  ajaxFail(xhr, status, error, url) {
    // 0 == UNSENT -> most probably no internet connection
    if (xhr.readyState === 0) {
      return;
    }
    AlertFlash.show('Something went sideways: ' + error.toString());
    console.error('url: ', url, 'xhr: ', xhr, 'status: ', status, 'err: ', error.toString());
  }
}
<commit_msg>set the server updated at in the localstorage item<commit_after>class AutoSave {
  constructor(onServerSync) {
    this.onServerSyncCallback = onServerSync;

    this.setSyncStatus();
  }

  static get POLLING_INTERVAL() {
    return 3000;
  }

  startPolling() {
    setInterval(this.syncToServer.bind(this), AutoSave.POLLING_INTERVAL);
  }

  setChange(note) {
    this.setSyncStatus(false);

    localStorage.setItem(
      'note-' + note.uid,
      note.toJson()
    );
  }

  syncToServer() {
    if (jQuery.active) {
      return;
    }

    var keys = this.getLocalStorageKeys();

    for (var key of keys) {
      const noteRaw = localStorage.getItem(key);
      const note = JSON.parse(noteRaw);
      const url = '/api/notes/' + note.uid;

      $.ajax({
        url: url,
        method: 'PUT',
        dataType: 'json',
        data: { note: note }
      })
      // `serverNote` is just a partial note, the response doesn't contain all
      // attributes
      .done((serverNote) => this.ajaxDone(key, noteRaw, Note.fromAttributes(serverNote)))
      .fail((xhr, status, error) => this.ajaxFail(xhr, status, error, url));
    }
  }

  setSyncStatus(isSynced, serverNote) {
    if (isSynced === undefined) {
      isSynced = this.getLocalStorageKeys().length === 0;
    }

    if (isSynced) {
      window.onbeforeunload = undefined;
    }
    else {
      window.onbeforeunload = function() {
        return "Behold! You have unsynchronized changes. " +
          "If you leave the page now, your changes won't be saved to the server.\n" +
          "(Your data won't be lost, but it will only remain locally in your browser)";
      };
    }
    this.onServerSyncCallback({ isSynced: isSynced, note: serverNote });
  }

  getLocalStorageKeys() {
    var keys = [];
    var length = localStorage.length;

    for (var i = 0; i < length; ++i) {
      var key = localStorage.key(i);

      if (key.startsWith('note-')) {
        keys.push(key);
      }
    }

    return keys;
  }

  ajaxDone(key, noteRaw, serverNote) {
    // if the content is still the same -> clear from localStorage
    const localStorageNoteRaw = localStorage.getItem(key)
    if (noteRaw === localStorageNoteRaw) {
      localStorage.removeItem(key);
    }
    else {
      // update the server updated at in the localstorage item as well.  the
      // content may have been updated in the meantime from the same source. if
      // we don't do this we will get a conflict, which is not what we want in
      // this case.
      const note = Note.fromAttributes(JSON.parse(localStorageNoteRaw))
      note.serverUpdatedAt = serverNote.serverUpdatedAt;

      localStorage.setItem(
        'note-' + note.uid,
        note.toJson()
      );
    }

    this.setSyncStatus(undefined, serverNote);
  }

  ajaxFail(xhr, status, error, url) {
    // 0 == UNSENT -> most probably no internet connection
    if (xhr.readyState === 0) {
      return;
    }
    AlertFlash.show('Something went sideways: ' + error.toString());
    console.error('url: ', url, 'xhr: ', xhr, 'status: ', status, 'err: ', error.toString());
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import Model from 'ember-data/model';
import DS from 'ember-data';
import {memberAction} from 'ember-api-actions';
const {computed} = Ember;

export default Model.extend({
  nomen: DS.attr('string'),
  status: DS.attr('entry-status'),
  picture: DS.attr('string'),
  tenor: DS.belongsTo('person', {async: true}),
  lead: DS.belongsTo('person', {async: true}),
  baritone: DS.belongsTo('person', {async: true}),
  bass: DS.belongsTo('person', {async: true}),
  men: DS.attr('number'),
  risers: DS.attr('number'),
  is_evaluation: DS.attr('boolean'),
  is_private: DS.attr('boolean'),
  director: DS.belongsTo('person', {async: true}),
  codirector: DS.belongsTo('person', {async: true}),
  representing: DS.belongsTo('entity', {async: true}),
  seed: DS.attr('number'),
  prelim: DS.attr('number'),
  entity: DS.belongsTo('entity', {inverse: 'entries', async: true}),
  session: DS.belongsTo('session', {async: true}),
  appearances: DS.hasMany('appearance', {async: true}),
  contestants: DS.hasMany('contestant', {async: true}),
  participants: DS.hasMany('participant', {async: true}),
  submissions: DS.hasMany('submission', {async: true}),
  permissions: DS.attr(),

  submit: memberAction({path: 'submit', type: 'post'}),

  published: computed.equal(
    'status',
    'Published'
  ),

  notPublished: computed.not(
    'published'
  ),

  statusOptions: [
    'New',
    'Submitted',
    'Accepted',
    'Declined',
    'Dropped',
    'Validated',
    'Scratched',
    'Disqualified',
    'Started',
    'Finished',
    'Published',
  ],

  tp: computed.mapBy(
    'appearances',
    'totPoints'
  ),
  tc: computed.mapBy(
    'appearances',
    'stc'
  ),
  totPoints: computed.sum(
    'tp'
  ),
  stc: computed.sum(
    'tc'
  ),
  totScore: computed(
    'totPoints',
    'stc',
    function() {
      return (this.get('totPoints') / this.get('stc')).toFixed(1);
    }
  ),
  mp: computed.mapBy(
    'appearances',
    'musPoints'
  ),
  mc: computed.mapBy(
    'appearances',
    'smc'
  ),
  musPoints: computed.sum(
    'mp'
  ),
  smc: computed.sum(
    'mc'
  ),
  musScore: computed(
    'musPoints',
    'smc',
    function() {
      return (this.get('musPoints') / this.get('smc')).toFixed(1);
    }
  ),
  pp: computed.mapBy(
    'appearances',
    'perPoints'
  ),
  pc: computed.mapBy(
    'appearances',
    'spc'
  ),
  perPoints: computed.sum(
    'pp'
  ),
  spc: computed.sum(
    'pc'
  ),
  perScore: computed(
    'perPoints',
    'spc',
    function() {
      return (this.get('perPoints') / this.get('spc')).toFixed(1);
    }
  ),
  sp: computed.mapBy(
    'appearances',
    'sngPoints'
  ),
  sc: computed.mapBy(
    'appearances',
    'ssc'
  ),
  sngPoints: computed.sum(
    'sp'
  ),
  ssc: computed.sum(
    'sc'
  ),
  sngScore: computed(
    'sngPoints',
    'ssc',
    function() {
      return (this.get('sngPoints') / this.get('ssc')).toFixed(1);
    }
  ),
  totRank: computed(
    'session.ranks.@each.{score,rank}',
    'totPoints',
    function() {
      return this.get('session.ranks').findBy('score', this.get('totPoints')).rank || null;
    }
  ),
  contestsArray: computed(
    'contestants.@each.contest', function() {
      return this.get('contestants');
  }),
  membersArray: computed(
    'participants.@each.member', function() {
      return this.get('participants');
  }),
  selectedContests: computed.mapBy(
    'contestsArray',
    'contest.id'
  ),
  selectedMembers: computed.mapBy(
    'membersArray',
    'member.id'
  ),
  numSubmissions: computed(
    'submissions.length', function() {
      return this.get('submissions.length');
  })
});
<commit_msg>Disable TotRank for now<commit_after>import Ember from 'ember';
import Model from 'ember-data/model';
import DS from 'ember-data';
import {memberAction} from 'ember-api-actions';
const {computed} = Ember;

export default Model.extend({
  nomen: DS.attr('string'),
  status: DS.attr('entry-status'),
  picture: DS.attr('string'),
  tenor: DS.belongsTo('person', {async: true}),
  lead: DS.belongsTo('person', {async: true}),
  baritone: DS.belongsTo('person', {async: true}),
  bass: DS.belongsTo('person', {async: true}),
  men: DS.attr('number'),
  risers: DS.attr('number'),
  is_evaluation: DS.attr('boolean'),
  is_private: DS.attr('boolean'),
  director: DS.belongsTo('person', {async: true}),
  codirector: DS.belongsTo('person', {async: true}),
  representing: DS.belongsTo('entity', {async: true}),
  seed: DS.attr('number'),
  prelim: DS.attr('number'),
  entity: DS.belongsTo('entity', {inverse: 'entries', async: true}),
  session: DS.belongsTo('session', {async: true}),
  appearances: DS.hasMany('appearance', {async: true}),
  contestants: DS.hasMany('contestant', {async: true}),
  participants: DS.hasMany('participant', {async: true}),
  submissions: DS.hasMany('submission', {async: true}),
  permissions: DS.attr(),

  submit: memberAction({path: 'submit', type: 'post'}),

  published: computed.equal(
    'status',
    'Published'
  ),

  notPublished: computed.not(
    'published'
  ),

  statusOptions: [
    'New',
    'Submitted',
    'Accepted',
    'Declined',
    'Dropped',
    'Validated',
    'Scratched',
    'Disqualified',
    'Started',
    'Finished',
    'Published',
  ],

  tp: computed.mapBy(
    'appearances',
    'totPoints'
  ),
  tc: computed.mapBy(
    'appearances',
    'stc'
  ),
  totPoints: computed.sum(
    'tp'
  ),
  stc: computed.sum(
    'tc'
  ),
  totScore: computed(
    'totPoints',
    'stc',
    function() {
      return (this.get('totPoints') / this.get('stc')).toFixed(1);
    }
  ),
  mp: computed.mapBy(
    'appearances',
    'musPoints'
  ),
  mc: computed.mapBy(
    'appearances',
    'smc'
  ),
  musPoints: computed.sum(
    'mp'
  ),
  smc: computed.sum(
    'mc'
  ),
  musScore: computed(
    'musPoints',
    'smc',
    function() {
      return (this.get('musPoints') / this.get('smc')).toFixed(1);
    }
  ),
  pp: computed.mapBy(
    'appearances',
    'perPoints'
  ),
  pc: computed.mapBy(
    'appearances',
    'spc'
  ),
  perPoints: computed.sum(
    'pp'
  ),
  spc: computed.sum(
    'pc'
  ),
  perScore: computed(
    'perPoints',
    'spc',
    function() {
      return (this.get('perPoints') / this.get('spc')).toFixed(1);
    }
  ),
  sp: computed.mapBy(
    'appearances',
    'sngPoints'
  ),
  sc: computed.mapBy(
    'appearances',
    'ssc'
  ),
  sngPoints: computed.sum(
    'sp'
  ),
  ssc: computed.sum(
    'sc'
  ),
  sngScore: computed(
    'sngPoints',
    'ssc',
    function() {
      return (this.get('sngPoints') / this.get('ssc')).toFixed(1);
    }
  ),
  // totRank: computed(
  //   'session.ranks.@each.{score,rank}',
  //   'totPoints',
  //   function() {
  //     return this.get('session.ranks').findBy('score', this.get('totPoints')).rank || null;
  //   }
  // ),
  contestsArray: computed(
    'contestants.@each.contest', function() {
      return this.get('contestants');
  }),
  membersArray: computed(
    'participants.@each.member', function() {
      return this.get('participants');
  }),
  selectedContests: computed.mapBy(
    'contestsArray',
    'contest.id'
  ),
  selectedMembers: computed.mapBy(
    'membersArray',
    'member.id'
  ),
  numSubmissions: computed(
    'submissions.length', function() {
      return this.get('submissions.length');
  })
});
<|endoftext|>


<commit_before>import axios from "axios";
import UUID from "uuid-js";

import {WRITE_API_ENDPOINT} from "lib/config";
import {Types} from "lib/dnd-utils";
import {getSensorId, getSensorLabel, operatorToFormula} from "lib/sensors-utils";
import {getBasicObject} from "./utils";

export const ADD_ITEM_TO_FORMULA = "ADD_ITEM_TO_FORMULA";
export const ADD_SENSOR_TO_WORK_AREA = "ADD_SENSOR_TO_WORK_AREA";
export const FILTER_SENSORS = "FILTER_SENSORS";
export const GET_FORMULA_ITEMS = "GET_FORMULA_ITEMS";
export const REMOVE_ITEM_FROM_FORMULA = "REMOVE_ITEM_FROM_FORMULA";
export const REMOVE_SENSOR_FROM_WORK_AREA = "REMOVE_SENSOR_FROM_WORK_AREA";
export const RESET_FORMULA_ITEMS = "RESET_FORMULA_ITEMS";
export const RESET_WORK_AREA_SENSORS = "RESET_WORK_AREA_SENSORS";
export const SELECT_SENSOR = "SELECT_SENSOR";
export const SENSOR_CREATION_SUCCESS = "SENSOR_CREATION_SUCCESS";
export const SENSOR_DELETE_SUCCESS = "SENSOR_DELETE_SUCCESS";
export const SENSOR_UPDATE_SUCCESS = "SENSOR_UPDATE_SUCCESS";

function getSensorObj (collectionItem) {
    return {
        "name": getSensorLabel(collectionItem),
        "description": collectionItem.get("description"),
        "unitOfMeasurement": collectionItem.get("unitOfMeasurement"),
        "aggregationType": collectionItem.get("aggregationType"),
        "formulas": collectionItem.get("formulas"),
        "primaryTags": collectionItem.get("primaryTags"),
        "tags": collectionItem.get("tags"),
        "siteReference": collectionItem.get("siteReference"),
        "userReference": collectionItem.get("userReference"),
        "parentSensorId": collectionItem.get("parentSensorId")
    };
}

function addMonitoringAttrs (sensor) {
    normalizeSensorData(sensor);
    sensor.id = UUID.create().hex;
    return sensor;
}

function normalizeSensorData (sensorData) {
    sensorData._id = undefined;
    sensorData.createdDate = undefined;
    sensorData.lastModifiedDate = undefined;
    sensorData.isDeleted = undefined;
    sensorData.measurementType = undefined;
    sensorData.measurementTypes = undefined;
    sensorData.virtual = true;
    //TODO remove for unitOfMeasurement inside formula...
    // if (sensorData.unitOfMeasurement instanceof Object) {
    //     sensorData.unitOfMeasurement = sensorData.unitOfMeasurement.value;
    // }
    //TODO remove for aggregationType inside formula...
    if (sensorData.aggregationType instanceof Object) {
        sensorData.aggregationType = sensorData.aggregationType.value;
    }
}

function insertSensor (requestBody, dispatch, user) {
    var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors";
    let sensor = addMonitoringAttrs(requestBody);
    sensor.userId = user.get("_id");
    axios.post(endpoint, sensor)
        .then(() => dispatch({
            type: SENSOR_CREATION_SUCCESS,
            payload: requestBody
        }))
        .catch(() => dispatch({
            type: "SENSOR_CREATION_FAIL"
        }));
}

function buildFormulas (sensorData, formulaItems) {
    if (formulaItems && formulaItems.length > 0) {
        let formula = "";
        let variables = new Set();
        formulaItems.forEach((item) => {
            switch (item.type) {
                case Types.SENSOR: {
                    const sensorId = typeof item.sensor === "string" ? item.sensor : getSensorId(item.sensor);
                    formula += sensorId;
                    variables.add(sensorId);
                    break;
                }
                case Types.OPERATOR: {
                    formula += operatorToFormula[item.operator];
                    break;
                }
                case Types.NUMBER: {
                    formula += item.number;
                    break;
                }
            }
        });
        //TODO put unitOfMeasurement
        // if (sensorData.unitOfMeasurement instanceof Object) {
        //     sensorData.unitOfMeasurement = sensorData.unitOfMeasurement.value;
        // }
        //TODO put aggregationType
        // if (sensorData.aggregationType instanceof Object) {
        //     sensorData.aggregationType = sensorData.aggregationType.value;
        // }
        return [{
            formula: formula,
            start: "1970-01-01T00:00:00.000Z",
            end: "3000-01-01T00:00:00.000Z",
            //TODO understand measurementType
            variables: Array.from(variables).map(v => ({
                measurementType: "",
                sensorId: v,
                symbol: v
            })),
            measurementType: [],
            measurementSample: 60000
        }];
    }
}

export const addItemToFormula = (item) => getBasicObject(ADD_ITEM_TO_FORMULA, item);

export const removeItemFromFormula = (index) => getBasicObject(REMOVE_ITEM_FROM_FORMULA, index);

export const addSensorToWorkArea = (sensor) => getBasicObject(ADD_SENSOR_TO_WORK_AREA, sensor);

export const removeSensorFromWorkArea = (sensorId) => getBasicObject(REMOVE_SENSOR_FROM_WORK_AREA, sensorId);

export const addSensor = (user, sensor, formulaItems) => {
    sensor.formulas = buildFormulas(formulaItems);
    return dispatch => {
        dispatch({
            type: "ADDING_SENSOR"
        });
        insertSensor(sensor, dispatch, user);
    };
};

export const cloneSensors = (user, sensors) => {
    return dispatch => {
        dispatch({
            type: "CLONING_SENSORS"
        });
        sensors.forEach((el) => {
            var sensor = getSensorObj(el);
            sensor.name = "Copia di " + sensor.name;
            sensor.formulas = buildFormulas([{
                type: Types.SENSOR,
                sensor: el
            }]);
            insertSensor(sensor, dispatch, user);
        });
    };
};

export const deleteSensors = (sensors) => {
    return dispatch => {
        dispatch({
            type: "DELETING_SENSORS"
        });
        sensors.forEach(sensor => {
            if (sensor.get("userId")) {
                let id = sensor.get("_id");
                var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors/" + id;
                axios.delete(endpoint)
                    .then(() => dispatch({
                        type: SENSOR_DELETE_SUCCESS,
                        payload: id
                    }))
                    .catch(() => dispatch({
                        type: "SENSOR_DELETE_FAIL"
                    }));
            }
        });
    };
};

function callEditSensor (sensorData, sensorId) {
    return dispatch => {
        dispatch({
            type: "UPDATING_SENSOR"
        });
        var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors/" + sensorId;
        normalizeSensorData(sensorData);
        axios.put(endpoint, sensorData)
            .then(() => dispatch({
                type: SENSOR_UPDATE_SUCCESS,
                payload: {sensorData, sensorId}
            }))
            .catch(() => dispatch({
                type: "SENSOR_UPDATE_FAIL"
            }));
    };
}

export const editSensor = (user, sensorData, formulaItems, sensor) => {
    if (sensor.get("userId")) {
        let id = sensor.get("_id");
        sensorData.formulas = buildFormulas(sensorData, formulaItems);
        sensorData.id = id;
        sensorData.parentSensorId = sensor.get("parentSensorId");
        return callEditSensor(sensorData, id);
    } else {
        sensorData.parentSensorId = getSensorId(sensor);
        sensorData.formulas = buildFormulas(sensorData, [{
            type: Types.SENSOR,
            sensor: sensor
        }]);
        return dispatch => {
            dispatch({
                type: "OVERRIDING_SENSOR"
            });
            insertSensor(sensorData, dispatch, user);
        };
    }
};

export const favoriteSensor = (id) => getBasicObject("FAVORITE_SENSOR", id);

export const filterSensors = (payload) => getBasicObject(FILTER_SENSORS, payload);

export const getFormulaItems = () => getBasicObject(GET_FORMULA_ITEMS);

export const resetFormulaItems = (resetWorkArea) => getBasicObject(RESET_FORMULA_ITEMS, resetWorkArea);

export const resetWorkAreaSensors = () => getBasicObject(RESET_WORK_AREA_SENSORS);

export const monitorSensor = (id) => getBasicObject("MONITOR_SENSOR", id);

export const selectSensor = (sensor) => getBasicObject(SELECT_SENSOR, sensor);
<commit_msg>[IWWA-905] adapt Lucy PRO apis call to new sensor schema<commit_after>import axios from "axios";
import UUID from "uuid-js";

import {WRITE_API_ENDPOINT} from "lib/config";
import {Types} from "lib/dnd-utils";
import {getSensorId, getSensorLabel, operatorToFormula} from "lib/sensors-utils";
import {getBasicObject} from "./utils";

export const ADD_ITEM_TO_FORMULA = "ADD_ITEM_TO_FORMULA";
export const ADD_SENSOR_TO_WORK_AREA = "ADD_SENSOR_TO_WORK_AREA";
export const FILTER_SENSORS = "FILTER_SENSORS";
export const GET_FORMULA_ITEMS = "GET_FORMULA_ITEMS";
export const REMOVE_ITEM_FROM_FORMULA = "REMOVE_ITEM_FROM_FORMULA";
export const REMOVE_SENSOR_FROM_WORK_AREA = "REMOVE_SENSOR_FROM_WORK_AREA";
export const RESET_FORMULA_ITEMS = "RESET_FORMULA_ITEMS";
export const RESET_WORK_AREA_SENSORS = "RESET_WORK_AREA_SENSORS";
export const SELECT_SENSOR = "SELECT_SENSOR";
export const SENSOR_CREATION_SUCCESS = "SENSOR_CREATION_SUCCESS";
export const SENSOR_DELETE_SUCCESS = "SENSOR_DELETE_SUCCESS";
export const SENSOR_UPDATE_SUCCESS = "SENSOR_UPDATE_SUCCESS";

function getSensorObj (collectionItem) {
    return {
        "name": getSensorLabel(collectionItem),
        "description": collectionItem.get("description"),
        "unitOfMeasurement": collectionItem.get("unitOfMeasurement"),
        "aggregationType": collectionItem.get("aggregationType"),
        "formulas": collectionItem.get("formulas"),
        "primaryTags": collectionItem.get("primaryTags"),
        "tags": collectionItem.get("tags"),
        "siteReference": collectionItem.get("siteReference"),
        "userReference": collectionItem.get("userReference"),
        "parentSensorId": collectionItem.get("parentSensorId")
    };
}

function addMonitoringAttrs (sensor) {
    normalizeSensorData(sensor);
    sensor.id = UUID.create().hex;
    return sensor;
}

function normalizeSensorData (sensorData) {
    sensorData._id = undefined;
    sensorData.createdDate = undefined;
    sensorData.lastModifiedDate = undefined;
    sensorData.isDeleted = undefined;
    sensorData.measurementType = undefined;
    sensorData.measurementTypes = undefined;
    sensorData.virtual = true;
    if (sensorData.unitOfMeasurement instanceof Object) {
        sensorData.unitOfMeasurement = sensorData.unitOfMeasurement.value;
    }
    if (sensorData.aggregationType instanceof Object) {
        sensorData.aggregationType = sensorData.aggregationType.value;
    }
}

function insertSensor (requestBody, dispatch, user) {
    var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors";
    let sensor = addMonitoringAttrs(requestBody);
    sensor.userId = user.get("_id");
    axios.post(endpoint, sensor)
        .then(() => dispatch({
            type: SENSOR_CREATION_SUCCESS,
            payload: requestBody
        }))
        .catch(() => dispatch({
            type: "SENSOR_CREATION_FAIL"
        }));
}

function buildFormulas (formulaItems) {
    if (formulaItems && formulaItems.length > 0) {
        let formula = "";
        let variables = new Set();
        formulaItems.forEach((item) => {
            switch (item.type) {
                case Types.SENSOR: {
                    const sensorId = typeof item.sensor === "string" ? item.sensor : getSensorId(item.sensor);
                    formula += sensorId;
                    variables.add(sensorId);
                    break;
                }
                case Types.OPERATOR: {
                    formula += operatorToFormula[item.operator];
                    break;
                }
                case Types.NUMBER: {
                    formula += item.number;
                    break;
                }
            }
        });
        return [{
            formula: formula,
            start: "1970-01-01T00:00:00.000Z",
            end: "3000-01-01T00:00:00.000Z",
            variables: Array.from(variables).map(v => ({
                measurementType: "",
                sensorId: v,
                symbol: v
            })),
            measurementType: "",
            measurementUnit: "",
            measurementSample: 60000
        }];
    }
}

export const addItemToFormula = (item) => getBasicObject(ADD_ITEM_TO_FORMULA, item);

export const removeItemFromFormula = (index) => getBasicObject(REMOVE_ITEM_FROM_FORMULA, index);

export const addSensorToWorkArea = (sensor) => getBasicObject(ADD_SENSOR_TO_WORK_AREA, sensor);

export const removeSensorFromWorkArea = (sensorId) => getBasicObject(REMOVE_SENSOR_FROM_WORK_AREA, sensorId);

export const addSensor = (user, sensor, formulaItems) => {
    sensor.formulas = buildFormulas(formulaItems);
    return dispatch => {
        dispatch({
            type: "ADDING_SENSOR"
        });
        insertSensor(sensor, dispatch, user);
    };
};

export const cloneSensors = (user, sensors) => {
    return dispatch => {
        dispatch({
            type: "CLONING_SENSORS"
        });
        sensors.forEach((el) => {
            var sensor = getSensorObj(el);
            sensor.name = "Copia di " + sensor.name;
            sensor.formulas = buildFormulas([{
                type: Types.SENSOR,
                sensor: el
            }]);
            insertSensor(sensor, dispatch, user);
        });
    };
};

export const deleteSensors = (sensors) => {
    return dispatch => {
        dispatch({
            type: "DELETING_SENSORS"
        });
        sensors.forEach(sensor => {
            if (sensor.get("userId")) {
                let id = sensor.get("_id");
                var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors/" + id;
                axios.delete(endpoint)
                    .then(() => dispatch({
                        type: SENSOR_DELETE_SUCCESS,
                        payload: id
                    }))
                    .catch(() => dispatch({
                        type: "SENSOR_DELETE_FAIL"
                    }));
            }
        });
    };
};

function callEditSensor (sensorData, sensorId) {
    return dispatch => {
        dispatch({
            type: "UPDATING_SENSOR"
        });
        var endpoint = "http://" + WRITE_API_ENDPOINT + "/sensors/" + sensorId;
        normalizeSensorData(sensorData);
        axios.put(endpoint, sensorData)
            .then(() => dispatch({
                type: SENSOR_UPDATE_SUCCESS,
                payload: {sensorData, sensorId}
            }))
            .catch(() => dispatch({
                type: "SENSOR_UPDATE_FAIL"
            }));
    };
}

export const editSensor = (user, sensorData, formulaItems, sensor) => {
    if (sensor.get("userId")) {
        let id = sensor.get("_id");
        sensorData.formulas = buildFormulas(formulaItems);
        sensorData.id = id;
        sensorData.parentSensorId = sensor.get("parentSensorId");
        return callEditSensor(sensorData, id);
    } else {
        sensorData.parentSensorId = getSensorId(sensor);
        sensorData.formulas = buildFormulas([{
            type: Types.SENSOR,
            sensor: sensor
        }]);
        return dispatch => {
            dispatch({
                type: "OVERRIDING_SENSOR"
            });
            insertSensor(sensorData, dispatch, user);
        };
    }
};

export const favoriteSensor = (id) => getBasicObject("FAVORITE_SENSOR", id);

export const filterSensors = (payload) => getBasicObject(FILTER_SENSORS, payload);

export const getFormulaItems = () => getBasicObject(GET_FORMULA_ITEMS);

export const resetFormulaItems = (resetWorkArea) => getBasicObject(RESET_FORMULA_ITEMS, resetWorkArea);

export const resetWorkAreaSensors = () => getBasicObject(RESET_WORK_AREA_SENSORS);

export const monitorSensor = (id) => getBasicObject("MONITOR_SENSOR", id);

export const selectSensor = (sensor) => getBasicObject(SELECT_SENSOR, sensor);
<|endoftext|>


<commit_before>import { run } from 'ember-metal';
import Application from '../../system/application';
import { jQuery } from 'ember-views';

let app;

QUnit.module('Ember.Application initializers', {
  teardown() {
    if (app) {
      run(() => app.destroy());
    }
  }
});

QUnit.test('initializers require proper \'name\' and \'initialize\' properties', function() {
  let MyApplication = Application.extend();

  expectAssertion(() => {
    run(() => {
      MyApplication.initializer({ name: 'initializer' });
    });
  });

  expectAssertion(() => {
    run(() => {
      MyApplication.initializer({ initialize() {} });
    });
  });
});

QUnit.test('initializers that throw errors cause the boot promise to reject with the error', function() {
  QUnit.expect(2);
  QUnit.stop();

  let MyApplication = Application.extend();

  MyApplication.initializer({
    name: 'initializer',
    initialize() { throw new Error('boot failure'); }
  });

  app = MyApplication.create({
    autoboot: false
  });

  try {
    app.boot().then(
      (app) => {
        QUnit.start();
        ok(false, 'The boot promise should not resolve when there is a boot error');
      },
      (err) => {
        QUnit.start();
        ok(err instanceof Error, 'The boot promise should reject with an error');
        equal(err.message, 'boot failure');
      }
    );
  } catch (e) {
    QUnit.start();
    ok(false, 'The boot method should not throw');
    throw e;
  }
});

QUnit.test('initializers are passed an App', function() {
  let MyApplication = Application.extend();

  MyApplication.initializer({
    name: 'initializer',
    initialize(App) {
      ok(App instanceof Application, 'initialize is passed an Application');
    }
  });

  run(() => {
    app = MyApplication.create({
      router: false,
      rootElement: '#qunit-fixture'
    });
  });
});

QUnit.test('initializers can be registered in a specified order', function() {
  let order = [];
  let MyApplication = Application.extend();
  MyApplication.initializer({
    name: 'fourth',
    after: 'third',
    initialize(registry) {
      order.push('fourth');
    }
  });

  MyApplication.initializer({
    name: 'second',
    after: 'first',
    before: 'third',
    initialize(registry) {
      order.push('second');
    }
  });

  MyApplication.initializer({
    name: 'fifth',
    after: 'fourth',
    before: 'sixth',
    initialize(registry) {
      order.push('fifth');
    }
  });

  MyApplication.initializer({
    name: 'first',
    before: 'second',
    initialize(registry) {
      order.push('first');
    }
  });

  MyApplication.initializer({
    name: 'third',
    initialize(registry) {
      order.push('third');
    }
  });

  MyApplication.initializer({
    name: 'sixth',
    initialize(registry) {
      order.push('sixth');
    }
  });

  run(() => {
    app = MyApplication.create({
      router: false,
      rootElement: '#qunit-fixture'
    });
  });

  deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']);
});

QUnit.test('initializers can be registered in a specified order as an array', function() {
  let order = [];
  let MyApplication = Application.extend();

  MyApplication.initializer({
    name: 'third',
    initialize(registry) {
      order.push('third');
    }
  });

  MyApplication.initializer({
    name: 'second',
    after: 'first',
    before: ['third', 'fourth'],
    initialize(registry) {
      order.push('second');
    }
  });

  MyApplication.initializer({
    name: 'fourth',
    after: ['second', 'third'],
    initialize(registry) {
      order.push('fourth');
    }
  });

  MyApplication.initializer({
    name: 'fifth',
    after: 'fourth',
    before: 'sixth',
    initialize(registry) {
      order.push('fifth');
    }
  });

  MyApplication.initializer({
    name: 'first',
    before: ['second'],
    initialize(registry) {
      order.push('first');
    }
  });

  MyApplication.initializer({
    name: 'sixth',
    initialize(registry) {
      order.push('sixth');
    }
  });

  run(() => {
    app = MyApplication.create({
      router: false,
      rootElement: '#qunit-fixture'
    });
  });

  deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']);
});

QUnit.test('initializers can have multiple dependencies', function () {
  let order = [];
  let a = {
    name: 'a',
    before: 'b',
    initialize(registry) {
      order.push('a');
    }
  };
  let b = {
    name: 'b',
    initialize(registry) {
      order.push('b');
    }
  };
  let c = {
    name: 'c',
    after: 'b',
    initialize(registry) {
      order.push('c');
    }
  };
  let afterB = {
    name: 'after b',
    after: 'b',
    initialize(registry) {
      order.push('after b');
    }
  };
  let afterC = {
    name: 'after c',
    after: 'c',
    initialize(registry) {
      order.push('after c');
    }
  };

  Application.initializer(b);
  Application.initializer(a);
  Application.initializer(afterC);
  Application.initializer(afterB);
  Application.initializer(c);

  run(() => {
    app = Application.create({
      router: false,
      rootElement: '#qunit-fixture'
    });
  });

  ok(order.indexOf(a.name) < order.indexOf(b.name), 'a < b');
  ok(order.indexOf(b.name) < order.indexOf(c.name), 'b < c');
  ok(order.indexOf(b.name) < order.indexOf(afterB.name), 'b < afterB');
  ok(order.indexOf(c.name) < order.indexOf(afterC.name), 'c < afterC');
});

QUnit.test('initializers set on Application subclasses are not shared between apps', function() {
  let firstInitializerRunCount = 0;
  let secondInitializerRunCount = 0;
  let FirstApp = Application.extend();

  FirstApp.initializer({
    name: 'first',
    initialize(registry) {
      firstInitializerRunCount++;
    }
  });

  let SecondApp = Application.extend();

  SecondApp.initializer({
    name: 'second',
    initialize(registry) {
      secondInitializerRunCount++;
    }
  });

  jQuery('#qunit-fixture').html('

');

  let firstApp = run(() => {
    return FirstApp.create({
      router: false,
      rootElement: '#qunit-fixture #first'
    });
  });

  equal(firstInitializerRunCount, 1, 'first initializer only was run');
  equal(secondInitializerRunCount, 0, 'first initializer only was run');

  let secondApp = run(() => {
    return SecondApp.create({
      router: false,
      rootElement: '#qunit-fixture #second'
    });
  });

  equal(firstInitializerRunCount, 1, 'second initializer only was run');
  equal(secondInitializerRunCount, 1, 'second initializer only was run');

  run(() => {
    firstApp.destroy();
    secondApp.destroy();
  });
});

QUnit.test('initializers are concatenated', function() {
  let firstInitializerRunCount = 0;
  let secondInitializerRunCount = 0;
  let FirstApp = Application.extend();

  FirstApp.initializer({
    name: 'first',
    initialize(registry) {
      firstInitializerRunCount++;
    }
  });

  let SecondApp = FirstApp.extend();
  SecondApp.initializer({
    name: 'second',
    initialize(registry) {
      secondInitializerRunCount++;
    }
  });

  jQuery('#qunit-fixture').html('

');
  let firstApp = run(() => {
    return FirstApp.create({
      router: false,
      rootElement: '#qunit-fixture #first'
    });
  });
  equal(firstInitializerRunCount, 1, 'first initializer only was run when base class created');
  equal(secondInitializerRunCount, 0, 'first initializer only was run when base class created');
  firstInitializerRunCount = 0;

  let secondApp = run(() => {
    return SecondApp.create({
      router: false,
      rootElement: '#qunit-fixture #second'
    });
  });

  equal(firstInitializerRunCount, 1, 'first initializer was run when subclass created');
  equal(secondInitializerRunCount, 1, 'second initializers was run when subclass created');
  run(() => {
    firstApp.destroy();
    secondApp.destroy();
  });
});

QUnit.test('initializers are per-app', function() {
  expect(2);

  let FirstApp = Application.extend();

  FirstApp.initializer({
    name: 'abc',
    initialize(app) {}
  });

  expectAssertion(() => {
    FirstApp.initializer({
      name: 'abc',
      initialize(app) {}
    });
  });

  let SecondApp = Application.extend();
  SecondApp.instanceInitializer({
    name: 'abc',
    initialize(app) {}
  });

  ok(true, 'Two apps can have initializers named the same.');
});

QUnit.test('initializers are executed in their own context', function() {
  expect(1);
  let MyApplication = Application.extend();

  MyApplication.initializer({
    name: 'coolInitializer',
    myProperty: 'cool',
    initialize(application) {
      equal(this.myProperty, 'cool', 'should have access to its own context');
    }
  });

  run(() => {
    app = MyApplication.create({
      router: false,
      rootElement: '#qunit-fixture'
    });
  });
});

QUnit.test('initializers throw a deprecation warning when receiving a second argument', function() {
  expect(1);

  let MyApplication = Application.extend();

  MyApplication.initializer({
    name: 'deprecated',
    initialize(registry, application) {
    }
  });

  expectDeprecation(() => {
    run(() => {
      app = MyApplication.create({
        router: false,
        rootElement: '#qunit-fixture'
      });
    });
  }, /The `initialize` method for Application initializer 'deprecated' should take only one argument - `App`, an instance of an `Application`./);
});
<commit_msg>Decouple test from the default resolver for initializers_test<commit_after>import { assign } from 'ember-utils';
import { moduleFor, AutobootApplicationTestCase } from 'internal-test-helpers';
import { Application } from 'ember-application';
import { jQuery } from 'ember-views';

moduleFor('Ember.Application initializers', class extends AutobootApplicationTestCase {
  constructor() {
    jQuery('#qunit-fixture').html(`

ONE

TWO

    `);
    super();
  }

  get applicationOptions() {
    return assign(super.applicationOptions, {
      rootElement: '#one'
    });
  }

  createSecondApplication(options, MyApplication=Application) {
    let myOptions = assign(this.applicationOptions, {
      rootElement: '#two'
    }, options);
    let secondApp = this.secondApp = MyApplication.create(myOptions);
    return secondApp;
  }

  teardown() {
    super.teardown();

    if (this.secondApp) {
      this.runTask(() => this.secondApp.destroy());
    }
  }

  [`@test initializers require proper 'name' and 'initialize' properties`]() {
    let MyApplication = Application.extend();

    expectAssertion(() => {
      MyApplication.initializer({ name: 'initializer' });
    });

    expectAssertion(() => {
      MyApplication.initializer({ initialize() {} });
    });
  }

  [`@test initializers that throw errors cause the boot promise to reject with the error`](assert) {
    assert.expect(2);

    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'initializer',
      initialize() { throw new Error('boot failure'); }
    });

    this.runTask(() => {
      this.createApplication({
        autoboot: false
      }, MyApplication);
    });

    let app = this.application;

    try {
      this.runTask(() => {
        app.boot().then(app => {
          assert.ok(false, 'The boot promise should not resolve when there is a boot error');
        }, error => {
          assert.ok(error instanceof Error, 'The boot promise should reject with an error');
          assert.equal(error.message, 'boot failure');
        });
      });
    } catch (error) {
      assert.ok(false, 'The boot method should not throw');
      throw error;
    }
  }

  [`@test initializers are passed an App`](assert) {
    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'initializer',
      initialize(App) {
        assert.ok(App instanceof Application, 'initialize is passed an Application');
      }
    });

    this.runTask(() => this.createApplication({}, MyApplication));
  }

  [`@test initializers can be registered in a specified order`](assert) {
    let order = [];
    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'fourth',
      after: 'third',
      initialize(registry) {
        order.push('fourth');
      }
    });

    MyApplication.initializer({
      name: 'second',
      after: 'first',
      before: 'third',
      initialize(registry) {
        order.push('second');
      }
    });

    MyApplication.initializer({
      name: 'fifth',
      after: 'fourth',
      before: 'sixth',
      initialize(registry) {
        order.push('fifth');
      }
    });

    MyApplication.initializer({
      name: 'first',
      before: 'second',
      initialize(registry) {
        order.push('first');
      }
    });

    MyApplication.initializer({
      name: 'third',
      initialize(registry) {
        order.push('third');
      }
    });

    MyApplication.initializer({
      name: 'sixth',
      initialize(registry) {
        order.push('sixth');
      }
    });

    this.runTask(() => this.createApplication({}, MyApplication));

    assert.deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']);
  }

  [`@test initializers can be registered in a specified order as an array`](assert) {
    let order = [];
    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'third',
      initialize(registry) {
        order.push('third');
      }
    });

    MyApplication.initializer({
      name: 'second',
      after: 'first',
      before: ['third', 'fourth'],
      initialize(registry) {
        order.push('second');
      }
    });

    MyApplication.initializer({
      name: 'fourth',
      after: ['second', 'third'],
      initialize(registry) {
        order.push('fourth');
      }
    });

    MyApplication.initializer({
      name: 'fifth',
      after: 'fourth',
      before: 'sixth',
      initialize(registry) {
        order.push('fifth');
      }
    });

    MyApplication.initializer({
      name: 'first',
      before: ['second'],
      initialize(registry) {
        order.push('first');
      }
    });

    MyApplication.initializer({
      name: 'sixth',
      initialize(registry) {
        order.push('sixth');
      }
    });

    this.runTask(() => this.createApplication({}, MyApplication));

    assert.deepEqual(order, ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']);
  }

  [`@test initializers can have multiple dependencies`](assert) {
    let order = [];
    let MyApplication = Application.extend();
    let a = {
      name: 'a',
      before: 'b',
      initialize(registry) {
        order.push('a');
      }
    };
    let b = {
      name: 'b',
      initialize(registry) {
        order.push('b');
      }
    };
    let c = {
      name: 'c',
      after: 'b',
      initialize(registry) {
        order.push('c');
      }
    };
    let afterB = {
      name: 'after b',
      after: 'b',
      initialize(registry) {
        order.push('after b');
      }
    };
    let afterC = {
      name: 'after c',
      after: 'c',
      initialize(registry) {
        order.push('after c');
      }
    };

    MyApplication.initializer(b);
    MyApplication.initializer(a);
    MyApplication.initializer(afterC);
    MyApplication.initializer(afterB);
    MyApplication.initializer(c);

    this.runTask(() => this.createApplication({}, MyApplication));

    assert.ok(order.indexOf(a.name) < order.indexOf(b.name), 'a < b');
    assert.ok(order.indexOf(b.name) < order.indexOf(c.name), 'b < c');
    assert.ok(order.indexOf(b.name) < order.indexOf(afterB.name), 'b < afterB');
    assert.ok(order.indexOf(c.name) < order.indexOf(afterC.name), 'c < afterC');
  }

  [`@test initializers set on Application subclasses are not shared between apps`](assert) {
    let firstInitializerRunCount = 0;
    let secondInitializerRunCount = 0;
    let FirstApp = Application.extend();

    FirstApp.initializer({
      name: 'first',
      initialize(registry) {
        firstInitializerRunCount++;
      }
    });

    let SecondApp = Application.extend();

    SecondApp.initializer({
      name: 'second',
      initialize(registry) {
        secondInitializerRunCount++;
      }
    });

    this.runTask(() => this.createApplication({}, FirstApp));

    assert.equal(firstInitializerRunCount, 1, 'first initializer only was run');
    assert.equal(secondInitializerRunCount, 0, 'first initializer only was run');

    this.runTask(() => this.createSecondApplication({}, SecondApp));

    assert.equal(firstInitializerRunCount, 1, 'second initializer only was run');
    assert.equal(secondInitializerRunCount, 1, 'second initializer only was run');
  }

  [`@test initializers are concatenated`](assert) {
    let firstInitializerRunCount = 0;
    let secondInitializerRunCount = 0;
    let FirstApp = Application.extend();

    FirstApp.initializer({
      name: 'first',
      initialize(registry) {
        firstInitializerRunCount++;
      }
    });

    let SecondApp = FirstApp.extend();
    SecondApp.initializer({
      name: 'second',
      initialize(registry) {
        secondInitializerRunCount++;
      }
    });

    this.runTask(() => this.createApplication({}, FirstApp));

    assert.equal(firstInitializerRunCount, 1, 'first initializer only was run when base class created');
    assert.equal(secondInitializerRunCount, 0, 'first initializer only was run when base class created');

    firstInitializerRunCount = 0;
    this.runTask(() => this.createSecondApplication({}, SecondApp));

    assert.equal(firstInitializerRunCount, 1, 'first initializer was run when subclass created');
    assert.equal(secondInitializerRunCount, 1, 'second initializers was run when subclass created');
  }

  [`@test initializers are per-app`](assert) {
    assert.expect(2);

    let FirstApp = Application.extend();

    FirstApp.initializer({
      name: 'abc',
      initialize(app) {}
    });

    expectAssertion(() => {
      FirstApp.initializer({
        name: 'abc',
        initialize(app) {}
      });
    });

    let SecondApp = Application.extend();
    SecondApp.instanceInitializer({
      name: 'abc',
      initialize(app) {}
    });

    assert.ok(true, 'Two apps can have initializers named the same.');
  }

  [`@test initializers are executed in their own context`](assert) {
    assert.expect(1);
    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'coolInitializer',
      myProperty: 'cool',
      initialize(application) {
        assert.equal(this.myProperty, 'cool', 'should have access to its own context');
      }
    });

    this.runTask(() => this.createApplication({}, MyApplication));
  }

  [`@test initializers throw a deprecation warning when receiving a second argument`](assert) {
    assert.expect(1);

    let MyApplication = Application.extend();

    MyApplication.initializer({
      name: 'deprecated',
      initialize(registry, application) {
      }
    });

    expectDeprecation(() => {
      this.runTask(() => this.createApplication({}, MyApplication));
    }, /The `initialize` method for Application initializer 'deprecated' should take only one argument - `App`, an instance of an `Application`./);
  }
});
<|endoftext|>