<commit_before>// @flow

import * as React from 'react';
import PropTypes from 'prop-types';
import { createRefetchContainer, graphql } from 'react-relay/compat';
import SectionLoader from 'app/components/shared/SectionLoader';
import ShowMoreFooter from 'app/components/shared/ShowMoreFooter';
import UserSessionStore from 'app/stores/UserSessionStore';
import Pipeline from './Pipeline';
import Welcome from './Welcome';
import * as constants from './constants';
import type { RelayRefetchProp } from 'react-relay';
import type { Pipelines_organization } from './__generated__/Pipelines_organization.graphql';

type Props = {
  relay: RelayRefetchProp,
  teamFilter: string,
  nameFilter: string,
  organization: Pipelines_organization
};

type State = {
  loading: boolean,
  loadingMore: boolean,
  pageSize: number,
  includeGraphData: boolean
};

class Pipelines extends React.Component<Props, State> {
  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  state = {
    loading: false,
    loadingMore: false,
    pageSize: constants.PIPELINES_INITIAL_PAGE_SIZE,
    includeGraphData: false
  };

  get useLocalSearch() {
    return (
      this.props.organization.pipelines &&
      this.props.organization.allPipelines &&
      this.props.organization.allPipelines.count <= constants.PIPELINES_INITIAL_PAGE_SIZE
    );
  }

  get useRemoteSearch() {
    return !this.useLocalSearch;
  }

  get pipelines() {
    return (
      this.props.organization.pipelines &&
      this.props.organization.pipelines.edges
    ) ? this.props.organization.pipelines.edges : [];
  }

  componentDidMount() {
    this.props.relay.refetch((lastVars) => ({ ...lastVars, includeGraphData: true }), null, () => {
      this.setState({ includeGraphData: true });
    });

    // We might've started out with a new team, so let's see about updating the default!
    this.maybeUpdateDefaultTeam(this.props.organization.id, this.props.teamFilter);
  }

  componentWillReceiveProps(nextProps: Props) {
    const nextVars = {};

    // Are we switching teams?
    if (this.props.teamFilter !== nextProps.teamFilter) {
      nextVars.teamSearch = nextProps.teamFilter;
    }

    // Are we filtering, and can we do this locally?
    if (this.props.nameFilter !== nextProps.nameFilter && this.useRemoteSearch) {
      // if not, go to the server
      nextVars.pipelineFilter = nextProps.nameFilter;
    }

    if (Object.keys(nextVars).length > 0) {
      // Start by changing the `loading` state to show the spinner
      this.setState({ loading: true }, () => {
        // Once state has been set, force a full re-fetch of the pipelines
        this.props.relay.refetch((lastVars) => ({ ...lastVars, ...nextVars }), null, () => {
          this.setState({ loading: false });
        });
      });
    }

    // Let's try updating the default team - we don't rely on the last team
    // being different here because the store might've gotten out of sync,
    // and we do out own check!
    this.maybeUpdateDefaultTeam(nextProps.organization.id, nextProps.teamFilter);
  }

  maybeUpdateDefaultTeam(organization, team) {
    const orgDefaultTeamKey = `organization-default-team:${organization}`;

    if (team !== UserSessionStore.get(orgDefaultTeamKey)) {
      if (team) {
        UserSessionStore.set(orgDefaultTeamKey, team);
      } else {
        UserSessionStore.remove(orgDefaultTeamKey);
      }
    }
  }

  getRelevantPipelines() {
    const filter = (this.props.nameFilter || '').toLowerCase().trim();

    // if we're searching remotely, or there's no filter, it's all of 'em, baby
    if (this.useRemoteSearch || !this.props.nameFilter || !filter) {
      return this.pipelines;
    }

    // otherwise, let's filter 'em
    return this.pipelines.filter((pipeline) => (
      pipeline &&
      pipeline.node &&
      (
        pipeline.node.name.toLowerCase().indexOf(filter) !== -1 ||
        // $FlowExpectError
        pipeline.node.description && pipeline.node.description.toLowerCase().indexOf(filter) !== -1
      )
    ));
  }

  render() {
    // Are we switching teams or getting the first set of data? Lets bail out
    // early and show the spinner.
    if (this.state.loading || !this.props.organization.pipelines) {
      return (
        <SectionLoader />
      );
    }

    const relevantPipelines = this.getRelevantPipelines();

    // Switch between rendering the actual teams, or showing the "Welcome"
    // message
    if (relevantPipelines.length > 0) {
      return (

          {this.renderPipelines(relevantPipelines)}
          <ShowMoreFooter
            connection={this.props.organization.pipelines}
            label="pipelines"
            loading={this.state.loadingMore}
            onShowMore={this.handleShowMorePipelines}
          />

      );
    } else if (this.props.nameFilter) {
      return (

          {`No pipelines matching “${this.props.nameFilter}”`}

      );
    }

    return (
      <Welcome
        organization={this.props.organization}
        team={this.props.teamFilter}
      />
    );
  }

  renderPipelines(relevantPipelines) {
    // Split the pipelines into "favorited" and non "favorited". We don't
    // user a `sort` method so we preserve the current order the pipelines.
    const [favorited, remainder] = relevantPipelines.reduce((pipelines, pipeline) => {
      if (pipeline && pipeline.node) {
        pipelines[pipeline.node.favorite ? 0 : 1].push(
          <Pipeline
            key={pipeline.node.id}
            pipeline={pipeline.node}
            includeGraphData={this.state.includeGraphData}
          />
        );
      }
      return pipelines;
    }, [[], []]);

    if (favorited.length > 0 && remainder.length > 0) {
      return (
        <>
          {favorited}

          {remainder}
        </>
      );
    } else if (favorited.length > 0) {
      return favorited;
    } else if (remainder.length > 0) {
      return remainder;
    }

    // Just in case
    return [];
  }

  handleShowMorePipelines = () => {
    const pageSize = this.state.pageSize + constants.PIPELINES_PAGE_SIZE;
    this.setState({ loadingMore: true, pageSize }, () => {
      this.props.relay.refetch((lastVars) => ({ ...lastVars, pageSize, includeGraphData: true }), null, () => {
        this.setState({ loadingMore: false });
      });
    });
  }
}

export default createRefetchContainer(
  Pipelines,
  graphql`
    fragment Pipelines_organization on Organization @argumentDefinitions(
      teamSearch: {type: "TeamSelector"}
      pageSize: {type: "Int", defaultValue: 30}
      pipelineFilter: {type: "String"}
      includeGraphData: {type: "Boolean", defaultValue: false}
    ) {
      ...Welcome_organization
      id
      slug
      allPipelines: pipelines(team: $teamSearch) {
        count
      }
      pipelines(
        search: $pipelineFilter
        first: $pageSize
        team: $teamSearch
        order: NAME_WITH_FAVORITES_FIRST
      ) {
        ...ShowMoreFooter_connection
        edges {
          node {
            id
            name
            description
            favorite
            ...Pipeline_pipeline @arguments(includeGraphData: $includeGraphData)
          }
        }
      }
    }
  `,
  graphql`
    query PipelinesRefetchQuery(
      $organizationSlug: ID!
      $teamSearch: TeamSelector
      $includeGraphData: Boolean!
      $pageSize: Int!
      $pipelineFilter: String
    ) {
      organization(slug: $organizationSlug) {
        ...Pipelines_organization @arguments(
          teamSearch: $teamSearch
          includeGraphData: $includeGraphData
          pageSize: $pageSize
          pipelineFilter: $pipelineFilter
        )
      }
    }
  `
);
<commit_msg>eslint: componentWillReceiveProps -> UNSAFE_componentWillReceiveProps<commit_after>// @flow

import * as React from 'react';
import PropTypes from 'prop-types';
import { createRefetchContainer, graphql } from 'react-relay/compat';
import SectionLoader from 'app/components/shared/SectionLoader';
import ShowMoreFooter from 'app/components/shared/ShowMoreFooter';
import UserSessionStore from 'app/stores/UserSessionStore';
import Pipeline from './Pipeline';
import Welcome from './Welcome';
import * as constants from './constants';
import type { RelayRefetchProp } from 'react-relay';
import type { Pipelines_organization } from './__generated__/Pipelines_organization.graphql';

type Props = {
  relay: RelayRefetchProp,
  teamFilter: string,
  nameFilter: string,
  organization: Pipelines_organization
};

type State = {
  loading: boolean,
  loadingMore: boolean,
  pageSize: number,
  includeGraphData: boolean
};

class Pipelines extends React.Component<Props, State> {
  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  state = {
    loading: false,
    loadingMore: false,
    pageSize: constants.PIPELINES_INITIAL_PAGE_SIZE,
    includeGraphData: false
  };

  get useLocalSearch() {
    return (
      this.props.organization.pipelines &&
      this.props.organization.allPipelines &&
      this.props.organization.allPipelines.count <= constants.PIPELINES_INITIAL_PAGE_SIZE
    );
  }

  get useRemoteSearch() {
    return !this.useLocalSearch;
  }

  get pipelines() {
    return (
      this.props.organization.pipelines &&
      this.props.organization.pipelines.edges
    ) ? this.props.organization.pipelines.edges : [];
  }

  componentDidMount() {
    this.props.relay.refetch((lastVars) => ({ ...lastVars, includeGraphData: true }), null, () => {
      this.setState({ includeGraphData: true });
    });

    // We might've started out with a new team, so let's see about updating the default!
    this.maybeUpdateDefaultTeam(this.props.organization.id, this.props.teamFilter);
  }

  UNSAFE_componentWillReceiveProps(nextProps: Props) {
    const nextVars = {};

    // Are we switching teams?
    if (this.props.teamFilter !== nextProps.teamFilter) {
      nextVars.teamSearch = nextProps.teamFilter;
    }

    // Are we filtering, and can we do this locally?
    if (this.props.nameFilter !== nextProps.nameFilter && this.useRemoteSearch) {
      // if not, go to the server
      nextVars.pipelineFilter = nextProps.nameFilter;
    }

    if (Object.keys(nextVars).length > 0) {
      // Start by changing the `loading` state to show the spinner
      this.setState({ loading: true }, () => {
        // Once state has been set, force a full re-fetch of the pipelines
        this.props.relay.refetch((lastVars) => ({ ...lastVars, ...nextVars }), null, () => {
          this.setState({ loading: false });
        });
      });
    }

    // Let's try updating the default team - we don't rely on the last team
    // being different here because the store might've gotten out of sync,
    // and we do out own check!
    this.maybeUpdateDefaultTeam(nextProps.organization.id, nextProps.teamFilter);
  }

  maybeUpdateDefaultTeam(organization, team) {
    const orgDefaultTeamKey = `organization-default-team:${organization}`;

    if (team !== UserSessionStore.get(orgDefaultTeamKey)) {
      if (team) {
        UserSessionStore.set(orgDefaultTeamKey, team);
      } else {
        UserSessionStore.remove(orgDefaultTeamKey);
      }
    }
  }

  getRelevantPipelines() {
    const filter = (this.props.nameFilter || '').toLowerCase().trim();

    // if we're searching remotely, or there's no filter, it's all of 'em, baby
    if (this.useRemoteSearch || !this.props.nameFilter || !filter) {
      return this.pipelines;
    }

    // otherwise, let's filter 'em
    return this.pipelines.filter((pipeline) => (
      pipeline &&
      pipeline.node &&
      (
        pipeline.node.name.toLowerCase().indexOf(filter) !== -1 ||
        // $FlowExpectError
        pipeline.node.description && pipeline.node.description.toLowerCase().indexOf(filter) !== -1
      )
    ));
  }

  render() {
    // Are we switching teams or getting the first set of data? Lets bail out
    // early and show the spinner.
    if (this.state.loading || !this.props.organization.pipelines) {
      return (
        <SectionLoader />
      );
    }

    const relevantPipelines = this.getRelevantPipelines();

    // Switch between rendering the actual teams, or showing the "Welcome"
    // message
    if (relevantPipelines.length > 0) {
      return (

          {this.renderPipelines(relevantPipelines)}
          <ShowMoreFooter
            connection={this.props.organization.pipelines}
            label="pipelines"
            loading={this.state.loadingMore}
            onShowMore={this.handleShowMorePipelines}
          />

      );
    } else if (this.props.nameFilter) {
      return (

          {`No pipelines matching “${this.props.nameFilter}”`}

      );
    }

    return (
      <Welcome
        organization={this.props.organization}
        team={this.props.teamFilter}
      />
    );
  }

  renderPipelines(relevantPipelines) {
    // Split the pipelines into "favorited" and non "favorited". We don't
    // user a `sort` method so we preserve the current order the pipelines.
    const [favorited, remainder] = relevantPipelines.reduce((pipelines, pipeline) => {
      if (pipeline && pipeline.node) {
        pipelines[pipeline.node.favorite ? 0 : 1].push(
          <Pipeline
            key={pipeline.node.id}
            pipeline={pipeline.node}
            includeGraphData={this.state.includeGraphData}
          />
        );
      }
      return pipelines;
    }, [[], []]);

    if (favorited.length > 0 && remainder.length > 0) {
      return (
        <>
          {favorited}

          {remainder}
        </>
      );
    } else if (favorited.length > 0) {
      return favorited;
    } else if (remainder.length > 0) {
      return remainder;
    }

    // Just in case
    return [];
  }

  handleShowMorePipelines = () => {
    const pageSize = this.state.pageSize + constants.PIPELINES_PAGE_SIZE;
    this.setState({ loadingMore: true, pageSize }, () => {
      this.props.relay.refetch((lastVars) => ({ ...lastVars, pageSize, includeGraphData: true }), null, () => {
        this.setState({ loadingMore: false });
      });
    });
  }
}

export default createRefetchContainer(
  Pipelines,
  graphql`
    fragment Pipelines_organization on Organization @argumentDefinitions(
      teamSearch: {type: "TeamSelector"}
      pageSize: {type: "Int", defaultValue: 30}
      pipelineFilter: {type: "String"}
      includeGraphData: {type: "Boolean", defaultValue: false}
    ) {
      ...Welcome_organization
      id
      slug
      allPipelines: pipelines(team: $teamSearch) {
        count
      }
      pipelines(
        search: $pipelineFilter
        first: $pageSize
        team: $teamSearch
        order: NAME_WITH_FAVORITES_FIRST
      ) {
        ...ShowMoreFooter_connection
        edges {
          node {
            id
            name
            description
            favorite
            ...Pipeline_pipeline @arguments(includeGraphData: $includeGraphData)
          }
        }
      }
    }
  `,
  graphql`
    query PipelinesRefetchQuery(
      $organizationSlug: ID!
      $teamSearch: TeamSelector
      $includeGraphData: Boolean!
      $pageSize: Int!
      $pipelineFilter: String
    ) {
      organization(slug: $organizationSlug) {
        ...Pipelines_organization @arguments(
          teamSearch: $teamSearch
          includeGraphData: $includeGraphData
          pageSize: $pageSize
          pipelineFilter: $pipelineFilter
        )
      }
    }
  `
);
<|endoftext|>


<commit_before>Covered.IndexRoute = Ember.Route.extend({

  redirect: function() {
    if (!Covered.isSignedIn()) return;
    return Covered.CurrentUser.fetch().then(function(currentUser) {
      var organization = currentUser.get('organizations').objectAt(0);
      if (organization) this.transitionTo('my_conversations', organization.get('slug'));
    });
  }

});
<commit_msg>fixed a bug that was breaking sign in<commit_after>Covered.IndexRoute = Ember.Route.extend({

  redirect: function() {
    if (!Covered.isSignedIn()) return;
    return Covered.CurrentUser.fetch().then(function(currentUser) {
      var organization = currentUser.get('organizations').objectAt(0);
      if (organization) this.transitionTo('my_conversations', organization.get('slug'));
    }.bind(this));
  }

});
<|endoftext|>


<commit_before>App.TreeNodeView = Ember.View.extend({
  opened: false,
  //keep track of which uri has children
  hasChildrenList: {},
  fetchingData: false,
  highlighted: false,

  hidden: function() {
	return this.get('content').get('hidden');
  }.property('content.hidden'),

  branch: function(){
    return this.get('content').get('hasChildren');
  }.property('content.hasChildren'),

   node: function(){
    return (this.get('content').get('hasChildren') === false);
  }.property('content.hasChildren'),

  opened: function() {
    return (this.get('content').get('opened') === true);
  }.property('content.opened'),

  closed: function() {
    return (this.get('content').get('opened') === false);
  }.property('content.closed'),

  subBranch: undefined,
  fetchedData: false,
  indentLevel: function(){
	return 'indentLevel' + this.get('content').get('level');
  }.property('content.level'),
  tagName: 'div',
  // class names that determine what icons are used beside the node
  classNameBindings: [':medium-padding-bottom', 'hidden', 'indentLevel', 'highlighted:highlight-on'],
  classNames: ['treerow'],
  templateName: 'treenode',
  // Ember had some issues with finding the treenode template when the branch view is dynamically added to
  // the parent collection view in the click event. Had to compile the template here instead

actions: {
  expand: function() {
        console.log('expand');
        var controller = this.get('controller');
		var contentIndex = controller.get('content').indexOf(this.get('content'));
		var parent = controller.get('content')[contentIndex];
        var me = this;
	this.set('fetchingData', true);
		// the initial treebranch is loaded with data from the controller, sub branches are given data directly
		// hence the need to get the data slightly differently. Sure it's a fudge but.....
		if (parent.get('opened')) {
			// user wants to close the branch
			var index = this.get('parentView').indexOf(this) + 1;
			me.iterateOverChildren(this.get('content'), true);
			this.set('opened', false);
			this.get('content').set('opened', false);
			this.set('fetchingData', false);
		} else if (parent.get('fetchedData')){
			// user wants to open the branch and we have already created the view before
			var index = this.get('parentView').indexOf(this) + 1;
			me.iterateOverChildren(this.get('content'), false);
			this.set('fetchingData', false);
			this.set('opened', true);
			this.get('content').set('opened', true);
		} else {
			// user wants to open the branch for the first time
			var name, uri;
			var me = this;
            var parent = this.get('content');
			name = this.get('content').name ? this.get('content').name : this.get('content').get('name');
			uri = this.get('content').uri ? this.get('content').uri : this.get('content').get('uri');
		    console.log("Clicked on " + name + " " + uri);
		    if (this.get('content').get('hasChildren')) {
                var contentIndex = controller.get('content').indexOf(this.get('content'));
			    var searcher = new Openphacts.TreeSearch(ldaBaseUrl, appID, appKey);
		        var callback = function(success, status, response) {
			        if (success && response) {
			me.set('fetchingData', false);
me.set('opened', true);
		me.get('content').set('opened', true);
				        var members = searcher.parseChildNodes(response);
				        var membersWithSingleName = [];
                        var allMembers = [];
                        //firstly find all the children
				        $.each(members.children, function(index, member) {
							var enzyme = me.get('controller').store.createRecord('tree');
                            if (member.uri != null && member.names[0] != null) {
						      enzyme.set('uri', member.uri);
							  enzyme.set('name', member.names[0]);
							  enzyme.set('id', member.uri.split('/').pop());
                              // assume that all the children have children until clicked unless we have already loaded this one
			      if (me.get('hasChildrenList')[member.uri] != null && me.get('hasChildrenList')[member.uri] === true) {
							  enzyme.set('hasChildren', true);
			      } else if (me.get('hasChildrenList')[member.uri] != null && me.get('hasChildrenList')[member.uri] === false) {
                              enzyme.set('hasChildren', false);
			      } else {
                                  enzyme.set('hasChildren', true);
			      }
                              enzyme.set('level', parent.get('level') + 1);
                              allMembers.push(enzyme);
                            }
				        });
                        //then sort them
                        allMembers.sort(function(a, b) {
                            var x = a.get('uri').split('/').pop();
                            var y = b.get('uri').split('/').pop();
                            if (x === y) {
                              return 0;
                            }
                            return y < x ? -1 : 1;
                        });
                        $.each(allMembers, function(index, member) {
                            controller.get('content').insertAt(contentIndex + 1, member);
                            controller.get('content')[contentIndex].get('children').pushObject(member);
                        });
				    } else {
				      // api sent false (or it broke!)
				      console.log(uri + ' has no children');
				      me.set('fetchingData', false);
                                      me.get('content').set('hasChildren', false);
				      me.get('hasChildrenList')[uri] = false;
				    }
			}
			    searcher.getChildNodes(uri, callback);
		    }
		}
  }
},
  iterateOverChildren: function(child, hidden) {
	var me = this;
	console.log('iterating over ' + child.id);
    $.each(child.get('children').get('content'), function(index, innerChild) {
      console.log('parent is opened ' + innerChild.get('parent').get('opened'));
	  if (innerChild.get('parent').get('opened') == hidden) {
		  innerChild.set('hidden', hidden);
		  console.log('inner child is ' + innerChild.id + ' ' + innerChild.get('hidden'));
		  me.iterateOverChildren(innerChild, hidden);
	  }
    });
    child.set('opened', hidden);
  }

});
<commit_msg>js reformat treeNodeView for readability<commit_after>App.TreeNodeView = Ember.View.extend({
    opened: false,
    //keep track of which uri has children
    hasChildrenList: {},
    fetchingData: false,
    highlighted: false,

    hidden: function() {
        return this.get('content').get('hidden');
    }.property('content.hidden'),

    branch: function() {
        return this.get('content').get('hasChildren');
    }.property('content.hasChildren'),

    node: function() {
        return (this.get('content').get('hasChildren') === false);
    }.property('content.hasChildren'),

    opened: function() {
        return (this.get('content').get('opened') === true);
    }.property('content.opened'),

    closed: function() {
        return (this.get('content').get('opened') === false);
    }.property('content.closed'),

    subBranch: undefined,
    fetchedData: false,
    indentLevel: function() {
        return 'indentLevel' + this.get('content').get('level');
    }.property('content.level'),
    tagName: 'div',
    // class names that determine what icons are used beside the node
    classNameBindings: [':medium-padding-bottom', 'hidden', 'indentLevel', 'highlighted:highlight-on'],
    classNames: ['treerow'],
    templateName: 'treenode',
    // Ember had some issues with finding the treenode template when the branch view is dynamically added to
    // the parent collection view in the click event. Had to compile the template here instead

    actions: {
        expand: function() {
            console.log('expand');
            var controller = this.get('controller');
            var contentIndex = controller.get('content').indexOf(this.get('content'));
            var parent = controller.get('content')[contentIndex];
            var me = this;
            this.set('fetchingData', true);
            // the initial treebranch is loaded with data from the controller, sub branches are given data directly
            // hence the need to get the data slightly differently. Sure it's a fudge but.....
            if (parent.get('opened')) {
                // user wants to close the branch
                var index = this.get('parentView').indexOf(this) + 1;
                me.iterateOverChildren(this.get('content'), true);
                this.set('opened', false);
                this.get('content').set('opened', false);
                this.set('fetchingData', false);
            } else if (parent.get('fetchedData')) {
                // user wants to open the branch and we have already created the view before
                var index = this.get('parentView').indexOf(this) + 1;
                me.iterateOverChildren(this.get('content'), false);
                this.set('fetchingData', false);
                this.set('opened', true);
                this.get('content').set('opened', true);
            } else {
                // user wants to open the branch for the first time
                var name, uri;
                var me = this;
                var parent = this.get('content');
                name = this.get('content').name ? this.get('content').name : this.get('content').get('name');
                uri = this.get('content').uri ? this.get('content').uri : this.get('content').get('uri');
                console.log("Clicked on " + name + " " + uri);
                if (this.get('content').get('hasChildren')) {
                    var contentIndex = controller.get('content').indexOf(this.get('content'));
                    var searcher = new Openphacts.TreeSearch(ldaBaseUrl, appID, appKey);
                    var callback = function(success, status, response) {
                        if (success && response) {
                            me.set('fetchingData', false);
                            me.set('opened', true);
                            me.get('content').set('opened', true);
                            var members = searcher.parseChildNodes(response);
                            var membersWithSingleName = [];
                            var allMembers = [];
                            //firstly find all the children
                            $.each(members.children, function(index, member) {
                                var enzyme = me.get('controller').store.createRecord('tree');
                                if (member.uri != null && member.names[0] != null) {
                                    enzyme.set('uri', member.uri);
                                    enzyme.set('name', member.names[0]);
                                    enzyme.set('id', member.uri.split('/').pop());
                                    // assume that all the children have children until clicked unless we have already loaded this one
                                    if (me.get('hasChildrenList')[member.uri] != null && me.get('hasChildrenList')[member.uri] === true) {
                                        enzyme.set('hasChildren', true);
                                    } else if (me.get('hasChildrenList')[member.uri] != null && me.get('hasChildrenList')[member.uri] === false) {
                                        enzyme.set('hasChildren', false);
                                    } else {
                                        enzyme.set('hasChildren', true);
                                    }
                                    enzyme.set('level', parent.get('level') + 1);
                                    allMembers.push(enzyme);
                                }
                            });
                            //then sort them
                            allMembers.sort(function(a, b) {
                                var x = a.get('uri').split('/').pop();
                                var y = b.get('uri').split('/').pop();
                                if (x === y) {
                                    return 0;
                                }
                                return y < x ? -1 : 1;
                            });
                            $.each(allMembers, function(index, member) {
                                controller.get('content').insertAt(contentIndex + 1, member);
                                controller.get('content')[contentIndex].get('children').pushObject(member);
                            });
                        } else {
                            // api sent false (or it broke!)
                            console.log(uri + ' has no children');
                            me.set('fetchingData', false);
                            me.get('content').set('hasChildren', false);
                            me.get('hasChildrenList')[uri] = false;
                        }
                    }
                    searcher.getChildNodes(uri, callback);
                }
            }
        }
    },
    iterateOverChildren: function(child, hidden) {
        var me = this;
        console.log('iterating over ' + child.id);
        $.each(child.get('children').get('content'), function(index, innerChild) {
            console.log('parent is opened ' + innerChild.get('parent').get('opened'));
            if (innerChild.get('parent').get('opened') == hidden) {
                innerChild.set('hidden', hidden);
                console.log('inner child is ' + innerChild.id + ' ' + innerChild.get('hidden'));
                me.iterateOverChildren(innerChild, hidden);
            }
        });
        child.set('opened', hidden);
    }

});
<|endoftext|>


<commit_before>(function () {

    /**
     * D3 drawing function
     * @param  {[type]} d3
     * @param  {[type]} $element
     * @param  {Array} data
     */
     function chart(d3, $element, data) {

 var margin = {top: 100, right: 80, bottom: 30, left: 30};
  var width = 1100 - margin.left - margin.right;
  var height = 650 - margin.top - margin.bottom;

  var margin_first_text = 500;
  var margin_last_text = 60;

  var width_graph = width - margin_first_text - margin_last_text;

  var svg = d3.select("#vis")
  .append("svg")
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append('g')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var xScale = d3.scale.linear().range([0, width_graph]);
  var colorScale = d3.scale.category10();
  var color_ref = "red";

  var x = d3.scale.linear()
  .domain([0, 100])
  .range([0, width])
  .clamp(true);

  var div_tooltip = d3.select('body').append('div').attr('class', 'tooltip').style('opacity', 0);

    var x0 = 0;

    data.forEach(function(d) {
      d.name = d.nom;
      d.value = +d.Impots;
      d.value0 = x0;
      x0 = x0 + d.value;

    });

var sum_values = d3.sum(data, function(d){return d.value});

xScale.domain([0, sum_values]);

var RefType = svg.append("g")
.attr('class', 'type')
.attr("transform", function(){return "translate(0 ,0)";});

RefType
.append('rect')
.attr('height', 40)
.attr("width", function(){return xScale(sum_values);})
.attr('fill', color_ref)
.attr("x", margin_first_text);

RefType
.append('text')
.attr("class", "name_text")
.attr("y", 25)
.text("Situation de référence")
.style("font-weight", "bold");

RefType
.append('text')
.attr("class", "name_text")
.attr("y", 25)
.attr("x", margin_first_text + width_graph)
.html(sum_values + " €  24,1%")
.attr("fill", color_ref);

RefType.select('rect')
.on('mouseover', function() {
  var this_left_val = margin_first_text + width_graph - xScale(sum_values) + xScale(sum_values)/2;
  var this_top_val = margin.top + 50;
  div_tooltip.html('
 Référence
' + '
' + sum_values + ' euros
 ').style('left', this_left_val + 'px').style('top', this_top_val  + 'px').style('height', 50 + 'px').style('opacity', 0.9);
})
.on('mouseout', function(d) {
  div_tooltip.style('opacity', 0);
});

var Types_ = svg.selectAll('types')
.data(data);

var Types = Types_.enter()
.append("g")
.attr('class', 'type')
.attr("transform", function(d, i){return "translate(0 ," + parseInt(i*43 + 50) + ")";});

Types
.append('rect')
.attr('height', 40)
.attr("width", function(d){return xScale(d.value);})
.attr('fill', function(d){return colorScale(d.typologie);})
.attr("x", function(d){return margin_first_text + width_graph - xScale(d.value0) - xScale(d.value);});

Types
.append('text')
.attr("class", "name_text")
.attr("y", 25)
.attr("x", 250)
.text(function(d){return d.Type_impact;})
.attr("fill", function(d){return colorScale(d.typologie)})
.style("font-size", 14);

Types
.append('text')
.attr("class", "title_text")
.attr("y", 25)
.text(function(d){return d.title;})
.style("font-weight", "bold");

Types
.append('text')
.attr("class", "name_text")
.attr("y", 25)
.attr("x", margin_first_text + width_graph)
.text(function(d){if (d.typologie == "deduction"){var minus_sign = "-"}else{var minus_sign = ""};if (d.percentage){var this_percentage = " " + d.percentage}else{var this_percentage = ""}; return minus_sign + d.value + " € " + this_percentage;})
.attr("fill", function(d){return colorScale(d.typologie)});

Types.select('rect')
.on('mouseover', function(d, i) {

  var this_left_val = margin_first_text + width_graph - xScale(d.value0) - xScale(d.value)/2;
  var this_top_val = margin.top + i*43 + 50;
  var this_title = ""
  if (d.title){this_title  = d.title};

  div_tooltip.html('
' + this_title + '
' + d.Type_impact + '
' + '
' + d.value + ' euros
 ').style('left', this_left_val + 'px').style('top', this_top_val  + 'px').style('height', 50 + 'px').style('opacity', 0.9);
})
.on('mouseout', function(d) {
  div_tooltip.style('opacity', 0);
});

    }

    angular
    .module('codeimpot.results')
    .directive('barChart', ['d3Service', 'ResultsService', function (d3Service, ResultsService) {
      return {
        restrict: 'EA',
        scope: {},
        templateUrl: 'components/results/barchart.template.html',
        link: function(scope, element, attrs) {
          d3Service.d3().then(function (d3) {
            var data_results = ResultsService.get();
            var data = [{
              "Situation": "Situation de r\u00e9f\u00e9rence",
              "Montant net": 19254,
              "Impots": 6544,
              "Type_impact": "couple marié",
              "nom": "Mariage",
              "typologie": "deduction",
              "title":"Impacts liés au foyer fiscal"
            }, {
              "Situation": "Enfants",
              "Montant net": 12710,
              "Impots": 3015,
              "Type_impact": "deux enfants à charge",
              "nom": "enfants",
              "typologie": "deduction"
            }, {
              "Situation": "D\u00e9duction des frais professionnels",
              "Montant net": 9695,
              "Impots": 2400,
              "Type_impact": "d\u00e9duction des frais professionnels",
              "nom": "Frais pro",
              "typologie": "deduction",
              "title":"Impacts liés aux abattements"
            }, {
              "Situation": "Aux oeuvres reconnues d'utilit\u00e9 publique ou fiscalement assimil\u00e9es en mati\u00e8re de dons, aux oeuvres d'int\u00e9r\u00eat g\u00e9n\u00e9ral 7UF",
              "Montant net": 7295,
              "Impots": 1320,
              "Type_impact": "dons aux œuvres",
              "nom": "Dons",
              "typologie": "deduction",
              "title":"Impacts liés aux"
            }, {
              "Situation": "Mat\u00e9riaux d\u2019isolation thermique des parois vitr\u00e9es (fen\u00eatres, portes-fen\u00eatres\u2026)  7AM",
              "Montant net": 5975,
              "Impots": 2000,
              "Type_impact": "dépenses d'équipements pour les PH",
              "nom": "Isolation",
              "typologie": "deduction",
              "title":"réductions et crédits d’impôts"
            }, {
              "Situation": "Frais de garde des enfants de moins de 6 ans au 1\/1\/2015 7GA",
              "Montant net": 3975,
              "Impots": 2300,
              "Type_impact": "frais de garde d'enfants",
              "nom": "garde enfants",
              "typologie": "deduction"
            }, {
              "Situation": "Situation r\u00e9elle",
              "Montant net": 1675,
              "Impots": 1675,
              "nom": "A payer",
              "typologie": "reel",
              "title":"Situation réelle",
              "percentage":"3,0%"
            }];

            chart(d3, element, data);
          });
        }
      };
    }]);
  }());<commit_msg>Minor fixes<commit_after>(function () {

    /**
     * D3 drawing function
     * @param  {[type]} d3
     * @param  {[type]} $element
     * @param  {Array} data
     */
     function chart(d3, $element, data) {

      var margin = {top: 100, right: 80, bottom: 30, left: 30};
      var width = 1100 - margin.left - margin.right;
      var height = 650 - margin.top - margin.bottom;

      var margin_first_text = 500;
      var margin_last_text = 60;

      var width_graph = width - margin_first_text - margin_last_text;

      var svg = d3.select("#vis")
      .append("svg")
      .attr('width', width + margin.left + margin.right)
      .attr('height', height + margin.top + margin.bottom)
      .append('g')
      .attr('width', width + margin.left + margin.right)
      .attr('height', height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

      var xScale = d3.scale.linear().range([0, width_graph]);
      var colorScale = d3.scale.category10();
      var color_ref = "red";

      var x = d3.scale.linear()
      .domain([0, 100])
      .range([0, width])
      .clamp(true);

      var div_tooltip = d3.select('body').append('div').attr('class', 'tooltip').style('opacity', 0);

      var x0 = 0;

      data.forEach(function(d) {
        d.name = d.nom;
        d.value = +d.Impots;
        d.value0 = x0;
        x0 = x0 + d.value;

      });

      var sum_values = d3.sum(data, function(d){
        return d.value;
      });

      xScale.domain([0, sum_values]);

      var RefType = svg.append("g")
      .attr('class', 'type')
      .attr("transform", function(){return "translate(0 ,0)";});

      RefType
      .append('rect')
      .attr('height', 40)
      .attr("width", function(){return xScale(sum_values);})
      .attr('fill', color_ref)
      .attr("x", margin_first_text);

      RefType
      .append('text')
      .attr("class", "name_text")
      .attr("y", 25)
      .text("Situation de référence")
      .style("font-weight", "bold");

      RefType
      .append('text')
      .attr("class", "name_text")
      .attr("y", 25)
      .attr("x", margin_first_text + width_graph)
      .html(sum_values + " €  24,1%")
      .attr("fill", color_ref);

      RefType.select('rect')
      .on('mouseover', function() {
        var this_left_val = margin_first_text + width_graph - xScale(sum_values) + xScale(sum_values)/2;
        var this_top_val = margin.top + 50;
        div_tooltip.html('
 Référence
' + '
' + sum_values + ' euros
 ').style('left', this_left_val + 'px').style('top', this_top_val  + 'px').style('height', 50 + 'px').style('opacity', 0.9);
      })
      .on('mouseout', function(d) {
        div_tooltip.style('opacity', 0);
      });

      var Types_ = svg.selectAll('types')
      .data(data);

      var Types = Types_.enter()
      .append("g")
      .attr('class', 'type')
      .attr("transform", function(d, i){return "translate(0 ," + parseInt(i*43 + 50) + ")";});

      Types
      .append('rect')
      .attr('height', 40)
      .attr("width", function(d){return xScale(d.value);})
      .attr('fill', function(d){return colorScale(d.typologie);})
      .attr("x", function(d){return margin_first_text + width_graph - xScale(d.value0) - xScale(d.value);});

      Types
      .append('text')
      .attr("class", "name_text")
      .attr("y", 25)
      .attr("x", 250)
      .text(function(d){return d.Type_impact;})
      .attr("fill", function(d){return colorScale(d.typologie);})
      .style("font-size", 14);

      Types
      .append('text')
      .attr("class", "title_text")
      .attr("y", 25)
      .text(function(d){return d.title;})
      .style("font-weight", "bold");

      Types
      .append('text')
      .attr("class", "name_text")
      .attr("y", 25)
      .attr("x", margin_first_text + width_graph)
      .text(function(d){

        var minus_sign = "";
        if (d.typologie == "deduction"){
          minus_sign = "-";
        }

        var this_percentage = "";
        if (d.percentage){
          this_percentage = " " + d.percentage;
        }

        return minus_sign + d.value + " € " + this_percentage;
      })
      .attr("fill", function(d){
        return colorScale(d.typologie);
      });

      Types.select('rect')
      .on('mouseover', function(d, i) {

        var this_left_val = margin_first_text + width_graph - xScale(d.value0) - xScale(d.value)/2;
        var this_top_val = margin.top + i*43 + 50;
        var this_title = "";

        if (d.title){
          this_title  = d.title;
        }

        div_tooltip.html('
' + this_title + '
' + d.Type_impact + '
' + '
' + d.value + ' euros
 ').style('left', this_left_val + 'px').style('top', this_top_val  + 'px').style('height', 50 + 'px').style('opacity', 0.9);
      })
      .on('mouseout', function(d) {
        div_tooltip.style('opacity', 0);
      });
    }

    angular
    .module('codeimpot.results')
    .directive('barChart', ['d3Service', 'ResultsService', function (d3Service, ResultsService) {
      return {
        restrict: 'EA',
        scope: {},
        templateUrl: 'components/results/barchart.template.html',
        link: function(scope, element, attrs) {
          d3Service.d3().then(function (d3) {
            var data_results = ResultsService.get();
            var data = [{
              "Situation": "Situation de r\u00e9f\u00e9rence",
              "Montant net": 19254,
              "Impots": 6544,
              "Type_impact": "couple marié",
              "nom": "Mariage",
              "typologie": "deduction",
              "title":"Impacts liés au foyer fiscal"
            }, {
              "Situation": "Enfants",
              "Montant net": 12710,
              "Impots": 3015,
              "Type_impact": "deux enfants à charge",
              "nom": "enfants",
              "typologie": "deduction"
            }, {
              "Situation": "D\u00e9duction des frais professionnels",
              "Montant net": 9695,
              "Impots": 2400,
              "Type_impact": "d\u00e9duction des frais professionnels",
              "nom": "Frais pro",
              "typologie": "deduction",
              "title":"Impacts liés aux abattements"
            }, {
              "Situation": "Aux oeuvres reconnues d'utilit\u00e9 publique ou fiscalement assimil\u00e9es en mati\u00e8re de dons, aux oeuvres d'int\u00e9r\u00eat g\u00e9n\u00e9ral 7UF",
              "Montant net": 7295,
              "Impots": 1320,
              "Type_impact": "dons aux œuvres",
              "nom": "Dons",
              "typologie": "deduction",
              "title":"Impacts liés aux"
            }, {
              "Situation": "Mat\u00e9riaux d\u2019isolation thermique des parois vitr\u00e9es (fen\u00eatres, portes-fen\u00eatres\u2026)  7AM",
              "Montant net": 5975,
              "Impots": 2000,
              "Type_impact": "dépenses d'équipements pour les PH",
              "nom": "Isolation",
              "typologie": "deduction",
              "title":"réductions et crédits d’impôts"
            }, {
              "Situation": "Frais de garde des enfants de moins de 6 ans au 1\/1\/2015 7GA",
              "Montant net": 3975,
              "Impots": 2300,
              "Type_impact": "frais de garde d'enfants",
              "nom": "garde enfants",
              "typologie": "deduction"
            }, {
              "Situation": "Situation r\u00e9elle",
              "Montant net": 1675,
              "Impots": 1675,
              "nom": "A payer",
              "typologie": "reel",
              "title":"Situation réelle",
              "percentage":"3,0%"
            }];

            chart(d3, element, data);
          });
        }
      };
    }]);
  }());<|endoftext|>


<commit_before>// jscs:disable

app.controller('ViewHubCtrl', ViewHubCtrl);
ViewHubCtrl.$inject = ['$rootScope', '$scope', '$state', '$stateParams', '$timeout', '$q', '$controller', '$interval', 'hub', 'printer', 'sensor'];

function ViewHubCtrl($rootScope, $scope, $state, $stateParams, $timeout, $q, $controller, $interval, hub, printer, sensor) {
  var hubId = Number($stateParams.hubId);

  $scope.sensors = {};
  $scope.updateSensorModal = {};
  $scope.updateSensorModal.form = {};
  $scope.updateSensorModal.attributes = {};
  $scope.updateSensorModalVisible = false;
  $scope.addSensorModal = {};
  $scope.addSensorModal.form = {};
  $scope.addSensorModal.attributes = {};
  $scope.addSensorModalVisible = false;
  $scope.deleteSensorModal = {};
  $scope.deleteSensorModalVisible = false;
  $scope.showDeleteModal = false; // Set to true to show the delete confirmation modal
  $scope.printersCurrentPage = 1;
  $scope.printersItemsPerPage = 2;

  $controller('AlertCtrl', { $scope: $scope });
  $controller('AlertCtrl', { $scope: $scope.updateSensorModal});
  $controller('AlertCtrl', { $scope: $scope.addSensorModal});

  /*********************************************************
   *
   * FUNCTIONS
   *
   * /

  /**
   * Modal visibility toggling
   */
  $scope.showSensorModal = function() {
    $scope.updateSensorModalVisible = true;
  };

  $scope.hideSensorModal = function() {
    $scope.updateSensorModalVisible = false;
    $scope.updateSensorModal.alerts = [];
    $scope.updateSensorModal.form.$setPristine();
  };

  $scope.showAddSensorModal = function() {
    $scope.addSensorModalVisible = true;
    $scope.addSensorModal.alerts = [];
    $scope.addSensorModal.addAlert('warning', 'All fields are required unless otherwise stated.');
  };

  $scope.hideAddSensorModal = function() {
    $scope.addSensorModalVisible = false;
    $scope.addSensorModal.alerts = [];
    $scope.addSensorModal.attributes = {};
    $scope.addSensorModal.attributes.category = 'Specify the type of sensor';
    $scope.addSensorModal.attributes.node_id = 'Specify the ID of the node that the sensor is connected to';
    $scope.addSensorModal.attributes.pin = 'Specify which GPIO pin the sensor is connected to';
  };
  $scope.showDeleteSensorModal = function() {
    $scope.deleteSensorModalVisible = true;
  };

  $scope.hideDeleteSensorModal = function() {
    $scope.deleteSensorModalVisible = false;
  };

  /**
   * Add a sensor
   */
  $scope.addSensor = function(attributes) {
    // Check whether form has not been filled out
    if ($scope.addSensorModal.form.$pristine) {
      $scope.addSensorModal.addAlert('warning', 'Please fill out the form below before submitting.');
      return;
    }

    // Check whether any validation errors are present on the form
    if (!$scope.addSensorModal.form.$valid) {
      $scope.addSensorModal.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    hub.addSensor($stateParams.hubId, attributes)
      .success(function(response) {
        $scope.hideAddSensorModal();
        $scope.getSensors();
      })
      .error(function(response) {
        $scope.addSensorModal.addAlert('danger', 'Unable to add sensor. Please double check that the specified name is not already in use by another sensor and then try again.');
        console.log('Unable to add sensor to hub.');
        console.log(response);
      });
  };

  /**
   * Update a sensor
   */
  $scope.updateSensor = function(sensorId, attributes) {
    // Check whether form has not been filled out
    if ($scope.updateSensorModal.form.$pristine) {
      $scope.updateSensorModal.addAlert('warning', 'Please fill out the form below before submitting.');
      return;
    }

    // Check whether any validation errors are present on the form
    if (!$scope.updateSensorModal.form.$valid) {
      $scope.updateSensorModal.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    hub.updateSensor(sensorId, attributes)
      .success(function(response) {
        $scope.updateSensorModal.addAlert('success', 'The sensor has been updated successfully.');
        angular.forEach(attributes, function(attribute, key){
            if(attribute) {
              $scope.updateSensorModal.sensor[key] = attribute;
            }
        });
        $scope.updateSensorModal.attributes = {};
        $scope.updateSensorModal.form.$setPristine();
        $scope.getSensors();
      })
      .error(function(response) {
          $scope.updateSensorModal.addAlert('danger', 'Unable to update sensor. Please double check that the specified name is not already in use by another sensor, and that the high threshold is greater than the low threshold.');
          console.log(response);
      });
  };

  /**
   * Delete a sensor
   */
  $scope.deleteSensor = function(sensorId) {
    hub.deleteSensor(sensorId)
      .then(function(response) {
        $scope.hideDeleteSensorModal();
        $scope.getSensors();
      });
  };

  /**
   * ToHubsPage
   * Waits 500 milliseconds for the animation to fade
   * Sets the state to the main hubs page
   * @param {boolean} reload
   *  if reload = true the ListHubs controller will refresh
   * @returns {undefined}
   */
  $scope.toHubsPage = function(reload) {
    $timeout(function() {
      $state.go('dashboard.listHubs',{},{reload: reload});
    },500);
  };

  /**
   * UpdateHub
   * Updates a hub in the DB with the hub object gathered from the form
   * Performs multiple checks on the form, check if there are no warnings
   *  checks if the form is empty or not
   *  Checks if the user is an admin, incase they edit some htlm and get the form to show
   * If all checks clear, then it updates the hub, if the entity is invalid it will add the alert to tell the user
   *
   * @param _hubId
   * @param _hub
   * @returns {undefined}
   */
  $scope.updateHub = function(_hubId, _hub) {
    if (!$scope.updateHubForm.$valid) {
      $scope.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    // Check whether form has not been filled out
    if ($scope.updateHubForm.$pristine) {
      $scope.addAlert('warning', 'Please fill out the form below before saving.');
      return;
    }

    // Remove empty fields from profile to prevent errors
    Object.keys($scope.hub).forEach(function(key) {
      if ($scope.hub[key] === '') {
        delete $scope.hub[key];
      }
    });

    if ($scope.user.isAdmin()) {
      updateHubPromise = hub.updateHub(_hubId, _hub);

      updateHubPromise.then(function(data) {
        if (typeof (data) === 'object') {
          $scope.resetForm();
          $scope.addAlert('success', 'Hub updated successfully.');
          $scope.hub = data;
          $rootScope.$broadcast('hub:updated');
        } else {
          $scope.addAlert('danger', 'Sorry but this hub could not be modified.  Some values are unprocessable.');
        }
      });
      return;
    }
  };

  /**
   * ResetForm
   * clears the $scope.hub and sets the form to pristine(cleared)
   *
   * @returns {undefined}
   */
  $scope.resetForm = function() {
    $scope.hubDetails = {};
    $scope.updateHubForm.$setPristine();
  };

  /**
   * DeleteHub
   * calls deleteHub from the service
   * deleteHub in the service removes the hub by id
   * @param _id
   * @returns {}
   */
  $scope.deleteHub = function(_id) {
    $scope.showDeleteModal = false;
    if ($scope.user._user.admin === true) {
      hub.deleteHub(_id);
      this.toHubsPage(true);
      console.log($scope.showDeleteModal);
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * DeleteModal
   * Called by the delete button
   * makes the deleteModal visible
   *
   * @returns {undefined}
   */
  $scope.deleteModal = function() {
    console.log('DeleteModal firing');
    $scope.showDeleteModal = !$scope.showDeleteModal;
  };

  /**
   * GenerateApiKey
   * calls generateApiKey from the service
   * generateApiKey in the service generates a new hub API key
   * @param _id
   * @returns a new hub api key
   */
  $scope.generateApiKey = function(_id) {
    if ($scope.user._user.admin === true) {
      hub.generateApiKey(_id).then(function(resp) {
        console.log(resp);
        $scope.apiKey = resp.api_key;
      });
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * ViewPrinter
   * Sets the state to that of the printer with the associated _printerId
   *
   * @param _printerId
   * @returns {undefined}
   */
  $scope.viewPrinter = function(_printerId) {
    $state.go('dashboard.printer', {hubId: hubId, printerId: _printerId});
  };

  $scope.getSensors = function() {
    hub.getSensors(hubId)
      .success(function(response) {
        $scope.sensors = response;
      })
      .error(function(response) {
        console.log('Unable to retrieve a list of sensors.');
        console.log(response);
      });
  };

  $scope.getPrinters = function() {
    hub.getPrinters(hubId)
      .then(function(_printers) {
        $scope.printers = _printers;
        $scope.printersTotalItems = _printers.length;
      });
  };

  $scope.getHub = function() {
    hub.getHub(hubId)
    .then(function(_hub) {
      $scope.hub = _hub;
    });
  };

  $scope.refresh = function() {
    $scope.getPrinters();
    $scope.getSensors();
    $scope.getHub();
  };

  $scope.refresh();

  var timerPromise;
  $scope.timer = function() {
    timerPromise = $interval($scope.refresh, 2000);
  };

  $scope.timer();

  $scope.$on('$destroy',function(){
      if(timerPromise) {
          $interval.cancel(timerPromise);
      }
  });

}
<commit_msg>Tweak hub save error message<commit_after>// jscs:disable

app.controller('ViewHubCtrl', ViewHubCtrl);
ViewHubCtrl.$inject = ['$rootScope', '$scope', '$state', '$stateParams', '$timeout', '$q', '$controller', '$interval', 'hub', 'printer', 'sensor'];

function ViewHubCtrl($rootScope, $scope, $state, $stateParams, $timeout, $q, $controller, $interval, hub, printer, sensor) {
  var hubId = Number($stateParams.hubId);

  $scope.sensors = {};
  $scope.updateSensorModal = {};
  $scope.updateSensorModal.form = {};
  $scope.updateSensorModal.attributes = {};
  $scope.updateSensorModalVisible = false;
  $scope.addSensorModal = {};
  $scope.addSensorModal.form = {};
  $scope.addSensorModal.attributes = {};
  $scope.addSensorModalVisible = false;
  $scope.deleteSensorModal = {};
  $scope.deleteSensorModalVisible = false;
  $scope.showDeleteModal = false; // Set to true to show the delete confirmation modal
  $scope.printersCurrentPage = 1;
  $scope.printersItemsPerPage = 2;

  $controller('AlertCtrl', { $scope: $scope });
  $controller('AlertCtrl', { $scope: $scope.updateSensorModal});
  $controller('AlertCtrl', { $scope: $scope.addSensorModal});

  /*********************************************************
   *
   * FUNCTIONS
   *
   * /

  /**
   * Modal visibility toggling
   */
  $scope.showSensorModal = function() {
    $scope.updateSensorModalVisible = true;
  };

  $scope.hideSensorModal = function() {
    $scope.updateSensorModalVisible = false;
    $scope.updateSensorModal.alerts = [];
    $scope.updateSensorModal.form.$setPristine();
  };

  $scope.showAddSensorModal = function() {
    $scope.addSensorModalVisible = true;
    $scope.addSensorModal.alerts = [];
    $scope.addSensorModal.addAlert('warning', 'All fields are required unless otherwise stated.');
  };

  $scope.hideAddSensorModal = function() {
    $scope.addSensorModalVisible = false;
    $scope.addSensorModal.alerts = [];
    $scope.addSensorModal.attributes = {};
    $scope.addSensorModal.attributes.category = 'Specify the type of sensor';
    $scope.addSensorModal.attributes.node_id = 'Specify the ID of the node that the sensor is connected to';
    $scope.addSensorModal.attributes.pin = 'Specify which GPIO pin the sensor is connected to';
  };
  $scope.showDeleteSensorModal = function() {
    $scope.deleteSensorModalVisible = true;
  };

  $scope.hideDeleteSensorModal = function() {
    $scope.deleteSensorModalVisible = false;
  };

  /**
   * Add a sensor
   */
  $scope.addSensor = function(attributes) {
    // Check whether form has not been filled out
    if ($scope.addSensorModal.form.$pristine) {
      $scope.addSensorModal.addAlert('warning', 'Please fill out the form below before submitting.');
      return;
    }

    // Check whether any validation errors are present on the form
    if (!$scope.addSensorModal.form.$valid) {
      $scope.addSensorModal.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    hub.addSensor($stateParams.hubId, attributes)
      .success(function(response) {
        $scope.hideAddSensorModal();
        $scope.getSensors();
      })
      .error(function(response) {
        $scope.addSensorModal.addAlert('danger', 'Unable to add sensor. Please double check that the specified name is not already in use by another sensor and then try again.');
        console.log('Unable to add sensor to hub.');
        console.log(response);
      });
  };

  /**
   * Update a sensor
   */
  $scope.updateSensor = function(sensorId, attributes) {
    // Check whether form has not been filled out
    if ($scope.updateSensorModal.form.$pristine) {
      $scope.updateSensorModal.addAlert('warning', 'Please fill out the form below before submitting.');
      return;
    }

    // Check whether any validation errors are present on the form
    if (!$scope.updateSensorModal.form.$valid) {
      $scope.updateSensorModal.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    hub.updateSensor(sensorId, attributes)
      .success(function(response) {
        $scope.updateSensorModal.addAlert('success', 'The sensor has been updated successfully.');
        angular.forEach(attributes, function(attribute, key){
            if(attribute) {
              $scope.updateSensorModal.sensor[key] = attribute;
            }
        });
        $scope.updateSensorModal.attributes = {};
        $scope.updateSensorModal.form.$setPristine();
        $scope.getSensors();
      })
      .error(function(response) {
          $scope.updateSensorModal.addAlert('danger', 'Unable to update sensor. Please double check that the specified name is not already in use by another sensor, and that the high threshold is greater than the low threshold.');
          console.log(response);
      });
  };

  /**
   * Delete a sensor
   */
  $scope.deleteSensor = function(sensorId) {
    hub.deleteSensor(sensorId)
      .then(function(response) {
        $scope.hideDeleteSensorModal();
        $scope.getSensors();
      });
  };

  /**
   * ToHubsPage
   * Waits 500 milliseconds for the animation to fade
   * Sets the state to the main hubs page
   * @param {boolean} reload
   *  if reload = true the ListHubs controller will refresh
   * @returns {undefined}
   */
  $scope.toHubsPage = function(reload) {
    $timeout(function() {
      $state.go('dashboard.listHubs',{},{reload: reload});
    },500);
  };

  /**
   * UpdateHub
   * Updates a hub in the DB with the hub object gathered from the form
   * Performs multiple checks on the form, check if there are no warnings
   *  checks if the form is empty or not
   *  Checks if the user is an admin, incase they edit some htlm and get the form to show
   * If all checks clear, then it updates the hub, if the entity is invalid it will add the alert to tell the user
   *
   * @param _hubId
   * @param _hub
   * @returns {undefined}
   */
  $scope.updateHub = function(_hubId, _hub) {
    if (!$scope.updateHubForm.$valid) {
      $scope.addAlert('danger', 'Please correct the errors below and try submitting the form again.');
      return;
    }

    // Check whether form has not been filled out
    if ($scope.updateHubForm.$pristine) {
      $scope.addAlert('warning', 'Please fill out the form below before saving.');
      return;
    }

    // Remove empty fields from profile to prevent errors
    Object.keys($scope.hub).forEach(function(key) {
      if ($scope.hub[key] === '') {
        delete $scope.hub[key];
      }
    });

    if ($scope.user.isAdmin()) {
      updateHubPromise = hub.updateHub(_hubId, _hub);

      updateHubPromise.then(function(data) {
        if (typeof (data) === 'object') {
          $scope.resetForm();
          $scope.addAlert('success', 'Hub updated successfully.');
          $scope.hub = data;
          $rootScope.$broadcast('hub:updated');
        } else {
          $scope.addAlert('danger', 'Unable to modify HUB. Please double check that the specified name is not already taken and then try again.');
        }
      });
      return;
    }
  };

  /**
   * ResetForm
   * clears the $scope.hub and sets the form to pristine(cleared)
   *
   * @returns {undefined}
   */
  $scope.resetForm = function() {
    $scope.hubDetails = {};
    $scope.updateHubForm.$setPristine();
  };

  /**
   * DeleteHub
   * calls deleteHub from the service
   * deleteHub in the service removes the hub by id
   * @param _id
   * @returns {}
   */
  $scope.deleteHub = function(_id) {
    $scope.showDeleteModal = false;
    if ($scope.user._user.admin === true) {
      hub.deleteHub(_id);
      this.toHubsPage(true);
      console.log($scope.showDeleteModal);
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * DeleteModal
   * Called by the delete button
   * makes the deleteModal visible
   *
   * @returns {undefined}
   */
  $scope.deleteModal = function() {
    console.log('DeleteModal firing');
    $scope.showDeleteModal = !$scope.showDeleteModal;
  };

  /**
   * GenerateApiKey
   * calls generateApiKey from the service
   * generateApiKey in the service generates a new hub API key
   * @param _id
   * @returns a new hub api key
   */
  $scope.generateApiKey = function(_id) {
    if ($scope.user._user.admin === true) {
      hub.generateApiKey(_id).then(function(resp) {
        console.log(resp);
        $scope.apiKey = resp.api_key;
      });
    } else {
      console.log('Permission Denied');
    }
  };

  /**
   * ViewPrinter
   * Sets the state to that of the printer with the associated _printerId
   *
   * @param _printerId
   * @returns {undefined}
   */
  $scope.viewPrinter = function(_printerId) {
    $state.go('dashboard.printer', {hubId: hubId, printerId: _printerId});
  };

  $scope.getSensors = function() {
    hub.getSensors(hubId)
      .success(function(response) {
        $scope.sensors = response;
      })
      .error(function(response) {
        console.log('Unable to retrieve a list of sensors.');
        console.log(response);
      });
  };

  $scope.getPrinters = function() {
    hub.getPrinters(hubId)
      .then(function(_printers) {
        $scope.printers = _printers;
        $scope.printersTotalItems = _printers.length;
      });
  };

  $scope.getHub = function() {
    hub.getHub(hubId)
    .then(function(_hub) {
      $scope.hub = _hub;
    });
  };

  $scope.refresh = function() {
    $scope.getPrinters();
    $scope.getSensors();
    $scope.getHub();
  };

  $scope.refresh();

  var timerPromise;
  $scope.timer = function() {
    timerPromise = $interval($scope.refresh, 2000);
  };

  $scope.timer();

  $scope.$on('$destroy',function(){
      if(timerPromise) {
          $interval.cancel(timerPromise);
      }
  });

}
<|endoftext|>


<commit_before>/* eslint-disable jsx-a11y/label-has-associated-control */
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import Form from 'react-bootstrap/lib/Form';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import injectT from '../../../i18n/injectT';
import FormTypes from '../../../constants/FormTypes';

export function validate() {
  const errors = {};
  return errors;
}

class UnconnectedInternalReservationForm extends Component {
  state = {
    internalReservationDefaultChecked: true
  }

  componentDidMount() {
    this.props.dispatch(this.internalReservationFormInitialValue());
  }

  internalReservationFormInitialValue() {
    return {
      type: '@@redux-form/CHANGE',
      meta: {
        form: 'RESERVATION',
        field: 'internalReservation',
        touch: false,
        persistentSubmitErrors: false
      },
      payload: this.state.internalReservationDefaultChecked
    };
  }

  render() {
    const { t } = this.props;
    /**
     * TODO Add FI/SV/EN translations!
     * {t('foo.bar.biz')}
     */
    const premiseStaffOnly = 'Premise staff only';
    const internalReservation = 'Internal reservation';
    const internalReservationDescription = `The Department's own event.
    Uncheck this box to make an external reservation on behalf of the user.`;
    const markAsClosed = 'Mark as closed';
    const markAsClosedDescription = 'Check if you are closing the resource by reserving.';
    const comment = 'Comment';
    return (

        <Form className="reservation-form" horizontal noValidate>

{premiseStaffOnly}

          <Row>
            <Col md={1}>
              <Field
                checked={this.state.internalReservationDefaultChecked}
                component="input"
                name="internalReservation"
                onChange={() => this.setState(
                  prevState => ({ internalReservationDefaultChecked: !prevState.internalReservationDefaultChecked })
                )}
                type="checkbox"
              />
            </Col>
            <Col md={11}>

                {internalReservation}

                {internalReservationDescription}

            </Col>
          </Row>
          <Row>
            <Col md={1}>
              <Field
                component="input"
                name="markAsClosed"
                type="checkbox"
              />
            </Col>
            <Col md={11}>

                {markAsClosed}

                {markAsClosedDescription}

            </Col>
          </Row>
          <Row>
            <Col md={12}>

                  {comment}
                  <Field
                    component="textarea"
                    name="internalReservationComments"
                    rows={5}
                  />

            </Col>
          </Row>
        </Form>

    );
  }
}

connect()(UnconnectedInternalReservationForm);

UnconnectedInternalReservationForm.propTypes = {
  t: PropTypes.func.isRequired,
  dispatch: PropTypes.func.isRequired
};
UnconnectedInternalReservationForm = injectT(UnconnectedInternalReservationForm);  // eslint-disable-line

export { UnconnectedInternalReservationForm };
export default injectT(reduxForm({
  form: FormTypes.RESERVATION,
  validate
})(UnconnectedInternalReservationForm));
<commit_msg>Added validate functionality.<commit_after>/* eslint-disable jsx-a11y/label-has-associated-control */
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import Form from 'react-bootstrap/lib/Form';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import injectT from '../../../i18n/injectT';
import FormTypes from '../../../constants/FormTypes';

const maxLengths = {
  internalReservationComments: 1
};

export function validate(values) {
  console.log('--- validate values', values);
  const errors = {};
  if (!values.internalReservation) {
    errors.internalReservation = 'Required';
  }
  if (values.internalReservationComments) {
    if (values.internalReservationComments.length > maxLengths.internalReservationComments) {
      errors.internalReservationComments = `Max length ${maxLengths.internalReservationComments}`;
    }
  }
  console.log('--- validate errors', errors);
  return errors;
}

class UnconnectedInternalReservationForm extends Component {
  state = {
    internalReservationDefaultChecked: true
  }

  componentDidMount() {
    this.props.dispatch(this.internalReservationFormInitialValue());
  }

  internalReservationFormInitialValue() {
    return {
      type: '@@redux-form/CHANGE',
      meta: {
        form: 'RESERVATION',
        field: 'internalReservation',
        touch: false,
        persistentSubmitErrors: false
      },
      payload: this.state.internalReservationDefaultChecked
    };
  }

  render() {
    console.log('--- render this.props', this.props);
    const { t } = this.props;
    /**
     * TODO Add FI/SV/EN translations!
     * {t('foo.bar.biz')}
     */
    const premiseStaffOnly = 'Premise staff only';
    const internalReservation = 'Internal reservation';
    const internalReservationDescription = `The Department's own event.
    Uncheck this box to make an external reservation on behalf of the user.`;
    const markAsClosed = 'Mark as closed';
    const markAsClosedDescription = 'Check if you are closing the resource by reserving.';
    const comment = 'Comment';
    return (

        <Form className="reservation-form" horizontal noValidate>

{premiseStaffOnly}

          <Row>
            <Col md={1}>
              <Field
                checked={this.state.internalReservationDefaultChecked}
                component="input"
                name="internalReservation"
                onChange={() => this.setState(
                  prevState => ({ internalReservationDefaultChecked: !prevState.internalReservationDefaultChecked })
                )}
                type="checkbox"
              />
            </Col>
            <Col md={11}>

                {internalReservation}

                {internalReservationDescription}

            </Col>
          </Row>
          <Row>
            <Col md={1}>
              <Field
                component="input"
                name="markAsClosed"
                type="checkbox"
              />
            </Col>
            <Col md={11}>

                {markAsClosed}

                {markAsClosedDescription}

            </Col>
          </Row>
          <Row>
            <Col md={12}>

                  {comment}
                  <Field
                    component="textarea"
                    name="internalReservationComments"
                    rows={5}
                  />

            </Col>
          </Row>
        </Form>

    );
  }
}

connect()(UnconnectedInternalReservationForm);

UnconnectedInternalReservationForm.propTypes = {
  t: PropTypes.func.isRequired,
  dispatch: PropTypes.func.isRequired
};
UnconnectedInternalReservationForm = injectT(UnconnectedInternalReservationForm);  // eslint-disable-line

export { UnconnectedInternalReservationForm };
export default injectT(reduxForm({
  form: FormTypes.RESERVATION,
  validate
})(UnconnectedInternalReservationForm));
<|endoftext|>


<commit_before>$(window).ready(function(){

    //main menu flyouts or mbmenu releacment
    //$( '#MenuView .parent, #HeaderLinksView .parent, #ShortcutsMenu .parent' ).hover(
    $( '.nav > .parent' ).hover(
        function(){
            if ( $(this).find('ul').length > 0 ){
                $(this).find('ul').stop(true, true).delay(0).fadeIn(100);
            }
        },
        function(){
            if ( $(this).find('ul').length > 0 ){
                $(this).find('ul').stop(true, true).fadeOut(250);
            }
        }
    );

    //Main nav hover

	 $('#MenuView a').hover(
        function(){
        	console.log($(this));
            $('span:first-child', this).stop(true, true).fadeTo( 500, 1 );
            //$('span', this).stop(true, true).animate({ color : '#555', color: '#fff' }, 250);
        },
        function(){
        	if ( $(this).parent().hasClass('active') === false ){
            	$('span:first-child',this).stop(true, true).fadeTo( 500, 0 );
            	//$('span', this).stop(true, true).animate({ color : '#fff', color: '#555' }, 250);
        	}
        }
    );

    /*Resizes the app to fill the browser's window case smaller'*/
    var viewportHeight = $(window).height();
    var wrapperDivHeight = $('body > div').outerHeight(true)
    var appChromeHeight = 0;
    var bufferHeight = 0;
    var recentlyViewedHeight = 0;

    if ( $('#LoginPageView').length > 0 ) {
        appChromeHeight = 38 + $('#FooterView').outerHeight(true);
        if ( wrapperDivHeight < viewportHeight  ){
            bufferHeight = viewportHeight - appChromeHeight;
            $('#LoginView').height(  bufferHeight   );
        }
    } else {
        recentlyViewedHeight = $('#RecentlyViewedView').outerHeight(true);
        appChromeHeight = recentlyViewedHeight + $('#MenuView').outerHeight(true) + $('#HeaderView').outerHeight(true) + $('#FooterView').outerHeight(true);
        if ( wrapperDivHeight < viewportHeight  ){
            bufferHeight = viewportHeight - appChromeHeight;
            $('#RecentlyViewedView').height( $('#RecentlyViewedView').height() + bufferHeight   );
        }
    }
    /*Label overlays input, address fields*/
    $(".overlay-label-field input").live('focus', function(){
        $(this).prev().fadeOut(100);
    });

    $(".overlay-label-field > input").live('blur', function(){
        if($(this).val() == "") {
            $(this).prev().fadeIn(250);
        }
    });
    $(".overlay-label-field > input").each( function(){
        if($(this).val() == "") {
            $('label', $(this)).fadeIn(250);
        }
    });

    /*Dropdowns - Dropkick - also see dropDownInteractions.js */
    $('html').click(function(e) {
        $.each($('select:not(.ignore-style)'), function(index, value) {
            $(value).dropkick('close');
        });
    });

    /*Checkboxes
     from: http://webdesign.maratz.com/lab/fancy-checkboxes-and-radio-buttons/jquery.html
     * */

    $('input:checkbox').each(function(){
        log( $(this).is(':checked')   );
        if ( $( this ).is(':checked') ) {
            $(this).parent().addClass('c_on');
        }
        $(this).bind( 'change', checkMyState );
    });

    function checkMyState(event){
        if (  $(event.target).is('input')  ){
            if (  $(event.target).is(':checked')  ){
                $(this).parent().addClass('c_on');
            } else {
                $(this).parent().removeClass('c_on');
            }
        }
    }

    function setupCheckboxes( $context ) {
        if ( $('input:checkbox', $context ).length ) {
            $('input:checkbox', $context ).each(function(){
                $(this).parent().removeClass('c_on');
            });
            $('label input:checked', $context ).each(function(){
                $(this).parent('label').addClass('c_on');
            });
        }

        $('label', $context[0] ).
            live( 'click', { $inputContext:$(this).content  },
                function( event ){
                    if ( $('input:checkbox', event.data.$inputContext ).length ) {
                        $('input:checkbox', event.data.$inputContext ).each(function(){
                            $(this).parent().removeClass('c_on');
                        });
                        $('label input:checked', event.data.$inputContext ).each(function(){
                            $(this).parent('label').addClass('c_on');
                        });
                    }
            });
    }

    //we're doing that because the multiselect widget isn't generated yet..
    window.setTimeout(
        function setCheckboxes(){
            setupCheckboxes( $('#search-form') );
            setupCheckboxes( $('#app-search') );
        },
    1000 );

});

// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function f(){ log.history = log.history || []; log.history.push(arguments); if(this.console) { var args = arguments, newarr; args.callee = args.callee.caller; newarr = [].slice.call(args); if (typeof console.log === 'object') log.apply.call(console.log, console, newarr); else console.log.apply(console, newarr);}};

// make it safe to use console.log always
(function(a){function b(){}for(var c="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),d;!!(d=c.pop());){a[d]=a[d]||b;}})
(function(){try{console.log();return window.console;}catch(a){return (window.console={});}}());<commit_msg>fix to animation of main nav<commit_after>$(window).ready(function(){

    //main menu flyouts or mbmenu releacment
    //$( '#MenuView .parent, #HeaderLinksView .parent, #ShortcutsMenu .parent' ).hover(
    $( '.nav > .parent' ).hover(
        function(){
            if ( $(this).find('ul').length > 0 ){
                $(this).find('ul').stop(true, true).delay(0).fadeIn(100);
            }
        },
        function(){
            if ( $(this).find('ul').length > 0 ){
                $(this).find('ul').stop(true, true).fadeOut(250);
            }
        }
    );

    //Main nav hover

	 $('#MenuView a').hover(
        function(){
        	console.log($(this));
            $('span:first-child', this).stop(true, true).fadeTo( 500, 1 );
            $('span:last-child', this).stop(true, true).animate({ color : '#555', color: '#fff' }, 250);
        },
        function(){
        	if ( $(this).parent().hasClass('active') === false ){
            	$('span:first-child',this).stop(true, true).fadeTo( 500, 0 );
            	$('span:last-child', this).stop(true, true).animate({ color : '#fff', color: '#555' }, 250);
        	}
        }
    );

    /*Resizes the app to fill the browser's window case smaller'*/
    var viewportHeight = $(window).height();
    var wrapperDivHeight = $('body > div').outerHeight(true)
    var appChromeHeight = 0;
    var bufferHeight = 0;
    var recentlyViewedHeight = 0;

    if ( $('#LoginPageView').length > 0 ) {
        appChromeHeight = 38 + $('#FooterView').outerHeight(true);
        if ( wrapperDivHeight < viewportHeight  ){
            bufferHeight = viewportHeight - appChromeHeight;
            $('#LoginView').height(  bufferHeight   );
        }
    } else {
        recentlyViewedHeight = $('#RecentlyViewedView').outerHeight(true);
        appChromeHeight = recentlyViewedHeight + $('#MenuView').outerHeight(true) + $('#HeaderView').outerHeight(true) + $('#FooterView').outerHeight(true);
        if ( wrapperDivHeight < viewportHeight  ){
            bufferHeight = viewportHeight - appChromeHeight;
            $('#RecentlyViewedView').height( $('#RecentlyViewedView').height() + bufferHeight   );
        }
    }
    /*Label overlays input, address fields*/
    $(".overlay-label-field input").live('focus', function(){
        $(this).prev().fadeOut(100);
    });

    $(".overlay-label-field > input").live('blur', function(){
        if($(this).val() == "") {
            $(this).prev().fadeIn(250);
        }
    });
    $(".overlay-label-field > input").each( function(){
        if($(this).val() == "") {
            $('label', $(this)).fadeIn(250);
        }
    });

    /*Dropdowns - Dropkick - also see dropDownInteractions.js */
    $('html').click(function(e) {
        $.each($('select:not(.ignore-style)'), function(index, value) {
            $(value).dropkick('close');
        });
    });

    /*Checkboxes
     from: http://webdesign.maratz.com/lab/fancy-checkboxes-and-radio-buttons/jquery.html
     * */

    $('input:checkbox').each(function(){
        log( $(this).is(':checked')   );
        if ( $( this ).is(':checked') ) {
            $(this).parent().addClass('c_on');
        }
        $(this).bind( 'change', checkMyState );
    });

    function checkMyState(event){
        if (  $(event.target).is('input')  ){
            if (  $(event.target).is(':checked')  ){
                $(this).parent().addClass('c_on');
            } else {
                $(this).parent().removeClass('c_on');
            }
        }
    }

    function setupCheckboxes( $context ) {
        if ( $('input:checkbox', $context ).length ) {
            $('input:checkbox', $context ).each(function(){
                $(this).parent().removeClass('c_on');
            });
            $('label input:checked', $context ).each(function(){
                $(this).parent('label').addClass('c_on');
            });
        }

        $('label', $context[0] ).
            live( 'click', { $inputContext:$(this).content  },
                function( event ){
                    if ( $('input:checkbox', event.data.$inputContext ).length ) {
                        $('input:checkbox', event.data.$inputContext ).each(function(){
                            $(this).parent().removeClass('c_on');
                        });
                        $('label input:checked', event.data.$inputContext ).each(function(){
                            $(this).parent('label').addClass('c_on');
                        });
                    }
            });
    }

    //we're doing that because the multiselect widget isn't generated yet..
    window.setTimeout(
        function setCheckboxes(){
            setupCheckboxes( $('#search-form') );
            setupCheckboxes( $('#app-search') );
        },
    1000 );

});

// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function f(){ log.history = log.history || []; log.history.push(arguments); if(this.console) { var args = arguments, newarr; args.callee = args.callee.caller; newarr = [].slice.call(args); if (typeof console.log === 'object') log.apply.call(console.log, console, newarr); else console.log.apply(console, newarr);}};

// make it safe to use console.log always
(function(a){function b(){}for(var c="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),d;!!(d=c.pop());){a[d]=a[d]||b;}})
(function(){try{console.log();return window.console;}catch(a){return (window.console={});}}());<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';
import { injectIntl } from 'react-intl';
import Markdown from 'react-remarkable';
import ContentBlock from 'components/ContentBlock';
import LanguageThemeProvider from 'components/LanguageThemeProvider';
import {ContentContainer} from 'components/ToolPage/Main';
import { injectStaticText } from 'containers/TranslatableStaticText';
import staticText from '../staticText';

const OriginsContent = styled(ContentBlock)`

`;

function Origins(props) {
  const { locale } = props.intl;
  const { buildMessage } = props.translatable;

  const originsText = buildMessage(staticText.origins);

  return (
    <ContentContainer>
      <LanguageThemeProvider>
        <OriginsContent>
          <Markdown source={`**${originsText}:** *${props.origins}*`}/>
        </OriginsContent>
      </LanguageThemeProvider>
    </ContentContainer>
  )
}

export default injectStaticText(injectIntl(Origins));
<commit_msg>Fixes https://3.basecamp.com/3712455/buckets/3534072/todos/649791315<commit_after>import React from 'react';
import styled from 'styled-components';
import { injectIntl } from 'react-intl';
import Markdown from 'react-remarkable';
import ContentBlock from 'components/ContentBlock';
import LanguageThemeProvider from 'components/LanguageThemeProvider';
import {ContentContainer} from 'components/ToolPage/Main';
import { injectStaticText } from 'containers/TranslatableStaticText';
import staticText from '../staticText';

const OriginsContent = styled(ContentBlock)`

`;

function Origins(props) {
  const { locale } = props.intl;
  const { buildMessage } = props.translatable;

  const originsText = buildMessage(staticText.origins);

  console.log("originsText :: ", originsText)
  if (props.origins === undefined || !props.origins) return null;

  return (
    <ContentContainer>
      <LanguageThemeProvider>
        <OriginsContent>
          <Markdown source={`**${originsText}:** *${props.origins}*`}/>
        </OriginsContent>
      </LanguageThemeProvider>
    </ContentContainer>
  )
}

export default injectStaticText(injectIntl(Origins));
<|endoftext|>


<commit_before>/*eslint camelcase: 0*/
(function(angular) {
  "use strict";

  angular.module('ps.widgets')
    .controller('bookmarkTreeCtrl', bookmarkTreeCtrl)
    .directive('psBrowserBookmarkTree', browserBookmarkTreeDirective);

  function bookmarkTreeCtrl($window, bookmarkTreeService, layoutService) {
    var vm = this;
    vm.getTreeData = getTreeData;
    vm.getTreeConfig = getTreeConfig;
    vm.searchTree = searchTree;
    vm.resetSearch = resetSearch;

    vm.mouseDownCB = mouseDownCB;
    vm.clickCB = clickCB;

    vm.treeEvents = {
      "ready": readyCB,
      "activate_node": activateNodeCB,
      "open_node": openNodeCB,
      "close_node": closeNodeCB,
    };
    //Intialize
    vm.treeData = [];
    vm.treeConfig = {
      version: 1,
    };
    vm.searchString = '';
    activate();

    function activate() {
      if (layoutService.isActive('bookmarkTree')) {
        vm.getTreeData();
        vm.treeConfig = getTreeConfig();
      }
      layoutService.setOnTabClick('bookmarkTree', getTreeData);
    }

    function getTreeData() {
      bookmarkTreeService.getTreeData()
        .then(function(treeData) {
          angular.copy(treeData, vm.treeData);
          vm.treeConfig.version++;
        });
    }

    function getTreeConfig() {
      return bookmarkTreeService.getTreeConfig();
    }

    function searchTree() {
      vm.treeInstance.jstree().search(vm.searchString);
    }

    function resetSearch() {
      vm.searchString = '';
      vm.treeInstance.jstree().clear_search();
    }

    function readyCB() {
      vm.treeInstance.jstree(true).deselect_all();
    }

    function activateNodeCB(e, data) {
      vm.treeInstance.jstree().deselect_node(data.node);
      if (data.node.type !== 'link') {
        if (vm.treeInstance.jstree().is_closed(data.node)) {
          vm.treeInstance.jstree().open_node(data.node);
        } else {
          vm.treeInstance.jstree().close_node(data.node);
        }
      }
    }

    function openNodeCB(e, data) {
      vm.treeInstance.jstree().set_icon(data.node, 'open folder icon');
    }

    function closeNodeCB(e, data) {
      vm.treeInstance.jstree().set_icon(data.node, 'folder icon');
    }

    function mouseDownCB(e) {
      var node = {};
      node.id = e.target.parentNode.id;
      node = vm.treeInstance.jstree().get_node(node.id);
      if (node.type === 'link') {
        if (e.which === 1 && e.ctrlKey === false) {
          $window.location.href = node.a_attr.href;
        }
        if ((e.which === 1 && e.ctrlKey === true) || (e.which === 2)) {
          bookmarkTreeService.openInNewTab(node.a_attr.href);
        }
      }
    }

    function clickCB(e) {
      var node = {};
      node.tagName = e.target.tagName;
      if (e.which === 2 && node.tagName === 'A') {
        e.preventDefault();
        e.stopPropagation();
      }
    }
  }

  function browserBookmarkTreeDirective() {
    return {
      restrict: 'E',
      scope: {
        tab: '=psTab',
        col: '=psCol',
        style: '=psStyle',
      },
      templateUrl: 'app/widgets/bookmarkTree/bookmarkTree.html',
      controller: 'bookmarkTreeCtrl',
      controllerAs: 'vm',
      bindToController: true,
    };
  }

})(angular);
<commit_msg>Fixed initation problem with bookmark tree<commit_after>/*eslint camelcase: 0*/
(function(angular) {
  "use strict";

  angular.module('ps.widgets')
    .controller('bookmarkTreeCtrl', bookmarkTreeCtrl)
    .directive('psBrowserBookmarkTree', browserBookmarkTreeDirective);

  function bookmarkTreeCtrl($window, bookmarkTreeService, layoutService) {
    var vm = this;
    vm.getTreeData = getTreeData;
    vm.getTreeConfig = getTreeConfig;
    vm.searchTree = searchTree;
    vm.resetSearch = resetSearch;

    vm.mouseDownCB = mouseDownCB;
    vm.clickCB = clickCB;

    vm.treeEvents = {
      "ready": readyCB,
      "activate_node": activateNodeCB,
      "open_node": openNodeCB,
      "close_node": closeNodeCB,
    };
    //Intialize
    vm.treeData = [];
    vm.treeConfig = {
      version: 1,
    };
    vm.searchString = '';
    activate();

    function activate() {
      vm.treeConfig = getTreeConfig();
      if (layoutService.isActive('bookmarkTree')) {
        vm.getTreeData();
      }
      layoutService.setOnTabClick('bookmarkTree', getTreeData);
    }

    function getTreeData() {
      bookmarkTreeService.getTreeData()
        .then(function(treeData) {
          angular.copy(treeData, vm.treeData);
          vm.treeConfig.version++;
        });
    }

    function getTreeConfig() {
      return bookmarkTreeService.getTreeConfig();
    }

    function searchTree() {
      vm.treeInstance.jstree().search(vm.searchString);
    }

    function resetSearch() {
      vm.searchString = '';
      vm.treeInstance.jstree().clear_search();
    }

    function readyCB() {
      vm.treeInstance.jstree(true).deselect_all();
    }

    function activateNodeCB(e, data) {
      vm.treeInstance.jstree().deselect_node(data.node);
      if (data.node.type !== 'link') {
        if (vm.treeInstance.jstree().is_closed(data.node)) {
          vm.treeInstance.jstree().open_node(data.node);
        } else {
          vm.treeInstance.jstree().close_node(data.node);
        }
      }
    }

    function openNodeCB(e, data) {
      vm.treeInstance.jstree().set_icon(data.node, 'open folder icon');
    }

    function closeNodeCB(e, data) {
      vm.treeInstance.jstree().set_icon(data.node, 'folder icon');
    }

    function mouseDownCB(e) {
      var node = {};
      node.id = e.target.parentNode.id;
      node = vm.treeInstance.jstree().get_node(node.id);
      if (node.type === 'link') {
        if (e.which === 1 && e.ctrlKey === false) {
          $window.location.href = node.a_attr.href;
        }
        if ((e.which === 1 && e.ctrlKey === true) || (e.which === 2)) {
          bookmarkTreeService.openInNewTab(node.a_attr.href);
        }
      }
    }

    function clickCB(e) {
      var node = {};
      node.tagName = e.target.tagName;
      if (e.which === 2 && node.tagName === 'A') {
        e.preventDefault();
        e.stopPropagation();
      }
    }
  }

  function browserBookmarkTreeDirective() {
    return {
      restrict: 'E',
      scope: {
        tab: '=psTab',
        col: '=psCol',
        style: '=psStyle',
      },
      templateUrl: 'app/widgets/bookmarkTree/bookmarkTree.html',
      controller: 'bookmarkTreeCtrl',
      controllerAs: 'vm',
      bindToController: true,
    };
  }

})(angular);
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { StandardPrivateApp } from 'react-components';
import {
    UserModel,
    MailSettingsModel,
    UserSettingsModel,
    SubscriptionModel,
    OrganizationModel,
    AddressesModel
} from 'proton-shared/lib/models';

import PrivateLayout from './components/layout/PrivateLayout';
import locales from './locales';

const PrivateApp = ({ onLogout }) => {
    return (
        <StandardPrivateApp
            onLogout={onLogout}
            locales={locales}
            preloadModels={[UserModel, UserSettingsModel]}
            eventModels={[
                UserModel,
                AddressesModel,
                MailSettingsModel,
                UserSettingsModel,
                SubscriptionModel,
                OrganizationModel
            ]}
        >
            <PrivateLayout />
        </StandardPrivateApp>
    );
};

PrivateApp.propTypes = {
    onLogout: PropTypes.func.isRequired
};

export default PrivateApp;
<commit_msg>Listen to payment methods update<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { StandardPrivateApp } from 'react-components';
import {
    UserModel,
    MailSettingsModel,
    UserSettingsModel,
    SubscriptionModel,
    OrganizationModel,
    AddressesModel,
    PaymentMethodsModel
} from 'proton-shared/lib/models';

import PrivateLayout from './components/layout/PrivateLayout';
import locales from './locales';

const PrivateApp = ({ onLogout }) => {
    return (
        <StandardPrivateApp
            onLogout={onLogout}
            locales={locales}
            preloadModels={[UserModel, UserSettingsModel]}
            eventModels={[
                UserModel,
                AddressesModel,
                MailSettingsModel,
                UserSettingsModel,
                SubscriptionModel,
                PaymentMethodsModel,
                OrganizationModel
            ]}
        >
            <PrivateLayout />
        </StandardPrivateApp>
    );
};

PrivateApp.propTypes = {
    onLogout: PropTypes.func.isRequired
};

export default PrivateApp;
<|endoftext|>