<commit_before>import React from 'react';

import { withStyles } from '@material-ui/core/styles';

import LinearProgress from '@material-ui/core/LinearProgress';
import Grid from '@material-ui/core/Grid';
import IconButton from '@material-ui/core/IconButton';

import CheckIcon from '@material-ui/icons/Check';
import CloseIcon from '@material-ui/icons/Close';
import CreateIcon from '@material-ui/icons/Create';

import blue from '@material-ui/core/colors/blue';
import grey from '@material-ui/core/colors/grey';
import red from '@material-ui/core/colors/red';

import IntroCard from '../components/IntroCard';

const styles = {
    root: {
        color: 'red'
    },
    button: {
        color: '#ffffff',
        position: 'absolute',
        bottom: '1rem',
        right: '1rem',
        boxShadow: '0 2px 2px 0 rgba(0, 0, 0, .14),0 3px 1px -2px rgba(0, 0, 0, .12),0 1px 5px 0 rgba(0, 0, 0, .2)'
    },
    save: {
        backgroundColor: red[500],
        right: '5rem',
        '&:hover': {
            backgroundColor: red[300]
        },
        '&:focus': {
            backgroundColor: red[500]
        }
    },
    close: {
        backgroundColor: grey[500],
        '&:hover': {
            backgroundColor: grey[300]
        },
        '&:focus': {
            backgroundColor: grey[500]
        }
    },
    edit: {
        backgroundColor: blue[500],
        opacity: '.7',
        '&:hover': {
            backgroundColor: blue[300]
        },
        '&:focus': {
            backgroundColor: blue[500]
        }
    }
};

class Intro extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            instances: [],
            edit: false
        };
    }

    static getDerivedStateFromProps(props) {

        const derived = {};

        if(props.instances) derived.instances = props.instances;

        return derived;
    }

    activateEditMode() {
        this.setState({
            edit: true
        });
    }

    deactivateEditMode() {

        const instances = this.state.instances.slice();

        for(const index in instances) {
            instances[index].editActive = instances[index].active;
        }

        this.setState({
            instances: instances,
            edit: false
        });
    }

    toggleCard(id) {

        const instances = this.state.instances.slice();

        if(!instances) return;

        for(const index in instances) {
            if(instances[index].id === id) {
                instances[index].editActive = !instances[index].editActive;
                break;
            }
        }

        this.setState({
            instances: instances
        });
    }

    saveCards() {
        const instances = this.state.instances.slice();

        for (const index in instances) {
            instances[index].active = instances[index].editActive;
        }

        this.setState({
            instances: instances,
            edit: false
        });

        this.props.updateIntro(instances);
    }

    getCards() {

        const cards = this.state.instances.map((instance, index) => {

            if ((!this.state.edit && instance.active) || this.state.edit) {

                let linkText = (instance.link) ? instance.link.replace(/^https?:\/\//, '') : '';
                const pos = linkText.indexOf('/');
                if (pos !== -1) {
                    linkText = linkText.substring(0, pos);
                }

                return (
                    <IntroCard
                        key={ index }
                        image={ instance.image }
                        title={ instance.name }
                        action={{ link: instance.link, text: linkText }}
                        color={ instance.color }
                        reveal={ instance.info }
                        edit={ this.state.edit }
                        enabled={ this.state.edit ? instance.editActive : instance.active }
                        toggleActivation={ () => this.toggleCard(instance.id) }
                    >
                        { instance.description }
                    </IntroCard>
                );
            } else {
                return null;
            }
        });

        return cards;
    }

    getButtons(classes) {

        const buttons = [];

        if (this.state.edit) {
            buttons.push(
                <IconButton
                    key="save"
                    className={ classes.button + ' ' + classes.save }
                    onClick={ () => this.saveCards() }
                >
                    <CheckIcon />
                </IconButton>
            );

            buttons.push(
                <IconButton
                    key="close"
                    className={ classes.button + ' ' + classes.close }
                    onClick={ () => this.deactivateEditMode() }
                >
                    <CloseIcon />
                </IconButton>
            )
        } else {
            buttons.push(
                <IconButton
                    key="edit"
                    className={ classes.button + ' ' + classes.edit }
                    onClick={ () => this.activateEditMode() }
                >
                    <CreateIcon />
                </IconButton>
            );
        }

        return buttons;
    }

    render() {

        if(!this.props.ready) {
            return(
                <LinearProgress />
            );
        }

        const { classes } = this.props;

        return(

                <Grid
                    container
                    spacing={ 2 }
                >
                    { this.getCards() }
                </Grid>
                { this.getButtons(classes) }

        );
    }
}

export default withStyles(styles)(Intro);<commit_msg>Added fab, changed styles, removed icon buttons<commit_after>import React from 'react';

import { withStyles } from '@material-ui/core/styles';

import LinearProgress from '@material-ui/core/LinearProgress';
import Fab from '@material-ui/core/Fab';
import Grid from '@material-ui/core/Grid';

import CheckIcon from '@material-ui/icons/Check';
import CloseIcon from '@material-ui/icons/Close';
import CreateIcon from '@material-ui/icons/Create';

import IntroCard from '../components/IntroCard';

const styles = theme => ({
    button: {
        position: 'absolute',
        bottom: theme.spacing(2),
        right: theme.spacing(2),
    },
    save: {
        backgroundColor: theme.palette.success.main,
        right: '5rem',
        '&:hover': {
            backgroundColor: theme.palette.success.dark
        }
    },
    close: {
        backgroundColor: theme.palette.error.main,
        '&:hover': {
            backgroundColor: theme.palette.error.dark
        }
    }
});

class Intro extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            instances: [],
            edit: false
        };
    }

    static getDerivedStateFromProps(props) {

        const derived = {};

        if(props.instances) derived.instances = props.instances;

        return derived;
    }

    activateEditMode() {
        this.setState({
            edit: true
        });
    }

    deactivateEditMode() {

        const instances = this.state.instances.slice();

        for(const index in instances) {
            instances[index].editActive = instances[index].active;
        }

        this.setState({
            instances: instances,
            edit: false
        });
    }

    toggleCard(id) {

        const instances = this.state.instances.slice();

        if(!instances) return;

        for(const index in instances) {
            if(instances[index].id === id) {
                instances[index].editActive = !instances[index].editActive;
                break;
            }
        }

        this.setState({
            instances: instances
        });
    }

    saveCards() {
        const instances = this.state.instances.slice();

        for (const index in instances) {
            instances[index].active = instances[index].editActive;
        }

        this.setState({
            instances: instances,
            edit: false
        });

        this.props.updateIntro(instances);
    }

    getCards() {

        const cards = this.state.instances.map((instance, index) => {

            if ((!this.state.edit && instance.active) || this.state.edit) {

                let linkText = (instance.link) ? instance.link.replace(/^https?:\/\//, '') : '';
                const pos = linkText.indexOf('/');
                if (pos !== -1) {
                    linkText = linkText.substring(0, pos);
                }

                return (
                    <IntroCard
                        key={ index }
                        image={ instance.image }
                        title={ instance.name }
                        action={{ link: instance.link, text: linkText }}
                        color={ instance.color }
                        reveal={ instance.info }
                        edit={ this.state.edit }
                        enabled={ this.state.edit ? instance.editActive : instance.active }
                        toggleActivation={ () => this.toggleCard(instance.id) }
                    >
                        { instance.description }
                    </IntroCard>
                );
            } else {
                return null;
            }
        });

        return cards;
    }

    getButtons(classes) {

        const buttons = [];

        if (this.state.edit) {
            buttons.push(
                <Fab
                    key="save"
                    color="primary"
                    className={ classes.button + ' ' + classes.save }
                    onClick={ () => this.saveCards() }
                >
                    <CheckIcon />
                </Fab>
            );

            buttons.push(
                <Fab
                    key="close"
                    color="primary"
                    className={ classes.button + ' ' + classes.close }
                    onClick={ () => this.deactivateEditMode() }
                >
                    <CloseIcon />
                </Fab>
            )
        } else {
            buttons.push(
                <Fab
                    color="primary"
                    key="edit"
                    className={ classes.button}
                    onClick={ () => this.activateEditMode() }
                >
                    <CreateIcon />
                </Fab>
            );
        }

        return buttons;
    }

    render() {

        if(!this.props.ready) {
            return(
                <LinearProgress />
            );
        }

        const { classes } = this.props;

        return(

                <Grid
                    container
                    spacing={ 2 }
                >
                    { this.getCards() }
                </Grid>
                { this.getButtons(classes) }

        );
    }
}

export default withStyles(styles)(Intro);<|endoftext|>


<commit_before>import '../../../assets/sass/_explorer.sass';
import templateUrl from './order-explorer.html';

export const OrderExplorerComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  templateUrl,
};

/** @ngInject */
function ComponentController($filter, lodash, ListView, Language, OrdersState, ShoppingCart, EventNotifications, Session, RBAC, ModalService,
                             CollectionsApi, sprintf, Polling, POLLING_INTERVAL) {
  const vm = this;
  vm.permissions = OrdersState.getPermissions();
  vm.$onInit = activate();
  vm.$onDestroy = function() {
    Polling.stop('orderListPolling');
  };

  function activate() {
    angular.extend(vm, {
      currentUser: Session.currentUser(),
      loading: false,
      orders: [],
      limit: 20,
      filterCount: 0,
      ordersList: [],
      selectedItemsList: [],
      limitOptions: [5, 10, 20, 50, 100, 200, 500, 1000],
      selectedItemsListCount: 0,
      // Functions
      resolveOrders: resolveOrders,
      listActionDisable: listActionDisable,
      updatePagination: updatePagination,
      updateMenuActionForItemFn: updateMenuActionForItemFn,
      // Config setup
      menuActions: getMenuActions(),
      toolbarConfig: getToolbarConfig(),
      listConfig: getListConfig(),
      expandedListConfig: getExpandedListConfig(),
      offset: 0,
      pollingInterval: POLLING_INTERVAL,
    });
    OrdersState.setSort({id: "placed_at", title: "Order Date", sortType: "numeric"}, false);
    resolveOrders(vm.limit, 0);
    Polling.start('orderListPolling', pollUpdateOrderList, vm.pollingInterval);
    Language.fixState(OrdersState, vm.toolbarConfig);
  }

  function getListConfig() {
    return {
      showSelectBox: checkApproval(),
      useExpandingRows: true,
      selectionMatchProp: 'id',
      onClick: expandRow,
      onCheckBoxChange: selectionChange,
    };
  }

  function pollUpdateOrderList() {
    resolveOrders(vm.limit, vm.offset, true);
  }

  function getExpandedListConfig() {
    return {
      showSelectBox: checkApproval(),
      selectionMatchProp: 'id',
      onClick: selectItem,
      onCheckBoxChange: extendedSelectionChange,
    };
  }

  function getToolbarConfig() {
    const sortConfig = {
      fields: getOrderSortFields(),
      onSortChange: sortChange,
      isAscending: OrdersState.getSort().isAscending,
      currentField: OrdersState.getSort().currentField,
    };

    const filterConfig = {
      fields: getOrderFilterFields(),
      resultsCount: 0,
      appliedFilters: OrdersState.filterApplied ? OrdersState.getFilters() : [],
      onFilterChange: orderFilterChange,
    };

    return {
      sortConfig: sortConfig,
      filterConfig: filterConfig,
      actionsConfig: {
        actionsInclude: checkApproval(),
      },
    };
  }

  function getOrderFilterFields() {
    return [
      ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
      ListView.createFilterField('id', __('Order ID'), __('Filter by ID'), 'text'),
      ListView.createFilterField('placed_at', __('Order Date'), __('Filter by Order Date'), 'text'),
    ];
  }

  function getOrderSortFields() {
    return [
      ListView.createSortField('name', __('Name'), 'alpha'),
      ListView.createSortField('id', __('Order ID'), 'numeric'),
      ListView.createSortField('placed_at', __('Order Date'), 'numeric'),
    ];
  }

  function getMenuActions() {
    const menuActions = [];
    if (vm.permissions.copy) {
      menuActions.push({
        name: __('Duplicate'),
        actionName: 'duplicate',
        title: __('Duplicate Order'),
        actionFn: duplicateOrder,
        isDisabled: true,
      });
    }

    if (vm.permissions.delete) {
      menuActions.push(
        {
          name: __('Remove'),
          actionName: 'remove',
          title: __('Remove Order'),
          actionFn: removeOrder,
          isDisabled: false,
        }
      );
    }

    return checkApproval() ? menuActions : null;
  }

  function expandRow(item) {
    if (!item.disableRowExpansion) {
      item.isExpanded = !item.isExpanded;
    }
  }

  function sortChange(sortId, direction) {
    OrdersState.setSort(sortId, direction);
    resolveOrders(vm.limit, 0);
  }

  function orderFilterChange(filters) {
    vm.ordersList = ListView.applyFilters(filters, vm.ordersList, vm.orders, OrdersState, orderMatchesFilter);
    resolveOrders(vm.limit, 0);
  }

  function orderMatchesFilter(item, filter) {
    if (filter.id === 'name') {
      return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'id') {
      return String(item.id).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'placed_at') {
      return $filter('date')(item.placed_at || item.updated_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    }

    return false;
  }

  function selectionChange(item) {
    if (angular.isDefined(item.service_requests)) {
      // if any child requests are unchecked, check them otherwise uncheck all
      if (item.service_requests.length === lodash.filter(item.service_requests, returnSelected).length) {
        item.service_requests.forEach((request) => {
          request.selected = false;
        });
      } else {
        item.service_requests.forEach((request) => {
          request.selected = true;
        });
      }
      vm.selectedItemsList = item.service_requests.filter(function(item) {
        return item.selected;
      });
    }
    vm.selectedItemsListCount = vm.selectedItemsList.length;
  }

  function extendedSelectionChange(item) {
    const parent = lodash.find(vm.ordersList, findItem);

    if (parent.service_requests.length === lodash.filter(parent.service_requests, returnSelected).length) {
      parent.selected = !parent.selected;
    } else {
      parent.selected = false;
    }

    lodash.indexOf(vm.selectedItemsList, item) === -1 ? vm.selectedItemsList.push(item) : lodash.pull(vm.selectedItemsList, item);

    vm.selectedItemsListCount = vm.selectedItemsList.length;

    function findItem(order) {
      return lodash.find(order.service_requests, item);
    }
  }

  function returnSelected(item) {
    return item.selected;
  }

  function resolveOrders(limit, offset, refresh) {
    if (!refresh) {
      vm.loading = true;
    }
    var existingOrders = (angular.isDefined(vm.ordersList) && refresh ? angular.copy(vm.ordersList) : []);

    vm.offset = offset;
    getFilterCount().then(() => {
      OrdersState.getOrders(
        limit,
        offset,
        OrdersState.getFilters(),
        OrdersState.getSort().currentField,
        OrdersState.getSort().isAscending,
        refresh).then(querySuccess, queryFailure);
    });

    function querySuccess(response) {
      vm.loading = false;
      vm.orders = [];
      vm.selectedItemsList = [];
      vm.toolbarConfig.filterConfig.resultsCount = vm.filterCount;

      angular.forEach(response.resources, checkExpansion);

      function checkExpansion(item) {
        if (angular.isDefined(item.id)) {
          item.disableRowExpansion = angular.isUndefined(item.service_requests)
            || (angular.isDefined(item.service_requests) && item.service_requests.length < 1);
          let dataRow = item;
          if (refresh) {
            dataRow = refreshRow(item);
          }
          vm.orders.push(dataRow);
        }
      }

      function refreshRow(item) {
        existingOrders.forEach((order) => {
          if (order.id === item.id) {
            item.isExpanded = angular.isDefined(order.isExpanded) ? order.isExpanded : false;
            item.selected = angular.isDefined(order.selected) ? order.selected : false;
            if (item.selected) {
              vm.selectedItemsList.push(item);
            }
            lodash.pull(existingOrders, order);
          }
        });

        return item;
      }

      vm.ordersList = angular.copy(vm.orders);
    }

    function queryFailure(_error) {
      vm.loading = false;
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function getFilterCount() {
    return new Promise((resolve, reject) => {
      OrdersState.getMinimal(OrdersState.getFilters()).then(querySuccess, queryFailure);

      function querySuccess(result) {
        vm.filterCount = result.subcount;
        resolve();
      }

      function queryFailure(_error) {
        EventNotifications.error(__('There was an error loading orders.'));
        reject();
      }
    });
  }

  function duplicateOrder(_action, item) {
    ShoppingCart.reset();
    ShoppingCart.delete();

    CollectionsApi.post('service_orders', null, null, {action: "copy", resources: [{id: item.id}]}).then(success, failure);

    function success(response) {
      ShoppingCart.reload();
      EventNotifications.success(sprintf(__('%s was duplicated, id # %d.'), item.name, response.results[0].id));
    }

    function failure(_error) {
      EventNotifications.error(sprintf(__('There was an error duplicating %s.'), item.name));
    }
  }

  function removeOrder(_action, item) {
    const modalOptions = {
      component: 'processOrderModal',
      resolve: {
        order: function() {
          return item;
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function checkApproval() {
    return lodash.reduce(lodash.map(['miq_request_approval', 'miq_request_admin'], RBAC.has));
  }

  function selectItem(item) {
    item.selected = !item.selected;
    extendedSelectionChange(item);
  }

  function listActionDisable(config, items) {
    items.length <= 0 ? config.isDisabled = true : config.isDisabled = false;
  }

  function updatePagination(limit, offset) {
    vm.limit = limit;
    vm.offset = offset;
    vm.resolveOrders(limit, offset);
  }

  function updateMenuActionForItemFn(action, item) {
    if (action.actionName === 'duplicate') {
      action.isDisabled = item.state !== 'cart' && angular.isUndefined(item.service_requests);
    }
  }
}
<commit_msg>Ensure my orders selection results are reported correctly<commit_after>import "../../../assets/sass/_explorer.sass";
import templateUrl from "./order-explorer.html";

export const OrderExplorerComponent = {
  controller: ComponentController,
  controllerAs: 'vm',
  templateUrl,
};

/** @ngInject */
function ComponentController($filter, lodash, ListView, Language, OrdersState, ShoppingCart, EventNotifications, Session, RBAC, ModalService,
                             CollectionsApi, sprintf, Polling, POLLING_INTERVAL) {
  const vm = this;
  vm.permissions = OrdersState.getPermissions();
  vm.$onInit = activate();
  vm.$onDestroy = function() {
    Polling.stop('orderListPolling');
  };

  function activate() {
    angular.extend(vm, {
      currentUser: Session.currentUser(),
      loading: false,
      orders: [],
      limit: 20,
      filterCount: 0,
      ordersList: [],
      selectedItemsList: [],
      limitOptions: [5, 10, 20, 50, 100, 200, 500, 1000],
      // Functions
      resolveOrders: resolveOrders,
      listActionDisable: listActionDisable,
      updatePagination: updatePagination,
      updateMenuActionForItemFn: updateMenuActionForItemFn,
      // Config setup
      menuActions: getMenuActions(),
      toolbarConfig: getToolbarConfig(),
      listConfig: getListConfig(),
      expandedListConfig: getExpandedListConfig(),
      offset: 0,
      pollingInterval: POLLING_INTERVAL,
    });
    OrdersState.setSort({id: "placed_at", title: "Order Date", sortType: "numeric"}, false);
    resolveOrders(vm.limit, 0);
    Polling.start('orderListPolling', pollUpdateOrderList, vm.pollingInterval);
    Language.fixState(OrdersState, vm.toolbarConfig);
  }

  function getListConfig() {
    return {
      showSelectBox: checkApproval(),
      useExpandingRows: true,
      selectionMatchProp: 'id',
      onClick: expandRow,
      onCheckBoxChange: selectionChange,
    };
  }

  function pollUpdateOrderList() {
    resolveOrders(vm.limit, vm.offset, true);
  }

  function getExpandedListConfig() {
    return {
      showSelectBox: checkApproval(),
      selectionMatchProp: 'id',
      onClick: selectItem,
      onCheckBoxChange: extendedSelectionChange,
    };
  }

  function getToolbarConfig() {
    const sortConfig = {
      fields: getOrderSortFields(),
      onSortChange: sortChange,
      isAscending: OrdersState.getSort().isAscending,
      currentField: OrdersState.getSort().currentField,
    };

    const filterConfig = {
      fields: getOrderFilterFields(),
      resultsCount: 0,
      totalCount: 0,
      selectedCount: 0,
      appliedFilters: OrdersState.filterApplied ? OrdersState.getFilters() : [],
      onFilterChange: orderFilterChange,
    };

    return {
      sortConfig: sortConfig,
      filterConfig: filterConfig,
      actionsConfig: {
        actionsInclude: checkApproval(),
      },
    };
  }

  function getOrderFilterFields() {
    return [
      ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
      ListView.createFilterField('id', __('Order ID'), __('Filter by ID'), 'text'),
      ListView.createFilterField('placed_at', __('Order Date'), __('Filter by Order Date'), 'text'),
    ];
  }

  function getOrderSortFields() {
    return [
      ListView.createSortField('name', __('Name'), 'alpha'),
      ListView.createSortField('id', __('Order ID'), 'numeric'),
      ListView.createSortField('placed_at', __('Order Date'), 'numeric'),
    ];
  }

  function getMenuActions() {
    const menuActions = [];
    if (vm.permissions.copy) {
      menuActions.push({
        name: __('Duplicate'),
        actionName: 'duplicate',
        title: __('Duplicate Order'),
        actionFn: duplicateOrder,
        isDisabled: true,
      });
    }

    if (vm.permissions.delete) {
      menuActions.push(
        {
          name: __('Remove'),
          actionName: 'remove',
          title: __('Remove Order'),
          actionFn: removeOrder,
          isDisabled: false,
        }
      );
    }

    return checkApproval() ? menuActions : null;
  }

  function expandRow(item) {
    if (!item.disableRowExpansion) {
      item.isExpanded = !item.isExpanded;
    }
  }

  function sortChange(sortId, direction) {
    OrdersState.setSort(sortId, direction);
    resolveOrders(vm.limit, 0);
  }

  function orderFilterChange(filters) {
    vm.ordersList = ListView.applyFilters(filters, vm.ordersList, vm.orders, OrdersState, orderMatchesFilter);
    resolveOrders(vm.limit, 0);
  }

  function orderMatchesFilter(item, filter) {
    if (filter.id === 'name') {
      return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'id') {
      return String(item.id).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    } else if (filter.id === 'placed_at') {
      return $filter('date')(item.placed_at || item.updated_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
    }

    return false;
  }

  function selectionChange(item) {
    if (angular.isDefined(item.service_requests)) {
      // if any child requests are unchecked, check them otherwise uncheck all
      if (item.service_requests.length === lodash.filter(item.service_requests, returnSelected).length) {
        item.service_requests.forEach((request) => {
          request.selected = false;
        });
      } else {
        item.service_requests.forEach((request) => {
          request.selected = true;
        });
      }
    }
    vm.selectedItemsList = vm.ordersList.filter((item) => item.selected);
    vm.toolbarConfig.filterConfig.selectedCount = vm.selectedItemsList.length;
  }

  function extendedSelectionChange(item) {
    const parent = lodash.find(vm.ordersList, findItem);

    if (parent.service_requests.length === lodash.filter(parent.service_requests, returnSelected).length) {
      parent.selected = !parent.selected;
    } else {
      parent.selected = false;
    }

    lodash.indexOf(vm.selectedItemsList, item) === -1 ? vm.selectedItemsList.push(item) : lodash.pull(vm.selectedItemsList, item);

    vm.toolbarConfig.filterConfig.selectedCount = vm.selectedItemsList.length;

    function findItem(order) {
      return lodash.find(order.service_requests, item);
    }
  }

  function returnSelected(item) {
    return item.selected;
  }

  function resolveOrders(limit, offset, refresh) {
    if (!refresh) {
      vm.loading = true;
    }
    var existingOrders = (angular.isDefined(vm.ordersList) && refresh ? angular.copy(vm.ordersList) : []);

    vm.offset = offset;
    getFilterCount().then(() => {
      OrdersState.getOrders(
        limit,
        offset,
        OrdersState.getFilters(),
        OrdersState.getSort().currentField,
        OrdersState.getSort().isAscending,
        refresh).then(querySuccess, queryFailure);
    });

    function querySuccess(response) {
      vm.loading = false;
      vm.orders = [];
      vm.selectedItemsList = [];
      vm.toolbarConfig.filterConfig.resultsCount = vm.filterCount;
      vm.toolbarConfig.filterConfig.totalCount = response.subcount;

      angular.forEach(response.resources, checkExpansion);

      function checkExpansion(item) {
        if (angular.isDefined(item.id)) {
          item.disableRowExpansion = angular.isUndefined(item.service_requests)
            || (angular.isDefined(item.service_requests) && item.service_requests.length < 1);
          let dataRow = item;
          if (refresh) {
            dataRow = refreshRow(item);
          }
          vm.orders.push(dataRow);
        }
      }

      function refreshRow(item) {
        existingOrders.forEach((order) => {
          if (order.id === item.id) {
            item.isExpanded = angular.isDefined(order.isExpanded) ? order.isExpanded : false;
            item.selected = angular.isDefined(order.selected) ? order.selected : false;
            if (item.selected) {
              vm.selectedItemsList.push(item);
            }
            lodash.pull(existingOrders, order);
          }
        });

        return item;
      }

      vm.ordersList = angular.copy(vm.orders);
    }

    function queryFailure(_error) {
      vm.loading = false;
      EventNotifications.error(__('There was an error loading orders.'));
    }
  }

  function getFilterCount() {
    return new Promise((resolve, reject) => {
      OrdersState.getMinimal(OrdersState.getFilters()).then(querySuccess, queryFailure);

      function querySuccess(result) {
        vm.filterCount = result.subcount;
        resolve();
      }

      function queryFailure(_error) {
        EventNotifications.error(__('There was an error loading orders.'));
        reject();
      }
    });
  }

  function duplicateOrder(_action, item) {
    ShoppingCart.reset();
    ShoppingCart.delete();

    CollectionsApi.post('service_orders', null, null, {action: "copy", resources: [{id: item.id}]}).then(success, failure);

    function success(response) {
      ShoppingCart.reload();
      EventNotifications.success(sprintf(__('%s was duplicated, id # %d.'), item.name, response.results[0].id));
    }

    function failure(_error) {
      EventNotifications.error(sprintf(__('There was an error duplicating %s.'), item.name));
    }
  }

  function removeOrder(_action, item) {
    const modalOptions = {
      component: 'processOrderModal',
      resolve: {
        order: function() {
          return item;
        },
      },
    };
    ModalService.open(modalOptions);
  }

  function checkApproval() {
    return lodash.reduce(lodash.map(['miq_request_approval', 'miq_request_admin'], RBAC.has));
  }

  function selectItem(item) {
    item.selected = !item.selected;
    extendedSelectionChange(item);
  }

  function listActionDisable(config, items) {
    items.length <= 0 ? config.isDisabled = true : config.isDisabled = false;
  }

  function updatePagination(limit, offset) {
    vm.limit = limit;
    vm.offset = offset;
    vm.resolveOrders(limit, offset);
  }

  function updateMenuActionForItemFn(action, item) {
    if (action.actionName === 'duplicate') {
      action.isDisabled = item.state !== 'cart' && angular.isUndefined(item.service_requests);
    }
  }
}
<|endoftext|>


<commit_before>/*global beforeEach, afterEach, describe, it, inject, expect, module, spyOn, CodeMirror, angular*/
describe('uiCodemirror', function () {
    'use strict';

    var scope, $compile;
    beforeEach(function() {
        // throw some garbage in the codemirror cfg to be sure it's getting thru to the directive
        angular.module('ui.config').value('ui.config', {codemirror: {bar: 'baz'}});
    });
    beforeEach(module('ui'));
    beforeEach(inject(function (_$rootScope_, _$compile_) {
        scope = _$rootScope_.$new();
        $compile = _$compile_;
    }));
    afterEach(function() {
        angular.module('ui.config').value('ui.config', {}); // cleanup
    });
    describe('compiling this directive', function () {
        it('should throw an error if used against a non-textarea', function () {
            function compile() {
                $compile('

')(scope);
            }
            expect(compile).toThrow();
        });
        it('should not throw an error when used against a textarea', function () {
            function compile() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            }
            expect(compile).not.toThrow();
        });
        it('should throw an error when no ngModel attribute defined', function () {
            function compile() {
                $compile('<textarea ui-codemirror></textarea>')(scope);
            }
            expect(compile).toThrow();
        });
        it('should watch the uiCodemirror attribute', function () {
            spyOn(scope, '$watch');
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            expect(scope.$watch).toHaveBeenCalled();
        });
        it('should include the passed options', function () {
            spyOn(CodeMirror, 'fromTextArea');
            $compile('<textarea ui-codemirror="{foo: \'bar\'}" ng-model="foo"></textarea>')(scope);
            expect(CodeMirror.fromTextArea.mostRecentCall.args[1].foo).toEqual('bar');
        });
        it('should include the default options', function () {
            spyOn(CodeMirror, 'fromTextArea');
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            expect(CodeMirror.fromTextArea.mostRecentCall.args[1].bar).toEqual('baz');
        });
    });
    describe('when the model changes', function () {
        it('should update the IDE', function () {
            var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.foo = 'bar';
            scope.$apply();
            expect(element.siblings().text().trim()).toBe(scope.foo);
        });
    });
    describe('when the IDE changes', function () {
        it('should update the model', function () {
            var codemirror,
                fromTextArea = CodeMirror.fromTextArea;
            spyOn(CodeMirror, 'fromTextArea').andCallFake(function () {
                codemirror = fromTextArea.apply(this, arguments);
                return codemirror;
            });
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.foo = 'bar';
            scope.$apply();
            var value = 'baz';
            codemirror.setValue(value);
            expect(scope.foo).toBe(value);
        });
    });
    describe('when the model is undefined/null', function () {
        it('should update the IDE with an empty string', function () {
            var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.$apply();
            expect(scope.foo).toBe(undefined);
            expect(element.siblings().text().trim()).toBe('');
            scope.foo = null;
            scope.$apply();
            expect(scope.foo).toBe(null);
            expect(element.siblings().text().trim()).toBe('');
        });
    });
    describe('when the model is an object or an array', function () {
        it('should throw an error', function () {
            function compileWithObject() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
                scope.foo = {};
                scope.$apply();
            }

            function compileWithArray() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
                scope.foo = [];
                scope.$apply();
            }

            expect(compileWithObject).toThrow();
            expect(compileWithArray).toThrow();
        });
    });
});<commit_msg>adding whitespace for readability<commit_after>/*global beforeEach, afterEach, describe, it, inject, expect, module, spyOn, CodeMirror, angular*/
describe('uiCodemirror', function () {
    'use strict';

    var scope, $compile;
    beforeEach(function() {
        // throw some garbage in the codemirror cfg to be sure it's getting thru to the directive
        angular.module('ui.config').value('ui.config', {codemirror: {bar: 'baz'}});
    });
    beforeEach(module('ui'));
    beforeEach(inject(function (_$rootScope_, _$compile_) {
        scope = _$rootScope_.$new();
        $compile = _$compile_;
    }));

    afterEach(function() {
        angular.module('ui.config').value('ui.config', {}); // cleanup
    });

    describe('compiling this directive', function () {
        it('should throw an error if used against a non-textarea', function () {
            function compile() {
                $compile('

')(scope);
            }
            expect(compile).toThrow();
        });

        it('should not throw an error when used against a textarea', function () {
            function compile() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            }
            expect(compile).not.toThrow();
        });

        it('should throw an error when no ngModel attribute defined', function () {
            function compile() {
                $compile('<textarea ui-codemirror></textarea>')(scope);
            }
            expect(compile).toThrow();
        });

        it('should watch the uiCodemirror attribute', function () {
            spyOn(scope, '$watch');
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            expect(scope.$watch).toHaveBeenCalled();
        });

        it('should include the passed options', function () {
            spyOn(CodeMirror, 'fromTextArea');
            $compile('<textarea ui-codemirror="{foo: \'bar\'}" ng-model="foo"></textarea>')(scope);
            expect(CodeMirror.fromTextArea.mostRecentCall.args[1].foo).toEqual('bar');
        });

        it('should include the default options', function () {
            spyOn(CodeMirror, 'fromTextArea');
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            expect(CodeMirror.fromTextArea.mostRecentCall.args[1].bar).toEqual('baz');
        });
    });

    describe('when the model changes', function () {
        it('should update the IDE', function () {
            var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.foo = 'bar';
            scope.$apply();
            expect(element.siblings().text().trim()).toBe(scope.foo);
        });
    });

    describe('when the IDE changes', function () {
        it('should update the model', function () {
            var codemirror,
                fromTextArea = CodeMirror.fromTextArea;
            spyOn(CodeMirror, 'fromTextArea').andCallFake(function () {
                codemirror = fromTextArea.apply(this, arguments);
                return codemirror;
            });
            $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.foo = 'bar';
            scope.$apply();
            var value = 'baz';
            codemirror.setValue(value);
            expect(scope.foo).toBe(value);
        });
    });

    describe('when the model is undefined/null', function () {
        it('should update the IDE with an empty string', function () {
            var element = $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
            scope.$apply();
            expect(scope.foo).toBe(undefined);
            expect(element.siblings().text().trim()).toBe('');
            scope.foo = null;
            scope.$apply();
            expect(scope.foo).toBe(null);
            expect(element.siblings().text().trim()).toBe('');
        });
    });

    describe('when the model is an object or an array', function () {
        it('should throw an error', function () {
            function compileWithObject() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
                scope.foo = {};
                scope.$apply();
            }

            function compileWithArray() {
                $compile('<textarea ui-codemirror ng-model="foo"></textarea>')(scope);
                scope.foo = [];
                scope.$apply();
            }

            expect(compileWithObject).toThrow();
            expect(compileWithArray).toThrow();
        });
    });
});<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 SUSE Linux
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE.txt file for details.
 */

(function () {
  'use strict';

  angular.module('janusHangouts')
    .directive('jhMainFeedInfo', jhMainFeedInfoDirective);

  jhMainFeedInfoDirective.$inject = ['FeedsService'];

  function jhMainFeedInfoDirective(FeedsService) {
    return {
      restrict: 'EA',
      templateUrl: 'app/components/feed/jh-main-feed-info.html',
      scope: {},
      controllerAs: 'vm',
      bindToController: true,
      controller: jhMainFeedInfoCtrl
    };

    function jhMainFeedInfoCtrl() {
      /* jshint: validthis */
      var vm = this;
      vm.name = name;

      function name() {
        return FeedsService.findMain().display;
      }
    }
  }
})();
<commit_msg>Fix bug in jh-main-feed-info<commit_after>/*
 * Copyright (C) 2015 SUSE Linux
 *
 * This software may be modified and distributed under the terms
 * of the MIT license.  See the LICENSE.txt file for details.
 */

(function () {
  'use strict';

  angular.module('janusHangouts')
    .directive('jhMainFeedInfo', jhMainFeedInfoDirective);

  jhMainFeedInfoDirective.$inject = ['FeedsService'];

  function jhMainFeedInfoDirective(FeedsService) {
    return {
      restrict: 'EA',
      templateUrl: 'app/components/feed/jh-main-feed-info.html',
      scope: {},
      controllerAs: 'vm',
      bindToController: true,
      controller: jhMainFeedInfoCtrl
    };

    function jhMainFeedInfoCtrl() {
      /* jshint: validthis */
      var vm = this;
      vm.name = name;

      function name() {
        var feed = FeedsService.findMain();
        var name = (feed !== null) ? feed.display : "";
        return name;
      }
    }
  }
})();
<|endoftext|>


<commit_before>'use strict'

const { toNumber } = require('lodash')
const strmatch = require('str-match')
// TODO: pass options to strmatch to decide how to apply the clean regex

/**
 * Detect year of 4 digits in [2000-2999] range.
 * @example 2013
 */
const REGEX_YEAR = /2[0-9]{3}/

function response (year, output) {
  return { data: {year}, output }
}

function year (str) {
  const year = strmatch(str, REGEX_YEAR)
  if (!year.test) return response(undefined, str)
  year.match = toNumber(year.match)
  return response(year.match, year.output)
}

year.regex = REGEX_YEAR

module.exports = year
<commit_msg>Add more info<commit_after>'use strict'

const { toNumber } = require('lodash')
const strmatch = require('str-match')
// TODO: pass options to strmatch to decide how to apply the clean regex
// That's useful for example for clean global results instead of only first.

/**
 * Detect year of 4 digits in [2000-2999] range.
 * @example 2013
 */
const REGEX_YEAR = /2[0-9]{3}/

function response (year, output) {
  return { data: {year}, output }
}

function year (str) {
  const year = strmatch(str, REGEX_YEAR)
  if (!year.test) return response(undefined, str)
  year.match = toNumber(year.match)
  return response(year.match, year.output)
}

year.regex = REGEX_YEAR

module.exports = year
<|endoftext|>


<commit_before>/* PLAYER_ASSET.JS
 *
 */

"use strict"

////////////////////////////////////////////////////////////////////////////////
var tick = 0;
// Player
GameAsset.player = new GameAsset(0.8, 0.8, true, function(x,y,asset,player) {
	context.save();
	// Precomputations ---------------------------------------------------------

	tick++;
	// Time-Oscillating tail wag amplitude, increases with proximity to meat
	var meatDist = meatProximity(player.x, player.y) + 1
	var tailWag = Math.sin(tick/meatDist/12)/3;

	// Player speed
	var playerSpeed =  magnitude(player.vx, player.vy);
	var legAmplitude = Math.min(0.16, 2 * ( 2/(1+Math.exp(-playerSpeed)) - 1));
	var legPhase = tick / 3;

	// Entering Player Coordinates ---------------------------------------------

	// Move origin to player center
	context.translate(x,y);
	asset.vel.x = player.vx;
	asset.vel.y = player.vy;

	// Draw Feet ---------------------------------------------------------------

	// Store body segments
	var frontBody = asset.segments[1];
	var backBody = asset.segments[2];

	// Center origin on front body segment
	context.save();
		context.translate(frontBody.pos.x, frontBody.pos.y);
		context.rotate(frontBody.dir.angle());
		// Front Right
		var fl_off = Math.sin( legPhase ) * legAmplitude;
		context.drawImage(asset.frontRightImg, -0.35+fl_off, 0.15, 0.4, 0.25);
		// Front Left
		var fr_off = Math.sin( legPhase + Math.PI ) * legAmplitude;
		context.drawImage(asset.frontLeftImg, -0.35+fr_off, -0.12, 0.4, -0.25);
	context.restore();

	// Center origin on back body segment
	context.save();
		context.translate(backBody.pos.x, backBody.pos.y);
		context.rotate(backBody.dir.angle());
		// Back Right
		var bl_off = Math.sin( legPhase + Math.PI / 2) * legAmplitude;
		context.drawImage(asset.backRightImg, -0.35+bl_off, 0.15, 0.4, 0.25);
		// Back Left
		var br_off = Math.sin( legPhase + 3 * Math.PI / 2 ) * legAmplitude;
		context.drawImage(asset.backLeftImg, -0.35+br_off, -0.12, 0.4, -0.25);
	context.restore();

	// Move Trailing Segments --------------------------------------------------

	// Draw and position remaining segments
	for(var i = 1; i < asset.segments.length; i++){
		var follow = asset.segments[i-1];	// segment to follow
		var segment = asset.segments[i];	// current segment to control

		// Move towards back end of 'follow'
		var goalPos = follow.pos.subtract(follow.dir.norm().multiply(follow.size+follow.offset));
		segment.pos = segment.pos.add(
			segment.pos.to( goalPos )
		);

		// Rotate in direction of 'follow'
		segment.dir = segment.dir.rotateTowards2(follow.dir, segment.spring);

		// Draw
		context.save();
			context.translate(segment.pos.x, segment.pos.y);
			context.rotate(segment.dir.angle()+(i==3?tailWag:0));
			if(segment.img){
				context.drawImage(
					 segment.img,		// image
					-segment.size,		// top-left x
					-segment.width/2, 	// top-left y
					 segment.size,		// length
					 segment.width		// thickness
				);
			}
		context.restore();
	}

	// Move Head (needs to draw on top) ----------------------------------------

	// First Segment
	var headSegment = asset.segments[0];

	// If player is moving, rotate head in direction of velocity
	if(asset.vel.mag() > 0.03){
		headSegment.dir = headSegment.dir.rotateTowards2(asset.vel, 1/10);
		player.drawx = headSegment.dir.x;
		player.drawy = headSegment.dir.y;
	}

	// Draw first segment
	context.save();
	context.fillStyle = "rgba(0,0,0,0.5)";
	context.rotate( headSegment.dir.angle(), 1/5 );
	context.drawImage(
		headSegment.img,
		-headSegment.size,
		-headSegment.width/2,
		headSegment.size,
		headSegment.width
	);
	context.restore();

	// Exiting Player Coordinates ----------------------------------------------
	context.restore();
});

//// Player Setup --------------------------------------------------------------

// Create HTML Img elements
GameAsset.player.headImg = new Image();
GameAsset.player.headImg.src = "assets/graphics/wolf/wolf-head.png";
GameAsset.player.frontImg = new Image();
GameAsset.player.frontImg.src = "assets/graphics/wolf/wolf-front.png";
GameAsset.player.behindImg = new Image();
GameAsset.player.behindImg.src = "assets/graphics/wolf/wolf-behind.png";
GameAsset.player.tailImg = new Image();
GameAsset.player.tailImg.src = "assets/graphics/wolf/wolf-tail.png";
GameAsset.player.frontLeftImg = new Image();
GameAsset.player.frontLeftImg.src = "assets/graphics/wolf/wolf_fl_leg.png";
GameAsset.player.frontRightImg = new Image();
GameAsset.player.frontRightImg.src = "assets/graphics/wolf/wolf_fr_leg.png";
GameAsset.player.backLeftImg = new Image();
GameAsset.player.backLeftImg.src = "assets/graphics/wolf/wolf_bl_leg.png";
GameAsset.player.backRightImg = new Image();
GameAsset.player.backRightImg.src = "assets/graphics/wolf/wolf_br_leg.png";

// Things
var segmentImages = [GameAsset.player.headImg,
				 GameAsset.player.frontImg,
				 GameAsset.player.behindImg,
				 GameAsset.player.tailImg];
var segmentSizes = [0.6,0.6,0.6,0.8];
var segmentWidths =[0.6,0.5,0.6,0.2];
var segmentOffsets=[-0.1,-0.15,-0.1,0];
var segmentSpring =[1,1/5,1/10,1/10];

// Segments
GameAsset.player.segments = [];
var numSegments = 4;
var positionSum = 0;
var offsetSum = 0;
for(var i=0; i < numSegments; i++){
	GameAsset.player.segments.push({
		pos: new Vector(positionSum, 0),// position (tiles)
		dir: new Vector(1,0).norm(),	// vector in direction of segment
		size: segmentSizes[i],
		offset: segmentOffsets[i],
		width: segmentWidths[i],
		img: segmentImages[i],
		spring: segmentSpring[i]
	});
	// accumulate sizes
	positionSum += segmentSizes[i] + segmentOffsets[i];
}
GameAsset.player.vel = new Vector(0,0);

////////////////////////////////////////////////////////////////////////////////

/*GameAsset.player = new GameAsset(0.8, 0.8, true, function(x,y,asset,obj) {
	// Save coordinate transforms to leave untouched by this function
	context.save();

	// Move context origin to player's center
	context.translate(x,y);

	// If the player is moving at least a little...
	if (magnitude(obj.vx, obj.vy) > 0.03) {
		// turning in the direction they're moving
		obj.drawx = obj.drawx * 0.9 + 0.1 * obj.vx;
		obj.drawy = obj.drawy * 0.9 + 0.1 * obj.vy;
	}

	// We're centered on the player's center so rotate in the right direction
	context.rotate( Math.atan2(  obj.drawy, obj.drawx ) + Math.PI / 2 );

	// Move up a little to center on neck
	context.translate(0, 0.44);

	// If we're currently leaping...
	if (obj.leapwait > 45) {
		// Motion blur
		for (var i = 0; i < 1.2; i += 0.4) {
			context.globalAlpha = (1 - i);
			context.drawImage(asset.img,-.25,-.75 + i, 0.5, 1.5);
		}
		context.globalAlpha = 1;
	}

	// Draw the wolf
	context.drawImage(asset.img,-.25,-.75, 0.5, 1.5);

	// Put the context like it was before
	context.restore();
});*/<commit_msg>player asset now uses global tick<commit_after>/* PLAYER_ASSET.JS
 *
 */

"use strict"

////////////////////////////////////////////////////////////////////////////////

// Player
GameAsset.player = new GameAsset(0.8, 0.8, true, function(x,y,asset,player) {
	context.save();
	// Precomputations ---------------------------------------------------------

	// Time-Oscillating tail wag amplitude, increases with proximity to meat
	var meatDist = meatProximity(player.x, player.y) + 1
	var tailWag = Math.sin(World.tick/meatDist/12)/3;

	// Player speed
	var playerSpeed =  magnitude(player.vx, player.vy);
	var legAmplitude = Math.min(0.16, 2 * ( 2/(1+Math.exp(-playerSpeed)) - 1));
	var legPhase = World.tick / 3;

	// Entering Player Coordinates ---------------------------------------------

	// Move origin to player center
	context.translate(x,y);
	asset.vel.x = player.vx;
	asset.vel.y = player.vy;

	// Draw Feet ---------------------------------------------------------------

	// Store body segments
	var frontBody = asset.segments[1];
	var backBody = asset.segments[2];

	// Center origin on front body segment
	context.save();
		context.translate(frontBody.pos.x, frontBody.pos.y);
		context.rotate(frontBody.dir.angle());
		// Front Right
		var fl_off = Math.sin( legPhase ) * legAmplitude;
		context.drawImage(asset.frontRightImg, -0.35+fl_off, 0.15, 0.4, 0.25);
		// Front Left
		var fr_off = Math.sin( legPhase + Math.PI ) * legAmplitude;
		context.drawImage(asset.frontLeftImg, -0.35+fr_off, -0.12, 0.4, -0.25);
	context.restore();

	// Center origin on back body segment
	context.save();
		context.translate(backBody.pos.x, backBody.pos.y);
		context.rotate(backBody.dir.angle());
		// Back Right
		var bl_off = Math.sin( legPhase + Math.PI / 2) * legAmplitude;
		context.drawImage(asset.backRightImg, -0.35+bl_off, 0.15, 0.4, 0.25);
		// Back Left
		var br_off = Math.sin( legPhase + 3 * Math.PI / 2 ) * legAmplitude;
		context.drawImage(asset.backLeftImg, -0.35+br_off, -0.12, 0.4, -0.25);
	context.restore();

	// Move Trailing Segments --------------------------------------------------

	// Draw and position remaining segments
	for(var i = 1; i < asset.segments.length; i++){
		var follow = asset.segments[i-1];	// segment to follow
		var segment = asset.segments[i];	// current segment to control

		// Move towards back end of 'follow'
		var goalPos = follow.pos.subtract(follow.dir.norm().multiply(follow.size+follow.offset));
		segment.pos = segment.pos.add(
			segment.pos.to( goalPos )
		);

		// Rotate in direction of 'follow'
		segment.dir = segment.dir.rotateTowards2(follow.dir, segment.spring);

		// Draw
		context.save();
			context.translate(segment.pos.x, segment.pos.y);
			context.rotate(segment.dir.angle()+(i==3?tailWag:0));
			if(segment.img){
				context.drawImage(
					 segment.img,		// image
					-segment.size,		// top-left x
					-segment.width/2, 	// top-left y
					 segment.size,		// length
					 segment.width		// thickness
				);
			}
		context.restore();
	}

	// Move Head (needs to draw on top) ----------------------------------------

	// First Segment
	var headSegment = asset.segments[0];

	// If player is moving, rotate head in direction of velocity
	if(asset.vel.mag() > 0.03){
		headSegment.dir = headSegment.dir.rotateTowards2(asset.vel, 1/10);
		player.drawx = headSegment.dir.x;
		player.drawy = headSegment.dir.y;
	}

	// Draw first segment
	context.save();
	context.fillStyle = "rgba(0,0,0,0.5)";
	context.rotate( headSegment.dir.angle(), 1/5 );
	context.drawImage(
		headSegment.img,
		-headSegment.size,
		-headSegment.width/2,
		headSegment.size,
		headSegment.width
	);
	context.restore();

	// Exiting Player Coordinates ----------------------------------------------
	context.restore();
});

//// Player Setup --------------------------------------------------------------

// Create HTML Img elements
GameAsset.player.headImg = new Image();
GameAsset.player.headImg.src = "assets/graphics/wolf/wolf-head.png";
GameAsset.player.frontImg = new Image();
GameAsset.player.frontImg.src = "assets/graphics/wolf/wolf-front.png";
GameAsset.player.behindImg = new Image();
GameAsset.player.behindImg.src = "assets/graphics/wolf/wolf-behind.png";
GameAsset.player.tailImg = new Image();
GameAsset.player.tailImg.src = "assets/graphics/wolf/wolf-tail.png";
GameAsset.player.frontLeftImg = new Image();
GameAsset.player.frontLeftImg.src = "assets/graphics/wolf/wolf_fl_leg.png";
GameAsset.player.frontRightImg = new Image();
GameAsset.player.frontRightImg.src = "assets/graphics/wolf/wolf_fr_leg.png";
GameAsset.player.backLeftImg = new Image();
GameAsset.player.backLeftImg.src = "assets/graphics/wolf/wolf_bl_leg.png";
GameAsset.player.backRightImg = new Image();
GameAsset.player.backRightImg.src = "assets/graphics/wolf/wolf_br_leg.png";

// Things
var segmentImages = [GameAsset.player.headImg,
				 GameAsset.player.frontImg,
				 GameAsset.player.behindImg,
				 GameAsset.player.tailImg];
var segmentSizes = [0.6,0.6,0.6,0.8];
var segmentWidths =[0.6,0.5,0.6,0.2];
var segmentOffsets=[-0.1,-0.15,-0.1,0];
var segmentSpring =[1,1/5,1/10,1/10];

// Segments
GameAsset.player.segments = [];
var numSegments = 4;
var positionSum = 0;
var offsetSum = 0;
for(var i=0; i < numSegments; i++){
	GameAsset.player.segments.push({
		pos: new Vector(positionSum, 0),// position (tiles)
		dir: new Vector(1,0).norm(),	// vector in direction of segment
		size: segmentSizes[i],
		offset: segmentOffsets[i],
		width: segmentWidths[i],
		img: segmentImages[i],
		spring: segmentSpring[i]
	});
	// accumulate sizes
	positionSum += segmentSizes[i] + segmentOffsets[i];
}
GameAsset.player.vel = new Vector(0,0);

////////////////////////////////////////////////////////////////////////////////

/*GameAsset.player = new GameAsset(0.8, 0.8, true, function(x,y,asset,obj) {
	// Save coordinate transforms to leave untouched by this function
	context.save();

	// Move context origin to player's center
	context.translate(x,y);

	// If the player is moving at least a little...
	if (magnitude(obj.vx, obj.vy) > 0.03) {
		// turning in the direction they're moving
		obj.drawx = obj.drawx * 0.9 + 0.1 * obj.vx;
		obj.drawy = obj.drawy * 0.9 + 0.1 * obj.vy;
	}

	// We're centered on the player's center so rotate in the right direction
	context.rotate( Math.atan2(  obj.drawy, obj.drawx ) + Math.PI / 2 );

	// Move up a little to center on neck
	context.translate(0, 0.44);

	// If we're currently leaping...
	if (obj.leapwait > 45) {
		// Motion blur
		for (var i = 0; i < 1.2; i += 0.4) {
			context.globalAlpha = (1 - i);
			context.drawImage(asset.img,-.25,-.75 + i, 0.5, 1.5);
		}
		context.globalAlpha = 1;
	}

	// Draw the wolf
	context.drawImage(asset.img,-.25,-.75, 0.5, 1.5);

	// Put the context like it was before
	context.restore();
});*/<|endoftext|>


<commit_before>/*
   This file is part of Rogue Vision.

   Copyright (C) 2016 Daniel Reischl, Rene Rathmann, Peter Tan,
       Tobias Dorsch, Shefali Shukla, Vignesh Govindarajulu,
       Aleksander Penew, Abinav Puri

   Rogue Vision is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   Rogue Vision is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with Rogue Vision.  If not, see <http://www.gnu.org/licenses/>.
*/

/* This file contains all Angualr JS Services*/

angular.module('app')

    .service('percentageService', function(sessionService) {
	/*
	   Provides percantage data of carriers
	*/
	var percentageData = [];
	function getFromDB() {
	    /*
	       Fetches data from backend
	       So far this is called each time when getAll is called, but this is probably not necessary
	    */

	    Papa.parse('django/dataInterface/percentages_creeping.csv?session=' +sessionService.getCurrentSession(), {  download: true,
													       dynamicTyping: true,
													       complete: function(results) {
														   percentageData = results.data[1];
													       }
													    }
		      );
	}

	this.getAll = function() {
	    getFromDB();
	    return percentageData;
	}

	this.getColorOfCarrier = function(carrier) {
	    getFromDB();
	    var percentageOfEnergy = percentageData[carrier - 1];
	    var color = {'background-color': 'rgb(255,255,141)'};

	    if(percentageOfEnergy > 1.05) {
		color = {'background-color' : 'rgb(201, 24, 38)'};
            }

            if(percentageOfEnergy <= 1.025 ) {
		color = {'background-color' : 'rgb(115,173,33)'};
            }

            return color;
	}

	return {
	    getAll: this.getAll,
	    getColorOfCarrier: this.getColorOfCarrier
	};
    });

/* The carrierService, proved carrier data to all controllers
For now it is used to saves the carriers for comparison, chosen by the user and proved them to all controller
who need the data.
*/

angular.module('app')

.service('carrierService', function(sessionService) {
    var carriersForComparison = [];

    this.hasCarrier = function(carrierId) {
	return carriersForComparison.some(function(carrier){return carrier.carrierNumber == carrierId;});
    }

    // function adds a carrier with a given ID
    this.addCarrier = function(newCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == newCarrier) {
                return false;
             }
        }
        carriersForComparison.push({carrierNumber: newCarrier});
        return true;
    };

    // returns the array with CarrierIDs to be compared
    this.getCarrier = function(){
        return carriersForComparison;
    }

    // deletes a carrier with a given ID
    this.deleteCarrier = function(removeCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == removeCarrier) {
                carriersForComparison.splice(i,1);
                return true;
            }
        }
        return false;
    }

    // this function empties the array, so that no carrier item is left inside anymore.
    this.emptyCarrierArray = function() {
        carriersForComparison.splice(0,carriersForComparison.length);
    }

    // this service returns 5 functions to the caller, which he can use.
    return {
        hasCarrier: this.hasCarrier,
        addCarrier: this.addCarrier,
        getCarrier: this.getCarrier,
        deleteCarrier: this.deleteCarrier,
        emptyCarrierArray: this.emptyCarrierArray,
    };
});

angular.module('app')

    .service('sessionService', function() {
	var numberOfSessions = 0;
	var currentSession = 1;

	function update () {
	    var xmlHttp = new XMLHttpRequest();
	    // so far session, carrier and iteration have to be set - they are disregarded however
	    xmlHttp.open( "GET", 'django/dataInterface/values.request?session=1&carrier=1&iteration=1&value=currentSession', false );
	    xmlHttp.send(null);
	    numberOfSessions = xmlHttp.responseText;

	    // reset session number, if necessary
	    if (currentSession < numberOfSessions) {
		currentSession = 1;
	    }
	}

	this.getNumberOfSessions = function() {
	    update();
	    return numberOfSessions;
	}

	this.getCurrentSession = function() {
	    update();
	    return currentSession;
	}

	this.setCurrentSession = function(newSession) {
	    if (newSession <= currentSession) {
		currentSession = newSession;
	    }
	}

	return {
            getNumberOfSessions: this.getNumberOfSessions,
            getCurrentSession: this.getCurrentSession,
            setCurrentSession: this.setCurrentSession,
	};

});
<commit_msg>FIXED: bug that prevented sessions to get stored when movin between pages<commit_after>/*
   This file is part of Rogue Vision.

   Copyright (C) 2016 Daniel Reischl, Rene Rathmann, Peter Tan,
       Tobias Dorsch, Shefali Shukla, Vignesh Govindarajulu,
       Aleksander Penew, Abinav Puri

   Rogue Vision is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   Rogue Vision is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with Rogue Vision.  If not, see <http://www.gnu.org/licenses/>.
*/

/* This file contains all Angualr JS Services*/

angular.module('app')

    .service('percentageService', function(sessionService) {
	/*
	   Provides percantage data of carriers
	*/
	var percentageData = [];
	function getFromDB() {
	    /*
	       Fetches data from backend
	       So far this is called each time when getAll is called, but this is probably not necessary
	    */

	    Papa.parse('django/dataInterface/percentages_creeping.csv?session=' +sessionService.getCurrentSession(), {  download: true,
													       dynamicTyping: true,
													       complete: function(results) {
														   percentageData = results.data[1];
													       }
													    }
		      );
	}

	this.getAll = function() {
	    getFromDB();
	    return percentageData;
	}

	this.getColorOfCarrier = function(carrier) {
	    getFromDB();
	    var percentageOfEnergy = percentageData[carrier - 1];
	    var color = {'background-color': 'rgb(255,255,141)'};

	    if(percentageOfEnergy > 1.05) {
		color = {'background-color' : 'rgb(201, 24, 38)'};
            }

            if(percentageOfEnergy <= 1.025 ) {
		color = {'background-color' : 'rgb(115,173,33)'};
            }

            return color;
	}

	return {
	    getAll: this.getAll,
	    getColorOfCarrier: this.getColorOfCarrier
	};
    });

/* The carrierService, proved carrier data to all controllers
For now it is used to saves the carriers for comparison, chosen by the user and proved them to all controller
who need the data.
*/

angular.module('app')

.service('carrierService', function(sessionService) {
    var carriersForComparison = [];

    this.hasCarrier = function(carrierId) {
	return carriersForComparison.some(function(carrier){return carrier.carrierNumber == carrierId;});
    }

    // function adds a carrier with a given ID
    this.addCarrier = function(newCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == newCarrier) {
                return false;
             }
        }
        carriersForComparison.push({carrierNumber: newCarrier});
        return true;
    };

    // returns the array with CarrierIDs to be compared
    this.getCarrier = function(){
        return carriersForComparison;
    }

    // deletes a carrier with a given ID
    this.deleteCarrier = function(removeCarrier) {
        for(var i = 0; i < carriersForComparison.length; i++) {
            if (carriersForComparison[i].carrierNumber == removeCarrier) {
                carriersForComparison.splice(i,1);
                return true;
            }
        }
        return false;
    }

    // this function empties the array, so that no carrier item is left inside anymore.
    this.emptyCarrierArray = function() {
        carriersForComparison.splice(0,carriersForComparison.length);
    }

    // this service returns 5 functions to the caller, which he can use.
    return {
        hasCarrier: this.hasCarrier,
        addCarrier: this.addCarrier,
        getCarrier: this.getCarrier,
        deleteCarrier: this.deleteCarrier,
        emptyCarrierArray: this.emptyCarrierArray,
    };
});

angular.module('app')

    .service('sessionService', function() {
	var numberOfSessions = 0;
	var currentSession = 1;

	function update () {
	    var xmlHttp = new XMLHttpRequest();
	    // so far session, carrier and iteration have to be set - they are disregarded however
	    xmlHttp.open( "GET", 'django/dataInterface/values.request?session=1&carrier=1&iteration=1&value=currentSession', false );
	    xmlHttp.send(null);
	    numberOfSessions = xmlHttp.responseText;

	    // reset session number, if necessary
	    if (currentSession < numberOfSessions) {
		currentSession = 1;
	    }
	}

	this.getNumberOfSessions = function() {
	    update();
	    return numberOfSessions;
	}

	this.getCurrentSession = function() {
	    update();
	    return currentSession;
	}

	this.setCurrentSession = function(newSession) {
	    if (newSession <= numberOfSessions) {
		currentSession = newSession;
	    }
	}

	return {
            getNumberOfSessions: this.getNumberOfSessions,
            getCurrentSession: this.getCurrentSession,
            setCurrentSession: this.setCurrentSession,
	};

});
<|endoftext|>


<commit_before>var CT = {
	"_": {
		"extReqs": {},
		"scriptImportCb": {},
		"onImport": function(fullpath) {
			CT._.scriptImportCb[fullpath].forEach(function(cb) { cb(); });
		},
		"onload": [],
		"triggerOnload": function() {
			CT._.onload.forEach(function(cb) { cb(); });
		}
	},
	"style": {
		"panel": {
			"title": "bigger blue bold bottompadded"
		}
	},
	"info": {
		"page": location.pathname.slice(1,-5),
		"userAgent": navigator.userAgent || navigator.vendor || window.opera
	},
	"net": {
		// defaults
		"_path": "",
		"_encode": false,
		"_encoder": function (d) { return d; },
		"_decoder": function (d) { return d; },
		"_silentFail": true,
		// functions
		"setEncoder": function(func) {
			CT.net._encoder = func;
		},
		"setDecoder": function(func) {
			CT.net._decoder = func;
		},
		"fullPath": function(p) {
			if (!CT.net._path) {
				var s = document.getElementsByTagName("script");
				for (var i = 0; i < s.length; i++) {
					if (s[i].src.slice(-8) == "CT/ct.js") {
						CT.net._path = s[i].src.replace("CT/ct.js", "");
						break;
					}
				}
			}
			return CT.net._path + p;
		},
		"xhr": function(path, method, params, async, cb, headers) {
		    var xhr = window.XMLHttpRequest
		    	? new XMLHttpRequest()
		    	: new ActiveXObject("Microsoft.XMLHTTP");
		    xhr.open(method, path, async);
		    if ( !(headers && "Content-Type" in headers))
			    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		    for (var header in headers)
		    	xhr.setRequestHeader(header, headers[header]);
		    xhr.onreadystatechange = cb && function() { cb(xhr); };
		    if (params) {
		    	params = JSON.stringify(params);
		    	if (CT.net._encode)
		    		params = CT.net._encoder(params)
		    }
		    xhr.send(params);
		    if (!async)
		    	return xhr.responseText;
		},
		"_fallback_error": function(msg) {
			if (CT.net._silentFail)
				console.log(msg);
			else
				alert(msg);
		},
		"post": function(path, params, errMsg, cb, eb, headers, cbarg, ebarg) {
			CT.net.xhr(path, "POST", params, true, function(xhr) {
		        if (xhr.readyState == 4) {
		            if (xhr.status == 200) {
		                var data = xhr.responseText.trim();
		                if (CT.net._encode)
		                    data = CT.net._decoder(data);
		                var payload = data.slice(1);
		                if (data.charAt(0) == '0') {
		                    if (eb) eb(payload, ebarg);
		                    else CT.net._fallback_error(errMsg + ": " + payload);
		                }
		                else if (cb != null)
		                    cb(JSON.parse(payload), cbarg);
		            }
		            else if (!CT.net._encode)
		                CT.net._fallback_error("request to " + path + " failed!");
		        }
		    }, headers);
		},
		"get": function(path) {
			return CT.net.xhr(path, "GET");
		}
	},
	"scriptImport": function(modpath, cb, delay) {
		var h = document.getElementsByTagName("head")[0],
			fp = CT.net.fullPath(modpath.replace(/\./g, "/") + ".js");
		if (!(fp in CT._.scriptImportCb)) {
			CT._.scriptImportCb[fp] = [];
			h.appendChild(CT.dom.script(fp));
			h.appendChild(CT.dom.script(null, "CT._.onImport('" + fp + "');", delay));
		}
		if (cb)
			CT._.scriptImportCb[fp].push(cb);
	},
	"require": function(modname, lazy) { // lazy only matters compile-time
		if (modname.slice(0, 4) == "http") {
			if (!(modname in CT._extReqs)) {
				CT._.extReqs[modname] = true;
				eval(CT.net.get(modname));
			}
		} else {
			var modpath = modname.split("."),
				curpath, curmod = window;
			while (curmod && modpath.length) {
				curpath = modpath.shift();
				if (curpath in curmod)
					curmod = curmod[curpath];
				else {
					modpath.unshift(curpath);
					modpath.forEach(function(p, i) {
						if (i == modpath.length - 1)
							curmod[p] = true; // mark module as imported
						else
							curmod = curmod[p] = {};
					});
					modpath.length = 0;
					curmod = null;
				}
			}
			if (!curmod)
				eval(CT.net.get(CT.net.fullPath(modname.replace(/\./g, "/") + ".js")));
		}
	},
	"onload": function(cb) {
		if (!CT._.onload.length)
			window.onload = CT._.triggerOnload;
		CT._.onload.push(cb);
	},
	"log": function(msg, level) {
		var s = Date() + " ::";
		if (level) for (var i = 0; i < level; i++)
			s += "  ";
		console.log(s, msg);
	}
};
CT.log._silent = false;
CT.log.set = function(bool) {
	CT.log._silent = bool;
};
CT.log.getLogger = function(component) {
	var logger = function() {
		if (!CT.log._silent) {
			var str_arr = [];
			for (var i = 0; i < logger.arguments.length; i++) {
				var a = logger.arguments[i];
				str_arr.push((typeof(a) == "object") ? JSON.stringify(a) : a);
			}
			CT.log("[" + component + "] " + str_arr.join(" "));
		}
	};
	return logger;
};

CT.info.mobile = /android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(CT.info.userAgent)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(CT.info.userAgent.substr(0,4));

// shims (fallbacks for old browsers)
if (!window.JSON)
	CT.require("CT.lib.shims.JSON", true);
if (!window.sessionStorage)
	CT.require("CT.lib.shims.sessionStorage", true);
if (!document.createElement("div").classList)
	CT.require("CT.lib.shims.classList", true);<commit_msg>CT.merge(), CT.Class(). todo: fix grandparent-level property inheritance.<commit_after>var CT = {
	"_": {
		"extReqs": {},
		"scriptImportCb": {},
		"onImport": function(fullpath) {
			CT._.scriptImportCb[fullpath].forEach(function(cb) { cb(); });
		},
		"onload": [],
		"triggerOnload": function() {
			CT._.onload.forEach(function(cb) { cb(); });
		}
	},
	"style": {
		"panel": {
			"title": "bigger blue bold bottompadded"
		}
	},
	"info": {
		"page": location.pathname.slice(1,-5),
		"userAgent": navigator.userAgent || navigator.vendor || window.opera
	},
	"net": {
		// defaults
		"_path": "",
		"_encode": false,
		"_encoder": function (d) { return d; },
		"_decoder": function (d) { return d; },
		"_silentFail": true,
		// functions
		"setEncoder": function(func) {
			CT.net._encoder = func;
		},
		"setDecoder": function(func) {
			CT.net._decoder = func;
		},
		"fullPath": function(p) {
			if (!CT.net._path) {
				var s = document.getElementsByTagName("script");
				for (var i = 0; i < s.length; i++) {
					if (s[i].src.slice(-8) == "CT/ct.js") {
						CT.net._path = s[i].src.replace("CT/ct.js", "");
						break;
					}
				}
			}
			return CT.net._path + p;
		},
		"xhr": function(path, method, params, async, cb, headers) {
		    var xhr = window.XMLHttpRequest
		    	? new XMLHttpRequest()
		    	: new ActiveXObject("Microsoft.XMLHTTP");
		    xhr.open(method, path, async);
		    if ( !(headers && "Content-Type" in headers))
			    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		    for (var header in headers)
		    	xhr.setRequestHeader(header, headers[header]);
		    xhr.onreadystatechange = cb && function() { cb(xhr); };
		    if (params) {
		    	params = JSON.stringify(params);
		    	if (CT.net._encode)
		    		params = CT.net._encoder(params)
		    }
		    xhr.send(params);
		    if (!async)
		    	return xhr.responseText;
		},
		"_fallback_error": function(msg) {
			if (CT.net._silentFail)
				console.log(msg);
			else
				alert(msg);
		},
		"post": function(path, params, errMsg, cb, eb, headers, cbarg, ebarg) {
			CT.net.xhr(path, "POST", params, true, function(xhr) {
		        if (xhr.readyState == 4) {
		            if (xhr.status == 200) {
		                var data = xhr.responseText.trim();
		                if (CT.net._encode)
		                    data = CT.net._decoder(data);
		                var payload = data.slice(1);
		                if (data.charAt(0) == '0') {
		                    if (eb) eb(payload, ebarg);
		                    else CT.net._fallback_error(errMsg + ": " + payload);
		                }
		                else if (cb != null)
		                    cb(JSON.parse(payload), cbarg);
		            }
		            else if (!CT.net._encode)
		                CT.net._fallback_error("request to " + path + " failed!");
		        }
		    }, headers);
		},
		"get": function(path) {
			return CT.net.xhr(path, "GET");
		}
	},
	"scriptImport": function(modpath, cb, delay) {
		var h = document.getElementsByTagName("head")[0],
			fp = CT.net.fullPath(modpath.replace(/\./g, "/") + ".js");
		if (!(fp in CT._.scriptImportCb)) {
			CT._.scriptImportCb[fp] = [];
			h.appendChild(CT.dom.script(fp));
			h.appendChild(CT.dom.script(null, "CT._.onImport('" + fp + "');", delay));
		}
		if (cb)
			CT._.scriptImportCb[fp].push(cb);
	},
	"require": function(modname, lazy) { // lazy only matters compile-time
		if (modname.slice(0, 4) == "http") {
			if (!(modname in CT._extReqs)) {
				CT._.extReqs[modname] = true;
				eval(CT.net.get(modname));
			}
		} else {
			var modpath = modname.split("."),
				curpath, curmod = window;
			while (curmod && modpath.length) {
				curpath = modpath.shift();
				if (curpath in curmod)
					curmod = curmod[curpath];
				else {
					modpath.unshift(curpath);
					modpath.forEach(function(p, i) {
						if (i == modpath.length - 1)
							curmod[p] = true; // mark module as imported
						else
							curmod = curmod[p] = {};
					});
					modpath.length = 0;
					curmod = null;
				}
			}
			if (!curmod)
				eval(CT.net.get(CT.net.fullPath(modname.replace(/\./g, "/") + ".js")));
		}
	},
	"onload": function(cb) {
		if (!CT._.onload.length)
			window.onload = CT._.triggerOnload;
		CT._.onload.push(cb);
	},
	"merge": function() { // properties on earlier objects trump those on later ones
		var i, k, o = {};
		for (i = arguments.length - 1; i > -1; i--) {
			for (k in arguments[i])
				o[k] = arguments[i][k];
		}
		return o;
	},
	"Class": function(obj, parent) {
		var c = function() {
			var instance = CT.merge(obj, parent && parent.prototype);
			if (parent)
				parent.prototype.fullInit.apply(instance, arguments);
			if (obj.init)
				obj.init.apply(instance, arguments);
			return instance;
		};
		obj.fullInit = c;
		c.prototype = obj;
		return c;
	}
};

// logging
CT.log = function(msg, level) {
	var s = Date() + " ::";
	if (level) for (var i = 0; i < level; i++)
		s += "  ";
	console.log(s, msg);
};
CT.log._silent = false;
CT.log.set = function(bool) {
	CT.log._silent = bool;
};
CT.log.getLogger = function(component) {
	var logger = function() {
		if (!CT.log._silent) {
			var str_arr = [];
			for (var i = 0; i < logger.arguments.length; i++) {
				var a = logger.arguments[i];
				str_arr.push((typeof(a) == "object") ? JSON.stringify(a) : a);
			}
			CT.log("[" + component + "] " + str_arr.join(" "));
		}
	};
	return logger;
};

CT.info.mobile = /android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(CT.info.userAgent)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(CT.info.userAgent.substr(0,4));

// shims (fallbacks for old browsers)
if (!window.JSON)
	CT.require("CT.lib.shims.JSON", true);
if (!window.sessionStorage)
	CT.require("CT.lib.shims.sessionStorage", true);
if (!document.createElement("div").classList)
	CT.require("CT.lib.shims.classList", true);<|endoftext|>


<commit_before>import WebGPUUniformsGroup from './WebGPUUniformsGroup.js';
import { FloatUniform, Vector3Uniform } from './WebGPUUniform.js';

import NodeSlot from '../nodes/core/NodeSlot.js';
import NodeBuilder from '../nodes/core/NodeBuilder.js';

class WebGPUNodeUniformsGroup extends WebGPUUniformsGroup {

	constructor( shaderStage ) {

		super( 'nodeUniforms' );

		let shaderStageVisibility;

		if ( shaderStage === 'vertex' ) shaderStageVisibility = GPUShaderStage.VERTEX;
		else if ( shaderStage === 'fragment' ) shaderStageVisibility = GPUShaderStage.FRAGMENT;

		this.setVisibility( shaderStageVisibility );

		this.setOnBeforeUpdate( this._onBeforeUpdate );

	}

	_onBeforeUpdate( object, camera ) {

		const material = object.material;

		console.log( 1 );

	}

}

class WebGPUNodeBuilder extends NodeBuilder {

	constructor( material, renderer ) {

		super( material, renderer );

		this.uniformsGroup = {};

		this._parseMaterial();

	}

	_parseMaterial() {

		const material = this.material;

		if ( material.isMeshBasicMaterial || material.isPointsMaterial ) {

			if ( material.colorNode !== undefined ) {

				this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec3' ) );

			}

			if ( material.opacityNode !== undefined ) {

				this.addSlot( 'fragment', new NodeSlot( material.opacityNode, 'OPACITY', 'float' ) );

			}

		}

	}

	getUniformNSName( nodeUniform ) {

		return `nodeUniforms.${nodeUniform.name}`;

	}

	getBindings() {

		const bindings = [];

		const uniformsVertexGroup = this.uniformsGroup[ 'vertex' ];
		const uniformsFragmentGroup = this.uniformsGroup[ 'fragment' ];

		if ( uniformsVertexGroup ) bindings.push( uniformsVertexGroup );
		if ( uniformsFragmentGroup ) bindings.push( uniformsFragmentGroup );

		return bindings;

	}

	getUniformFromNode( node, shaderStage, type ) {

		const uniformNode = super.getUniformFromNode( node, shaderStage, type )
		const nodeData = this.getDataFromNode( node, shaderStage );

		if ( nodeData.uniformGroup === undefined ) {

			let uniformsGroup = this.uniformsGroup[shaderStage];

			if (uniformsGroup === undefined) {

				uniformsGroup = new WebGPUNodeUniformsGroup( shaderStage );

				this.uniformsGroup[shaderStage] = uniformsGroup;

			}

			let uniformGroup;

			if ( type === 'float' ) {

				uniformGroup = new FloatUniform( uniformNode.name, uniformNode.value );

			} else if ( type === 'vec3' ) {

				uniformGroup = new Vector3Uniform( uniformNode.name, uniformNode.value );

			} else {

				console.error( `Uniform "${type}" not declared.` );

			}

			uniformsGroup.addUniform( uniformGroup );

			nodeData.uniformGroup = uniformGroup;

		}

		return uniformNode;

	}

	buildShader( shaderStage, code ) {

		// use regex maybe for security?
		const versionStrIndex = code.indexOf("\n");

		let finalCode = code.substr( 0, versionStrIndex ) + "\n\n";

		const shaderCodes = this.build( shaderStage );

		finalCode += shaderCodes.defines;

		finalCode += code.substr( versionStrIndex );

		console.log( finalCode );

		return finalCode;

	}

	parse( vertexShader, fragmentShader ) {

		vertexShader = this.buildShader( 'vertex', vertexShader );
		fragmentShader = this.buildShader( 'fragment', fragmentShader );

		return {
			vertexShader,
			fragmentShader
		};

	}

}

export default WebGPUNodeBuilder;
<commit_msg>cleanup debug code<commit_after>import WebGPUUniformsGroup from './WebGPUUniformsGroup.js';
import { FloatUniform, Vector3Uniform } from './WebGPUUniform.js';

import NodeSlot from '../nodes/core/NodeSlot.js';
import NodeBuilder from '../nodes/core/NodeBuilder.js';

class WebGPUNodeUniformsGroup extends WebGPUUniformsGroup {

	constructor( shaderStage ) {

		super( 'nodeUniforms' );

		let shaderStageVisibility;

		if ( shaderStage === 'vertex' ) shaderStageVisibility = GPUShaderStage.VERTEX;
		else if ( shaderStage === 'fragment' ) shaderStageVisibility = GPUShaderStage.FRAGMENT;

		this.setVisibility( shaderStageVisibility );

		//this.setOnBeforeUpdate( this._onBeforeUpdate );

	}
	/*
	_onBeforeUpdate( object, camera ) {

		const material = object.material;

	}
	*/
}

class WebGPUNodeBuilder extends NodeBuilder {

	constructor( material, renderer ) {

		super( material, renderer );

		this.uniformsGroup = {};

		this._parseMaterial();

	}

	_parseMaterial() {

		const material = this.material;

		if ( material.isMeshBasicMaterial || material.isPointsMaterial ) {

			if ( material.colorNode !== undefined ) {

				this.addSlot( 'fragment', new NodeSlot( material.colorNode, 'COLOR', 'vec3' ) );

			}

			if ( material.opacityNode !== undefined ) {

				this.addSlot( 'fragment', new NodeSlot( material.opacityNode, 'OPACITY', 'float' ) );

			}

		}

	}

	getUniformNSName( nodeUniform ) {

		return `nodeUniforms.${nodeUniform.name}`;

	}

	getBindings() {

		const bindings = [];

		const uniformsVertexGroup = this.uniformsGroup[ 'vertex' ];
		const uniformsFragmentGroup = this.uniformsGroup[ 'fragment' ];

		if ( uniformsVertexGroup ) bindings.push( uniformsVertexGroup );
		if ( uniformsFragmentGroup ) bindings.push( uniformsFragmentGroup );

		return bindings;

	}

	getUniformFromNode( node, shaderStage, type ) {

		const uniformNode = super.getUniformFromNode( node, shaderStage, type )
		const nodeData = this.getDataFromNode( node, shaderStage );

		if ( nodeData.uniformGroup === undefined ) {

			let uniformsGroup = this.uniformsGroup[shaderStage];

			if (uniformsGroup === undefined) {

				uniformsGroup = new WebGPUNodeUniformsGroup( shaderStage );

				this.uniformsGroup[shaderStage] = uniformsGroup;

			}

			let uniformGroup;

			if ( type === 'float' ) {

				uniformGroup = new FloatUniform( uniformNode.name, uniformNode.value );

			} else if ( type === 'vec3' ) {

				uniformGroup = new Vector3Uniform( uniformNode.name, uniformNode.value );

			} else {

				console.error( `Uniform "${type}" not declared.` );

			}

			uniformsGroup.addUniform( uniformGroup );

			nodeData.uniformGroup = uniformGroup;

		}

		return uniformNode;

	}

	buildShader( shaderStage, code ) {

		// use regex maybe for security?
		const versionStrIndex = code.indexOf("\n");

		let finalCode = code.substr( 0, versionStrIndex ) + "\n\n";

		const shaderCodes = this.build( shaderStage );

		finalCode += shaderCodes.defines;

		finalCode += code.substr( versionStrIndex );

		return finalCode;

	}

	parse( vertexShader, fragmentShader ) {

		vertexShader = this.buildShader( 'vertex', vertexShader );
		fragmentShader = this.buildShader( 'fragment', fragmentShader );

		return {
			vertexShader,
			fragmentShader
		};

	}

}

export default WebGPUNodeBuilder;
<|endoftext|>


<commit_before>(function() {
  'use strict';
  angular
    .module('lucidworksView.controllers.home', ['lucidworksView.services', 'angucomplete-alt', 'angular-humanize'])
    .controller('HomeController', HomeController);

  function HomeController($filter, $log, $scope, $timeout, ConfigService, QueryService, URLService, Orwell, AuthService, _) {

    'ngInject';
    var hc = this; //eslint-disable-line
    var resultsObservable;
    var query;
    var sorting, sortingOptionWatch;

    hc.searchQuery = '*:*';

    activate();

    ////////////////

    /**
     * Initializes a search from the URL object
     */
    function activate() {
      hc.search = doSearch;
      hc.logout = logout;
      hc.appName = ConfigService.config.search_app_title;
      hc.logoLocation = ConfigService.config.logo_location;
      hc.status = 'loading';
      hc.lastQuery = '';
      hc.sorting = {};

      query = URLService.getQueryFromUrl();
      //Setting the query object... also populating the the view model
      hc.searchQuery = _.get(query,'q','*:*');

      // Use an observable to get the contents of a queryResults after it is updated.
      resultsObservable = Orwell.getObservable('queryResults');
      resultsObservable.addObserver(function(data) {
        if (data.hasOwnProperty('response')) {
          hc.numFound = data.response.numFound;
          hc.numFoundFormatted = $filter('humanizeNumberFormat')(hc.numFound, 0);
          hc.lastQuery = data.responseHeader.params.q;
        } else {
          hc.numFound = 0;
        }
        updateStatus();

        // Initializing sorting
        sorting = hc.sorting;
        sorting.switchSort = switchSort;
        createSortList();

      });

      // Force set the query object to change one digest cycle later
      // than the digest cycle of the initial load-rendering
      // The $timeout is needed or else the query to fusion is not made.
      $timeout(function(){
        URLService.setQuery(query);
      });
    }

    function updateStatus(){
      var status = '';
      if(hc.numFound === 0){
        status = 'no-results';
        if(hc.lastQuery === ''){
          status = 'get-started';
        }
      } else {
        status = 'normal';
      }
      hc.status = status;
    }

    /**
     * Initializes a new search.
     */
    function doSearch() {
      query = {
        q: hc.searchQuery,
        start: 0,
        // TODO better solution for turning off fq on a new query
        fq: []
      };

      URLService.setQuery(query);
    }

    /**
     * Creates a sorting list from ConfigService
     */
    function createSortList(){
      var sortOptions = [{label:'default sort', type:'default', order:'', active: true}];
      _.forEach(ConfigService.config.sort_fields, function(value){
        sortOptions.push({label: value, type: 'text', order: 'asc', active: false});
        sortOptions.push({label: value, type: 'text', order: 'desc', active: false});
      });
      sorting.sortOptions = sortOptions;
      sorting.selectedSort = sorting.sortOptions[0];
    }

    /**
     * Switches sort parameter in the page
     */
    function switchSort(sort){
      sorting.selectedSort = sort;
      var query = QueryService.getQueryObject();
      switch(sort.type) {
      case 'text':
        query.sort = sort.label+' '+sort.order;
        URLService.setQuery(query);
        break;
      default:
        delete query.sort;
        URLService.setQuery(query);
      }
    }

    /**
     * Logs a user out of a session.
     */
    function logout(){
      AuthService.destroySession();
    }
  }
})();
<commit_msg>Removed unused dependencies<commit_after>(function() {
  'use strict';
  angular
    .module('lucidworksView.controllers.home', ['lucidworksView.services', 'angucomplete-alt', 'angular-humanize'])
    .controller('HomeController', HomeController);

  function HomeController($filter, $timeout, ConfigService, QueryService, URLService, Orwell, AuthService, _) {

    'ngInject';
    var hc = this; //eslint-disable-line
    var resultsObservable;
    var query;
    var sorting, sortingOptionWatch;

    hc.searchQuery = '*:*';

    activate();

    ////////////////

    /**
     * Initializes a search from the URL object
     */
    function activate() {
      hc.search = doSearch;
      hc.logout = logout;
      hc.appName = ConfigService.config.search_app_title;
      hc.logoLocation = ConfigService.config.logo_location;
      hc.status = 'loading';
      hc.lastQuery = '';
      hc.sorting = {};

      query = URLService.getQueryFromUrl();
      //Setting the query object... also populating the the view model
      hc.searchQuery = _.get(query,'q','*:*');

      // Use an observable to get the contents of a queryResults after it is updated.
      resultsObservable = Orwell.getObservable('queryResults');
      resultsObservable.addObserver(function(data) {
        if (data.hasOwnProperty('response')) {
          hc.numFound = data.response.numFound;
          hc.numFoundFormatted = $filter('humanizeNumberFormat')(hc.numFound, 0);
          hc.lastQuery = data.responseHeader.params.q;
        } else {
          hc.numFound = 0;
        }
        updateStatus();

        // Initializing sorting
        sorting = hc.sorting;
        sorting.switchSort = switchSort;
        createSortList();

      });

      // Force set the query object to change one digest cycle later
      // than the digest cycle of the initial load-rendering
      // The $timeout is needed or else the query to fusion is not made.
      $timeout(function(){
        URLService.setQuery(query);
      });
    }

    function updateStatus(){
      var status = '';
      if(hc.numFound === 0){
        status = 'no-results';
        if(hc.lastQuery === ''){
          status = 'get-started';
        }
      } else {
        status = 'normal';
      }
      hc.status = status;
    }

    /**
     * Initializes a new search.
     */
    function doSearch() {
      query = {
        q: hc.searchQuery,
        start: 0,
        // TODO better solution for turning off fq on a new query
        fq: []
      };

      URLService.setQuery(query);
    }

    /**
     * Creates a sorting list from ConfigService
     */
    function createSortList(){
      var sortOptions = [{label:'default sort', type:'default', order:'', active: true}];
      _.forEach(ConfigService.config.sort_fields, function(value){
        sortOptions.push({label: value, type: 'text', order: 'asc', active: false});
        sortOptions.push({label: value, type: 'text', order: 'desc', active: false});
      });
      sorting.sortOptions = sortOptions;
      sorting.selectedSort = sorting.sortOptions[0];
    }

    /**
     * Switches sort parameter in the page
     */
    function switchSort(sort){
      sorting.selectedSort = sort;
      var query = QueryService.getQueryObject();
      switch(sort.type) {
      case 'text':
        query.sort = sort.label+' '+sort.order;
        URLService.setQuery(query);
        break;
      default:
        delete query.sort;
        URLService.setQuery(query);
      }
    }

    /**
     * Logs a user out of a session.
     */
    function logout(){
      AuthService.destroySession();
    }
  }
})();
<|endoftext|>