<commit_before>/* eslint-disable no-underscore-dangle */

import { Checkbox, Button, Col, Row, Grid, Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';

import getCSRF from '../../../../shared/util/getcsrf';
import Utility from '../../../../shared/util/Utility';
import * as Security from '../../../../shared/reducers/Security';

export const Reducers = [Security];

export class loginScreen extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checkboxChecked: false,
      username: '',
      password: '',
      _csrf: getCSRF(),
      submitLogin: true,
      canSubmit: false,
      invalidUsername: false
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  componentWillMount() {
    if (this.props.loggedIn) {
      this.props.setPageByName('/');
    } else {
      this.props.clearAuthResponse();
    }
  }

  setLoginSubmitMode(submitLogin) {
    this.setState({
      submitLogin
    });
  }

  getValidationState() {
    // success, warning, error, or null
    if (this.haveFailedAuth()) {
      return 'error';
    } else if (this.haveSucceededAuth()) {
      return 'success';
    }

    return null;
  }
  handleChange(e) {
    this.setState({ checkboxChecked: e.target.checked });
  }

  handleInputChange(e) {
    this.setState({ [e.target.name]: e.target.value });
    if(e.target.name==='username'){this.validateUsername(e)}
  }
  validateUsername(e){
      let regex = RegExp('[^A-Za-z0-9]+');
      this.setState({invalidUsername : regex.test(e.target.value)});
  }

  handleSubmit(formData) {
    formData.preventDefault();

    if (this.state.submitLogin) {
      this.props.requestUserLogin(formData, this.props.redirectUrl || '/');
    } else {
      this.props.requestUserRegister(formData, this.props.redirectUrl || '/');
    }
  }

  haveSucceededAuth() {
    return (
      !this.props.loginInProgress &&
      !this.props.registerInProgress &&
      this.props.authSuccess &&
      this.props.authResponse !== ''
    );
  }
  haveFailedAuth() {
    return (
      !this.props.loginInProgress &&
      !this.props.registerInProgress &&
      !this.props.authSuccess &&
      this.props.authResponse !== ''
    );
  }
  render() {
    return (
      <Grid>
        <Row>
          <Col
            mdOffset={0}
            md={4}
          >

Registrera dig snabbt och enkelt här

                Vi sparar inga personuppgifter så var noga med att komma ihåg ditt lösenord då vi inte kan återställa
                det åt dig.

                Materialet är anpassat efter det svenska språket och du kan lära dig från svenska till japanska och
                japanska till svenska

          </Col>
          <Col
            mdOffset={1}
            md={4}
          >
            <Form onSubmit={this.handleSubmit}>
              <fieldset>
                <FormGroup
                  controlId="formBasicText"
                  validationState={this.getValidationState()}
                >
                  <legend>Logga in eller registrera dig</legend>
                  {this.props.authResponse && this.getValidationState() ? (
                    <ControlLabel name="authFeedback">{this.props.authResponse}</ControlLabel>
                  ) : null}
                </FormGroup>
                <FormGroup>
                  <FormControl
                    type="text"
                    name="username"
                    placeholder="Användarnamn"
                    value={this.state.username}
                    onChange={this.handleInputChange}
                  />
                    {this.state.invalidUsername===true ?

                            Ett användarnamn kan endast innehålla bokstäver och nummer

 : null}
                  <FormControl.Feedback />
                </FormGroup>
                <FormGroup>
                  <FormControl
                    type="password"
                    name="password"
                    placeholder="Lösenord"
                    value={this.state.password}
                    onChange={this.handleInputChange}
                  />
                </FormGroup>
                <FormControl
                  type="hidden"
                  name="_csrf"
                  value={this.state._csrf}
                />
                <FormGroup>
                  <Button
                    label="login"
                    onClick={() => this.setLoginSubmitMode(true)}
                    bsStyle="primary"
                    name="login"
                    type="submit"
                    disabled={!this.state.username || !this.state.password}
                  >
                    Logga in
                  </Button>{' '}
                  <Button
                    label="login"
                    onClick={() => this.setLoginSubmitMode(false)}
                    bsStyle="success"
                    name="register"
                    type="submit"
                    disabled={!this.state.username || !this.state.password || this.state.invalidUsername}
                  >
                    Registrera
                  </Button>{' '}
                  <Checkbox
                    label="remember-me"
                    name="remember-me"
                    checked={this.state.checkboxChecked}
                    onChange={this.handleChange}
                  >
                    Håll mig inloggad
                  </Checkbox>{' '}
                </FormGroup>
              </fieldset>
            </Form>
          </Col>
        </Row>
      </Grid>
    );
  }
}

loginScreen.defaultProps = Utility.reduxEnabledDefaultProps({}, Reducers);

loginScreen.propTypes = Utility.reduxEnabledPropTypes({}, Reducers);

export default Utility.superConnect(this, Reducers)(loginScreen);
<commit_msg>Constraint description<commit_after>/* eslint-disable no-underscore-dangle */

import { Checkbox, Button, Col, Row, Grid, Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';

import getCSRF from '../../../../shared/util/getcsrf';
import Utility from '../../../../shared/util/Utility';
import * as Security from '../../../../shared/reducers/Security';

export const Reducers = [Security];

export class loginScreen extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      checkboxChecked: false,
      username: '',
      password: '',
      _csrf: getCSRF(),
      submitLogin: true,
      canSubmit: false,
      invalidUsername: false
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
  }

  componentWillMount() {
    if (this.props.loggedIn) {
      this.props.setPageByName('/');
    } else {
      this.props.clearAuthResponse();
    }
  }

  setLoginSubmitMode(submitLogin) {
    this.setState({
      submitLogin
    });
  }

  getValidationState() {
    // success, warning, error, or null
    if (this.haveFailedAuth()) {
      return 'error';
    } else if (this.haveSucceededAuth()) {
      return 'success';
    }

    return null;
  }
  handleChange(e) {
    this.setState({ checkboxChecked: e.target.checked });
  }

  handleInputChange(e) {
    this.setState({ [e.target.name]: e.target.value });
    if(e.target.name==='username'){this.validateUsername(e)}
  }
  validateUsername(e){
      let regex = RegExp('[^A-Za-z0-9]+');
      this.setState({invalidUsername : regex.test(e.target.value)});
  }

  handleSubmit(formData) {
    formData.preventDefault();

    if (this.state.submitLogin) {
      this.props.requestUserLogin(formData, this.props.redirectUrl || '/');
    } else {
      this.props.requestUserRegister(formData, this.props.redirectUrl || '/');
    }
  }

  haveSucceededAuth() {
    return (
      !this.props.loginInProgress &&
      !this.props.registerInProgress &&
      this.props.authSuccess &&
      this.props.authResponse !== ''
    );
  }
  haveFailedAuth() {
    return (
      !this.props.loginInProgress &&
      !this.props.registerInProgress &&
      !this.props.authSuccess &&
      this.props.authResponse !== ''
    );
  }
  render() {
    return (
      <Grid>
        <Row>
          <Col
            mdOffset={0}
            md={4}
          >

Registrera dig snabbt och enkelt här

                Vi sparar inga personuppgifter så var noga med att komma ihåg ditt lösenord då vi inte kan återställa
                det åt dig.

                Materialet är anpassat efter det svenska språket och du kan lära dig från svenska till japanska och
                japanska till svenska

          </Col>
          <Col
            mdOffset={1}
            md={4}
          >
            <Form onSubmit={this.handleSubmit}>
              <fieldset>
                <FormGroup
                  controlId="formBasicText"
                  validationState={this.getValidationState()}
                >
                  <legend>Logga in eller registrera dig</legend>
                  {this.props.authResponse && this.getValidationState() ? (
                    <ControlLabel name="authFeedback">{this.props.authResponse}</ControlLabel>
                  ) : null}
                </FormGroup>
                <FormGroup>
                    {this.state.invalidUsername===true ?

                            Ett användarnamn kan endast innehålla bokstäver och siffror och måste vara mellan 2 och 32 tecken

 : null}
                  <FormControl
                    type="text"
                    name="username"
                    placeholder="Användarnamn"
                    value={this.state.username}
                    onChange={this.handleInputChange}
                  />
                  <FormControl.Feedback />
                </FormGroup>
                <FormGroup>
                  <FormControl
                    type="password"
                    name="password"
                    placeholder="Lösenord"
                    value={this.state.password}
                    onChange={this.handleInputChange}
                  />
                </FormGroup>
                <FormControl
                  type="hidden"
                  name="_csrf"
                  value={this.state._csrf}
                />
                <FormGroup>
                  <Button
                    label="login"
                    onClick={() => this.setLoginSubmitMode(true)}
                    bsStyle="primary"
                    name="login"
                    type="submit"
                    disabled={!this.state.username || !this.state.password}
                  >
                    Logga in
                  </Button>{' '}
                  <Button
                    label="login"
                    onClick={() => this.setLoginSubmitMode(false)}
                    bsStyle="success"
                    name="register"
                    type="submit"
                    disabled={!this.state.username || !this.state.password || this.state.invalidUsername}
                  >
                    Registrera
                  </Button>{' '}
                  <Checkbox
                    label="remember-me"
                    name="remember-me"
                    checked={this.state.checkboxChecked}
                    onChange={this.handleChange}
                  >
                    Håll mig inloggad
                  </Checkbox>{' '}
                </FormGroup>
              </fieldset>
            </Form>
          </Col>
        </Row>
      </Grid>
    );
  }
}

loginScreen.defaultProps = Utility.reduxEnabledDefaultProps({}, Reducers);

loginScreen.propTypes = Utility.reduxEnabledPropTypes({}, Reducers);

export default Utility.superConnect(this, Reducers)(loginScreen);
<|endoftext|>


<commit_before>'use strict';

var remove   = require('es5-ext/lib/Array/prototype/remove')
  , d        = require('es5-ext/lib/Object/descriptor')
  , callable = require('es5-ext/lib/Object/valid-callable')
  , ee       = require('event-emitter/lib/core')
  , nextTick = require('next-tick')
  , now      = require('time-uuid/lib/time')
  , proto    = require('./_proto')
  , Event    = require('./event')
  , objects  = require('./objects')
  , history  = require('./history')

  , call = Function.prototype.call
  , getObject = objects._get
  , out = exports, stamp = null, reverse = {}
  , clear = function () { stamp = null; }
  , byStamp = function (a, b) { return b.stamp - a.stamp; }
  , relType = { relation: true, 'relation-set-item': true }
  , objectType = { object: true, namespace: true, prototype: true };

Object.defineProperties(ee(out), {
	_id: d('0'),
	_add: d(function (event) {
		var obj, id, previous, objHistory, dismissed, assigned, addedTo
		  , removedFrom, masterObj;

		obj = event.obj;
		id = obj._id_;

		// Update history and reverse relations index
		objHistory = history.hasOwnProperty(id) && history[id];
		if (!objHistory) {
			history[id] = [event];
		} else {
			previous = objHistory[0];
			if (previous) {
				if (previous.stamp > event.stamp) {
					// Outdated update, add to history and quit
					objHistory.unshift(event);
					objHistory.sort(byStamp);
					event.fulfilled = true;
					return;
				} else if (previous.stamp < event.stamp) {
					objHistory.unshift(event);
				} else {
					if ((previous.sourceId === event.sourceId) &&
							(previous.value === event.value)) {
						obj.$$setValue(event.value);
						event.fulfilled = true;
						return;
					}
					objHistory.splice(0, 1, event);
					if (previous.value === event.value) {
						obj.$$setValue(event.value);
						out.emit('update', event, previous);
						event.fulfilled = true;
						return;
					}
				}
				if (previous.value && (previous.value !== event.value)) {
					if (obj._type_ === 'relation-set-item') {
						if (obj._key_[0] === '7') {
							id = obj._key_.slice(1);
							dismissed = getObject(id);
							if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
							else dismissed = null;
						}
					}
					if (previous.value._type_) {
						if (obj._type_ === 'relation') {
							if (previous.value._type_ === 'object') {
								id = previous.value._id_;
								remove.call(reverse[id], obj);
								dismissed = previous.value;
							}
						} else if (objectType[previous.value._type_]) {
							removedFrom = previous.value;
						}
					}
				}
			} else {
				objHistory.unshift(event);
			}
		}
		if (event.value && (!previous || (previous.value !== event.value))) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					assigned = getObject(id);
					if (assigned._type_ === 'object') {
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
					} else {
						assigned = null;
					}
				}
			}
			if (event.value._type_) {
				if (obj._type_ === 'relation') {
					if (event.value._type_ === 'object') {
						id = event.value._id_;
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
						assigned = event.value;
					}
				} else if (objectType[event.value._type_]) {
					addedTo = event.value;
				}
			}
		}

		obj.$$setValue(event.value);
		obj.emit('selfupdate', event, previous);
		if (relType[obj._type_]) {
			masterObj = obj.obj;
			while (masterObj && relType[masterObj._type_]) masterObj = masterObj.obj;
			if (masterObj) masterObj.emit('update', event, previous);
			if (dismissed) dismissed.emit('dismiss', event, previous);
			if (assigned) assigned.emit('assign', event, previous);
		} else if (removedFrom || addedTo) {
			if (removedFrom) removedFrom.emit('reduce', event, previous);
			if (addedTo) addedTo.emit('extend', event, previous);
		}
		out.emit('update', event, previous);
		event.fulfilled = true;
	}),
	_remove: d(function (id) {
		var obj = getObject(id), subId
		  , objHistory = history.hasOwnProperty(id) && history[id]
		  , lastEvent = objHistory[0], dismissed, removedFrom;

		if (lastEvent && lastEvent.value) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					subId = obj._key_.slice(1);
					dismissed = getObject(subId);
					if (dismissed._type_ === 'object') remove.call(reverse[subId], obj);
					else dismissed = null;
				}
			}
			if (lastEvent.value._type_) {
				if (obj._type_ === 'relation') {
					if (lastEvent.value._type_ === 'object') {
						subId = lastEvent.value._id_;
						remove.call(reverse[subId], obj);
						dismissed = lastEvent.value;
					}
				} else if (objectType[lastEvent.value._type_]) {
					removedFrom = lastEvent.value;
				}
			}
		}

		delete history[id];
		obj.$$setValue();
		if (relType[obj._type_]) {
			do {
				obj = obj.obj;
				if (!obj) break;
			} while (relType[obj._type_]);
			if (obj && lastEvent) obj.emit('update', null, lastEvent);
			if (dismissed) dismissed.emit('dismiss', null, lastEvent);
		} else if (removedFrom) {
			obj.emit('selfupdate', null, lastEvent);
			removedFrom.emit('reduce', null, lastEvent);
		}
		out.emit('remove', id);
	})
});

Object.defineProperties(proto, {
	_signal_: d(function (value) {
		if (stamp == null) {
			stamp = now();
			nextTick(clear);
		}
		out._add(new Event(this, value, stamp));
	}),
	_forEachReverse_: d(function (cb/*, thisArg*/) {
		var data, thisArg = arguments[1];
		callable(cb);
		data = reverse.hasOwnProperty(this._id_) && reverse[this._id_];
		if (!data) return;
		data.forEach(function (rel) {
			call.call(cb, thisArg, rel, rel._id_, this);
		}, this);
	})
});
<commit_msg>Improve logic of signal._remove<commit_after>'use strict';

var remove   = require('es5-ext/lib/Array/prototype/remove')
  , d        = require('es5-ext/lib/Object/descriptor')
  , callable = require('es5-ext/lib/Object/valid-callable')
  , ee       = require('event-emitter/lib/core')
  , nextTick = require('next-tick')
  , now      = require('time-uuid/lib/time')
  , proto    = require('./_proto')
  , Event    = require('./event')
  , objects  = require('./objects')
  , history  = require('./history')

  , call = Function.prototype.call
  , getObject = objects._get
  , out = exports, stamp = null, reverse = {}
  , clear = function () { stamp = null; }
  , byStamp = function (a, b) { return b.stamp - a.stamp; }
  , relType = { relation: true, 'relation-set-item': true }
  , objectType = { object: true, namespace: true, prototype: true };

Object.defineProperties(ee(out), {
	_id: d('0'),
	_add: d(function (event) {
		var obj, id, previous, objHistory, dismissed, assigned, addedTo
		  , removedFrom, masterObj;

		obj = event.obj;
		id = obj._id_;

		// Update history and reverse relations index
		objHistory = history.hasOwnProperty(id) && history[id];
		if (!objHistory) {
			history[id] = [event];
		} else {
			previous = objHistory[0];
			if (previous) {
				if (previous.stamp > event.stamp) {
					// Outdated update, add to history and quit
					objHistory.unshift(event);
					objHistory.sort(byStamp);
					event.fulfilled = true;
					return;
				} else if (previous.stamp < event.stamp) {
					objHistory.unshift(event);
				} else {
					if ((previous.sourceId === event.sourceId) &&
							(previous.value === event.value)) {
						obj.$$setValue(event.value);
						event.fulfilled = true;
						return;
					}
					objHistory.splice(0, 1, event);
					if (previous.value === event.value) {
						obj.$$setValue(event.value);
						out.emit('update', event, previous);
						event.fulfilled = true;
						return;
					}
				}
				if (previous.value && (previous.value !== event.value)) {
					if (obj._type_ === 'relation-set-item') {
						if (obj._key_[0] === '7') {
							id = obj._key_.slice(1);
							dismissed = getObject(id);
							if (dismissed._type_ === 'object') remove.call(reverse[id], obj);
							else dismissed = null;
						}
					}
					if (previous.value._type_) {
						if (obj._type_ === 'relation') {
							if (previous.value._type_ === 'object') {
								id = previous.value._id_;
								remove.call(reverse[id], obj);
								dismissed = previous.value;
							}
						} else if (objectType[previous.value._type_]) {
							removedFrom = previous.value;
						}
					}
				}
			} else {
				objHistory.unshift(event);
			}
		}
		if (event.value && (!previous || (previous.value !== event.value))) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					id = obj._key_.slice(1);
					assigned = getObject(id);
					if (assigned._type_ === 'object') {
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
					} else {
						assigned = null;
					}
				}
			}
			if (event.value._type_) {
				if (obj._type_ === 'relation') {
					if (event.value._type_ === 'object') {
						id = event.value._id_;
						if (reverse.hasOwnProperty(id)) reverse[id].push(obj);
						else reverse[id] = [obj];
						assigned = event.value;
					}
				} else if (objectType[event.value._type_]) {
					addedTo = event.value;
				}
			}
		}

		obj.$$setValue(event.value);
		obj.emit('selfupdate', event, previous);
		if (relType[obj._type_]) {
			masterObj = obj.obj;
			while (masterObj && relType[masterObj._type_]) masterObj = masterObj.obj;
			if (masterObj) masterObj.emit('update', event, previous);
			if (dismissed) dismissed.emit('dismiss', event, previous);
			if (assigned) assigned.emit('assign', event, previous);
		} else if (removedFrom || addedTo) {
			if (removedFrom) removedFrom.emit('reduce', event, previous);
			if (addedTo) addedTo.emit('extend', event, previous);
		}
		out.emit('update', event, previous);
		event.fulfilled = true;
	}),
	_remove: d(function (id) {
		var obj, subId, lastEvent, dismissed, removedFrom;
		if (!history.hasOwnProperty(id)) return;
		lastEvent = history[id][0];
		delete history[id];
		if (!lastEvent) return;
		obj = getObject(id);

		if (lastEvent.value) {
			if (obj._type_ === 'relation-set-item') {
				if (obj._key_[0] === '7') {
					subId = obj._key_.slice(1);
					dismissed = getObject(subId);
					if (dismissed._type_ === 'object') remove.call(reverse[subId], obj);
					else dismissed = null;
				}
			}
			if (lastEvent.value._type_) {
				if (obj._type_ === 'relation') {
					if (lastEvent.value._type_ === 'object') {
						subId = lastEvent.value._id_;
						remove.call(reverse[subId], obj);
						dismissed = lastEvent.value;
					}
				} else if (objectType[lastEvent.value._type_]) {
					removedFrom = lastEvent.value;
				}
			}
		}

		obj.$$setValue();
		if (relType[obj._type_]) {
			do {
				obj = obj.obj;
				if (!obj) break;
			} while (relType[obj._type_]);
			if (obj) obj.emit('update', null, lastEvent);
			if (dismissed) dismissed.emit('dismiss', null, lastEvent);
		} else if (removedFrom) {
			removedFrom.emit('reduce', null, lastEvent);
		}
		obj.emit('selfupdate', null, lastEvent);
		out.emit('remove', id);
	})
});

Object.defineProperties(proto, {
	_signal_: d(function (value) {
		if (stamp == null) {
			stamp = now();
			nextTick(clear);
		}
		out._add(new Event(this, value, stamp));
	}),
	_forEachReverse_: d(function (cb/*, thisArg*/) {
		var data, thisArg = arguments[1];
		callable(cb);
		data = reverse.hasOwnProperty(this._id_) && reverse[this._id_];
		if (!data) return;
		data.forEach(function (rel) {
			call.call(cb, thisArg, rel, rel._id_, this);
		}, this);
	})
});
<|endoftext|>


<commit_before>import Ember from 'ember'
import layout from './template'
import computed, {readOnly} from 'ember-computed-decorators'

const {
  A,
  Component,
  inject
} = Ember

export default Component.extend({
  // == Services ==============================================================

  notifier: inject.service('notifier'),

  // == Component properties ==================================================

  layout: layout,
  classNames: ['frost-notifications'],
  classNameBindings: [
    'processedType',
    'notification.dismiss::frost-notifications-in',
    'autoClear::dismissable'
  ],

  // == Computed properties ===================================================

  @readOnly
  @computed('notification.type')
  /**
   * Computed icon path based on type
   * @param {String} type - notification type
   * @returns {String} the icon path
   * NOTE: 'success' isn't handled since there is no success icon available yet
   */
  notificationIcon: function (type) {
    switch (type) {
      case 'warning':
        return 'warning'
      case 'error':
        return 'error'
      case 'info':
        return 'info'
    }
  },

  @readOnly
  @computed('notification.type')
  /**
   * Class name binding for type
   * @param {String} type - notification type
   * @returns {String} class type
   */
  processedType: function (type) {
    if (type && A(['info', 'success', 'warning', 'error']).includes(type)) {
      return `frost-notifications-${type}`
    }
  },

  // == Actions ===============================================================

  actions: {
    removeNotification () {
      this.get('notifier').removeNotification(this.get('notification'))
    },
    onDetailsClicked () {
      const notification = this.get('notification')
      if (notification.onDetailsClick) {
        notification.onDetailsClick(notification.details)
      }
    }
  }
})
<commit_msg>Fix build for Ember 2.3<commit_after>import Ember from 'ember'
const {Component, inject} = Ember
import computed, {readOnly} from 'ember-computed-decorators'

import layout from './template'

export default Component.extend({
  // == Services ==============================================================

  notifier: inject.service('notifier'),

  // == Component properties ==================================================

  layout: layout,
  classNames: ['frost-notifications'],
  classNameBindings: [
    'processedType',
    'notification.dismiss::frost-notifications-in',
    'autoClear::dismissable'
  ],

  // == Computed properties ===================================================

  @readOnly
  @computed('notification.type')
  /**
   * Computed icon path based on type
   * @param {String} type - notification type
   * @returns {String} the icon path
   * NOTE: 'success' isn't handled since there is no success icon available yet
   */
  notificationIcon: function (type) {
    switch (type) {
      case 'warning':
        return 'warning'
      case 'error':
        return 'error'
      case 'info':
        return 'info'
    }
  },

  @readOnly
  @computed('notification.type')
  /**
   * Class name binding for type
   * @param {String} type - notification type
   * @returns {String} class type
   */
  processedType: function (type) {
    if (type && ['info', 'success', 'warning', 'error'].indexOf(type) !== -1) {
      return `frost-notifications-${type}`
    }
  },

  // == Actions ===============================================================

  actions: {
    removeNotification () {
      this.get('notifier').removeNotification(this.get('notification'))
    },
    onDetailsClicked () {
      const notification = this.get('notification')
      if (notification.onDetailsClick) {
        notification.onDetailsClick(notification.details)
      }
    }
  }
})
<|endoftext|>


<commit_before>import jwt from 'jsonwebtoken';
import axios from 'axios';

import Podcast from '../models/podcast';
import RSS from '../models/rss';
import Article from '../models/article';
import Episode from '../models/episode';
import { DetectLanguage } from '../parsers/detect-language';
import { getStreamClient } from '../utils/stream';

import config from '../config';
import logger from './logger';

// replaces TrackMetadata and events() calls
export async function upsertCollections(type, content) {
	if (!content.length || config.analyticsDisabled) {
		return;
	}

	const streamClient = getStreamClient();

	try {
		return await streamClient.collections.upsert(type, content);
	} catch (err) {
		logger.error(`failed to update collections with type ${type}`, { err });
	}
}

const feedModels = {
    rss: { feed: RSS, content: Article },
    podcast: { feed: Podcast, content: Episode }
};

function sizeInBytes(s) {
	return ~-encodeURI(String(s)).split(/%..|./).length;
}

function estimateSize(content) {
	let size = 2; // {}
	for (const [key, value] of Object.entries(content)) {
		size += sizeInBytes(key);
		size += sizeInBytes(value);
		size += 2; // :,
	}
	return size;
}

export async function sendFeedToCollections(type, feed) {
	const model = feedModels[type];

	if (!feed.language) {
		feed.language = await DetectLanguage(feed.feedUrl);
		await model.feed.findByIdAndUpdate(feed.id, { language: feed.language }, { new: true });
	}
	const content = await model.content.find({ [type]: feed.id })
		.sort({ publicationDate: -1 })
		.limit(1000);

	let mostRecentPublicationDate;
	if (content.length) {
		mostRecentPublicationDate = content[0].publicationDate;
	}

	await upsertCollections(type, [{
		id: feed.id,
		title: feed.title,
		language: feed.language,
		description: feed.description,
		articleCount: content.length,
		mostRecentPublicationDate
	}]);

	const contentModelName = model.content.collection.collectionName;
	const chunkSize = 1000;
	const sizeLimit = 126 * 1024; // a bit less then 128Kb to lease some space for external data
	for (let offset = 0; offset < content.length;) {
		const data = [];
		const limit = Math.min(content.length, offset + chunkSize);
		let currentSize = 0;
		for (; offset < limit; ++offset) {
			const source = content[offset];
			const item = {
				id: source.id,
				title: source.title,
				likes: source.likes,
				socialScore: source.socialScore,
				description: source.description,
				publicationDate: source.publicationDate,
				[type]: feed.id,
			};
			//XXX: we overestimate object size by 5-10%
			const size = estimateSize(item);
			if (currentSize + size > sizeLimit) {
				break;
			}

			currentSize += size;
			data.push(item);
		}

		await upsertCollections(contentModelName, data);
	}
}
<commit_msg>Use Buffer to determine byte count for JSON size estimation<commit_after>import jwt from 'jsonwebtoken';
import axios from 'axios';

import Podcast from '../models/podcast';
import RSS from '../models/rss';
import Article from '../models/article';
import Episode from '../models/episode';
import { DetectLanguage } from '../parsers/detect-language';
import { getStreamClient } from '../utils/stream';

import config from '../config';
import logger from './logger';

// replaces TrackMetadata and events() calls
export async function upsertCollections(type, content) {
	if (!content.length || config.analyticsDisabled) {
		return;
	}

	const streamClient = getStreamClient();

	try {
		return await streamClient.collections.upsert(type, content);
	} catch (err) {
		logger.error(`failed to update collections with type ${type}`, { err });
	}
}

const feedModels = {
    rss: { feed: RSS, content: Article },
    podcast: { feed: Podcast, content: Episode }
};

function estimateSize(content) {
	let size = 2; // {}
	for (const [key, value] of Object.entries(content)) {
		size += Buffer.byteLength(String(key), 'utf8');
		size += Buffer.byteLength(String(value), 'utf8');
		size += 2; // :,
	}
	return size;
}

export async function sendFeedToCollections(type, feed) {
	const model = feedModels[type];

	if (!feed.language) {
		feed.language = await DetectLanguage(feed.feedUrl);
		await model.feed.findByIdAndUpdate(feed.id, { language: feed.language }, { new: true });
	}
	const content = await model.content.find({ [type]: feed.id })
		.sort({ publicationDate: -1 })
		.limit(1000);

	let mostRecentPublicationDate;
	if (content.length) {
		mostRecentPublicationDate = content[0].publicationDate;
	}

	await upsertCollections(type, [{
		id: feed.id,
		title: feed.title,
		language: feed.language,
		description: feed.description,
		articleCount: content.length,
		mostRecentPublicationDate
	}]);

	const contentModelName = model.content.collection.collectionName;
	const chunkSize = 1000;
	const sizeLimit = 126 * 1024; // a bit less then 128Kb to lease some space for external data
	for (let offset = 0; offset < content.length;) {
		const data = [];
		const limit = Math.min(content.length, offset + chunkSize);
		let currentSize = 0;
		for (; offset < limit; ++offset) {
			const source = content[offset];
			const item = {
				id: source.id,
				title: source.title,
				likes: source.likes,
				socialScore: source.socialScore,
				description: source.description,
				publicationDate: source.publicationDate,
				[type]: feed.id,
			};
			//XXX: we overestimate object size by 5-10%
			const size = estimateSize(item);
			if (currentSize + size > sizeLimit) {
				break;
			}

			currentSize += size;
			data.push(item);
		}

		await upsertCollections(contentModelName, data);
	}
}
<|endoftext|>


<commit_before>export default function() {

  var tabs, scrollTabs;

  var activeStatusClass = 'is-active';
  var selectors = {
    tab: '.evo_c-tab',
    list: '[class*="tab__list"]',
    item: '[class*="tab__item"]',
    scrollTabs: '[class*="tab--scroll"]',
    navigation: '[class*="tab__navigation"]',
    sticky: '[class*="tab__sticky"]'
  };

  var mediaTablet = 750;

  /**
   * Convert an Object List to an Array
   * @param  {Object}   list An Object list
   * @return {Array}
   */

  var toArr = function ( list ) {
      return [].slice.call( list );
  };

  /**
   * Get the closest matching element up the DOM tree.
   * @param  {Element} elem     Starting element
   * @param  {String}  selector Selector to match notwithstanding
   * @return {Boolean|Element}  Returns null if not match found
   */
  var getClosest = function ( elem, selector ) {

    // When elem is a Text node, get its parent node
    if (elem.nodeType === 3) {
        elem = elem.parentNode;
    }

    // Element.matches() polyfill
    if (!Element.prototype.matches) {
        Element.prototype.matches =
        Element.prototype.matchesSelector ||
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector ||
        Element.prototype.oMatchesSelector ||
        Element.prototype.webkitMatchesSelector ||
        function(s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;
        };
    }

    // Get closest match
    for ( ; elem && elem !== document; elem = elem.parentNode ) {
        if ( elem.matches( selector ) ) return elem;
    }

    return null;

  };

  Array.prototype.where = function ( inclusionTest ) {
    var results = [];
    for (var i = 0; i<this.length; i++) {
      if ( inclusionTest(this[i]) ) {
        results.push(this[i]);
      }
    }
    return results;
  };

  function getClassName(node, subString) {
    return [].slice.call(node.classList).where(function(className) {
      return className.indexOf(subString) !== -1;
    });
  }

  function isNotEmpty( array ) {
    return array.length > 0;
  }

  function hasClassName(node, subString) {
    return isNotEmpty(getClassName(node, subString));
  }

  function $(selector, parent) {
    return (parent || document).querySelector(selector);
  }

  function $$(selector, parent) {
    return (parent || document).querySelectorAll(selector);
  }

  function setAriaStatus(tab, status) {
    var panelId = tab.firstElementChild.getAttribute('href');
    var panel   = $(panelId, panel);
    tab.setAttribute('aria-selected', status);
    panel && panel.setAttribute('aria-hidden', !status);
  }

  function initAriaStatus(tabComponent) {

    var tabs = toArr($$('[role="tab"]', tabComponent));
    var activeTab = $('[class$="tab__item ' + activeStatusClass +'"]', tabComponent);

    setAriaStatus(activeTab, true);

    tabs.filter(function(tab) {
      return !hasClassName(tab, activeStatusClass);
    }).forEach(function(tab) {
      setAriaStatus(tab, false);
    });

  }

  function handleKeyDown(event) {
    var key;
    var tabComponent;
    var targetLink;
    var tabList;
    var targetTab;
    var activeTab;

    event = event || window.event;
    targetLink = event.target;
    activeTab = targetLink.parentElement;
    tabComponent = getClosest(targetLink, selectors.tab);
    tabList    = getClosest(targetLink, selectors.list);
    key   = event.keyCode;

    if (key === 34 || key === 35) {
        // end / page down
        targetTab = tabList.lastElementChild;
    } else if (key === 33 || key === 36) {
        // home / page up
        targetTab = tabList.firstElementChild;
    } else if (key === 37 || key === 38) {
        // left/up arrow
        if (activeTab.previousElementSibling) {
            targetTab = activeTab.previousElementSibling;
        } else {
            targetTab = tabList.lastElementChild;
        }
    }  else if (key === 39 || key === 40) {
        // right/down arrow
        if (activeTab.nextElementSibling) {
            targetTab = activeTab.nextElementSibling;
        } else {
            targetTab = tabList.firstElementChild;
        }
    }

    if (key === 33 || key === 34 || key === 35 || key === 36 ||
        key === 37 || key === 38 || key === 39 || key === 40) {
        setActiveTab(tabComponent, targetTab);
    }

  }

  function setActiveTab(tabComponent, targetTab) {
    var oldActiveTab   = $('[class$="tab__item ' + activeStatusClass +'"]', tabComponent);
    var oldActivePanel = $('[class$="tab__panel ' + activeStatusClass +'"]', tabComponent);
    var link = targetTab && targetTab.firstElementChild;
    var targetPanelSel = link && link.getAttribute('href') || 'null';
    var targetPanel    = $( targetPanelSel, tabComponent );

    // When the active tab is the same as the target one, focus it and return
    if ( oldActiveTab && ( targetPanel.id === oldActivePanel.id )) {
      link.focus();
      return;
    }

    if (oldActiveTab && oldActivePanel) {
      oldActiveTab.classList.remove(activeStatusClass);
      oldActivePanel.classList.remove(activeStatusClass);
      setAriaStatus(oldActiveTab, false);
    }

    if (targetTab && targetPanel) {
      targetTab.classList.add(activeStatusClass);
      targetPanel.classList.add(activeStatusClass);
      setAriaStatus(targetTab, true);
      targetTab.firstElementChild.focus();
    }
  }

  function handleClick(event) {

    event.stopPropagation();
    event.preventDefault();

    var target = event.target;
    var targetSelector;
    var targetTab;
    var targetPanel;

    var isLink = hasClassName(target, 'tab__link');
    var isItem = hasClassName(target, 'tab__item');
    var isIcon = target.nodeName === 'I' || false;
    var tabComponent = getClosest(target, selectors.tab);
    var activeTab = $('[class$="tab__item ' + activeStatusClass +'"]', tabComponent);
    var activePanel = $('[class$="tab__panel ' + activeStatusClass +'"]', tabComponent);

    if (!isLink && !isItem && !isIcon) {
      // focus the link of the active tab
      activeTab.firstElementChild.focus();
      return;
    }

    if ( isItem ) {
      targetTab = target;
    } else {
      targetTab = getClosest(target, selectors.item);
    }

    setActiveTab(tabComponent, targetTab);
  }

  function getCompStyle(el) {
    return window.getComputedStyle(el);
  }

  function getAbsoluteHeight(el) {

    el = (typeof el === 'string') ? document.querySelector(el) : el;

    var styles = getCompStyle(el);
    var margin = parseFloat(styles['marginTop']) +
                 parseFloat(styles['marginBottom']);
    var padding = parseFloat(styles['paddingTop']) +
                  parseFloat(styles['paddingBottom']);

    return Math.ceil(el.offsetHeight + margin + padding);
  }

  function calculateMinHeight(scrollTab) {

    var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    var navigation = $(selectors.navigation, scrollTab);
    var navigationH = navigation && getAbsoluteHeight(navigation) || 0;
    var sticky = $(selectors.sticky, scrollTab);
    var stickyH = sticky && getAbsoluteHeight(sticky) || 0;
    var isLateral = hasClassName(scrollTab, 'tab--lateral');
    var scrollTabs = $$('[class*="tab__panel"]', scrollTab);
    var activeItem = $('[class$="tab__item ' + activeStatusClass +'"]', scrollTab);
    var activeTabContent = $('[class$="tab__panel ' + activeStatusClass +'"]', scrollTab);
    var tallerTabContent;
    var firstTabContent = scrollTabs && scrollTabs[0];
    var scrollTabHeight = 0;

    scrollTabs = toArr(scrollTabs).sort(function(tabA, tabB) {
      return tabA.offsetHeight - tabB.offsetHeight;
    });

    tallerTabContent = scrollTabs[scrollTabs.length-1];

    // When the tab's type is lateral remove the top property (if any)
    if (isLateral) {
      scrollTabs.forEach(function(tab) {
        tab.style.top = null;
      })
    } else if (stickyH > 0) {
      // When there exists a sticky element, place the tab under it
      scrollTabs.forEach(function(tab) {
        var styles = getCompStyle(tab);
        var margin = parseFloat(styles['marginTop']);
        var padding = parseFloat(styles['paddingTop']);
        tab.style.top += stickyH + margin + padding + 'px';
      })
    }

    // When the tab's type is lateral and the viewport width is less than or
    // equal to the media tablet, add to each panel a top position equal
    // to the navigation's heigth
    if (isLateral && w <= mediaTablet) {
      scrollTabs.forEach(function(tab) {
        tab.style.top = navigationH +  stickyH + 'px';
      });
      scrollTabHeight = navigationH + stickyH + getAbsoluteHeight(tallerTabContent);
    } else {
      scrollTabHeight = getAbsoluteHeight(tallerTabContent) + stickyH;
    }

    scrollTab.style.minHeight = scrollTabHeight + 'px';

    // On load ad the status class on the first tab content
    if (!activeTabContent) {
      firstTabContent.classList.add(activeStatusClass);
    }

  }

  // Get all tabs in the page
  tabs       = $$(selectors.tab);
  scrollTabs = $$(selectors.scrollTabs);

  toArr(tabs).forEach(function(tab) {
    tab.addEventListener( 'click', handleClick );
  });

  // When all the content as been load, resize the min-height property
  // of scrollTabs
  window.addEventListener('load', function (event) {
    toArr(scrollTabs).forEach(function(scrollTab) {
        calculateMinHeight(scrollTab);
      });
  });

  window.addEventListener('DOMContentLoaded', function (event) {
    toArr(tabs).forEach(function(tab) {
        initAriaStatus(tab);
        tab.addEventListener('keyup', handleKeyDown );
      });
  });

  window.addEventListener('resize', function (event) {
    toArr(scrollTabs).forEach(function(scrollTab) {
        calculateMinHeight(scrollTab);
      });
  });

}
<commit_msg>Move to Object oriented<commit_after>export default function() {

function Tab(element) {

  var activeStatus = 'is-active';

  this.component = element;
  this._activeStatus = activeStatus;
  this.isScrollable = this._hasClassName(element, 'tab--scroll');
  this.isLateral = this._hasClassName(element, 'tab--lateral');
  this.flexDirection = this._getCompStyle(element)['flex-direction'];

  this.selectors = {
    component: '.evo_c-tab',
    tab: '[role="tab"]',
    panel: '[class*="tab__panel"]',
    list: '[class*="tab__list"]',
    item: '[class*="tab__item"]',
    scrollTabs: '[class*="tab--scroll"]',
    navigation: '[class*="tab__navigation"]',
    sticky: '[class*="tab__sticky"]',
    activeTab: '[class$="tab__item ' + activeStatus +'"]',
    activePanel: '[class$="tab__panel ' + activeStatus +'"]'
  }

  this.init();
}

Tab.prototype.init = function(){
  var self = this;

  this.cacheDOM = {
    tabs: self._$$(self.selectors.tab, self.component),
    panels: self._$$(self.selectors.panel, self.component),
    navigation: self._$(self.selectors.navigation, self.component),
    list: self._$(self.selectors.list, self.component),
    sticky: self._$(self.selectors.sticky, self.component),
    scrollTabs: self._$$(self.selectors.scrollTabs, self.component),
    activeTab: self._$(self.selectors.activeTab, self.component),
    activePanel: self._$(self.selectors.activePanel, self.component),
  }

  this.calculateInitSizes();
  this.initARIA();
  this.addClickListener();
  this.addKeyDownListener();

  // When a tab is scrollable we need to handle the sizes
  if (this.isScrollable) {
    this.initPanelsHeight();
    this.addResizeListener();
  }
};

Tab.prototype.calculateInitSizes = function() {

  var stickyH;
  var navigationH;

  stickyH     = this.cacheDOM['sticky'] &&
                this._getAbsoluteHeight(this.cacheDOM['sticky']) || 0;

  navigationH = this.cacheDOM['navigation'] &&
                this._getAbsoluteHeight(this.cacheDOM['navigation']) || 0;

  this.sizes = {
    viewportW: Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
    viewportH: Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
    navigation: navigationH,
    sticky: stickyH,
    tallestPanel: 0
  }
}

Tab.prototype.initARIA = function() {

  var self = this;
  var tabs = self._toArr(self.cacheDOM['tabs']);

  self.setAriaStatus(self.cacheDOM['activeTab'], true);

  tabs.filter(function(tab) {
    return !self._hasClassName(tab, self._activeStatus);
  }).forEach(function(tab) {
    self.setAriaStatus(tab, false);
  });

}

Tab.prototype.addClickListener = function() {

  this.component.addEventListener('click', this.handleClick.bind(this));
}

Tab.prototype.addResizeListener = function() {

  var self = this;

  window.addEventListener('resize', self._throttle(function() {
      self.handleResize();
  }, 50));

}

Tab.prototype.initPanelsHeight = function() {
  var self = this;
  window.addEventListener('load', function (event) {
    self._calculateTallestPanel(self.handleResize.bind(self));
  });
}

Tab.prototype.handleResize = function () {

  var viewportW = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  var flexD = this._getCompStyle(this.component)['flex-direction'];

  var activePanel = this.cacheDOM['activePanel'];
  var panels = this.cacheDOM['panels'];
  var tallestPanel = this.cacheDOM['tallestPanel'];
  var sticky = this.cacheDOM['sticky'];

  var tallestPanelH;
  var navigationH;
  var stickyH = this.sizes['sticky'];
  var minHeightComponent = 0;
  var panelTop = 0;

  if (!this.cacheDOM['activePanel']) {
    return;
  }

  navigationH = this._getAbsoluteHeight(this.cacheDOM['navigation']) || 0;
  tallestPanelH = this._getAbsoluteHeight(this.cacheDOM['tallestPanel']) || 0;

  // When the tab's type is lateral and the viewport width is less than or
  // equal to the media tablet, add to each panel a top position equal
  // to the navigation's heigth
  if (viewportW < 750 || !this.isLateral) {

    minHeightComponent = navigationH + stickyH + tallestPanelH;
    panelTop = navigationH + stickyH;

  } else {

    minHeightComponent = tallestPanelH + stickyH;
    panelTop = stickyH;

  }

  if (this.isLateral) {
    this._toArr(panels).forEach(function(panel) {
      panel.style.top = panelTop + 'px';
    })
  }

  this.component.style.minHeight = minHeightComponent + 'px';

  this.sizes.viewportW = viewportW;

}

Tab.prototype.handleClick = function(event) {

  var target = event.target;
  var targetSelector;
  var targetTab;
  var targetPanel;

  var isLink = this._hasClassName(target, 'tab__link');
  var isItem = this._hasClassName(target, 'tab__item');
  var isIcon = target.nodeName === 'I' || false;
  var tabComponent = this._getClosest(target, this.selectors['tab']);

  if (!isLink && !isItem && !isIcon) {
    return;
  }

  event.stopPropagation();
  event.preventDefault();

  if ( isItem ) {
    targetTab = target;
  } else {
    targetTab = this._getClosest(target, this.selectors['item']);
  }

  this.setActiveTab(targetTab);
}

Tab.prototype.addKeyDownListener = function() {
  this.component.addEventListener('keyup', this.handleKeyDown.bind(this));
}

Tab.prototype.handleKeyDown = function(event) {
  var key;
  var tabComponent;
  var targetLink;
  var tabList;
  var targetTab;
  var activeTab;

  event = event || window.event;
  targetLink = event.target;
  activeTab = targetLink.parentElement;
  tabComponent = this._getClosest(targetLink, this.selectors['tab']);
  tabList      = this._getClosest(targetLink, this.selectors['list']);
  key   = event.keyCode;

  if (key === 34 || key === 35) {
      // end / page down
      targetTab = tabList.lastElementChild;
  } else if (key === 33 || key === 36) {
      // home / page up
      targetTab = tabList.firstElementChild;
  } else if (key === 37 || key === 38) {
      // left/up arrow
      if (activeTab.previousElementSibling) {
          targetTab = activeTab.previousElementSibling;
      } else {
          targetTab = tabList.lastElementChild;
      }
  }  else if (key === 39 || key === 40) {
      // right/down arrow
      if (activeTab.nextElementSibling) {
          targetTab = activeTab.nextElementSibling;
      } else {
          targetTab = tabList.firstElementChild;
      }
  }

  if (!targetTab) {
    return;
  }

  if (key === 33 || key === 34 || key === 35 || key === 36 ||
      key === 37 || key === 38 || key === 39 || key === 40) {
      this.setActiveTab(targetTab);
  }

}

Tab.prototype.setAriaStatus = function(tab, status) {
  var panelId = tab.firstElementChild.getAttribute('href');
  var panel   = this._$(panelId, panel);

  tab.setAttribute('aria-selected', status);
  panel && panel.setAttribute('aria-hidden', !status);
}

Tab.prototype.setActiveTab = function(targetTab) {

  var oldTab  = this.cacheDOM['activeTab'];
  var oldPanel = this.cacheDOM['activePanel'];

  var link = targetTab && targetTab.firstElementChild;
  var targetPanelSel = link && link.getAttribute('href') || 'null';
  var targetPanel    = this._$( targetPanelSel, this.component );

  // When the active tab is the same as the target one, focus it and return
  if ( oldTab && ( targetPanel.id === oldPanel.id )) {
    link.focus();
    return;
  }

  if (oldTab && oldPanel) {
    oldTab.classList.remove(this._activeStatus);
    oldPanel.classList.remove(this._activeStatus);
    this.setAriaStatus(oldTab, false);
  }

  if (targetTab && targetPanel) {
    targetTab.classList.add(this._activeStatus);
    targetPanel.classList.add(this._activeStatus);
    this.setAriaStatus(targetTab, true);
    targetTab.firstElementChild.focus();
  }

  //Update the cache
  this.cacheDOM['activeTab'] = targetTab;
  this.cacheDOM['activePanel'] = targetPanel;
}

Tab.prototype._calculateTallestPanel = function(callback) {

  var orderedTabs;
  var tallestPanel;

  orderedTabs = this._toArr(this.cacheDOM['panels']).sort(function(tabA, tabB) {
    return tabA.offsetHeight - tabB.offsetHeight;
  });

  tallestPanel = orderedTabs[orderedTabs.length-1];

  // Store the information
  this.sizes.tallestPanel = this._getAbsoluteHeight(tallestPanel) || 0;
  this.cacheDOM.tallestPanel = tallestPanel;

  if (typeof callback === 'function') {
    callback();
  }

}

Tab.prototype._$ = function(selector, parent) {
  return (parent || document).querySelector(selector);
}

Tab.prototype._$$ = function(selector, parent) {
  return (parent || document).querySelectorAll(selector);
}

/**
 * Convert a List into an Array
 *
 * @param  {List}  A list
 * @return {Array}
 */

Tab.prototype._toArr = function(list) {
  return [].slice.call(list);
};

Tab.prototype._getCompStyle = function(el) {
  return window.getComputedStyle(el);
}

Tab.prototype._hasClassName = function(node, subString) {
  return this._isNotEmptyA(this._getClassName(node, subString));
}

Tab.prototype._getAbsoluteHeight = function(el) {

  el = (typeof el === 'string') ? document.querySelector(el) : el;

  var styles = this._getCompStyle(el);
  var margin = parseFloat(styles['marginTop']) +
               parseFloat(styles['marginBottom']);
  var padding = parseFloat(styles['paddingTop']) +
                parseFloat(styles['paddingBottom']);

  return Math.ceil(el.offsetHeight + margin + padding);
}

Tab.prototype._isNotEmptyA = function(array) {
  return array.length > 0;
}

Tab.prototype._where = function (Arr) {

  return function (inclusionTest) {
    var results = [];
    var len = Arr.length;
    for (var i = 0; i<len; i++) {
      if ( inclusionTest(Arr[i]) ) {
        results.push(Arr[i]);
      }
    }
    return results;
  }

};

Tab.prototype._getClassName = function(node, subString) {
  var list = this._toArr(node.classList);
  var where = this._where(list);

  return where(function(className) {
    return className.indexOf(subString) !== -1;
  });
}

/**
 * Get the closest matching element up the DOM tree.
 * @param  {Element} elem     Starting element
 * @param  {String}  selector Selector to match notwithstanding
 * @return {Boolean|Element}  Returns null if not match found
 */
Tab.prototype._getClosest = function(elem, selector) {

  // When elem is a Text node, get its parent node
  if (elem.nodeType === 3) {
      elem = elem.parentNode;
  }

  // Element.matches() polyfill
  if (!Element.prototype.matches) {
      Element.prototype.matches =
      Element.prototype.matchesSelector ||
      Element.prototype.mozMatchesSelector ||
      Element.prototype.msMatchesSelector ||
      Element.prototype.oMatchesSelector ||
      Element.prototype.webkitMatchesSelector ||
      function(s) {
          var matches = (this.document || this.ownerDocument).querySelectorAll(s),
              i = matches.length;
          while (--i >= 0 && matches.item(i) !== this) {}
          return i > -1;
      };
  }

  // Get closest match
  for ( ; elem && elem !== document; elem = elem.parentNode ) {
      if ( elem.matches( selector ) ) return elem;
  }

  return null;

};

Tab.prototype._throttle = function(fn, delay) {
  var timeout = null;
  var self = this;

  return function throttledFn() {
    window.clearTimeout(timeout);
    var ctx = this;
    var args = self._toArr(arguments);

    timeout = window.setTimeout(function callThrottledFn() {
      fn.apply(ctx, args);
    }, delay);
  }
}

// ------------------------------------------------------------------------------

  // Get all tabs in the page
  var tabs = document.querySelectorAll('.evo_c-tab');

  [].slice.call(tabs).forEach(function(tab) {
    new Tab(tab);
  });

}

<|endoftext|>


<commit_before>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var crypto = require('crypto');
var http = require('http');
var util = require('util');

var sprintf = util.format;

///--- Globals

var Algorithms = {
    'rsa-sha1': true,
    'rsa-sha256': true,
    'rsa-sha512': true,
    'dsa-sha1': true,
    'hmac-sha1': true,
    'hmac-sha256': true,
    'hmac-sha512': true
};

var AuthorizationKeys = {
    Signature: 'Signature',
    keyId: 'keyId',
    algorithm: 'algorithm',
    headers: 'headers',
    jwt: 'jwt',
    signature: 'signature'
};

function formatSignature(options) {
    var sig = AuthorizationKeys.Signature.concat(
        ' ', AuthorizationKeys.keyId, '="', options.keyId, '"',
        ',', AuthorizationKeys.algorithm, '="', options.algorithm, '"',
        ',', AuthorizationKeys.headers, '="', options.headers.join(' '), '"'
    );
    if (options.jwt) {
        sig = sig.concat(',', AuthorizationKeys.jwt, '="', options.jwt, '"');
    }
    return sig.concat(',', AuthorizationKeys.signature, '="', options.signature, '"');
}

///--- Specific Errors

function MissingHeaderError(message) {
    Error.call(this, message);
    this.name = 'MissingHeaderError';
}
util.inherits(MissingHeaderError, Error);

function InvalidAlgorithmError(message) {
    Error.call(this, message);
    this.name = 'InvalidAlgorithmError';
}
util.inherits(InvalidAlgorithmError, Error);

///--- Internal Functions

function _pad(val) {
    if (parseInt(val, 10) < 10) {
        val = '0' + val;
    }
    return val;
}

function _rfc1123() {
    var date = new Date();

    var months = ['Jan',
        'Feb',
        'Mar',
        'Apr',
        'May',
        'Jun',
        'Jul',
        'Aug',
        'Sep',
        'Oct',
        'Nov',
        'Dec'
    ];
    var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    return days[date.getUTCDay()] + ', ' +
        _pad(date.getUTCDate()) + ' ' +
        months[date.getUTCMonth()] + ' ' +
        date.getUTCFullYear() + ' ' +
        _pad(date.getUTCHours()) + ':' +
        _pad(date.getUTCMinutes()) + ':' +
        _pad(date.getUTCSeconds()) +
        ' GMT';
}

///--- Exported API

module.exports = {

    /**
     * Adds an 'Authorization' header to an http.ClientRequest object.
     *
     * Note that this API will add a Date header if it's not already set. Any
     * other headers in the options.headers array MUST be present, or this
     * will throw.
     *
     * You shouldn't need to check the return type; it's just there if you want
     * to be pedantic.
     *
     * @param {Object} request an instance of http.ClientRequest.
     * @param {Object} options signing parameters object:
     *                   - {String} keyId required.
     *                   - {String} key required (either a PEM or HMAC key).
     *                   - {Array} headers optional; defaults to ['date'].
     *                   - {String} jwt optional; elided if not specified.
     *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
     *                   - {String} httpVersion optional; defaults to '1.1'.
     * @return {Boolean} true if Authorization (and optionally Date) were added.
     * @throws {TypeError} on bad parameter types (input).
     * @throws {InvalidAlgorithmError} if algorithm was bad.
     * @throws {MissingHeaderError} if a header to be signed was specified but
     *                              was not present.
     */
    signRequest: function signRequest(request, options) {
        assert.object(request, 'request');
        assert.object(options, 'options');
        assert.optionalString(options.algorithm, 'options.algorithm');
        assert.string(options.keyId, 'options.keyId');
        assert.optionalArrayOfString(options.headers, 'options.headers');
        assert.optionalString(options.jwt, 'options.jwt');
        assert.optionalString(options.httpVersion, 'options.httpVersion');

        if (!request.getHeader('Date'))
            request.setHeader('Date', _rfc1123());
        if (!options.headers)
            options.headers = ['date'];
        if (!options.algorithm)
            options.algorithm = 'rsa-sha256';
        if (!options.httpVersion)
            options.httpVersion = '1.1';

        options.algorithm = options.algorithm.toLowerCase();

        if (!Algorithms[options.algorithm])
            throw new InvalidAlgorithmError(options.algorithm + ' is not supported');

        var i = -1,
            h,
            len = options.headers.length,
            stringToSign = '';
        while (++i) {
            h = options.headers[i];
            if (typeof(h) !== 'string')
                throw new TypeError('options.headers must be an array of Strings');
            h = h.toLowerCase();
            if (h !== 'request-line') {
                var value = request.getHeader(h);
                if (!value) {
                    throw new MissingHeaderError(h + ' was not in the request');
                }
                stringToSign += h + ': ' + value;
            } else {
                stringToSign +=
                    request.method + ' ' + request.path + ' HTTP/' + options.httpVersion;
            }
            if ((i + 1) < len)
                stringToSign += '\n';
        }

        var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
        var signature;
        if (alg[1] === 'hmac') {
            var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
            hmac.update(stringToSign);
            signature = hmac.digest('base64');
        } else {
            var signer = crypto.createSign(options.algorithm.toUpperCase());
            signer.update(stringToSign);
            signature = signer.sign(options.key, 'base64');
        }
        request.setHeader('Authorization', formatSignature(options));
        return true;
    }

};
<commit_msg>actually generates signature and assigns it to the header rather than "undefined"<commit_after>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var crypto = require('crypto');
var http = require('http');
var util = require('util');

var sprintf = util.format;

///--- Globals

var Algorithms = {
    'rsa-sha1': true,
    'rsa-sha256': true,
    'rsa-sha512': true,
    'dsa-sha1': true,
    'hmac-sha1': true,
    'hmac-sha256': true,
    'hmac-sha512': true
};

var AuthorizationKeys = {
    Signature: 'Signature',
    keyId: 'keyId',
    algorithm: 'algorithm',
    headers: 'headers',
    jwt: 'jwt',
    signature: 'signature'
};

function formatSignature(options) {
    var sig = AuthorizationKeys.Signature.concat(
        ' ', AuthorizationKeys.keyId, '="', options.keyId, '"',
        ',', AuthorizationKeys.algorithm, '="', options.algorithm, '"',
        ',', AuthorizationKeys.headers, '="', options.headers.join(' '), '"'
    );
    if (options.jwt) {
        sig = sig.concat(',', AuthorizationKeys.jwt, '="', options.jwt, '"');
    }
    return sig.concat(',', AuthorizationKeys.signature, '="', options.signature, '"');
}

///--- Specific Errors

function MissingHeaderError(message) {
    Error.call(this, message);
    this.name = 'MissingHeaderError';
}
util.inherits(MissingHeaderError, Error);

function InvalidAlgorithmError(message) {
    Error.call(this, message);
    this.name = 'InvalidAlgorithmError';
}
util.inherits(InvalidAlgorithmError, Error);

///--- Internal Functions

function _pad(val) {
    if (parseInt(val, 10) < 10) {
        val = '0' + val;
    }
    return val;
}

function _rfc1123() {
    var date = new Date();

    var months = ['Jan',
        'Feb',
        'Mar',
        'Apr',
        'May',
        'Jun',
        'Jul',
        'Aug',
        'Sep',
        'Oct',
        'Nov',
        'Dec'
    ];
    var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    return days[date.getUTCDay()] + ', ' +
        _pad(date.getUTCDate()) + ' ' +
        months[date.getUTCMonth()] + ' ' +
        date.getUTCFullYear() + ' ' +
        _pad(date.getUTCHours()) + ':' +
        _pad(date.getUTCMinutes()) + ':' +
        _pad(date.getUTCSeconds()) +
        ' GMT';
}

///--- Exported API

module.exports = {

    /**
     * Adds an 'Authorization' header to an http.ClientRequest object.
     *
     * Note that this API will add a Date header if it's not already set. Any
     * other headers in the options.headers array MUST be present, or this
     * will throw.
     *
     * You shouldn't need to check the return type; it's just there if you want
     * to be pedantic.
     *
     * @param {Object} request an instance of http.ClientRequest.
     * @param {Object} options signing parameters object:
     *                   - {String} keyId required.
     *                   - {String} key required (either a PEM or HMAC key).
     *                   - {Array} headers optional; defaults to ['date'].
     *                   - {String} jwt optional; elided if not specified.
     *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
     *                   - {String} httpVersion optional; defaults to '1.1'.
     * @return {Boolean} true if Authorization (and optionally Date) were added.
     * @throws {TypeError} on bad parameter types (input).
     * @throws {InvalidAlgorithmError} if algorithm was bad.
     * @throws {MissingHeaderError} if a header to be signed was specified but
     *                              was not present.
     */
    signRequest: function signRequest(request, options) {
        assert.object(request, 'request');
        assert.object(options, 'options');
        assert.optionalString(options.algorithm, 'options.algorithm');
        assert.string(options.keyId, 'options.keyId');
        assert.optionalArrayOfString(options.headers, 'options.headers');
        assert.optionalString(options.jwt, 'options.jwt');
        assert.optionalString(options.httpVersion, 'options.httpVersion');

        if (!request.getHeader('Date'))
            request.setHeader('Date', _rfc1123());
        if (!options.headers)
            options.headers = ['date'];
        if (!options.algorithm)
            options.algorithm = 'rsa-sha256';
        if (!options.httpVersion)
            options.httpVersion = '1.1';

        options.algorithm = options.algorithm.toLowerCase();

        if (!Algorithms[options.algorithm])
            throw new InvalidAlgorithmError(options.algorithm + ' is not supported');

        var i = -1,
            h,
            len = options.headers.length,
            stringToSign = '';
        while (++i < len) {
            h = options.headers[i];
            if (typeof(h) !== 'string')
                throw new TypeError('options.headers must be an array of Strings');
            h = h.toLowerCase();
            if (h !== 'request-line') {
                var value = request.getHeader(h);
                if (!value) {
                    throw new MissingHeaderError(h + ' was not in the request');
                }
                stringToSign += h + ': ' + value;
            } else {
                stringToSign +=
                    request.method + ' ' + request.path + ' HTTP/' + options.httpVersion;
            }
            if ((i + 1) < len)
                stringToSign += '\n';
        }

        var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
        if (alg[1] === 'hmac') {
            var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
            hmac.update(stringToSign);
            options.signature = hmac.digest('base64');
        } else {
            var signer = crypto.createSign(options.algorithm.toUpperCase());
            signer.update(stringToSign);
            options.signature = signer.sign(options.key, 'base64');
        }
        request.setHeader('Authorization', formatSignature(options));
        return true;
    }

};
<|endoftext|>


<commit_before>/**
 * @ngdoc service
 * @name Vocab
 * @description
 * Handles getting and parsing the pre-defined vocabularies
 */
angular.module('locApp.modules.profile.services').factory('Vocab', function($q, $http, localStorageService, Server) {
    vocab = {};

    var choosenResource = -1;
    var choosenProperty = -1;

    var vocabResourceData = [];
    var vocabPropertyData = [];

    var languageList = [];

    // Takes in the rdf JSON object and puts a list of resources
    // to save to local storage
    var buildResources = function(rdfResources) {
        var resourceData = [];

        if(!Array.isArray(rdfResources) && rdfResources !== undefined) {
            var data = {};

            if(rdfResources.label != null) {
               data.label = rdfResources.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (rdfResources.comment != null) ? rdfResources.comment.__text.toString() : "";
            data.uri = rdfResources["_rdf:about"];
            resourceData.push(data);
            return resourceData;
        }

        angular.forEach(rdfResources, function(value) {
            var data = {};

            if(value.label === undefined) {
                value.label = null;
            }
            if(value.label != null) {
               data.label = value.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (value.comment != null) ? value.comment.__text.toString() : "";
            data.uri = value["_rdf:about"];
            resourceData.push(data);
        });

        return resourceData;
    };

    var buildProperties = function(rdfProperties) {
        var propertyData = [];

        if(!Array.isArray(rdfProperties) && rdfProperties !== undefined) {
            var data = {};

            if(rdfProperties.label != null) {
               data.label = rdfProperties.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (rdfProperties.comment != null) ? rdfProperties.comment.__text.toString() : "";
            data.uri = rdfProperties["_rdf:about"];
            propertyData.push(data);
            return propertyData;
        }

        angular.forEach(rdfProperties, function(value) {
            var data = {};
            if(value.label === undefined) {
                value.label = null;
            }
            if(value.label != null) {
               data.label = value.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (value.comment != null) ? value.comment.__text.toString() : "";
            data.uri = value["_rdf:about"];
            propertyData.push(data);
        });

        return propertyData;
    };

    // Method that will set the vocab data for each list.
    var _setVocabData = function(name, url, properties, resources) {
        var item = $q.defer();

        Server.get(url,{},false)
        .then(function(response) {
            // if a vocab file is empty then we will pass over it and return.
            if(response === undefined || response === "") {
                item.reject("No data");
                return;
            }

            // set the local storage with this data
            var jsonObj = response.json;

            var resource = {};
            var property = {};

            resource.key = name;
            resource.value = buildResources(jsonObj.RDF.Class);
            resources.push(resource);

            property.key = name;
            property.value = buildProperties(jsonObj.RDF.Property);
            properties.push(property);

            // Resolve the queue
            item.resolve("Finished");
        });

        return item.promise;
    };

    // Method to set the local storage of resource and properties
    var _setLocalStorage = function(resources, properties) {
        localStorageService.set("resourceReference", resources);
        localStorageService.set("propertyReference", properties);
        // Set Vocab data
        vocabResourceData = resources;
        vocabPropertyData = properties;
    };

    /**
     * @ngdoc function
     * @name setVocabData
     * @description
     * Gets the vocab data and adds them to the local machine.
     */
    vocab.setVocabData = function() {
        // if the local storage has expired, gather the data and set it up again
        // TODO: make this connect to the real RDF

        const vurl = '/verso/api/configs?filter[where][configType]=vocabulary&filter[fields][name]=true&filter[fields][id]=true&filter[where][name][neq]=Languages';

        Server.get(vurl, {}, false)
        .then(function(response){
            var listLength = 0;
            var returnNumber = 0;
            var resources = [];
            var properties = [];

            // loop through the list of vocabs and gather up the data.
            angular.forEach(response, function(value) {

                var url = '/verso/api/configs/' + value.id;
                // test that we hvae a key and this isn't a comment.
                if(value.id != null) {
                    listLength++;
                    _setVocabData(value.name, url, properties, resources)
                        .then(function() {
                            returnNumber++;

                            // Set local storage once we have all the data.
                            if(returnNumber >= listLength) {
                                _setLocalStorage(resources, properties);
                            }
                        }, function() {
                            returnNumber++;
                        });
                }

            });
        });
    };

    /**
     * @ngdoc function
     * @name retrieveVocabData
     * @description
     * Sets vocabResourceData and vocabPropertyData with current data. Called
     * when the app first runs.
     */
    vocab.retrieveVocabData = function() {
        // returns the vocab data
        var lsDate = localStorageService.get('date');
        var currDate = new Date(lsDate);
        var beginDate = new Date();
        var endDate = new Date();

        beginDate.setDate(beginDate.getDate() - 7);
        endDate.setDate(endDate.getDate() + 7);

        if(!lsDate || !(currDate >= beginDate && currDate <= endDate)) {
            localStorageService.clearAll();
            vocab.setVocabData();
            localStorageService.set('date', (new Date()).toDateString());
        }
        else {
            vocabResourceData = localStorageService.get("resourceReference");
            vocabPropertyData = localStorageService.get("propertyReference");
        }
    };

    /**
     * @ngdoc function
     * @name updateChosenResource
     * @description
     * Gets the resource data to use to update the resource that is open on
     * the page
     * @param {Number} resourceNumber - the number of the resource to update
     * @returns {Array} - The resource data
     */
    vocab.updateChosenResource = function(resourceNumber) {
        choosenResource = resourceNumber;

        vocab.fillData = fillResource;

        return vocabResourceData;
    };

    /**
     * @ngdoc function
     * @name updateChosenProperty
     * @description
     * Gets the property data to use to update the property template that is
     * open on the page
     * @param {Number} resourceNumber - the resource template number
     * @param {Number} propertyNumber - the property template number
     * @returns {Array} - the property template data
     */
    vocab.updateChosenProperty = function(item) {
        choosenProperty = item;

        vocab.fillData = fillProperty;

        return vocabPropertyData;
    };

    vocab.getLanguages = function() {
        var queue = $q.defer();

        if(languageList.length > 0) {
            queue.resolve(languageList);
        }
        else {
            Server.get('/verso/api/configs?filter[where][configType]=vocabulary&filter[where][name]=Languages', {}, false)
            .then(function(response) {
                var jsonObj = response[0].json;

                var data = jsonObj.RDF.MADSScheme.hasTopMemberOfMADSScheme;
                var language;

                for(var i = 0; i < data.length; i++) {
                    language = data[i].Language;
                    if(typeof(language.label[0]) !== 'undefined') {
                        //Make sure it's the English name of the language
                        if(language.label[0]["_xml:lang"] === "en") {
                            languageList.push({key: language.label[0].__text,
                                value: language["_rdf:about"]});
                        } else {
                            for(var j = 0; j < language.label.length; j++) {
                                if(language.label[j]["_xml:lang"] === "en") {
                                    languageList.push({key: language.label[j].__text,
                                        value: language["_rdf:about"]});
                                }
                            }
                        }
                    } else if(typeof(language.label) !== 'undefined') {
                        languageList.push({key: language.label.__text,
                            value: language["_rdf:about"]});
                    } else {
                        languageList.push({key: language["_rdf:about"],
                            value: language["_rdf:about"]});
                    }
                }
                queue.resolve(languageList);
            });
        }

        return queue.promise;

    };

    fillResource = function(vocab) {
        var resource = choosenResource;
        resource.resourceURI = vocab.uri;
        resource.resourceLabel = vocab.label;
        resource.remark = vocab.comment;

    };

    fillProperty = function(vocab) {
        var property = choosenProperty;
        property.propertyURI = vocab.uri;
        property.propertyLabel = vocab.label;
        property.remark = vocab.comment;

    };

    return vocab;
});

<commit_msg>Get setVocabData function working with new verso config.<commit_after>/**
 * @ngdoc service
 * @name Vocab
 * @description
 * Handles getting and parsing the pre-defined vocabularies
 */
angular.module('locApp.modules.profile.services').factory('Vocab', function($q, $http, localStorageService, Server) {
    vocab = {};

    var choosenResource = -1;
    var choosenProperty = -1;

    var vocabResourceData = [];
    var vocabPropertyData = [];

    var languageList = [];

    // Takes in the rdf JSON object and puts a list of resources
    // to save to local storage
    var buildResources = function(rdfResources) {
        var resourceData = [];

        if(!Array.isArray(rdfResources) && rdfResources !== undefined) {
            var data = {};

            if(rdfResources.label != null) {
               data.label = rdfResources.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (rdfResources.comment != null) ? rdfResources.comment.__text.toString() : "";
            data.uri = rdfResources["_rdf:about"];
            resourceData.push(data);
            return resourceData;
        }

        angular.forEach(rdfResources, function(value) {
            var data = {};

            if(value.label === undefined) {
                value.label = null;
            }
            if(value.label != null) {
               data.label = value.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (value.comment != null) ? value.comment.__text.toString() : "";
            data.uri = value["_rdf:about"];
            resourceData.push(data);
        });

        return resourceData;
    };

    var buildProperties = function(rdfProperties) {
        var propertyData = [];

        if(!Array.isArray(rdfProperties) && rdfProperties !== undefined) {
            var data = {};

            if(rdfProperties.label != null) {
               data.label = rdfProperties.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (rdfProperties.comment != null) ? rdfProperties.comment.__text.toString() : "";
            data.uri = rdfProperties["_rdf:about"];
            propertyData.push(data);
            return propertyData;
        }

        angular.forEach(rdfProperties, function(value) {
            var data = {};
            if(value.label === undefined) {
                value.label = null;
            }
            if(value.label != null) {
               data.label = value.label.__text.toString();
            }
            else {
                data.label = "";
            }

            data.comment = (value.comment != null) ? value.comment.__text.toString() : "";
            data.uri = value["_rdf:about"];
            propertyData.push(data);
        });

        return propertyData;
    };

    // Method that will set the vocab data for each list.
    var _setVocabData = function(name, url, properties, resources) {
        var item = $q.defer();
        console.log(name);
        console.log(url);
        Server.$jsonp(url,{},false)
        .then(function(response) {
            console.log(response);
            item.resolve("Finished");
        })
        /* Server.get(url,{},false)
        .then(function(response) {
            // if a vocab file is empty then we will pass over it and return.
            if(response === undefined || response === "") {
                item.reject("No data");
                return;
            }

            // set the local storage with this data
            var jsonObj = response.json;

            var resource = {};
            var property = {};

            resource.key = name;
            resource.value = buildResources(jsonObj.RDF.Class);
            resources.push(resource);

            property.key = name;
            property.value = buildProperties(jsonObj.RDF.Property);
            properties.push(property);

            // Resolve the queue
            item.resolve("Finished");
        }); */

        return item.promise;
    };

    // Method to set the local storage of resource and properties
    var _setLocalStorage = function(resources, properties) {
        localStorageService.set("resourceReference", resources);
        localStorageService.set("propertyReference", properties);
        // Set Vocab data
        vocabResourceData = resources;
        vocabPropertyData = properties;
    };

    /**
     * @ngdoc function
     * @name setVocabData
     * @description
     * Gets the vocab data and adds them to the local machine.
     */
    vocab.setVocabData = function() {
        // if the local storage has expired, gather the data and set it up again
        // TODO: make this connect to the real RDF

        // const vurl = '/verso/api/configs?filter[where][configType]=vocabulary&filter[fields][name]=true&filter[fields][id]=true&filter[where][name][neq]=Languages';
        const vurl = '/verso/api/configs?filter[where][configType]=ontology';

        Server.get(vurl, {}, false)
        .then(function(response){
            var listLength = 0;
            var returnNumber = 0;
            var resources = [];
            var properties = [];

            // loop through the list of vocabs and gather up the data.
            angular.forEach(response, function(value) {
                var url = value.json.url;

                // test that we hvae a key and this isn't a comment.
                if(value.id != null) {
                    listLength++;
                    _setVocabData(value.json.label, url, properties, resources)
                        .then(function() {
                            returnNumber++;

                            // Set local storage once we have all the data.
                            if(returnNumber >= listLength) {
                                _setLocalStorage(resources, properties);
                            }
                        }, function() {
                            returnNumber++;
                        });
                }

            });
        });
    };

    /**
     * @ngdoc function
     * @name retrieveVocabData
     * @description
     * Sets vocabResourceData and vocabPropertyData with current data. Called
     * when the app first runs.
     */
    vocab.retrieveVocabData = function() {
        // returns the vocab data
        var lsDate = localStorageService.get('date');
        var currDate = new Date(lsDate);
        var beginDate = new Date();
        var endDate = new Date();

        beginDate.setDate(beginDate.getDate() - 7);
        endDate.setDate(endDate.getDate() + 7);

        if(!lsDate || !(currDate >= beginDate && currDate <= endDate)) {
            localStorageService.clearAll();
            vocab.setVocabData();
            localStorageService.set('date', (new Date()).toDateString());
        }
        else {
            vocabResourceData = localStorageService.get("resourceReference");
            vocabPropertyData = localStorageService.get("propertyReference");
        }
    };

    /**
     * @ngdoc function
     * @name updateChosenResource
     * @description
     * Gets the resource data to use to update the resource that is open on
     * the page
     * @param {Number} resourceNumber - the number of the resource to update
     * @returns {Array} - The resource data
     */
    vocab.updateChosenResource = function(resourceNumber) {
        choosenResource = resourceNumber;

        vocab.fillData = fillResource;

        return vocabResourceData;
    };

    /**
     * @ngdoc function
     * @name updateChosenProperty
     * @description
     * Gets the property data to use to update the property template that is
     * open on the page
     * @param {Number} resourceNumber - the resource template number
     * @param {Number} propertyNumber - the property template number
     * @returns {Array} - the property template data
     */
    vocab.updateChosenProperty = function(item) {
        choosenProperty = item;

        vocab.fillData = fillProperty;

        return vocabPropertyData;
    };

    vocab.getLanguages = function() {
        var queue = $q.defer();

        if(languageList.length > 0) {
            queue.resolve(languageList);
        }
        else {
            Server.get('/verso/api/configs?filter[where][configType]=vocabulary&filter[where][name]=Languages', {}, false)
            .then(function(response) {
                var jsonObj = response[0].json;

                var data = jsonObj.RDF.MADSScheme.hasTopMemberOfMADSScheme;
                var language;

                for(var i = 0; i < data.length; i++) {
                    language = data[i].Language;
                    if(typeof(language.label[0]) !== 'undefined') {
                        //Make sure it's the English name of the language
                        if(language.label[0]["_xml:lang"] === "en") {
                            languageList.push({key: language.label[0].__text,
                                value: language["_rdf:about"]});
                        } else {
                            for(var j = 0; j < language.label.length; j++) {
                                if(language.label[j]["_xml:lang"] === "en") {
                                    languageList.push({key: language.label[j].__text,
                                        value: language["_rdf:about"]});
                                }
                            }
                        }
                    } else if(typeof(language.label) !== 'undefined') {
                        languageList.push({key: language.label.__text,
                            value: language["_rdf:about"]});
                    } else {
                        languageList.push({key: language["_rdf:about"],
                            value: language["_rdf:about"]});
                    }
                }
                queue.resolve(languageList);
            });
        }

        return queue.promise;

    };

    fillResource = function(vocab) {
        var resource = choosenResource;
        resource.resourceURI = vocab.uri;
        resource.resourceLabel = vocab.label;
        resource.remark = vocab.comment;

    };

    fillProperty = function(vocab) {
        var property = choosenProperty;
        property.propertyURI = vocab.uri;
        property.propertyLabel = vocab.label;
        property.remark = vocab.comment;

    };

    return vocab;
});<|endoftext|>