<commit_before>/***********************************************************************
 * Popup Directive
 * Author: Brenton Klik
 *
 * Prerequisites:
 *  - AngularJS
 *  - styleSheetFactory (https://github.com/bklik/styleSheetFactory)
 *
 * Description:
 * Create a popup positioned under the given element.
/**********************************************************************/
angular.module('popupDirective', ['styleSheetFactory'])

.directive('popupDirective', ['styleSheetFactory', function(styleSheetFactory) {
    return {
        scope: {
            api: '='
        },
        restrict: 'E',
        link: function($scope, $element, $attrs) {
            // The document's stylesheet.
            var styleSheet = styleSheetFactory.getStyleSheet();

            // The prefix used by the browser for non-standard properties.
            var prefix = styleSheetFactory.getPrefix();

            // Add this directive's styles to the document's stylesheet.
            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive',
                'background: white;' +
                'border: 1px solid gray;' +
                'border-radius: 2px;' +
                'box-shadow: 0 2px 8px rgba(black, .25);' +
                'display: none;' +
                'min-height: 32px;' +
                'min-width: 32px;' +
                'padding: 8px;' +
                'position: absolute;'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive::after',
                'background-color: white;' +
                'border-left: 1px solid gray;' +
                'border-top: 1px solid gray;' +
                'box-sizing: border-box;' +
                'content: \'\';' +
                'display: block;' +
                '' +
                'position: absolute;' +
                'top: -6px;' +
                'left: 10px;' +
                'height: 10px;' +
                'width: 10px;' +
                '' +
                '-'+prefix+'-transform: rotate(45deg);' +
                'transform: rotate(45deg);'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive.arrow-right::after',
                'left: auto;' +
                'right: 16px;'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive.show',
                'display: inline-block;' +
                '' +
                '-webkit-animation: popup-slidein 250ms;' +
                '-moz-animation: popup-slidein 250ms;' +
                'animation: popup-slidein 250ms;'
            );

            styleSheetFactory.addCSSKeyframes(styleSheet, 'popup-slidein',
                'from {' +
                    'opacity: 0;' +
                    '-'+prefix+'-transform: translateY(-.5em);' +
                    'transform: translateY(-.5em);' +
                '}' +
                'to {' +
                    'opacity: 1;' +
                    '-'+prefix+'-transform: translateY(0);' +
                    'transform: translateY(0);' +
                '}'
            );

            // Target element the popup should appear next to.
            var target = null;

            // Used by event listeners to prevent the popup from closing.
            var preventClose = function(event) {
                event.stopPropagation();
            }

            $element.bind('mousedown', preventClose);

            var show = function(event) {
                if(typeof event !== 'undefined') {
                    if(typeof event.target !== 'undefined') {
                        target = event.target;
                    } else {
                        target = event;
                    }

                    $element.addClass('show');
                    position(target);

                    target.addEventListener('mousedown', preventClose);
                    target.addEventListener('keydown', hide);
                    window.addEventListener('mousedown', hide);
                } else {
                    console.error('Popup Directive method "show" requires a target element.');
                }
            };

            var hide = function() {
                $element.removeClass('show');
                target.removeEventListener('mousedown', preventClose);
                target.removeEventListener('keydown', hide);
                window.removeEventListener('mousedown', hide);
                target = null;
            }

            var position = function(target) {
                var targetRect = target.getBoundingClientRect();
                var popupRect = $element[0].getBoundingClientRect();
                var bodyRect = document.body.getBoundingClientRect();

                var top = targetRect.top + targetRect.height + 16;
                var left = targetRect.left;

                if(targetRect.left + popupRect.width > bodyRect.width) {
                    left = (targetRect.left + targetRect.width) - popupRect.width;

                    if(left > 0) {
                        $element.addClass('arrow-right');
                    } else {
                        left = targetRect.left;
                        $element.removeClass('arrow-right');
                    }
                }

                $element.attr('style',
                    'top: '+top+'px;' +
                    'left: '+left+'px;'
                );
            };

            $scope.api = {
                show: function(event) {
                    show(event);
                },

                hide: function() {
                    hide();
                }
            };
        }
    }
}]);<commit_msg>Added hide-callback property. Add a function you want the popup to call when it closes.<commit_after>/***********************************************************************
 * Popup Directive
 * Author: Brenton Klik
 *
 * Prerequisites:
 *  - AngularJS
 *  - styleSheetFactory (https://github.com/bklik/styleSheetFactory)
 *
 * Description:
 * Create a popup positioned under the given element.
/**********************************************************************/
angular.module('popupDirective', ['styleSheetFactory'])

.directive('popupDirective', ['styleSheetFactory', function(styleSheetFactory) {
    return {
        scope: {
            api: '=',
            hideCallback: '&'
        },
        restrict: 'E',
        link: function($scope, $element, $attrs) {
            // The document's stylesheet.
            var styleSheet = styleSheetFactory.getStyleSheet();

            // The prefix used by the browser for non-standard properties.
            var prefix = styleSheetFactory.getPrefix();

            // Add this directive's styles to the document's stylesheet.
            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive',
                'background: white;' +
                'border: 1px solid gray;' +
                'border-radius: 2px;' +
                'box-shadow: 0 2px 8px rgba(black, .25);' +
                'display: none;' +
                'min-height: 32px;' +
                'min-width: 32px;' +
                'padding: 8px;' +
                'position: absolute;'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive::after',
                'background-color: white;' +
                'border-left: 1px solid gray;' +
                'border-top: 1px solid gray;' +
                'box-sizing: border-box;' +
                'content: \'\';' +
                'display: block;' +
                '' +
                'position: absolute;' +
                'top: -6px;' +
                'left: 10px;' +
                'height: 10px;' +
                'width: 10px;' +
                '' +
                '-'+prefix+'-transform: rotate(45deg);' +
                'transform: rotate(45deg);'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive.arrow-right::after',
                'left: auto;' +
                'right: 16px;'
            );

            styleSheetFactory.addCSSRule(styleSheet, 'popup-directive.show',
                'display: inline-block;' +
                '' +
                '-webkit-animation: popup-slidein 250ms;' +
                '-moz-animation: popup-slidein 250ms;' +
                'animation: popup-slidein 250ms;'
            );

            styleSheetFactory.addCSSKeyframes(styleSheet, 'popup-slidein',
                'from {' +
                    'opacity: 0;' +
                    '-'+prefix+'-transform: translateY(-.5em);' +
                    'transform: translateY(-.5em);' +
                '}' +
                'to {' +
                    'opacity: 1;' +
                    '-'+prefix+'-transform: translateY(0);' +
                    'transform: translateY(0);' +
                '}'
            );

            // Target element the popup should appear next to.
            var target = null;

            // Used by event listeners to prevent the popup from closing.
            var preventClose = function(event) {
                event.stopPropagation();
            }

            $element.bind('mousedown', preventClose);

            var show = function(event) {
                if(typeof event !== 'undefined') {
                    if(typeof event.target !== 'undefined') {
                        target = event.target;
                    } else {
                        target = event;
                    }

                    $element.addClass('show');
                    position(target);

                    target.addEventListener('mousedown', preventClose);
                    target.addEventListener('keydown', hide);
                    window.addEventListener('mousedown', hide);
                } else {
                    console.error('Popup Directive method "show" requires a target element.');
                }
            };

            var hide = function() {
                if(typeof $scope.hideCallback == 'function') {
                    $scope.hideCallback();
                };

                $element.removeClass('show');
                target.removeEventListener('mousedown', preventClose);
                target.removeEventListener('keydown', hide);
                window.removeEventListener('mousedown', hide);
                target = null;
            }

            var position = function(target) {
                var targetRect = target.getBoundingClientRect();
                var popupRect = $element[0].getBoundingClientRect();
                var bodyRect = document.body.getBoundingClientRect();

                var top = targetRect.top + targetRect.height + 16;
                var left = targetRect.left;

                if(targetRect.left + popupRect.width > bodyRect.width) {
                    left = (targetRect.left + targetRect.width) - popupRect.width;

                    if(left > 0) {
                        $element.addClass('arrow-right');
                    } else {
                        left = targetRect.left;
                        $element.removeClass('arrow-right');
                    }
                }

                $element.attr('style',
                    'top: '+top+'px;' +
                    'left: '+left+'px;'
                );
            };

            $scope.api = {
                show: function(event) {
                    show(event);
                },

                hide: function() {
                    hide();
                },
            };
        }
    }
}]);<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { withRouter, Redirect } from 'react-router';
import registerServiceWorker from './registerServiceWorker';
import './style/style.css';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

import {
  BrowserRouter,
  Route,

} from 'react-router-dom'

import history from './components/common/history'
import { init } from './components/common/Backend'

import SignIn from './components/pages/SignIn.jsx'
import SignUp from './components/pages/SignUp.jsx'

import AdminOverview from './components/views/AdminOverview'
import CreateProject from './components/views/CreateProject'
import CreateProjectByURL from './components/views/CreateProjectByURL'
import CreateProjectFromFile from './components/views/CreateProjectFromFile'
import CreateProjectChoice from './components/views/CreateProjectChoice.jsx'
import ProfileContainer from './components/views/ProfileContainer.jsx'
import ProjectContainer from './components/views/ProjectContainer'
import SearchPage from './components/views/SearchPage'
import BookmarksTable from './components/views/BookmarksTable'
import UserProjects from './components/views/UserProjects.jsx'
import SavedQueries from './components/views/SavedQueries.jsx'

import TopBar from './components/common/TopBar'
import SideBar from './components/common/SideBar'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import styles from './components/common/Styles.jsx'

var injectTapEventPlugin = require("react-tap-event-plugin")
injectTapEventPlugin()

const muiTheme = getMuiTheme(styles)

const PageRoute = ({ component: Component, path, sitePath, ...rest }) => (
  <Route {...rest} path={path} render={props => {
    return (

        <TopBar />

          <SideBar location={sitePath} />

            <Component {...props} />

    );
  }}/>
)

init(() => {
  ReactDOM.render(
    <MuiThemeProvider  muiTheme={muiTheme}>
      <BrowserRouter history={history}>

        <PageRoute site_path="/discovery" path="/discovery/:query" component={SearchPage} />
          <PageRoute sitePath="/discovery" path="/discovery/" component={SearchPage} />
          <PageRoute sitePath="/admin" path="/admin" component={AdminOverview} />
          <PageRoute sitePath="/createNew" exact path="/createNew" component={CreateProject} />
          <PageRoute sitePath="/createNew" path="/createByURL/:getURL" component={CreateProjectByURL} />
          <PageRoute sitePath="/createNew" path="/createFromFile/:data" component={CreateProjectFromFile} />
          <PageRoute sitePath="/update" path="/update/:uuid" component={CreateProject} />
          <PageRoute sitePath="/createbylink" path="/createbylink" component={CreateProjectChoice} />
          <PageRoute sitePath="/project" path="/project/:uuid" component={ProjectContainer} />
          <PageRoute sitePath="/bookmarks" path="/bookmarks" component={BookmarksTable} />
          <PageRoute sitePath="/profile" path="/profile/:email" component={ProfileContainer} />
          <PageRoute sitePath="/yourprojects" path="/yourprojects" component={UserProjects} />
          <PageRoute sitePath="/queries" path="/queries" component={SavedQueries} />
          <Route path="/register" component={SignUp} />
          <Route exact path="/" component={SignIn} />
          <Route component={() => (<Redirect to="/"/>)} />

      </BrowserRouter>
    </MuiThemeProvider>
  , document.getElementById('root'))
  registerServiceWorker()
});
<commit_msg>Fix discovery on reload<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { Redirect } from 'react-router';
import { Switch } from 'react-router-dom';
import registerServiceWorker from './registerServiceWorker';
import './style/style.css';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

import {
  BrowserRouter,
  Route,

} from 'react-router-dom'

import history from './components/common/history'
import { init } from './components/common/Backend'

import SignIn from './components/pages/SignIn.jsx'
import SignUp from './components/pages/SignUp.jsx'

import AdminOverview from './components/views/AdminOverview'
import CreateProject from './components/views/CreateProject'
import CreateProjectByURL from './components/views/CreateProjectByURL'
import CreateProjectFromFile from './components/views/CreateProjectFromFile'
import CreateProjectChoice from './components/views/CreateProjectChoice.jsx'
import ProfileContainer from './components/views/ProfileContainer.jsx'
import ProjectContainer from './components/views/ProjectContainer'
import SearchPage from './components/views/SearchPage'
import BookmarksTable from './components/views/BookmarksTable'
import UserProjects from './components/views/UserProjects.jsx'
import SavedQueries from './components/views/SavedQueries.jsx'

import TopBar from './components/common/TopBar'
import SideBar from './components/common/SideBar'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import styles from './components/common/Styles.jsx'

var injectTapEventPlugin = require("react-tap-event-plugin")
injectTapEventPlugin()

const muiTheme = getMuiTheme(styles)

const PageRoute = ({ component: Component, path, sitePath, ...rest }) => (
  <Route {...rest} path={path} render={props => {
    return (

        <TopBar />

          <SideBar location={sitePath} />

            <Component {...props} />

    );
  }}/>
)

init(() => {
  ReactDOM.render(
    <MuiThemeProvider  muiTheme={muiTheme}>
      <BrowserRouter history={history}>
        <Switch>
          <PageRoute sitePath="/discovery" path="/discovery/:query" component={SearchPage} />
          <PageRoute sitePath="/discovery" path="/discovery/" component={SearchPage} />
          <PageRoute sitePath="/admin" path="/admin" component={AdminOverview} />
          <PageRoute sitePath="/createNew" exact path="/createNew" component={CreateProject} />
          <PageRoute sitePath="/createNew" path="/createByURL/:getURL" component={CreateProjectByURL} />
          <PageRoute sitePath="/createNew" path="/createFromFile/:data" component={CreateProjectFromFile} />
          <PageRoute sitePath="/update" path="/update/:uuid" component={CreateProject} />
          <PageRoute sitePath="/createbylink" path="/createbylink" component={CreateProjectChoice} />
          <PageRoute sitePath="/project" path="/project/:uuid" component={ProjectContainer} />
          <PageRoute sitePath="/bookmarks" path="/bookmarks" component={BookmarksTable} />
          <PageRoute sitePath="/profile" path="/profile/:email" component={ProfileContainer} />
          <PageRoute sitePath="/yourprojects" path="/yourprojects" component={UserProjects} />
          <PageRoute sitePath="/queries" path="/queries" component={SavedQueries} />
          <Route path="/register" component={SignUp} />
          <Route exact path="/" component={SignIn} />
          <Route component={() => (<Redirect to="/"/>)} />
       </Switch>
      </BrowserRouter>
    </MuiThemeProvider>
  , document.getElementById('root'))
  registerServiceWorker()
});
<|endoftext|>


<commit_before>
var widgets = require ("sdk/widget");
var tabs = require ("sdk/tabs");
var data = require ("sdk/self").data;

var EksiPanel = require ("sdk/panel").Panel ({
  position: {
    left: 0,
    top: 0,
    right: 0,
    bottom: 0
  },
  contentURL: data.url ("index.html"),
  contentScriptFile: [
    data.url ('require.js'),
    data.url ('main-built.js')
  ]
});

EksiPanel.on ("show", function (){
  EksiPanel.port.emit ("show");
});

var widget = widgets.Widget ({
  id: "eksi-okuyucu",
  label: "Eksi Okuyucu",
  contentURL: require ("sdk/self").data.url ("img/icon.png"),
  onClick: function () {
    EksiPanel.show ();
  }
});
<commit_msg>update script url<commit_after>
var widgets = require ("sdk/widget");
var tabs = require ("sdk/tabs");
var data = require ("sdk/self").data;

var EksiPanel = require ("sdk/panel").Panel ({
  position: {
    left: 0,
    top: 0,
    right: 0,
    bottom: 0
  },
  contentURL: data.url ("index.html"),
  contentScriptFile: [
    data.url ('js/main.js')
  ]
});

EksiPanel.on ("show", function (){
  EksiPanel.port.emit ("show");
});

var widget = widgets.Widget ({
  id: "eksi-okuyucu",
  label: "Eksi Okuyucu",
  contentURL: require ("sdk/self").data.url ("img/icon.png"),
  onClick: function () {
    EksiPanel.show ();
  }
});
<|endoftext|>


<commit_before>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule createHierarchyRenderer
 */

'use strict';

var React = require('React');

/**
 * Creates a render method that makes it easier to create, render, and inspect a
 * hierarchy of mock React component classes.
 *
 * A component class is created for each of the supplied render methods. Each
 * render method is invoked with the classes created using the render methods
 * that come after it in the supplied list of render methods.
 *
 *   var renderHierarchy = createHierarchyRenderer(
 *     function ComponentA(ComponentB, ComponentC) {...},
 *     function ComponentB(ComponentC) {...},
 *     function ComponentC() {...}
 *   );
 *
 * When the hierarchy is invoked, a two-dimensional array is returned. Each
 * array corresponds to a supplied render method and contains the instances
 * returned by that render method in the order it was invoked.
 *
 *   var instances = renderHierarchy(
 *     function(ComponentA[, ComponentB, ComponentC]) {
 *       ReactDOM.render(<ComponentA />, ...);
 *     })
 *   );
 *   instances[0][0]; // First return value of first render method.
 *   instances[1][0]; // First return value of second render method.
 *   instances[1][1]; // Second return value of second render method.
 *
 * Refs should be used to reference components that are not the return value of
 * render methods.
 *
 *   expect(instances[0][0].refs.X).toBe(...);
 *
 * NOTE: The component classes created for each render method are re-used for
 * each invocation of the hierarchy renderer. If new classes are needed, you
 * should re-execute `createHierarchyRenderer` with the same arguments.
 *
 * @param {array<function>} ...renderMethods
 * @return {function}
 */
function createHierarchyRenderer(...renderMethods) {
  var instances;
  var Components = renderMethods.reduceRight(
    function(ComponentsAccumulator, renderMethod, depth) {
      var Component = React.createClass({
        displayName: renderMethod.name,
        render: function() {
          instances[depth].push(this);
          return renderMethod.apply(this, ComponentsAccumulator);
        },
      });
      return [Component].concat(ComponentsAccumulator);
    },
    []
  );
  /**
   * @param {function} renderComponent
   * @return {array<array<*>>}
   */
  function renderHierarchy(renderComponent) {
    instances = renderMethods.map(() => []);
    renderComponent.apply(null, Components);
    return instances;
  }
  return renderHierarchy;
}

module.exports = createHierarchyRenderer;
<commit_msg>Remove unused createHierarchyRenderer (#7454)<commit_after><|endoftext|>


<commit_before>/* global bp, bsync, PHILOSOPHER_COUNT */

bp.log.info('Tic-Tac-Toe - Let the game begin!');

var countX = 0;
var countO = 0;

/*
 * Block further marking of a square already
 * marked by X or O.
 */
bp.registerBThread("squareTaken", function() {
	while (true) {

		var e = bsync(
                {
					waitFor : [ bp.Event("Pick" + i + "R"),
							    bp.Event("Pick" + j + "L") ],
					block : [ bp.Event("Rel" + i + "R"),
							  bp.Event("Rel" + j + "L") ]
				}).name;

		var wt = (e.equals("Pick" + i + "R")) ? "Rel" + i + "R" : "Rel" + j	+ "L";
		// Request to pick the right stick
		bsync({
			request : bp.Event("Pick" + philNum + "R")
		});

	}
});

/*
 * Alternately block O moves while waiting
 * for X moves, and vice versa (we assume that X always plays first).
 */
bp.registerBThread("EnforceTurns", function() {
	while (true) {

	}
});

/*
 * Wait for placement of three X marks
 * in a line and request XWin.
 * To-do: Priority-------------------------------------
 */
bp.registerBThread("DetectXWin", function() {
	while (true) {
		bsync({
			waitFor : [ bp.Event("3XRow"),
					    bp.Event("3XCol") ],
						bp.Event("3XDia") ]
		}).name;

		bsync({
			request : bp.Event("XWin")
		});
	}
});

/*
 * Wait for placement of three O marks
 * in a line and request OWin.
 * To-do: Priority-------------------------------------
 */
bp.registerBThread("DetectOWin", function() {
	while (true) {
		bsync({
			waitFor : [ bp.Event("3ORow"),
					    bp.Event("3OCol") ],
						bp.Event("3ODia") ]
		}).name;

		bsync({
			request : bp.Event("OWin")
		});
	}
});

/*
 * Wait for nine moves and request draw event.
 */
bp.registerBThread("DetectDraw", function() {
	while (true) {
		if(countX+countO == 9)

	}
});

<commit_msg>fixed .js file<commit_after>/* global bp, bsync, PHILOSOPHER_COUNT */

bp.log.info('Tic-Tac-Toe - Let the game begin!');

var countX = 0;
var countO = 0;

/*
 * Block further marking of a square already
 * marked by X or O.
 */
bp.registerBThread("squareTaken", function() {
	while (true) {

		var e = bsync(
                {
					waitFor : [ bp.Event("Pick" + i + "R"),
							    bp.Event("Pick" + j + "L") ],
					block : [ bp.Event("Rel" + i + "R"),
							  bp.Event("Rel" + j + "L") ]
				}).name;

		var wt = (e.equals("Pick" + i + "R")) ? "Rel" + i + "R" : "Rel" + j	+ "L";
		// Request to pick the right stick
		bsync({
			request : bp.Event("Pick" + philNum + "R")
		});

	}
});

/*
 * Alternately block O moves while waiting
 * for X moves, and vice versa (we assume that X always plays first).
 */
bp.registerBThread("EnforceTurns", function() {
	while (true) {

	}
});

/*
 * Wait for placement of three X marks
 * in a line and request XWin.
 * To-do: Priority-------------------------------------
 */
bp.registerBThread("DetectXWin", function() {
	while (true) {
		bsync({
			waitFor : [ bp.Event("3XRow"),
					    bp.Event("3XCol"),
						bp.Event("3XDia") ]
		}).name;

		bsync({
			request : bp.Event("XWin")
		});
	}
});

/*
 * Wait for placement of three O marks
 * in a line and request OWin.
 * To-do: Priority-------------------------------------
 */
bp.registerBThread("DetectOWin", function() {
	while (true) {
		bsync({
			waitFor : [ bp.Event("3ORow"),
					    bp.Event("3OCol"),
						bp.Event("3ODia") ]
		}).name;

		bsync({
			request : bp.Event("OWin")
		});
	}
});

/*
 * Wait for nine moves and request draw event.
 */
bp.registerBThread("DetectDraw", function() {
	while (true) {
		if ( countX+countO === 9 ) {
            // TODO what?
        }

	}
});

<|endoftext|>


<commit_before>/* eslint-disable no-unused-expressions */

/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */
import { batch } from 'react-redux';

import { UIDatabase, createRecord } from '../database';

import { PrescriberActions } from './PrescriberActions';
import { WizardActions } from './WizardActions';

export const PRESCRIPTION_ACTIONS = {
  REFRESH: 'Prescription/refresh',
};

export const updateDirection = (id, newValue) => (_, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const item = items.filtered('id == $0', id)[0];
  item?.setItemDirection(UIDatabase, newValue);
};

export const removeItem = id => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const item = items.filtered('id == $0', id);

  UIDatabase.write(() => {
    UIDatabase.delete('TransactionItem', item);
  });
  dispatch({ type: PRESCRIPTION_ACTIONS.REFRESH });
};

export const editQuantity = (id, quantity) => (_, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const itemToUpdate = items.filtered('id == $0', id)[0];

  UIDatabase.write(() => {
    itemToUpdate.setTotalQuantity(UIDatabase, quantity);
    UIDatabase.save('TransactionItem', itemToUpdate);
  });
};

const assignPrescriber = prescriberID => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const prescriber = UIDatabase.get('Prescriber', prescriberID);

  UIDatabase.write(() =>
    UIDatabase.update('Transaction', {
      ...transaction,
      prescriber,
    })
  );

  batch(() => {
    dispatch(PrescriberActions.setPrescriber(prescriber));
    dispatch(WizardActions.nextTab());
  });
};

export const addItem = itemID => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const item = UIDatabase.get('Item', itemID);

  if (!transaction.hasItem(item)) {
    UIDatabase.write(() => {
      createRecord(UIDatabase, 'TransactionItem', transaction, item, 1);
    });
  }

  dispatch({ type: PRESCRIPTION_ACTIONS.REFRESH });
};

export const PrescriptionActions = {
  addItem,
  assignPrescriber,
  editQuantity,
  removeItem,
  updateDirection,
};
<commit_msg>Add remove exporting<commit_after>/* eslint-disable no-unused-expressions */

/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */
import { batch } from 'react-redux';

import { UIDatabase, createRecord } from '../database';

import { PrescriberActions } from './PrescriberActions';
import { WizardActions } from './WizardActions';

export const PRESCRIPTION_ACTIONS = {
  REFRESH: 'Prescription/refresh',
};

const updateDirection = (id, newValue) => (_, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const item = items.filtered('id == $0', id)[0];
  item?.setItemDirection(UIDatabase, newValue);
};

const removeItem = id => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const item = items.filtered('id == $0', id);

  UIDatabase.write(() => {
    UIDatabase.delete('TransactionItem', item);
  });
  dispatch({ type: PRESCRIPTION_ACTIONS.REFRESH });
};

const editQuantity = (id, quantity) => (_, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const { items } = transaction;

  const itemToUpdate = items.filtered('id == $0', id)[0];

  UIDatabase.write(() => {
    itemToUpdate.setTotalQuantity(UIDatabase, quantity);
    UIDatabase.save('TransactionItem', itemToUpdate);
  });
};

const assignPrescriber = prescriberID => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const prescriber = UIDatabase.get('Prescriber', prescriberID);

  UIDatabase.write(() =>
    UIDatabase.update('Transaction', {
      ...transaction,
      prescriber,
    })
  );

  batch(() => {
    dispatch(PrescriberActions.setPrescriber(prescriber));
    dispatch(WizardActions.nextTab());
  });
};

const addItem = itemID => (dispatch, getState) => {
  const { prescription } = getState();
  const { transaction } = prescription;
  const item = UIDatabase.get('Item', itemID);

  if (!transaction.hasItem(item)) {
    UIDatabase.write(() => {
      createRecord(UIDatabase, 'TransactionItem', transaction, item, 1);
    });
  }

  dispatch({ type: PRESCRIPTION_ACTIONS.REFRESH });
};

export const PrescriptionActions = {
  addItem,
  assignPrescriber,
  editQuantity,
  removeItem,
  updateDirection,
};
<|endoftext|>


<commit_before>/* globals describe, it, expect, expectObservable, expectSubscription, hot, cold */
var Rx = require('../../dist/cjs/Rx');
var Observable = Rx.Observable;
var Scheduler = Rx.Scheduler;

describe('Observable.prototype.throttleTime()', function () {
  it('should throttle events by 50 time units', function (done) {
    Observable.of(1, 2, 3).throttleTime(50)
      .subscribe(function (x) {
        expect(x).toBe(1);
      }, null, done);
  });

  it('should throttle events multiple times', function (done) {
    var expected = ['1-0', '2-0'];
    Observable.concat(
      Observable.timer(0, 10).take(3).map(function (x) { return '1-' + x; }),
      Observable.timer(80, 10).take(5).map(function (x) { return '2-' + x; })
      )
      .throttleTime(50)
      .subscribe(function (x) {
        expect(x).toBe(expected.shift());
      }, null, done);
  });

  it('should simply mirror the source if values are not emitted often enough', function () {
    var e1 =   hot('-a--------b-----c----|');
    var subs =     '^                    !';
    var expected = '-a--------b-----c----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should immediately emit the first value in each time window', function () {
    var e1 =   hot('-a-x-y----b---x-cx---|');
    var subs =     '^                    !';
    var expected = '-a--------b-----c----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a busy producer emitting a regular repeating sequence', function () {
    var e1 =   hot('abcdefabcdefabcdefabcdefa|');
    var subs =     '^                        !';
    var expected = 'a-----a-----a-----a-----a|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should complete when source does not emit', function () {
    var e1 =   hot('-----|');
    var subs =     '^    !';
    var expected = '-----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should raise error when source does not emit and raises error', function () {
    var e1 =   hot('-----#');
    var expected = '-----#';

    expectObservable(e1.throttleTime(10, rxTestScheduler)).toBe(expected);
  });

  it('should handle an empty source', function () {
    var e1 =  cold('|');
    var subs =     '(^!)';
    var expected = '|';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a never source', function () {
    var e1 =  cold('-');
    var subs =     '^';
    var expected = '-';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a throw source', function () {
    var e1 =  cold('#');
    var subs =     '(^!)';
    var expected = '#';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should throttle and does not complete when source does not completes', function () {
    var e1 =   hot('-a--(bc)-------d----------------');
    var unsub =    '                               !';
    var subs =     '^                              !';
    var expected = '-a-------------d----------------';

    expectObservable(e1.throttleTime(50, rxTestScheduler), unsub).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should throttle values until source raises error', function () {
    var e1 =   hot('-a--(bc)-------d---------------#');
    var subs =     '^                              !';
    var expected = '-a-------------d---------------#';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });
});<commit_msg>test(throttleTime): improve subscription assertions<commit_after>/* globals describe, it, expect, expectObservable, expectSubscription, hot, cold */
var Rx = require('../../dist/cjs/Rx');
var Observable = Rx.Observable;
var Scheduler = Rx.Scheduler;

describe('Observable.prototype.throttleTime()', function () {
  it('should throttle events by 50 time units', function (done) {
    Observable.of(1, 2, 3).throttleTime(50)
      .subscribe(function (x) {
        expect(x).toBe(1);
      }, null, done);
  });

  it('should throttle events multiple times', function (done) {
    var expected = ['1-0', '2-0'];
    Observable.concat(
      Observable.timer(0, 10).take(3).map(function (x) { return '1-' + x; }),
      Observable.timer(80, 10).take(5).map(function (x) { return '2-' + x; })
      )
      .throttleTime(50)
      .subscribe(function (x) {
        expect(x).toBe(expected.shift());
      }, null, done);
  });

  it('should simply mirror the source if values are not emitted often enough', function () {
    var e1 =   hot('-a--------b-----c----|');
    var subs =     '^                    !';
    var expected = '-a--------b-----c----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should immediately emit the first value in each time window', function () {
    var e1 =   hot('-a-x-y----b---x-cx---|');
    var subs =     '^                    !';
    var expected = '-a--------b-----c----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a busy producer emitting a regular repeating sequence', function () {
    var e1 =   hot('abcdefabcdefabcdefabcdefa|');
    var subs =     '^                        !';
    var expected = 'a-----a-----a-----a-----a|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should complete when source does not emit', function () {
    var e1 =   hot('-----|');
    var subs =     '^    !';
    var expected = '-----|';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should raise error when source does not emit and raises error', function () {
    var e1 =   hot('-----#');
    var subs =     '^    !';
    var expected = '-----#';

    expectObservable(e1.throttleTime(10, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle an empty source', function () {
    var e1 =  cold('|');
    var subs =     '(^!)';
    var expected = '|';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a never source', function () {
    var e1 =  cold('-');
    var subs =     '^';
    var expected = '-';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should handle a throw source', function () {
    var e1 =  cold('#');
    var subs =     '(^!)';
    var expected = '#';

    expectObservable(e1.throttleTime(30, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should throttle and does not complete when source does not completes', function () {
    var e1 =   hot('-a--(bc)-------d----------------');
    var unsub =    '                               !';
    var subs =     '^                              !';
    var expected = '-a-------------d----------------';

    expectObservable(e1.throttleTime(50, rxTestScheduler), unsub).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });

  it('should throttle values until source raises error', function () {
    var e1 =   hot('-a--(bc)-------d---------------#');
    var subs =     '^                              !';
    var expected = '-a-------------d---------------#';

    expectObservable(e1.throttleTime(50, rxTestScheduler)).toBe(expected);
    expectSubscriptions(e1.subscriptions).toBe(subs);
  });
});<|endoftext|>


<commit_before>/*jslint browser: true, for: true, node: true */
/*global window */

/*!

   hlsjs engine plugin for Flowplayer HTML5

   Copyright (c) 2015-2016, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Includes hls.js
   Copyright (c) 2015 Dailymotion (http://www.dailymotion.com)
   https://github.com/dailymotion/hls.js/blob/master/LICENSE

   requires:
   - Flowplayer HTML5 version 6.x or greater
   - hls.js https://github.com/dailymotion/hls.js
   revision: $GIT_ID$

*/

(function (flowplayer, Hls) {
    "use strict";
    var engineName = "hlsjs",
        hlsconf,
        common = flowplayer.common,
        extend = flowplayer.extend,
        support = flowplayer.support,
        version = flowplayer.version,

        isHlsType = function (typ) {
            return typ.toLowerCase().indexOf("mpegurl") > -1;
        },

        engineImpl = function hlsjsEngine(player, root) {
            var bean = flowplayer.bean,
                videoTag,
                hls,
                recover,

                bc,
                has_bg,
                posterHack = function (e) {
                    // abuse timeupdate to re-instate poster
                    var posterClass = "is-poster";

                    // not fired on ready in Firefox
                    // must be fired on ready in webkit
                    bean.one(videoTag, "timeupdate." + engineName, function () {
                        common.addClass(root, posterClass);
                        player.poster = true;
                        // timeupdate after ready for webkit
                        bean.one(videoTag, (e.type === "stop"
                            ? "play."
                            : "timeupdate.") + engineName, function () {
                            common.removeClass(root, posterClass);
                            player.poster = false;
                        });
                    });
                },

                getStartLevelConf = function () {
                    var value = hlsconf.startLevel;

                    switch (value) {
                    case "auto":
                        value = -1;
                        break;
                    case "firstLevel":
                        value = undefined;
                        break;
                    }
                    return value;
                },
                disableAutoLevel = 0,

                qActive = "active",
                dataQuality = function (quality) {
                    // e.g. "Level 1" -> "level1"
                    if (!quality) {
                        quality = player.quality;
                    }
                    return quality.toLowerCase().replace(/\ /g, "");
                },
                removeAllQualityClasses = function () {
                    var qualities = player.qualities;

                    if (!qualities || !qualities.length) {
                        return;
                    }
                    common.removeClass(root, "quality-abr");
                    qualities.forEach(function (quality) {
                        common.removeClass(root, "quality-" + dataQuality(quality));
                    });
                },
                qClean = function () {
                    delete player.hlsQualities;
                    player.qualities = [];
                    removeAllQualityClasses();
                    common.find(".fp-quality-selector li", root).forEach(bean.off);
                    common.find(".fp-quality-selector", root).forEach(common.removeNode);
                },
                qIndex = function () {
                    return player.hlsQualities[player.qualities.indexOf(player.quality) + 1];
                },
                initQualitySelection = function (hlsQualitiesConf, data) {
                    var levels = data.levels,
                        levelIndex = 0,
                        selector;

                    player.hlsQualities = [];
                    levels.forEach(function (level) {
                        if ((hlsQualitiesConf === true || hlsQualitiesConf.indexOf(levelIndex) > -1) &&
                                level.videoCodec &&
                                window.MediaSource.isTypeSupported('video/mp4;codecs=' + level.videoCodec)) {
                            // do not check audioCodec,
                            // as e.g. HE_AAC is decoded as LC_AAC by hls.js on Android
                            player.hlsQualities.push(levelIndex);
                        }
                        levelIndex += 1;
                    });
                    if (player.hlsQualities.length < 2) {
                        qClean();
                        return;
                    }

                    player.qualities = [];
                    player.hlsQualities.forEach(function (levelIndex) {
                        var level = levels[levelIndex],
                            width = level.width,
                            height = level.height,
                            label = (width && height)
                                ? Math.min(width, height) + "p"
                                : "Level " + (levelIndex + 1);

                        player.qualities.push(label);
                    });

                    selector = common.createElement("ul", {
                        "class": "fp-quality-selector"
                    });
                    common.find(".fp-ui", root)[0].appendChild(selector);

                    player.hlsQualities.unshift(-1);

                    if (!player.quality || player.qualities.indexOf(player.quality) < 0) {
                        hls.startLevel = getStartLevelConf();
                        player.quality = "abr";
                    } else {
                        hls.startLevel = qIndex();
                        disableAutoLevel = "startLevel";
                    }

                    selector.appendChild(common.createElement("li", {
                        "data-quality": "abr"
                    }, "Auto"));
                    player.qualities.forEach(function (q) {
                        selector.appendChild(common.createElement("li", {
                            "data-quality": dataQuality(q)
                        }, q));
                    });

                    common.addClass(root, "quality-" + dataQuality());

                    bean.on(root, "click", ".fp-quality-selector li", function (e) {
                        var choice = e.currentTarget,
                            selectors,
                            active,
                            i;

                        if (common.hasClass(choice, qActive)) {
                            return;
                        }

                        selectors = common.find(".fp-quality-selector li", root);

                        for (i = 0; i < selectors.length; i += 1) {
                            active = selectors[i] === choice;
                            if (active) {
                                player.quality = i > 0
                                    ? player.qualities[i - 1]
                                    : "abr";
                                if (hlsconf.smoothSwitching) {
                                    hls.nextLevel = qIndex();
                                } else {
                                    hls.currentLevel = qIndex();
                                }
                                player.resume();
                                common.addClass(choice, qActive);
                            }
                            common.toggleClass(selectors[i], qActive, active);
                        }
                        removeAllQualityClasses();
                        common.addClass(root, "quality-" + dataQuality());
                    });
                },

                engine = {
                    engineName: engineName,

                    pick: function (sources) {
                        var i,
                            source;

                        for (i = 0; i < sources.length; i += 1) {
                            source = sources[i];
                            if (isHlsType(source.type)
                                    && (!source.engine || source.engine === engineName)) {
                                if (typeof source.src === 'string') {
                                    source.src = common.createAbsoluteUrl(source.src);
                                }
                                return source;
                            }
                        }
                    },

                    load: function (video) {
                        var init = !hls,
                            conf = player.conf,
                            hlsQualitiesConf = conf.clip.hlsQualities || conf.hlsQualities,
                            hlsClientConf = extend({}, hlsconf),
                            hlsParams = [
                                "autoLevelCapping", "startLevel",
                                "adaptOnStartOnly", "smoothSwitching",
                                "anamorphic", "recover", "strict"
                            ];

                        if (init) {
                            common.removeNode(common.findDirect("video", root)[0]
                                    || common.find(".fp-player > video", root)[0]);
                            videoTag = common.createElement("video", {
                                className: "fp-engine " + engineName + "-engine",
                                autoplay: conf.autoplay
                                    ? "autoplay"
                                    : false
                            });
                            videoTag.setAttribute("x-webkit-airplay", "allow");

                        } else {
                            hls.destroy();
                        }

                        bean.on(videoTag, "play", function () {
                            player.trigger('resume', [player]);
                        });
                        bean.on(videoTag, "pause", function () {
                            player.trigger('pause', [player]);
                        });
                        bean.on(videoTag, "timeupdate", function () {
                            player.trigger('progress', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "loadeddata", function () {
                            video = extend(video, {
                                duration: videoTag.duration,
                                seekable: videoTag.seekable.end(null),
                                width: videoTag.videoWidth,
                                height: videoTag.videoHeight,
                                url: videoTag.currentSrc
                            });
                            player.trigger('ready', [player, video]);

                            var quality = player.quality,
                                selectorIndex;

                            if (quality) {
                                selectorIndex = quality === "abr"
                                    ? 0
                                    : player.qualities.indexOf(quality) + 1;
                                common.addClass(common.find(".fp-quality-selector li", root)[selectorIndex], qActive);
                            }
                        });
                        bean.on(videoTag, "seeked", function () {
                            player.trigger('seek', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "progress", function (e) {
                            var ct = videoTag.currentTime,
                                buffer = 0,
                                buffend,
                                buffered,
                                last,
                                i;

                            try {
                                buffered = videoTag.buffered;
                                last = buffered.length - 1;
                                buffend = 0;
                                // cycle through time ranges to obtain buffer
                                // nearest current time
                                if (ct) {
                                    for (i = last; i > -1; i -= 1) {
                                        buffend = buffered.end(i);

                                        if (buffend >= ct) {
                                            buffer = buffend;
                                        }
                                    }
                                }
                            } catch (ignore) {}

                            video.buffer = buffer;
                            player.trigger('buffer', [player, e]);
                        });
                        bean.on(videoTag, "ended", function () {
                            player.trigger('finish', [player]);
                        });
                        bean.on(videoTag, "volumechange", function () {
                            player.trigger('volume', [player, videoTag.volume]);
                        });

                        hlsParams.forEach(function (key) {
                            delete hlsClientConf[key];
                        });
                        hls = new Hls(hlsClientConf);
                        player.engine[engineName] = hls;

                        hlsParams.forEach(function (key) {
                            var value = hlsconf[key];

                            switch (key) {
                            case "adaptOnStartOnly":
                                if (value) {
                                    hls.startLevel = -1;
                                    disableAutoLevel = "currentLevel";
                                }
                                break;
                            case "autoLevelCapping":
                                if (value === false) {
                                    value = -1;
                                }
                                break;
                            case "recover":
                                recover = hlsconf.strict
                                    ? 0
                                    : value;
                                break;
                            case "startLevel":
                                value = (player.hlsQualities && player.quality)
                                    ? qIndex()
                                    : getStartLevelConf();
                                break;
                            }

                            if ((key === "autoLevelCapping" || key === "startLevel") && value !== undefined) {
                                hls[key] = value;
                            }
                        });

                        qClean();

                        Object.keys(Hls.Events).forEach(function (key) {
                            hls.on(Hls.Events[key], function (etype, data) {
                                var fperr,
                                    errobj = {};

                                switch (key) {
                                case "MANIFEST_PARSED":
                                    if (support.inlineVideo && hlsQualitiesConf) {
                                        initQualitySelection(hlsQualitiesConf, data);
                                    } else {
                                        delete player.quality;
                                    }
                                    break;

                                case "FRAG_CHANGED":
                                    if (disableAutoLevel) {
                                        hls.nextLevel = hls[disableAutoLevel];
                                        disableAutoLevel = 0;
                                    }
                                    break;

                                case "ERROR":
                                    if (data.fatal || hlsconf.strict > 0) {
                                        switch (data.type) {
                                        case Hls.ErrorTypes.NETWORK_ERROR:
                                            if (recover) {
                                                hls.startLoad();
                                                if (recover > 0) {
                                                    recover -= 1;
                                                }
                                            } else if (data.frag && data.frag.url) {
                                                errobj.url = data.frag.url;
                                                fperr = 2;
                                            } else {
                                                fperr = 4;
                                            }
                                            break;
                                        case Hls.ErrorTypes.MEDIA_ERROR:
                                            if (recover) {
                                                hls.recoverMediaError();
                                                if (recover > 0) {
                                                    recover -= 1;
                                                }
                                            } else {
                                                fperr = 3;
                                            }
                                            break;
                                        default:
                                            fperr = 5;
                                        }

                                        if (fperr !== undefined) {
                                            errobj.code = fperr;
                                            if (fperr > 2) {
                                                errobj.video = extend(video, {
                                                    src: video.src,
                                                    url: data.url || video.src
                                                });
                                            }
                                            player.trigger('error', [player, errobj]);
                                            return;
                                        }
                                    }
                                    // log non fatals?
                                    break;
                                }

                                player.trigger(etype, [player, data]);
                            });
                        });

                        if (init) {
                            common.prepend(common.find(".fp-player", root)[0], videoTag);
                        }

                        hls.loadSource(video.src);
                        hls.attachMedia(videoTag);

                        if (videoTag.paused && (video.autoplay || conf.autoplay)) {
                            videoTag.play();
                        }
                    },

                    resume: function () {
                        videoTag.play();
                    },

                    pause: function () {
                        videoTag.pause();
                    },

                    seek: function (time) {
                        videoTag.currentTime = time;
                    },

                    volume: function (level) {
                        if (videoTag) {
                            videoTag.volume = level;
                        }
                    },

                    speed: function (val) {
                        videoTag.playbackRate = val;
                        player.trigger('speed', [player, val]);
                    },

                    unload: function () {
                        // hls conditional probably not needed once
                        // https://github.com/flowplayer/flowplayer/commit/871ff783a8f23aa603e1120f4319d4a892125b0a
                        // is released
                        if (hls) {
                            hls.destroy();
                            hls = 0;
                            bean.off(videoTag);
                            common.removeNode(videoTag);
                            videoTag = 0;
                            qClean();
                        }
                    }
                };

            // pre 6.0.4: no boolean api.conf.poster and no poster with autoplay
            if (/^6\.0\.[0-3]$/.test(version) &&
                    !player.conf.splash && !player.conf.poster && !player.conf.autoplay) {
                bc = common.css(root, 'backgroundColor');
                // spaces in rgba arg mandatory for recognition
                has_bg = common.css(root, 'backgroundImage') !== "none" ||
                        (bc && bc !== "rgba(0, 0, 0, 0)" && bc !== "transparent");
                if (has_bg) {
                    player.conf.poster = true;
                }
            }
            if (player.conf.poster) {
                // when engine is loaded or player stopped
                // the engine is too late to the party:
                // poster is already removed and api.poster is false
                // poster state must be set again
                player.on("ready." + engineName + " stop." + engineName, posterHack);
            }

            return engine;
        };

    if (Hls.isSupported() && version.indexOf("5.") !== 0) {
        // only load engine if it can be used
        engineImpl.engineName = engineName; // must be exposed
        engineImpl.canPlay = function (type, conf) {
            var b = support.browser,
                wn = window.navigator,
                IE11 = wn.userAgent.indexOf("Trident/7") > -1;

            if (conf[engineName] === false || conf.clip[engineName] === false) {
                // engine disabled for player or clip
                return false;
            }

            // merge hlsjs clip config at earliest opportunity
            hlsconf = extend({
                smoothSwitching: true,
                recover: 0
            }, flowplayer.conf[engineName], conf[engineName], conf.clip[engineName]);

            if (isHlsType(type)) {
                // allow all browsers for hlsjs debugging
                if (hlsconf.debug) {
                    return true;
                }
                // https://bugzilla.mozilla.org/show_bug.cgi?id=1244294
                if (hlsconf.anamorphic &&
                        wn.platform.indexOf("Win") === 0 && b.mozilla && b.version.indexOf("44.") === 0) {
                    return false;
                }

                // https://github.com/dailymotion/hls.js/issues/9
                return IE11 || !b.safari;
            }
            return false;
        };

        // put on top of engine stack
        // so hlsjs is tested before html5 video hls and flash hls
        flowplayer.engines.unshift(engineImpl);

        flowplayer(function (api) {
            // to take precedence over VOD quality selector
            // hlsQualities must be configure at player or global level
            var hlsQualities = api.conf.hlsQualities || flowplayer.conf.hlsQualities;
            if (hlsQualities) {
                api.pluginQualitySelectorEnabled = engineImpl.canPlay("application/x-mpegurl", api.conf);
            }
        });

    }

}.apply(null, (typeof module === 'object' && module.exports)
    ? [require('flowplayer'), require('hls.js')]
    : [window.flowplayer, window.Hls]));
<commit_msg>Unregister .hlsjs api events (#26)<commit_after>/*jslint browser: true, for: true, node: true */
/*global window */

/*!

   hlsjs engine plugin for Flowplayer HTML5

   Copyright (c) 2015-2016, Flowplayer Oy

   Released under the MIT License:
   http://www.opensource.org/licenses/mit-license.php

   Includes hls.js
   Copyright (c) 2015 Dailymotion (http://www.dailymotion.com)
   https://github.com/dailymotion/hls.js/blob/master/LICENSE

   requires:
   - Flowplayer HTML5 version 6.x or greater
   - hls.js https://github.com/dailymotion/hls.js
   revision: $GIT_ID$

*/

(function (flowplayer, Hls) {
    "use strict";
    var engineName = "hlsjs",
        hlsconf,
        common = flowplayer.common,
        extend = flowplayer.extend,
        support = flowplayer.support,
        version = flowplayer.version,

        isHlsType = function (typ) {
            return typ.toLowerCase().indexOf("mpegurl") > -1;
        },

        engineImpl = function hlsjsEngine(player, root) {
            var bean = flowplayer.bean,
                videoTag,
                hls,
                recover,

                bc,
                has_bg,
                posterHack = function (e) {
                    // abuse timeupdate to re-instate poster
                    var posterClass = "is-poster";

                    // not fired on ready in Firefox
                    // must be fired on ready in webkit
                    bean.one(videoTag, "timeupdate." + engineName, function () {
                        common.addClass(root, posterClass);
                        player.poster = true;
                        // timeupdate after ready for webkit
                        bean.one(videoTag, (e.type === "stop"
                            ? "play."
                            : "timeupdate.") + engineName, function () {
                            common.removeClass(root, posterClass);
                            player.poster = false;
                        });
                    });
                },

                getStartLevelConf = function () {
                    var value = hlsconf.startLevel;

                    switch (value) {
                    case "auto":
                        value = -1;
                        break;
                    case "firstLevel":
                        value = undefined;
                        break;
                    }
                    return value;
                },
                disableAutoLevel = 0,

                qActive = "active",
                dataQuality = function (quality) {
                    // e.g. "Level 1" -> "level1"
                    if (!quality) {
                        quality = player.quality;
                    }
                    return quality.toLowerCase().replace(/\ /g, "");
                },
                removeAllQualityClasses = function () {
                    var qualities = player.qualities;

                    if (!qualities || !qualities.length) {
                        return;
                    }
                    common.removeClass(root, "quality-abr");
                    qualities.forEach(function (quality) {
                        common.removeClass(root, "quality-" + dataQuality(quality));
                    });
                },
                qClean = function () {
                    delete player.hlsQualities;
                    player.qualities = [];
                    removeAllQualityClasses();
                    common.find(".fp-quality-selector li", root).forEach(bean.off);
                    common.find(".fp-quality-selector", root).forEach(common.removeNode);
                },
                qIndex = function () {
                    return player.hlsQualities[player.qualities.indexOf(player.quality) + 1];
                },
                initQualitySelection = function (hlsQualitiesConf, data) {
                    var levels = data.levels,
                        levelIndex = 0,
                        selector;

                    player.hlsQualities = [];
                    levels.forEach(function (level) {
                        if ((hlsQualitiesConf === true || hlsQualitiesConf.indexOf(levelIndex) > -1) &&
                                level.videoCodec &&
                                window.MediaSource.isTypeSupported('video/mp4;codecs=' + level.videoCodec)) {
                            // do not check audioCodec,
                            // as e.g. HE_AAC is decoded as LC_AAC by hls.js on Android
                            player.hlsQualities.push(levelIndex);
                        }
                        levelIndex += 1;
                    });
                    if (player.hlsQualities.length < 2) {
                        qClean();
                        return;
                    }

                    player.qualities = [];
                    player.hlsQualities.forEach(function (levelIndex) {
                        var level = levels[levelIndex],
                            width = level.width,
                            height = level.height,
                            label = (width && height)
                                ? Math.min(width, height) + "p"
                                : "Level " + (levelIndex + 1);

                        player.qualities.push(label);
                    });

                    selector = common.createElement("ul", {
                        "class": "fp-quality-selector"
                    });
                    common.find(".fp-ui", root)[0].appendChild(selector);

                    player.hlsQualities.unshift(-1);

                    if (!player.quality || player.qualities.indexOf(player.quality) < 0) {
                        hls.startLevel = getStartLevelConf();
                        player.quality = "abr";
                    } else {
                        hls.startLevel = qIndex();
                        disableAutoLevel = "startLevel";
                    }

                    selector.appendChild(common.createElement("li", {
                        "data-quality": "abr"
                    }, "Auto"));
                    player.qualities.forEach(function (q) {
                        selector.appendChild(common.createElement("li", {
                            "data-quality": dataQuality(q)
                        }, q));
                    });

                    common.addClass(root, "quality-" + dataQuality());

                    bean.on(root, "click", ".fp-quality-selector li", function (e) {
                        var choice = e.currentTarget,
                            selectors,
                            active,
                            i;

                        if (common.hasClass(choice, qActive)) {
                            return;
                        }

                        selectors = common.find(".fp-quality-selector li", root);

                        for (i = 0; i < selectors.length; i += 1) {
                            active = selectors[i] === choice;
                            if (active) {
                                player.quality = i > 0
                                    ? player.qualities[i - 1]
                                    : "abr";
                                if (hlsconf.smoothSwitching) {
                                    hls.nextLevel = qIndex();
                                } else {
                                    hls.currentLevel = qIndex();
                                }
                                player.resume();
                                common.addClass(choice, qActive);
                            }
                            common.toggleClass(selectors[i], qActive, active);
                        }
                        removeAllQualityClasses();
                        common.addClass(root, "quality-" + dataQuality());
                    });
                },

                engine = {
                    engineName: engineName,

                    pick: function (sources) {
                        var i,
                            source;

                        for (i = 0; i < sources.length; i += 1) {
                            source = sources[i];
                            if (isHlsType(source.type)
                                    && (!source.engine || source.engine === engineName)) {
                                if (typeof source.src === 'string') {
                                    source.src = common.createAbsoluteUrl(source.src);
                                }
                                return source;
                            }
                        }
                    },

                    load: function (video) {
                        var init = !hls,
                            conf = player.conf,
                            hlsQualitiesConf = conf.clip.hlsQualities || conf.hlsQualities,
                            hlsClientConf = extend({}, hlsconf),
                            hlsParams = [
                                "autoLevelCapping", "startLevel",
                                "adaptOnStartOnly", "smoothSwitching",
                                "anamorphic", "recover", "strict"
                            ];

                        if (init) {
                            common.removeNode(common.findDirect("video", root)[0]
                                    || common.find(".fp-player > video", root)[0]);
                            videoTag = common.createElement("video", {
                                className: "fp-engine " + engineName + "-engine",
                                autoplay: conf.autoplay
                                    ? "autoplay"
                                    : false
                            });
                            videoTag.setAttribute("x-webkit-airplay", "allow");

                        } else {
                            hls.destroy();
                        }

                        bean.on(videoTag, "play", function () {
                            player.trigger('resume', [player]);
                        });
                        bean.on(videoTag, "pause", function () {
                            player.trigger('pause', [player]);
                        });
                        bean.on(videoTag, "timeupdate", function () {
                            player.trigger('progress', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "loadeddata", function () {
                            video = extend(video, {
                                duration: videoTag.duration,
                                seekable: videoTag.seekable.end(null),
                                width: videoTag.videoWidth,
                                height: videoTag.videoHeight,
                                url: videoTag.currentSrc
                            });
                            player.trigger('ready', [player, video]);

                            var quality = player.quality,
                                selectorIndex;

                            if (quality) {
                                selectorIndex = quality === "abr"
                                    ? 0
                                    : player.qualities.indexOf(quality) + 1;
                                common.addClass(common.find(".fp-quality-selector li", root)[selectorIndex], qActive);
                            }
                        });
                        bean.on(videoTag, "seeked", function () {
                            player.trigger('seek', [player, videoTag.currentTime]);
                        });
                        bean.on(videoTag, "progress", function (e) {
                            var ct = videoTag.currentTime,
                                buffer = 0,
                                buffend,
                                buffered,
                                last,
                                i;

                            try {
                                buffered = videoTag.buffered;
                                last = buffered.length - 1;
                                buffend = 0;
                                // cycle through time ranges to obtain buffer
                                // nearest current time
                                if (ct) {
                                    for (i = last; i > -1; i -= 1) {
                                        buffend = buffered.end(i);

                                        if (buffend >= ct) {
                                            buffer = buffend;
                                        }
                                    }
                                }
                            } catch (ignore) {}

                            video.buffer = buffer;
                            player.trigger('buffer', [player, e]);
                        });
                        bean.on(videoTag, "ended", function () {
                            player.trigger('finish', [player]);
                        });
                        bean.on(videoTag, "volumechange", function () {
                            player.trigger('volume', [player, videoTag.volume]);
                        });

                        hlsParams.forEach(function (key) {
                            delete hlsClientConf[key];
                        });
                        hls = new Hls(hlsClientConf);
                        player.engine[engineName] = hls;

                        hlsParams.forEach(function (key) {
                            var value = hlsconf[key];

                            switch (key) {
                            case "adaptOnStartOnly":
                                if (value) {
                                    hls.startLevel = -1;
                                    disableAutoLevel = "currentLevel";
                                }
                                break;
                            case "autoLevelCapping":
                                if (value === false) {
                                    value = -1;
                                }
                                break;
                            case "recover":
                                recover = hlsconf.strict
                                    ? 0
                                    : value;
                                break;
                            case "startLevel":
                                value = (player.hlsQualities && player.quality)
                                    ? qIndex()
                                    : getStartLevelConf();
                                break;
                            }

                            if ((key === "autoLevelCapping" || key === "startLevel") && value !== undefined) {
                                hls[key] = value;
                            }
                        });

                        qClean();

                        Object.keys(Hls.Events).forEach(function (key) {
                            hls.on(Hls.Events[key], function (etype, data) {
                                var fperr,
                                    errobj = {};

                                switch (key) {
                                case "MANIFEST_PARSED":
                                    if (support.inlineVideo && hlsQualitiesConf) {
                                        initQualitySelection(hlsQualitiesConf, data);
                                    } else {
                                        delete player.quality;
                                    }
                                    break;

                                case "FRAG_CHANGED":
                                    if (disableAutoLevel) {
                                        hls.nextLevel = hls[disableAutoLevel];
                                        disableAutoLevel = 0;
                                    }
                                    break;

                                case "ERROR":
                                    if (data.fatal || hlsconf.strict > 0) {
                                        switch (data.type) {
                                        case Hls.ErrorTypes.NETWORK_ERROR:
                                            if (recover) {
                                                hls.startLoad();
                                                if (recover > 0) {
                                                    recover -= 1;
                                                }
                                            } else if (data.frag && data.frag.url) {
                                                errobj.url = data.frag.url;
                                                fperr = 2;
                                            } else {
                                                fperr = 4;
                                            }
                                            break;
                                        case Hls.ErrorTypes.MEDIA_ERROR:
                                            if (recover) {
                                                hls.recoverMediaError();
                                                if (recover > 0) {
                                                    recover -= 1;
                                                }
                                            } else {
                                                fperr = 3;
                                            }
                                            break;
                                        default:
                                            fperr = 5;
                                        }

                                        if (fperr !== undefined) {
                                            errobj.code = fperr;
                                            if (fperr > 2) {
                                                errobj.video = extend(video, {
                                                    src: video.src,
                                                    url: data.url || video.src
                                                });
                                            }
                                            player.trigger('error', [player, errobj]);
                                            return;
                                        }
                                    }
                                    // log non fatals?
                                    break;
                                }

                                player.trigger(etype, [player, data]);
                            });
                        });

                        if (init) {
                            common.prepend(common.find(".fp-player", root)[0], videoTag);
                        }

                        hls.loadSource(video.src);
                        hls.attachMedia(videoTag);

                        if (videoTag.paused && (video.autoplay || conf.autoplay)) {
                            videoTag.play();
                        }
                    },

                    resume: function () {
                        videoTag.play();
                    },

                    pause: function () {
                        videoTag.pause();
                    },

                    seek: function (time) {
                        videoTag.currentTime = time;
                    },

                    volume: function (level) {
                        if (videoTag) {
                            videoTag.volume = level;
                        }
                    },

                    speed: function (val) {
                        videoTag.playbackRate = val;
                        player.trigger('speed', [player, val]);
                    },

                    unload: function () {
                        if (hls) {
                            hls.destroy();
                            hls = 0;
                            player.off("." + engineName);
                            bean.off(videoTag);
                            common.removeNode(videoTag);
                            videoTag = 0;
                            qClean();
                        }
                    }
                };

            // pre 6.0.4: no boolean api.conf.poster and no poster with autoplay
            if (/^6\.0\.[0-3]$/.test(version) &&
                    !player.conf.splash && !player.conf.poster && !player.conf.autoplay) {
                bc = common.css(root, 'backgroundColor');
                // spaces in rgba arg mandatory for recognition
                has_bg = common.css(root, 'backgroundImage') !== "none" ||
                        (bc && bc !== "rgba(0, 0, 0, 0)" && bc !== "transparent");
                if (has_bg) {
                    player.conf.poster = true;
                }
            }
            if (player.conf.poster) {
                // when engine is loaded or player stopped
                // the engine is too late to the party:
                // poster is already removed and api.poster is false
                // poster state must be set again
                player.on("ready." + engineName + " stop." + engineName, posterHack);
            }

            return engine;
        };

    if (Hls.isSupported() && version.indexOf("5.") !== 0) {
        // only load engine if it can be used
        engineImpl.engineName = engineName; // must be exposed
        engineImpl.canPlay = function (type, conf) {
            var b = support.browser,
                wn = window.navigator,
                IE11 = wn.userAgent.indexOf("Trident/7") > -1;

            if (conf[engineName] === false || conf.clip[engineName] === false) {
                // engine disabled for player or clip
                return false;
            }

            // merge hlsjs clip config at earliest opportunity
            hlsconf = extend({
                smoothSwitching: true,
                recover: 0
            }, flowplayer.conf[engineName], conf[engineName], conf.clip[engineName]);

            if (isHlsType(type)) {
                // allow all browsers for hlsjs debugging
                if (hlsconf.debug) {
                    return true;
                }
                // https://bugzilla.mozilla.org/show_bug.cgi?id=1244294
                if (hlsconf.anamorphic &&
                        wn.platform.indexOf("Win") === 0 && b.mozilla && b.version.indexOf("44.") === 0) {
                    return false;
                }

                // https://github.com/dailymotion/hls.js/issues/9
                return IE11 || !b.safari;
            }
            return false;
        };

        // put on top of engine stack
        // so hlsjs is tested before html5 video hls and flash hls
        flowplayer.engines.unshift(engineImpl);

        flowplayer(function (api) {
            // to take precedence over VOD quality selector
            // hlsQualities must be configure at player or global level
            var hlsQualities = api.conf.hlsQualities || flowplayer.conf.hlsQualities;
            if (hlsQualities) {
                api.pluginQualitySelectorEnabled = engineImpl.canPlay("application/x-mpegurl", api.conf);
            }
        });

    }

}.apply(null, (typeof module === 'object' && module.exports)
    ? [require('flowplayer'), require('hls.js')]
    : [window.flowplayer, window.Hls]));
<|endoftext|>


<commit_before>var $ = require('jquery');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var checkAndBuildOpts = require('../../../helpers/required-opts');

var REQUIRED_OPTS = [
  'onboardingNotification',
  'editorModel',
  'template',
  'numberOfSteps',
  'notificationKey',
  'modifier'
];

var LEFT_KEY_CODE = 37;
var RIGHT_KEY_CODE = 39;

module.exports = CoreView.extend({
  className: 'LayerOnboarding is-step0 is-opening',

  events: {
    'click .js-start': '_onClickNext',
    'click .js-next': '_onClickNext',
    'click .js-close': '_close'
  },

  initialize: function (opts) {
    checkAndBuildOpts(opts, REQUIRED_OPTS, this);
    this.model = new Backbone.Model({
      step: 0
    });

    this.model.bind('change:step', this._onChangeStep, this);

    this._keyDown = this._onKeyDown.bind(this);
    $(document).on('keydown', this._keyDown);

    this.$el.addClass('LayerOnboarding' + this._modifier);

    this._initBinds();
  },

  render: function () {
    this.$el.html(this._template());

    return this;
  },

  _initBinds: function () {
    this.listenTo(this.model, 'destroy', this._close);
    this.listenTo(this._editorModel, 'change:edition', this._changeEdition);
    this.add_related_model(this._editorModel);
  },

  _changeEdition: function (mdl) {
    var isEditing = !!mdl.get('edition');
    this.$el.toggleClass('is-editing', isEditing);
  },

  _prev: function () {
    if (this.model.get('step') >= 1) {
      this.model.set('step', this.model.get('step') - 1);
    }
  },

  _next: function () {
    if (this.model.get('step') < this._numberOfSteps) {
      this.model.set('step', this.model.get('step') + 1);
    }
  },

  _onClickNext: function () {
    this._next();
  },

  _onChangeStep: function () {
    var self = this;
    this.$el.removeClass('is-step' + this.model.previous('step'), function () {
      self.$el.addClass('is-step' + self.model.get('step'));
    });

    this.$('.js-step').removeClass('is-step' + this.model.previous('step'), function () {
      self.$('.js-step').addClass('is-step' + self.model.get('step'));
    });
  },

  _close: function () {
    this._checkForgetStatus();
    this.trigger('close', this);
  },

  _onKeyDown: function (e) {
    e.stopPropagation();

    if (e.which === LEFT_KEY_CODE) {
      this._prev();
    } else if (e.which === RIGHT_KEY_CODE) {
      this._next();
    }
  },

  _checkForgetStatus: function () {
    if (this.$('.js-forget:checked').val()) {
      this._forget();
    }
  },

  _forget: function () {
    this._onboardingNotification.setKey(this._notificationKey, true);
    this._onboardingNotification.save();
  },

  clean: function () {
    $(document).off('keydown', this._keyDown);
    CoreView.prototype.clean.apply(this);
  }
});
<commit_msg>CR feedback applied<commit_after>var $ = require('jquery');
var Backbone = require('backbone');
var CoreView = require('backbone/core-view');
var checkAndBuildOpts = require('../../../helpers/required-opts');

var REQUIRED_OPTS = [
  'onboardingNotification',
  'editorModel',
  'template',
  'numberOfSteps',
  'notificationKey',
  'modifier'
];

var LEFT_KEY_CODE = 37;
var RIGHT_KEY_CODE = 39;

module.exports = CoreView.extend({
  className: 'LayerOnboarding is-step0 is-opening',

  events: {
    'click .js-start': '_onClickNext',
    'click .js-next': '_onClickNext',
    'click .js-close': '_close'
  },

  initialize: function (opts) {
    checkAndBuildOpts(opts, REQUIRED_OPTS, this);
    this.model = new Backbone.Model({
      step: 0
    });

    this._keyDown = this._onKeyDown.bind(this);
    this._initBinds();
  },

  render: function () {
    this.$el.html(this._template());
    this.$el.addClass('LayerOnboarding' + this._modifier);
    return this;
  },

  _initBinds: function () {
    this.listenTo(this.model, 'change:step', this._onChangeStep);
    this.listenTo(this.model, 'destroy', this._close);
    this.listenTo(this._editorModel, 'change:edition', this._changeEdition);
    $(document).on('keydown', this._keyDown);
  },

  _changeEdition: function (mdl) {
    var isEditing = !!mdl.get('edition');
    this.$el.toggleClass('is-editing', isEditing);
  },

  _prev: function () {
    var currentStep = this.model.get('step');
    if (currentStep >= 1) {
      this.model.set('step', currentStep - 1);
    }
  },

  _next: function () {
    var currentStep = this.model.get('step');
    if (currentStep < this._numberOfSteps) {
      this.model.set('step', currentStep + 1);
    }
  },

  _onClickNext: function () {
    this._next();
  },

  _onChangeStep: function () {
    this.$el.removeClass('is-step' + this.model.previous('step'), function () {
      this.$el.addClass('is-step' + this.model.get('step'));
    }.bind(this));

    this.$('.js-step').removeClass('is-step' + this.model.previous('step'), function () {
      this.$('.js-step').addClass('is-step' + this.model.get('step'));
    }.bind(this));
  },

  _close: function () {
    this._checkForgetStatus();
    this.trigger('close', this);
  },

  _onKeyDown: function (e) {
    e.stopPropagation();

    if (e.which === LEFT_KEY_CODE) {
      this._prev();
    } else if (e.which === RIGHT_KEY_CODE) {
      this._next();
    }
  },

  _checkForgetStatus: function () {
    if (this.$('.js-forget:checked').val()) {
      this._forget();
    }
  },

  _forget: function () {
    this._onboardingNotification.setKey(this._notificationKey, true);
    this._onboardingNotification.save();
  },

  clean: function () {
    $(document).off('keydown', this._keyDown);
    CoreView.prototype.clean.apply(this);
  }
});
<|endoftext|>


<commit_before>// --------------------------------------------------------------------------------------
// define angular module/app
var etlog = angular.module('etlog', ['ui.router', 'angularUtils.directives.dirPagination' ]);
// --------------------------------------------------------------------------------------
// set page title
// --------------------------------------------------------------------------------------
etlog.run(['$rootScope', '$http', '$state', function($rootScope, $http, $state) {
  $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
    $rootScope.title = toState.title;   // set current state title
  });
  get_user_info($rootScope, $http);
  check_state_permissions($rootScope, $state, $http);
}]);
// --------------------------------------------------------------------------------------
// check the user has correct permissions to enter desired state
// --------------------------------------------------------------------------------------
function check_state_permissions($rootScope, $state, $http)
{
  $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    get_permissions($http, function(data) {
      var highest = data[data.length - 1];  // highest available privilege

      if(toState.allowed && toState.allowed.indexOf(highest) == -1) {
        event.preventDefault();

        if(!fromState.name)     // no previous state
          $state.go('search');  // "default" state
        else
          $state.go(fromState.name);    // go to previous state
      }
    });
  });
}
// --------------------------------------------------------------------------------------
// get user permissions from backend
// --------------------------------------------------------------------------------------
function get_permissions($http, callback)
{
  $http({
    method  : 'GET',
    url     : '/api/user/permissions'
  })
    .then(function(response) {
      callback(response.data);
  });
}
// --------------------------------------------------------------------------------------
// get basic user info
// --------------------------------------------------------------------------------------
function get_user_info($rootScope, $http)
{
  if(!$rootScope.user) {
    $http({
      method  : 'GET',
      url     : '/api/user/info'
    })
    .then(function(response) {
      $rootScope.user = response.data;
    });
  }
}
// --------------------------------------------------------------------------------------
// http interceptor to solve expired shibboleth sessions
// --------------------------------------------------------------------------------------
etlog.factory('expired_sessions_interceptor', function($q, $window) {
  return {
   // XMLHttpRequest cannot load https://ds.eduid.cz/wayf.php?filter=..... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://etlog-dev.cesnet.cz' is therefore not allowed access.
   // not a clean solution for reauthenticating the user if the SP session expires but it works
   'responseError': function(rejection) {
      console.log("responseError");
      console.log(rejection);
      $window.location.reload();    // reaload the page to force the reauthentication on idp
      return $q.reject(rejection);
    }
  };
});
// --------------------------------------------------------------------------------------
etlog.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push('expired_sessions_interceptor');
}]);
// --------------------------------------------------------------------------------------
<commit_msg>remove debug<commit_after>// --------------------------------------------------------------------------------------
// define angular module/app
var etlog = angular.module('etlog', ['ui.router', 'angularUtils.directives.dirPagination' ]);
// --------------------------------------------------------------------------------------
// set page title
// --------------------------------------------------------------------------------------
etlog.run(['$rootScope', '$http', '$state', function($rootScope, $http, $state) {
  $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
    $rootScope.title = toState.title;   // set current state title
  });
  get_user_info($rootScope, $http);
  check_state_permissions($rootScope, $state, $http);
}]);
// --------------------------------------------------------------------------------------
// check the user has correct permissions to enter desired state
// --------------------------------------------------------------------------------------
function check_state_permissions($rootScope, $state, $http)
{
  $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    get_permissions($http, function(data) {
      var highest = data[data.length - 1];  // highest available privilege

      if(toState.allowed && toState.allowed.indexOf(highest) == -1) {
        event.preventDefault();

        if(!fromState.name)     // no previous state
          $state.go('search');  // "default" state
        else
          $state.go(fromState.name);    // go to previous state
      }
    });
  });
}
// --------------------------------------------------------------------------------------
// get user permissions from backend
// --------------------------------------------------------------------------------------
function get_permissions($http, callback)
{
  $http({
    method  : 'GET',
    url     : '/api/user/permissions'
  })
    .then(function(response) {
      callback(response.data);
  });
}
// --------------------------------------------------------------------------------------
// get basic user info
// --------------------------------------------------------------------------------------
function get_user_info($rootScope, $http)
{
  if(!$rootScope.user) {
    $http({
      method  : 'GET',
      url     : '/api/user/info'
    })
    .then(function(response) {
      $rootScope.user = response.data;
    });
  }
}
// --------------------------------------------------------------------------------------
// http interceptor to solve expired shibboleth sessions
// --------------------------------------------------------------------------------------
etlog.factory('expired_sessions_interceptor', function($q, $window) {
  return {
   // XMLHttpRequest cannot load https://ds.eduid.cz/wayf.php?filter=..... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://etlog-dev.cesnet.cz' is therefore not allowed access.
   // not a clean solution for reauthenticating the user if the SP session expires but it works
   'responseError': function(rejection) {
      $window.location.reload();    // reaload the page to force the reauthentication on idp
      return $q.reject(rejection);
    }
  };
});
// --------------------------------------------------------------------------------------
etlog.config(['$httpProvider', function($httpProvider) {
  $httpProvider.interceptors.push('expired_sessions_interceptor');
}]);
// --------------------------------------------------------------------------------------
<|endoftext|>