<commit_before>/*
 * ES2015 simple and accessible hide-show system (collapsible regions), using ARIA
 * Website: https://van11y.net/accessible-hide-show/
 * License MIT: https://github.com/nico3333fr/van11y-accessible-hide-show-aria/blob/master/LICENSE
 */
;(doc => {

  'use strict';

  const HIDESHOW_EXPAND = 'js-expandmore';
  const HIDESHOW_BUTTON_EXPAND = 'js-expandmore-button';
  const HIDESHOW_BUTTON_EXPAND_STYLE = 'expandmore__button';
  const HIDESHOW_BUTTON_LABEL_ID = 'label_expand_';

  const DATA_PREFIX_CLASS = 'data-hideshow-prefix-class';

  const HIDESHOW_TO_EXPAND = 'js-to_expand';
  const HIDESHOW_TO_EXPAND_ID = 'expand_';
  const HIDESHOW_TO_EXPAND_STYLE = 'expandmore__to_expand';

  /*
   recommended settings by a11y expert
  */
  const ATTR_CONTROL = 'data-controls';
  const ATTR_EXPANDED = 'aria-expanded';
  const ATTR_LABELLEDBY = 'data-labelledby';
  const ATTR_HIDDEN = 'data-hidden';

  const IS_OPENED_CLASS = 'is-opened';

  const DISPLAY_FIRST_LOAD = 'js-first_load';
  const DISPLAY_FIRST_LOAD_DELAY = '1500';

  const findById = id => doc.getElementById(id);

  const addClass = (el, className) => {
        if (el.classList) {
          el.classList.add(className); // IE 10+
        }
        else {
             el.className += ' ' + className; // IE 8+
             }
        }

  const removeClass = (el, className) => {
        if (el.classList) {
          el.classList.remove(className); // IE 10+
        }
        else {
             el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); // IE 8+
             }
        }

  const hasClass = (el, className) => {
        if (el.classList) {
          return el.classList.contains(className); // IE 10+
        }
        else {
             return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); // IE 8+ ?
             }
        }

  const setAttributes = (node, attrs) => {
        Object
          .keys(attrs)
          .forEach((attribute) => {
            node.setAttribute(attribute, attrs[attribute]);
          });
        };

  const triggerEvent = (el, event_type) => {
        if (el.fireEvent) {
          el.fireEvent('on' + event_type);
        }
        else {
              let evObj = document.createEvent('Events');
              evObj.initEvent(event_type, true, false);
              el.dispatchEvent(evObj);
             }
        }

  // Find all expand
  const $listHideShows = () => [].slice.call(doc.querySelectorAll('.' + HIDESHOW_EXPAND));

  const onLoad = () => {

  $listHideShows()
    .forEach((node, index) => {

      let iLisible = index + 1;
      // let prefixClassName = typeof node.getAttribute(DATA_PREFIX_CLASS) !== 'undefined' ? node.getAttribute(DATA_PREFIX_CLASS) + '-' : '' ; // IE11+
      let prefixClassName = node.hasAttribute(DATA_PREFIX_CLASS) === true ? node.getAttribute(DATA_PREFIX_CLASS) + '-' : '' ;
      let toExpand = node.nextElementSibling;
      let expandmoreText = node.innerHTML;
      let expandButton = doc.createElement("BUTTON");

      // clear element before adding button to it
      node.innerHTML = '';

      // create a button with all attributes
      addClass( expandButton, prefixClassName + HIDESHOW_BUTTON_EXPAND_STYLE );
      addClass( expandButton, HIDESHOW_BUTTON_EXPAND );
      setAttributes(expandButton, {
         [ATTR_CONTROL] : HIDESHOW_TO_EXPAND_ID + iLisible ,
         [ATTR_EXPANDED] : 'false' ,
         'id' : HIDESHOW_BUTTON_LABEL_ID + iLisible
      });
      expandButton.innerHTML = expandmoreText;

      // Button goes into node
      node.appendChild(expandButton);

      // to expand attributes
      setAttributes(toExpand, {
         [ATTR_LABELLEDBY] : HIDESHOW_BUTTON_LABEL_ID + iLisible ,
         [ATTR_HIDDEN] : 'true' ,
         'id' : HIDESHOW_TO_EXPAND_ID + iLisible
      });

      // add delay if DISPLAY_FIRST_LOAD
      addClass( toExpand, prefixClassName + HIDESHOW_TO_EXPAND_STYLE );
      if ( hasClass( toExpand, DISPLAY_FIRST_LOAD) === true ){
         setTimeout(function(){ removeClass( toExpand, DISPLAY_FIRST_LOAD) ; }, DISPLAY_FIRST_LOAD_DELAY);
         }

      // quick tip to open
      if ( hasClass(toExpand, IS_OPENED_CLASS) === true ) {
         addClass( expandButton, IS_OPENED_CLASS );
         expandButton.setAttribute( ATTR_EXPANDED , 'true' );

         removeClass ( toExpand, IS_OPENED_CLASS );
         toExpand.removeAttribute( ATTR_HIDDEN );

         }

    });

  // click on
  ['click', 'keydown']
    .forEach(eventName => {

       doc.body
          .addEventListener(eventName, e => {
             // click on button
             if ( hasClass( e.target, HIDESHOW_BUTTON_EXPAND) === true && eventName === 'click' ) {
                let button_tag = e.target;
                let destination = findById(button_tag.getAttribute( ATTR_CONTROL ));
                let etat_button = button_tag.getAttribute(ATTR_EXPANDED);

                // if closed
                if ( etat_button === 'false' ){
                    button_tag.setAttribute( ATTR_EXPANDED , true );
                    addClass( button_tag, IS_OPENED_CLASS );
                    destination.removeAttribute( ATTR_HIDDEN );
                   }
                   else {
                        button_tag.setAttribute( ATTR_EXPANDED , false );
                        removeClass( button_tag, IS_OPENED_CLASS );
                        destination.setAttribute( ATTR_HIDDEN , true );
                        }

             }
             // click on hx (fix for voiceover = click or keydown on hx => click on button.
             // this makes no sense, but somebody has to do the job to make it fucking work
             if ( hasClass( e.target, HIDESHOW_EXPAND) === true ) {
                 let hx_tag = e.target;
                 let button_in = hx_tag.querySelector('.' + HIDESHOW_BUTTON_EXPAND)

                 if ( hx_tag != button_in ) {
                    if ( eventName === 'click') {
                       triggerEvent ( button_in , 'click');
                       return false;
                       }
                    if ( eventName === 'keydown' && (13 === e.keyCode || 32 === e.keyCode ) ) {
                       triggerEvent ( button_in , 'click');
                       return false;
                       }
                 }

             }
          }, true);
    });
    document.removeEventListener('DOMContentLoaded', onLoad);
  }

  document.addEventListener('DOMContentLoaded', onLoad);

})(document);
<commit_msg>Add type="button" to buttons<commit_after>/*
 * ES2015 simple and accessible hide-show system (collapsible regions), using ARIA
 * Website: https://van11y.net/accessible-hide-show/
 * License MIT: https://github.com/nico3333fr/van11y-accessible-hide-show-aria/blob/master/LICENSE
 */
;(doc => {

  'use strict';

  const HIDESHOW_EXPAND = 'js-expandmore';
  const HIDESHOW_BUTTON_EXPAND = 'js-expandmore-button';
  const HIDESHOW_BUTTON_EXPAND_STYLE = 'expandmore__button';
  const HIDESHOW_BUTTON_LABEL_ID = 'label_expand_';

  const DATA_PREFIX_CLASS = 'data-hideshow-prefix-class';

  const HIDESHOW_TO_EXPAND = 'js-to_expand';
  const HIDESHOW_TO_EXPAND_ID = 'expand_';
  const HIDESHOW_TO_EXPAND_STYLE = 'expandmore__to_expand';

  /*
   recommended settings by a11y expert
  */
  const ATTR_CONTROL = 'data-controls';
  const ATTR_EXPANDED = 'aria-expanded';
  const ATTR_LABELLEDBY = 'data-labelledby';
  const ATTR_HIDDEN = 'data-hidden';

  const IS_OPENED_CLASS = 'is-opened';

  const DISPLAY_FIRST_LOAD = 'js-first_load';
  const DISPLAY_FIRST_LOAD_DELAY = '1500';

  const findById = id => doc.getElementById(id);

  const addClass = (el, className) => {
        if (el.classList) {
          el.classList.add(className); // IE 10+
        }
        else {
             el.className += ' ' + className; // IE 8+
             }
        }

  const removeClass = (el, className) => {
        if (el.classList) {
          el.classList.remove(className); // IE 10+
        }
        else {
             el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); // IE 8+
             }
        }

  const hasClass = (el, className) => {
        if (el.classList) {
          return el.classList.contains(className); // IE 10+
        }
        else {
             return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); // IE 8+ ?
             }
        }

  const setAttributes = (node, attrs) => {
        Object
          .keys(attrs)
          .forEach((attribute) => {
            node.setAttribute(attribute, attrs[attribute]);
          });
        };

  const triggerEvent = (el, event_type) => {
        if (el.fireEvent) {
          el.fireEvent('on' + event_type);
        }
        else {
              let evObj = document.createEvent('Events');
              evObj.initEvent(event_type, true, false);
              el.dispatchEvent(evObj);
             }
        }

  // Find all expand
  const $listHideShows = () => [].slice.call(doc.querySelectorAll('.' + HIDESHOW_EXPAND));

  const onLoad = () => {

  $listHideShows()
    .forEach((node, index) => {

      let iLisible = index + 1;
      // let prefixClassName = typeof node.getAttribute(DATA_PREFIX_CLASS) !== 'undefined' ? node.getAttribute(DATA_PREFIX_CLASS) + '-' : '' ; // IE11+
      let prefixClassName = node.hasAttribute(DATA_PREFIX_CLASS) === true ? node.getAttribute(DATA_PREFIX_CLASS) + '-' : '' ;
      let toExpand = node.nextElementSibling;
      let expandmoreText = node.innerHTML;
      let expandButton = doc.createElement("BUTTON");

      // clear element before adding button to it
      node.innerHTML = '';

      // create a button with all attributes
      addClass( expandButton, prefixClassName + HIDESHOW_BUTTON_EXPAND_STYLE );
      addClass( expandButton, HIDESHOW_BUTTON_EXPAND );
      setAttributes(expandButton, {
         [ATTR_CONTROL] : HIDESHOW_TO_EXPAND_ID + iLisible ,
         [ATTR_EXPANDED] : 'false' ,
         'id' : HIDESHOW_BUTTON_LABEL_ID + iLisible ,
         'type' : 'button'
      });
      expandButton.innerHTML = expandmoreText;

      // Button goes into node
      node.appendChild(expandButton);

      // to expand attributes
      setAttributes(toExpand, {
         [ATTR_LABELLEDBY] : HIDESHOW_BUTTON_LABEL_ID + iLisible ,
         [ATTR_HIDDEN] : 'true' ,
         'id' : HIDESHOW_TO_EXPAND_ID + iLisible
      });

      // add delay if DISPLAY_FIRST_LOAD
      addClass( toExpand, prefixClassName + HIDESHOW_TO_EXPAND_STYLE );
      if ( hasClass( toExpand, DISPLAY_FIRST_LOAD) === true ){
         setTimeout(function(){ removeClass( toExpand, DISPLAY_FIRST_LOAD) ; }, DISPLAY_FIRST_LOAD_DELAY);
         }

      // quick tip to open
      if ( hasClass(toExpand, IS_OPENED_CLASS) === true ) {
         addClass( expandButton, IS_OPENED_CLASS );
         expandButton.setAttribute( ATTR_EXPANDED , 'true' );

         removeClass ( toExpand, IS_OPENED_CLASS );
         toExpand.removeAttribute( ATTR_HIDDEN );

         }

    });

  // click on
  ['click', 'keydown']
    .forEach(eventName => {

       doc.body
          .addEventListener(eventName, e => {
             // click on button
             if ( hasClass( e.target, HIDESHOW_BUTTON_EXPAND) === true && eventName === 'click' ) {
                let button_tag = e.target;
                let destination = findById(button_tag.getAttribute( ATTR_CONTROL ));
                let etat_button = button_tag.getAttribute(ATTR_EXPANDED);

                // if closed
                if ( etat_button === 'false' ){
                    button_tag.setAttribute( ATTR_EXPANDED , true );
                    addClass( button_tag, IS_OPENED_CLASS );
                    destination.removeAttribute( ATTR_HIDDEN );
                   }
                   else {
                        button_tag.setAttribute( ATTR_EXPANDED , false );
                        removeClass( button_tag, IS_OPENED_CLASS );
                        destination.setAttribute( ATTR_HIDDEN , true );
                        }

             }
             // click on hx (fix for voiceover = click or keydown on hx => click on button.
             // this makes no sense, but somebody has to do the job to make it fucking work
             if ( hasClass( e.target, HIDESHOW_EXPAND) === true ) {
                 let hx_tag = e.target;
                 let button_in = hx_tag.querySelector('.' + HIDESHOW_BUTTON_EXPAND)

                 if ( hx_tag != button_in ) {
                    if ( eventName === 'click') {
                       triggerEvent ( button_in , 'click');
                       return false;
                       }
                    if ( eventName === 'keydown' && (13 === e.keyCode || 32 === e.keyCode ) ) {
                       triggerEvent ( button_in , 'click');
                       return false;
                       }
                 }

             }
          }, true);
    });
    document.removeEventListener('DOMContentLoaded', onLoad);
  }

  document.addEventListener('DOMContentLoaded', onLoad);

})(document);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { ReactDom } from 'react-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getAuth } from 'src/auth';
import ReactTooltip from 'react-tooltip'

import { getCommentList } from 'src/comments';

import './task-view.css';
import Icon from '../icon';
import Textarea from 'react-textarea-autosize';

import Img from 'react-image'
import TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';
import Select from 'react-select';
import Button from '../button';
import CommentList from '../comment-list';
import TagsSuggestions from '../tags-suggestions';
import AddComment from '../add-comment/add-comment';
import TaskViewHeader from '../task-view-header/task-view-header';
import { I18n } from 'react-i18next';
import i18n from '../../../i18n.js';
import { appConfig } from 'src/config/app-config'

export class TaskView extends Component {
  constructor() {
    super(...arguments);

    this.state = {
      title: '',
      description: '',
      projectName: null,
      defaultProjectNames: [
        //TODO : add projects
      ],
      type: '',
      defaultType: [
        { value: 1, label: i18n.t('task.types.planning')},
        { value: 2, label: i18n.t('task.types.shifts')},
        { value: 3, label: i18n.t('task.types.camps')},
        { value: 4, label: i18n.t('task.types.art')},
        { value: 5, label: i18n.t('task.types.other')}
      ],
      label: [],
      isCritical: false
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleLabelChange = this.handleLabelChange.bind(this);
    this.handleAddLabel = this.handleAddLabel.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  static propTypes = {
    selectTask: PropTypes.func.isRequired,
    updateTask: PropTypes.func.isRequired,
    removeTask: PropTypes.func.isRequired,
    assignTask: PropTypes.func.isRequired,
    unassignTask: PropTypes.func.isRequired,
    selectedTask: PropTypes.object,
    isAdmin: PropTypes.bool.isRequired,
    isGuide: PropTypes.bool.isRequired,
    unloadComments: PropTypes.func.isRequired
  };

  componentWillMount() {
    this.updateStateByProps(this.props);
  }

  updateStateByProps(props) {
    let nextSelectedTask = props.selectedTask || {};
    let { id, title, description, type, projectName,
      label, isCritical, dueDate, created,
    } = nextSelectedTask;

      // this checks if we got another task, or we're updating the same one
      if (id != this.state.id) {
        const labelAsArray = label ?
          (Object.keys(label).map( l => { return l })) : [];

        this.setState({
          id: id || '',
          title: title || '',
          description:description || '',
          label: labelAsArray || [],
          isCritical: isCritical || false,
          created: created || null,
          dueDate: dueDate || null,
          type: type || '',
          projectName: projectName || ''
        });
      }
  }

  componentWillReceiveProps(nextProps) {
    // TODO - check this maybe called several times now that we use comments
    this.updateStateByProps(nextProps);
  }

  render() {
    const task = this.props.selectedTask;
    if(!task) {
      return(

      );
    }

    const isUserCreator = task.creator && task.creator.id == this.props.auth.id;
    const isUserAssignee = task.assignee && task.assignee.id == this.props.auth.id;
    const canEditTask = isUserCreator || isUserAssignee || this.props.isAdmin;
    const canDeleteTask = isUserCreator || this.props.isAdmin;
    const showUnassignButton = this.props.isAdmin || (this.props.isGuide && isUserCreator)

    return (
      <I18n ns='translations'>
      {
      (t, { i18n }) => (

          <TaskViewHeader
          task={ this.props.selectedTask }
          canDeleteTask={ canDeleteTask }
          selectTask={ this.props.selectTask }
          assignTask={ this.props.assignTask }
          unassignTask={ this.props.unassignTask }
          removeTask={ this.props.removeTask }
          showUnassignButton = { showUnassignButton }
          />

            <form onSubmit={this.handleSubmit} noValidate>
              {this.renderInput(task, 'title', t('task.name'), canEditTask)}
              {this.renderTextArea(task, 'description', t('task.description'), canEditTask)}

{t('task.type')}

              { this.renderSelect(task, 'type', t('task.type'), this.state.defaultType, canEditTask, t)}

{t('task.automatic-tags')}

                <TagsSuggestions
                  tags={appConfig.popularTags}
                  onTagSelected={(tag) => {
                    this.handleAddLabel(tag);
                    this.updateStateByProps(this.props); //TODO - maybe add bugs
                  }}
                />

<Icon className='label' name='loyalty' /> {this.renderLabel(canEditTask, t)}

{ this.renderCheckbox(task, 'isCritical', t('task.is-critical'), canEditTask) }

              {this.renderTaskCreator(t, task) }
            </form>
            {t('comments.title')}
            { this.props.comments ?
            <CommentList
            task={task}
            comments={this.props.comments}
            auth={this.props.auth} /> : ''}

          { this.renderAddComment() }

      )}
      </I18n>
    );
  }

  renderTaskCreator(t, task) {
    if (!task.creator) return;
    const avatar = task.creator.photoURL ?  : '';
      return (

          {t('task.creator')}

            <ReactTooltip type='light' effect='solid'/>
            { avatar }

      );
  }

  renderAddComment() {
    return (
      <AddComment
      task={ this.props.selectedTask }
      createComment={this.props.createComment }
      auth={this.props.auth}
      key='addComment' />)
  }

  renderSelect(task, fieldName, placeholder, options, isEditable, translation) {
    return (
      <Select
      type='text'
      name={fieldName}
      value={this.state[fieldName]}
      placeholder={placeholder}
      ref={e => this[fieldName+'Input'] = e}
      onChange={(e) => { let val=null; if (e) { val = e.value };
                this.setState({ [fieldName]: val}) }}
      options={options}
      onBlur={this.handleSubmit}
      noResultsText={translation('general.no-results-found')}
      searchable={ false }
      disabled = { !isEditable }/>
  );
  }

  renderInput(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (
        <input
        className={`changing-input${classNames}`}
        type = 'text'
        name = { fieldName }
        value = { this.state[fieldName] }
        placeholder = { placeholder }
        ref = { e => this[fieldName+'Input'] = e }
        onChange = { this.handleChange }
        onBlur = { this.handleSubmit }
        disabled = { !isEditable } />
    );
  }

  renderTextArea(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (
        <Textarea
        className={`changing-input${classNames}`}
        name={fieldName}
        value={this.state[fieldName]}
        placeholder={placeholder}
        ref={e => this[fieldName+'Input'] = e}
        onChange={this.handleChange}
        onBlur={this.handleSubmit}
        disabled = { !isEditable } />
    );
  }

  renderLabel(isEditable, translation) {
    const showPlaceholder = true;
    const classNames = isEditable ? ' editable' : ''
    return (
      <TagsInput className={`react-tagsinput-changing${classNames}`}
      value={this.state.label}
      onChange={this.handleLabelChange}
      onlyUnique={true}
      addOnBlur={true}
      inputProps={{ placeholder: showPlaceholder ? translation('task.input-tags') : ''}}
      disabled = { !isEditable }
      />
    )
  }

  renderCheckbox(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (

        <input
        type = 'checkbox'
        checked = { this.state[fieldName] }
        value = { placeholder }
        onChange={e => { this.setState({ [fieldName]: !this.state[fieldName]}) }}
        disabled = { !isEditable }
        onBlur={this.handleSubmit}
        />
        { placeholder }

    );
  }

  handleChange(e) {
    let fieldName = e.target.name;
    this.setState({
      [fieldName]: e.target.value
    });
  }

  handleAddLabel(label) {
    var newLabels = this.state.label
    newLabels.push(label)
    this.handleLabelChange(newLabels)
  }

  handleLabelChange(label) {
    this.setState({label})
    this.handleSubmit() // TODO: might not be good as we want to have initially a save button
  }

  handleKeyUp(event) {
    if (event.keyCode === 13) {
      this.handleSubmit(event);
    }
  }

  handleSubmit(event) {
    if(event) {
      event.preventDefault();
    }
    let labelAsObject = this.arrayToObject(this.state.label);
    const fieldsToUpdate = {
      title: this.state.title,
      description: this.state.description,
      label: labelAsObject,
      isCritical: this.state.isCritical,
      type: this.state.type,
      projectName: this.state.projectName
    };
    fieldsToUpdate.dueDate = this.state.dueDate || null;

    this.props.updateTask(this.props.selectedTask, fieldsToUpdate);
  }

  arrayToObject(array) {
    var result = {};
    for (var i = 0; i < array.length; ++i)
      result[array[i]] = true;
    return result;
  }
}

//=====================================
//  CONNECT
//-------------------------------------

const mapStateToProps = createSelector(
  getCommentList,
  getAuth,
  (comments, auth) => ({
    comments,
    auth
  })
);

const mapDispatchToProps = Object.assign(
  {},
);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TaskView);
<commit_msg>Removed task creator from inside task<commit_after>import React, { Component } from 'react';
import { ReactDom } from 'react-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { getAuth } from 'src/auth';
import ReactTooltip from 'react-tooltip'

import { getCommentList } from 'src/comments';

import './task-view.css';
import Icon from '../icon';
import Textarea from 'react-textarea-autosize';

import Img from 'react-image'
import TagsInput from 'react-tagsinput';
import 'react-tagsinput/react-tagsinput.css';
import Select from 'react-select';
import Button from '../button';
import CommentList from '../comment-list';
import TagsSuggestions from '../tags-suggestions';
import AddComment from '../add-comment/add-comment';
import TaskViewHeader from '../task-view-header/task-view-header';
import { I18n } from 'react-i18next';
import i18n from '../../../i18n.js';
import { appConfig } from 'src/config/app-config'

export class TaskView extends Component {
  constructor() {
    super(...arguments);

    this.state = {
      title: '',
      description: '',
      projectName: null,
      defaultProjectNames: [
        //TODO : add projects
      ],
      type: '',
      defaultType: [
        { value: 1, label: i18n.t('task.types.planning')},
        { value: 2, label: i18n.t('task.types.shifts')},
        { value: 3, label: i18n.t('task.types.camps')},
        { value: 4, label: i18n.t('task.types.art')},
        { value: 5, label: i18n.t('task.types.other')}
      ],
      label: [],
      isCritical: false
    }

    this.handleChange = this.handleChange.bind(this);
    this.handleLabelChange = this.handleLabelChange.bind(this);
    this.handleAddLabel = this.handleAddLabel.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  static propTypes = {
    selectTask: PropTypes.func.isRequired,
    updateTask: PropTypes.func.isRequired,
    removeTask: PropTypes.func.isRequired,
    assignTask: PropTypes.func.isRequired,
    unassignTask: PropTypes.func.isRequired,
    selectedTask: PropTypes.object,
    isAdmin: PropTypes.bool.isRequired,
    isGuide: PropTypes.bool.isRequired,
    unloadComments: PropTypes.func.isRequired
  };

  componentWillMount() {
    this.updateStateByProps(this.props);
  }

  updateStateByProps(props) {
    let nextSelectedTask = props.selectedTask || {};
    let { id, title, description, type, projectName,
      label, isCritical, dueDate, created,
    } = nextSelectedTask;

      // this checks if we got another task, or we're updating the same one
      if (id != this.state.id) {
        const labelAsArray = label ?
          (Object.keys(label).map( l => { return l })) : [];

        this.setState({
          id: id || '',
          title: title || '',
          description:description || '',
          label: labelAsArray || [],
          isCritical: isCritical || false,
          created: created || null,
          dueDate: dueDate || null,
          type: type || '',
          projectName: projectName || ''
        });
      }
  }

  componentWillReceiveProps(nextProps) {
    // TODO - check this maybe called several times now that we use comments
    this.updateStateByProps(nextProps);
  }

  render() {
    const task = this.props.selectedTask;
    if(!task) {
      return(

      );
    }

    const isUserCreator = task.creator && task.creator.id == this.props.auth.id;
    const isUserAssignee = task.assignee && task.assignee.id == this.props.auth.id;
    const canEditTask = isUserCreator || isUserAssignee || this.props.isAdmin;
    const canDeleteTask = isUserCreator || this.props.isAdmin;
    const showUnassignButton = this.props.isAdmin || (this.props.isGuide && isUserCreator)

    return (
      <I18n ns='translations'>
      {
      (t, { i18n }) => (

          <TaskViewHeader
          task={ this.props.selectedTask }
          canDeleteTask={ canDeleteTask }
          selectTask={ this.props.selectTask }
          assignTask={ this.props.assignTask }
          unassignTask={ this.props.unassignTask }
          removeTask={ this.props.removeTask }
          showUnassignButton = { showUnassignButton }
          />

            <form onSubmit={this.handleSubmit} noValidate>
              {this.renderInput(task, 'title', t('task.name'), canEditTask)}
              {this.renderTextArea(task, 'description', t('task.description'), canEditTask)}

{t('task.type')}

              { this.renderSelect(task, 'type', t('task.type'), this.state.defaultType, canEditTask, t)}

{t('task.automatic-tags')}

                <TagsSuggestions
                  tags={appConfig.popularTags}
                  onTagSelected={(tag) => {
                    this.handleAddLabel(tag);
                    this.updateStateByProps(this.props); //TODO - maybe add bugs
                  }}
                />

<Icon className='label' name='loyalty' /> {this.renderLabel(canEditTask, t)}

{ this.renderCheckbox(task, 'isCritical', t('task.is-critical'), canEditTask) }

            </form>
            {t('comments.title')}
            { this.props.comments ?
            <CommentList
            task={task}
            comments={this.props.comments}
            auth={this.props.auth} /> : ''}

          { this.renderAddComment() }

      )}
      </I18n>
    );
  }

  renderAddComment() {
    return (
      <AddComment
      task={ this.props.selectedTask }
      createComment={this.props.createComment }
      auth={this.props.auth}
      key='addComment' />)
  }

  renderSelect(task, fieldName, placeholder, options, isEditable, translation) {
    return (
      <Select
      type='text'
      name={fieldName}
      value={this.state[fieldName]}
      placeholder={placeholder}
      ref={e => this[fieldName+'Input'] = e}
      onChange={(e) => { let val=null; if (e) { val = e.value };
                this.setState({ [fieldName]: val}) }}
      options={options}
      onBlur={this.handleSubmit}
      noResultsText={translation('general.no-results-found')}
      searchable={ false }
      disabled = { !isEditable }/>
  );
  }

  renderInput(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (
        <input
        className={`changing-input${classNames}`}
        type = 'text'
        name = { fieldName }
        value = { this.state[fieldName] }
        placeholder = { placeholder }
        ref = { e => this[fieldName+'Input'] = e }
        onChange = { this.handleChange }
        onBlur = { this.handleSubmit }
        disabled = { !isEditable } />
    );
  }

  renderTextArea(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (
        <Textarea
        className={`changing-input${classNames}`}
        name={fieldName}
        value={this.state[fieldName]}
        placeholder={placeholder}
        ref={e => this[fieldName+'Input'] = e}
        onChange={this.handleChange}
        onBlur={this.handleSubmit}
        disabled = { !isEditable } />
    );
  }

  renderLabel(isEditable, translation) {
    const showPlaceholder = true;
    const classNames = isEditable ? ' editable' : ''
    return (
      <TagsInput className={`react-tagsinput-changing${classNames}`}
      value={this.state.label}
      onChange={this.handleLabelChange}
      onlyUnique={true}
      addOnBlur={true}
      inputProps={{ placeholder: showPlaceholder ? translation('task.input-tags') : ''}}
      disabled = { !isEditable }
      />
    )
  }

  renderCheckbox(task, fieldName, placeholder, isEditable) {
    const classNames = isEditable ? ' editable' : ''
    return (

        <input
        type = 'checkbox'
        checked = { this.state[fieldName] }
        value = { placeholder }
        onChange={e => { this.setState({ [fieldName]: !this.state[fieldName]}) }}
        disabled = { !isEditable }
        onBlur={this.handleSubmit}
        />
        { placeholder }

    );
  }

  handleChange(e) {
    let fieldName = e.target.name;
    this.setState({
      [fieldName]: e.target.value
    });
  }

  handleAddLabel(label) {
    var newLabels = this.state.label
    newLabels.push(label)
    this.handleLabelChange(newLabels)
  }

  handleLabelChange(label) {
    this.setState({label})
    this.handleSubmit() // TODO: might not be good as we want to have initially a save button
  }

  handleKeyUp(event) {
    if (event.keyCode === 13) {
      this.handleSubmit(event);
    }
  }

  handleSubmit(event) {
    if(event) {
      event.preventDefault();
    }
    let labelAsObject = this.arrayToObject(this.state.label);
    const fieldsToUpdate = {
      title: this.state.title,
      description: this.state.description,
      label: labelAsObject,
      isCritical: this.state.isCritical,
      type: this.state.type,
      projectName: this.state.projectName
    };
    fieldsToUpdate.dueDate = this.state.dueDate || null;

    this.props.updateTask(this.props.selectedTask, fieldsToUpdate);
  }

  arrayToObject(array) {
    var result = {};
    for (var i = 0; i < array.length; ++i)
      result[array[i]] = true;
    return result;
  }
}

//=====================================
//  CONNECT
//-------------------------------------

const mapStateToProps = createSelector(
  getCommentList,
  getAuth,
  (comments, auth) => ({
    comments,
    auth
  })
);

const mapDispatchToProps = Object.assign(
  {},
);

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TaskView);
<|endoftext|>


<commit_before>var AbstractVisualization = Fiber.extend(function() {
    return {
        init: function(container, history) {
            this.container = container;
            this.history = history;

            this.renderer = null;
            this.scene = null;
            this.camera = null;
            this.controls = null;
            this.stats = null;

            this.gui = null;
            this.guiIteration = null;

            this.iteration = 0;
            this.lastIteration = this.iteration;

            this.snapshot = null;
            this.loadLayersTimeout = null;
            this.loadLayersTimeoutDuration = 500; // default (in ms)

            this._initDrawings();
            this._initControls();
            this._initStats();
            this._initGUI();

            this.historyUpdated();
        },

        /* To Override */

        getInputDrawing: function() {return null;},
        getOutputDrawing: function() {return null;},

        /* Public */

        render: function() {
            if (this.stats) this.stats.begin();

            this._update();
            this.controls.update();
            this.renderer.render(this.scene, this.camera);

            if (this.stats) this.stats.end();

            requestAnimationFrame(this.render.bind(this));
        },

        historyUpdated: function() {
            var num = this.history.length(),
                guiIteration = this.guiIteration;

            var min = Number(num > 0),
                max = num;

            guiIteration.__min = min;
            guiIteration.__max = max;

            if (guiIteration.getValue() === 0) {
                guiIteration.setValue(min);
            }
        },

        /* Private */

        _initDrawings: function() {
            var container = this.container,
                width = container.width(),
                height = container.height(),
                viewAngle = 45,
                aspect = width / height,
                near = 0.1,
                far = 10000;

            var renderer = new THREE.WebGLRenderer();
            var camera = new THREE.PerspectiveCamera(viewAngle, aspect, near, far);
            var scene = new THREE.Scene();

            camera.position.z = 5000;
            scene.add(camera);

            renderer.setSize(width, height);
            this.container.append(renderer.domElement);

            this.renderer = renderer;
            this.camera = camera;
            this.scene = scene;

            var inputDrawing = this.getInputDrawing(scene),
                outputDrawing = this.getOutputDrawing(scene);

            outputDrawing.setInputDrawing(inputDrawing);

            this.inputDrawing = inputDrawing;
            this.outputDrawing = outputDrawing;
        },

        _initControls: function() {
            var camera = this.camera,
                renderer = this.renderer,
                controls = new THREE.TrackballControls(camera, renderer.domElement);

            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;
            controls.panSpeed = 0.8;

            controls.noZoom = false;
            controls.noPan = false;

            controls.staticMoving = true;
            controls.dynamicDampingFactor = 0.3;

            controls.keys = [65, 83, 68];

            this.controls = controls;
        },

        _initStats: function() {
            var stats = new Stats(),
                domElement = $(stats.domElement);

            stats.setMode(0); // 0: fps; 1: ms

            domElement.addClass("stats");
            this.container.append(domElement);

            this.stats = stats;
        },

        _initGUI: function() {
            var gui = new dat.GUI({ autoPlace: false }),
                domElement = $(gui.domElement);

            domElement.addClass("controls");
            this.container.append(domElement);

            this.guiIteration = gui.add(this, 'iteration', 0, 0).step(1);

            var callback = _.bind(this._updateDrawings, this);

            var viewFolder = gui.addFolder('View');
            viewFolder.add(this.outputDrawing, 'showActiveCells').onChange(callback);
            viewFolder.add(this.outputDrawing, 'showPredictiveCells').onChange(callback);
            viewFolder.add(this.outputDrawing, 'showProximalSynapses').onChange(callback);

            this.gui = gui;
        },

        _iterationUpdated: function() {
            var lastSnapshot = this.snapshot,
                snapshot = this.history.getSnapshotAtIndex(this.iteration - 1);

            if (!snapshot) {
                console.log("Invalid iteration index: " + this.iteration);
                return;
            }

            this.snapshot = snapshot;

            this._loadLayers();

            var inputDimensionsChanged  = true,
                outputDimensionsChanged = true,
                thisInputDimensions = snapshot.getInputLayer().getDimensions(),
                thisOutputDimensions = snapshot.getOutputLayer().getDimensions();

            if (lastSnapshot) {
                var lastInputDimensions = lastSnapshot.getInputLayer().getDimensions(),
                    lastOutputDimensions = lastSnapshot.getOutputLayer().getDimensions();

                if (_.isEqual(thisInputDimensions, lastInputDimensions))
                    inputDimensionsChanged = false;

                if (_.isEqual(thisOutputDimensions, lastOutputDimensions))
                    outputDimensionsChanged = false;
            }

            var inputDrawing = this.inputDrawing,
                outputDrawing = this.outputDrawing;

            inputDrawing.setLayerDimensions(thisInputDimensions);
            outputDrawing.setLayerDimensions(thisOutputDimensions);

            if (inputDimensionsChanged) {
                inputDrawing.clear();
                inputDrawing.setup();
            }
            else {
                inputDrawing.update();
            }

            if (outputDimensionsChanged) {
                outputDrawing.clear();
                outputDrawing.setup();
            }
            else {
                outputDrawing.update();
            }
        },

        _updateDrawings: function() {
            this.inputDrawing.update();
            this.outputDrawing.update();
        },

        _update: function() {
            if (this.lastIteration != this.iteration) {
                this._iterationUpdated();
                this.lastIteration = this.iteration;
            }
        },

        _loadLayers: function() {
            var self = this,
                snapshot = this.snapshot,
                inputLayer = snapshot.getInputLayer(),
                outputLayer = snapshot.getOutputLayer(),
                inputDrawing = this.inputDrawing,
                outputDrawing = this.outputDrawing,
                timeout = this.loadLayersTimeout,
                timeoutDuration = this.loadLayersTimeoutDuration;

            inputDrawing.reset();
            outputDrawing.reset();

            if (timeout) clearTimeout(timeout);

            timeout = setTimeout(function() {
                inputLayer.getActiveCells(_.bind(function(error, activeCells) {
                    if (self.snapshot != this) return;

                    self.inputDrawing.setActiveCells(activeCells);
                    self.inputDrawing.update();
                }, snapshot));

                outputLayer.getActiveCells(_.bind(function(error, activeCells) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setActiveCells(activeCells);
                    self.outputDrawing.update();
                }, snapshot));

                outputLayer.getPredictiveCells(_.bind(function(error, predictiveCells) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setPredictiveCells(predictiveCells);
                    self.outputDrawing.update();
                }, snapshot));

                outputLayer.getProximalSynapses(_.bind(function(error, proximalSynapses) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setProximalSynapses(proximalSynapses);
                    self.outputDrawing.update();
                }, snapshot));
            }, timeoutDuration);

            this.loadLayersTimeout = timeout;
        }
    };
});
<commit_msg>Better organization<commit_after>var AbstractVisualization = Fiber.extend(function() {
    return {
        init: function(container, history) {
            this.container = container;
            this.history = history;

            this.renderer = null;
            this.scene = null;
            this.camera = null;
            this.controls = null;
            this.stats = null;

            this.gui = null;
            this.guiIteration = null;

            this.iteration = 0;
            this.lastIteration = this.iteration;

            this.snapshot = null;
            this.loadLayersTimeout = null;
            this.loadLayersTimeoutDuration = 500; // default (in ms)

            this._initDrawings();
            this._initControls();
            this._initStats();
            this._initGUI();

            this.historyUpdated();
        },

        /* To Override */

        getInputDrawing: function() {return null;},
        getOutputDrawing: function() {return null;},

        /* Public */

        render: function() {
            if (this.stats) this.stats.begin();

            this._update();
            this.controls.update();
            this.renderer.render(this.scene, this.camera);

            if (this.stats) this.stats.end();

            requestAnimationFrame(this.render.bind(this));
        },

        historyUpdated: function() {
            var num = this.history.length(),
                guiIteration = this.guiIteration;

            var min = Number(num > 0),
                max = num;

            guiIteration.__min = min;
            guiIteration.__max = max;

            if (guiIteration.getValue() === 0) {
                guiIteration.setValue(min);
            }
        },

        /* Private */

        _initDrawings: function() {
            var container = this.container,
                width = container.width(),
                height = container.height(),
                viewAngle = 45,
                aspect = width / height,
                near = 0.1,
                far = 10000;

            var renderer = new THREE.WebGLRenderer();
            var camera = new THREE.PerspectiveCamera(viewAngle, aspect, near, far);
            var scene = new THREE.Scene();

            camera.position.z = 5000;
            scene.add(camera);

            renderer.setSize(width, height);
            this.container.append(renderer.domElement);

            this.renderer = renderer;
            this.camera = camera;
            this.scene = scene;

            var inputDrawing = this.getInputDrawing(scene),
                outputDrawing = this.getOutputDrawing(scene);

            outputDrawing.setInputDrawing(inputDrawing);

            this.inputDrawing = inputDrawing;
            this.outputDrawing = outputDrawing;
        },

        _initControls: function() {
            var camera = this.camera,
                renderer = this.renderer,
                controls = new THREE.TrackballControls(camera, renderer.domElement);

            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 1.2;
            controls.panSpeed = 0.8;

            controls.noZoom = false;
            controls.noPan = false;

            controls.staticMoving = true;
            controls.dynamicDampingFactor = 0.3;

            controls.keys = [65, 83, 68];

            this.controls = controls;
        },

        _initStats: function() {
            var stats = new Stats(),
                domElement = $(stats.domElement);

            stats.setMode(0); // 0: fps; 1: ms

            domElement.addClass("stats");
            this.container.append(domElement);

            this.stats = stats;
        },

        _initGUI: function() {
            var gui = new dat.GUI({ autoPlace: false }),
                domElement = $(gui.domElement);

            domElement.addClass("controls");
            this.container.append(domElement);

            this.guiIteration = gui.add(this, 'iteration', 0, 0).step(1);

            var callback = _.bind(this._updateDrawings, this);

            var viewFolder = gui.addFolder('View');
            viewFolder.add(this.outputDrawing, 'showActiveCells').onChange(callback);
            viewFolder.add(this.outputDrawing, 'showPredictiveCells').onChange(callback);
            viewFolder.add(this.outputDrawing, 'showProximalSynapses').onChange(callback);

            this.gui = gui;
        },

        _update: function() {
            if (this.lastIteration != this.iteration) {
                this._iterationUpdated();
                this.lastIteration = this.iteration;
            }
        },

        _iterationUpdated: function() {
            var lastSnapshot = this.snapshot,
                snapshot = this.history.getSnapshotAtIndex(this.iteration - 1);

            if (!snapshot) {
                console.log("Invalid iteration index: " + this.iteration);
                return;
            }

            this.snapshot = snapshot;

            this._loadLayers();

            var inputDimensionsChanged  = true,
                outputDimensionsChanged = true,
                thisInputDimensions = snapshot.getInputLayer().getDimensions(),
                thisOutputDimensions = snapshot.getOutputLayer().getDimensions();

            if (lastSnapshot) {
                var lastInputDimensions = lastSnapshot.getInputLayer().getDimensions(),
                    lastOutputDimensions = lastSnapshot.getOutputLayer().getDimensions();

                if (_.isEqual(thisInputDimensions, lastInputDimensions))
                    inputDimensionsChanged = false;

                if (_.isEqual(thisOutputDimensions, lastOutputDimensions))
                    outputDimensionsChanged = false;
            }

            var inputDrawing = this.inputDrawing,
                outputDrawing = this.outputDrawing;

            inputDrawing.setLayerDimensions(thisInputDimensions);
            outputDrawing.setLayerDimensions(thisOutputDimensions);

            if (inputDimensionsChanged) {
                inputDrawing.clear();
                inputDrawing.setup();
            }
            else {
                inputDrawing.update();
            }

            if (outputDimensionsChanged) {
                outputDrawing.clear();
                outputDrawing.setup();
            }
            else {
                outputDrawing.update();
            }
        },

        _updateDrawings: function() {
            this.inputDrawing.update();
            this.outputDrawing.update();
        },

        _loadLayers: function() {
            var self = this,
                snapshot = this.snapshot,
                inputLayer = snapshot.getInputLayer(),
                outputLayer = snapshot.getOutputLayer(),
                inputDrawing = this.inputDrawing,
                outputDrawing = this.outputDrawing,
                timeout = this.loadLayersTimeout,
                timeoutDuration = this.loadLayersTimeoutDuration;

            inputDrawing.reset();
            outputDrawing.reset();

            if (timeout) clearTimeout(timeout);

            timeout = setTimeout(function() {
                inputLayer.getActiveCells(_.bind(function(error, activeCells) {
                    if (self.snapshot != this) return;

                    self.inputDrawing.setActiveCells(activeCells);
                    self.inputDrawing.update();
                }, snapshot));

                outputLayer.getActiveCells(_.bind(function(error, activeCells) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setActiveCells(activeCells);
                    self.outputDrawing.update();
                }, snapshot));

                outputLayer.getPredictiveCells(_.bind(function(error, predictiveCells) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setPredictiveCells(predictiveCells);
                    self.outputDrawing.update();
                }, snapshot));

                outputLayer.getProximalSynapses(_.bind(function(error, proximalSynapses) {
                    if (self.snapshot != this) return;

                    self.outputDrawing.setProximalSynapses(proximalSynapses);
                    self.outputDrawing.update();
                }, snapshot));
            }, timeoutDuration);

            this.loadLayersTimeout = timeout;
        }
    };
});
<|endoftext|>


<commit_before>import '../jquery/datetimepicker-easy';

const moment = require('moment');

function toggleConsentEditing() {
	const birthdayInput = document.getElementById('birthday');
	let birthday;
	let age;
	if (birthdayInput) {
		const birthdaytext = birthdayInput.value.split('.');
		birthday = moment(`${birthdaytext[2]}-${birthdaytext[1]}-${birthdaytext[0]}`);
		age = moment().diff(birthday, 'years');
	}

	document.getElementById('consents-overview').querySelectorAll('input').forEach((input) => {
		if (input.getAttribute('disabled') !== undefined) {
			if (age && age >= 18) {
				if ((input.name).match('parent') == null) {
					input.removeAttribute('disabled');
				}
			} else {
				input.removeAttribute('disabled');
			}
		} else {
			input.setAttribute('disabled', 'disabled');
		}
	});
}
window.addEventListener('DOMContentLoaded', () => {
	const target = document.getElementById('edit-consent');
	if (!target) { return; }
	target.addEventListener('click', (event) => {
		toggleConsentEditing();
		event.target.classList.add('hidden');
	});
});

$(document).ready(() => {
	const $pwModal = $('.pw-modal');
	const $deleteModal = $('.delete-modal');
	const $skipregModal = $('.skipreg-modal');

	$('.btn-pw').on('click', (e) => {
		e.preventDefault();
		populateModalForm($pwModal, {
			action: 'pw',
			title: 'Passwort ändern',
			closeLabel: 'Abbrechen',
			submitLabel: 'Speichern',
			fields: undefined,
		});
		$pwModal.appendTo('body').modal('show');
	});

	$('.btn-delete').on('click', (e) => {
		e.preventDefault();
		populateModalForm($deleteModal, {
			action: '',
			title: 'Benutzer löschen?',
			closeLabel: 'Abbrechen',
			submitLabel: 'Löschen',
			fields: {
				displayName: $('input[name="displayName"]').val(),
			},
		});
		$deleteModal.appendTo('body').modal('show');
	});

	$('.btn-skipreg').on('click', (e) => {
		e.preventDefault();
		populateModalForm($skipregModal, {
			action: 'skipregistration',
			title: 'Nutzerregistrierung abschließen',
			closeLabel: 'Abbrechen',
			submitLabel: 'Speichern',
			fields: undefined,
		});
		$skipregModal.appendTo('body').modal('show');
	});

	function createInvitationHashHandler(e) {
		e.preventDefault();
		const $invitationModal = $('.invitation-modal');
		const schoolId = $invitationModal.find("input[name='schoolId']").val();
		let role = 'student';
		const email = $('input[name="email"]').val();
		if ($(this).hasClass('teacher')) role = 'teacher';
		$.ajax({
			type: 'POST',
			url: `${window.location.origin}/administration/registrationlink`,
			data: {
				role,
				save: true,
				schoolId,
				host: window.location.origin,
				toHash: email,
				patchUser: true,
			},
			success(linkData) {
				populateModalForm($invitationModal, {
					title: 'Einladungslink generiert!',
					closeLabel: 'Abbrechen',
					submitLabel: 'Speichern',
					fields: { invitation: linkData.shortLink },
				});
				$invitationModal.find('.btn-submit').remove();
				// eslint-ignore func-names
				$invitationModal.find("input[name='invitation']").click(function () {
					$(this).select();
				});

				$invitationModal.appendTo('body').modal('show');
			},
		});
	}
	$('.btn-invitation-link-with-hash').on('click', createInvitationHashHandler);
});
<commit_msg>lint fix<commit_after>import '../jquery/datetimepicker-easy';

const moment = require('moment');

function toggleConsentEditing() {
	const birthdayInput = document.getElementById('birthday');
	let birthday;
	let age;
	if (birthdayInput) {
		const birthdaytext = birthdayInput.value.split('.');
		birthday = moment(`${birthdaytext[2]}-${birthdaytext[1]}-${birthdaytext[0]}`);
		age = moment().diff(birthday, 'years');
	}

	document.getElementById('consents-overview').querySelectorAll('input').forEach((input) => {
		if (input.getAttribute('disabled') !== undefined) {
			if (age && age >= 18) {
				if ((input.name).match('parent') == null) {
					input.removeAttribute('disabled');
				}
			} else {
				input.removeAttribute('disabled');
			}
		} else {
			input.setAttribute('disabled', 'disabled');
		}
	});
}
window.addEventListener('DOMContentLoaded', () => {
	const target = document.getElementById('edit-consent');
	if (!target) { return; }
	target.addEventListener('click', (event) => {
		toggleConsentEditing();
		event.target.classList.add('hidden');
	});
});

$(document).ready(() => {
	const $pwModal = $('.pw-modal');
	const $deleteModal = $('.delete-modal');
	const $skipregModal = $('.skipreg-modal');

	$('.btn-pw').on('click', (e) => {
		e.preventDefault();
		populateModalForm($pwModal, {
			action: 'pw',
			title: 'Passwort ändern',
			closeLabel: 'Abbrechen',
			submitLabel: 'Speichern',
			fields: undefined,
		});
		$pwModal.appendTo('body').modal('show');
	});

	$('.btn-delete').on('click', (e) => {
		e.preventDefault();
		populateModalForm($deleteModal, {
			action: '',
			title: 'Benutzer löschen?',
			closeLabel: 'Abbrechen',
			submitLabel: 'Löschen',
			fields: {
				displayName: $('input[name="displayName"]').val(),
			},
		});
		$deleteModal.appendTo('body').modal('show');
	});

	$('.btn-skipreg').on('click', (e) => {
		e.preventDefault();
		populateModalForm($skipregModal, {
			action: 'skipregistration',
			title: 'Nutzerregistrierung abschließen',
			closeLabel: 'Abbrechen',
			submitLabel: 'Speichern',
			fields: undefined,
		});
		$skipregModal.appendTo('body').modal('show');
	});

	function createInvitationHashHandler(e) {
		e.preventDefault();
		const $invitationModal = $('.invitation-modal');
		const schoolId = $invitationModal.find("input[name='schoolId']").val();
		let role = 'student';
		const email = $('input[name="email"]').val();
		if ($(this).hasClass('teacher')) role = 'teacher';
		$.ajax({
			type: 'POST',
			url: `${window.location.origin}/administration/registrationlink`,
			data: {
				role,
				save: true,
				schoolId,
				host: window.location.origin,
				toHash: email,
				patchUser: true,
			},
			success(linkData) {
				populateModalForm($invitationModal, {
					title: 'Einladungslink generiert!',
					closeLabel: 'Abbrechen',
					submitLabel: 'Speichern',
					fields: { invitation: linkData.shortLink },
				});
				$invitationModal.find('.btn-submit').remove();

				function selectThis() {
					$(this).select();
				}
				$invitationModal.find("input[name='invitation']").click(selectThis);

				$invitationModal.appendTo('body').modal('show');
			},
		});
	}
	$('.btn-invitation-link-with-hash').on('click', createInvitationHashHandler);
});
<|endoftext|>


<commit_before>// source: data.proto
/**
 * @fileoverview
 * @enhanceable
 * @suppress {messageConventions} JS Compiler reports an error if a variable or
 *     field starts with 'MSG_' and isn't a translatable message.
 * @public
 */
// GENERATED CODE -- DO NOT EDIT!

var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();

var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js');
goog.object.extend(proto, google_protobuf_timestamp_pb);
goog.exportSymbol('proto.CandidateInfo', null, global);
goog.exportSymbol('proto.Env', null, global);
goog.exportSymbol('proto.Project', null, global);
goog.exportSymbol('proto.Snapshot', null, global);
/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.CandidateInfo = function (opt_data) {
  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.CandidateInfo, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  /**
   * @public
   * @override
   */
  proto.CandidateInfo.displayName = 'proto.CandidateInfo';
}
/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Snapshot = function (opt_data) {
  jspb.Message.initialize(
    this,
    opt_data,
    0,
    -1,
    proto.Snapshot.repeatedFields_,
    null
  );
};
goog.inherits(proto.Snapshot, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  /**
   * @public
   * @override
   */
  proto.Snapshot.displayName = 'proto.Snapshot';
}
/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Env = function (opt_data) {
  jspb.Message.initialize(
    this,
    opt_data,
    0,
    -1,
    proto.Env.repeatedFields_,
    null
  );
};
goog.inherits(proto.Env, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  /**
   * @public
   * @override
   */
  proto.Env.displayName = 'proto.Env';
}
/**
 * Generated by JsPbCodeGenerator.
 * @param {Array=} opt_data Optional initial data array, typically from a
 * server response, or constructed directly in Javascript. The array is used
 * in place and becomes part of the constructed object. It is not cloned.
 * If no data is provided, the constructed object will be empty, but still
 * valid.
 * @extends {jspb.Message}
 * @constructor
 */
proto.Project = function (opt_data) {
  jspb.Message.initialize(
    this,
    opt_data,
    0,
    -1,
    proto.Project.repeatedFields_,
    null
  );
};
goog.inherits(proto.Project, jspb.Message);
if (goog.DEBUG && !COMPILED) {
  /**
   * @public
   * @override
   */
  proto.Project.displayName = 'proto.Project';
}

if (jspb.Message.GENERATE_TO_OBJECT) {
  /**
   * Creates an object representation of this proto.
   * Field names that are reserved in JavaScript and will be renamed to pb_name.
   * Optional fields that are not set will be set to undefined.
   * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
   * For the list of reserved names please see:
   *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
   * @param {boolean=} opt_includeInstance Deprecated. whether to include the
   *     JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @return {!Object}
   */
  proto.CandidateInfo.prototype.toObject = function (opt_includeInstance) {
    return proto.CandidateInfo.toObject(opt_includeInstance, this);
  };

  /**
   * Static version of the {@see toObject} method.
   * @param {boolean|undefined} includeInstance Deprecated. Whether to include
   *     the JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @param {!proto.CandidateInfo} msg The msg instance to transform.
   * @return {!Object}
   * @suppress {unusedLocalVariables} f is only used for nested messages
   */
  proto.CandidateInfo.toObject = function (includeInstance, msg) {
    var f,
      obj = {
        candidate: jspb.Message.getFieldWithDefault(msg, 1, ''),
        jobCount: jspb.Message.getFieldWithDefault(msg, 2, 0),
      };

    if (includeInstance) {
      obj.$jspbMessageInstance = msg;
    }
    return obj;
  };
}

/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.CandidateInfo}
 */
proto.CandidateInfo.deserializeBinary = function (bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.CandidateInfo();
  return proto.CandidateInfo.deserializeBinaryFromReader(msg, reader);
};

/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.CandidateInfo} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.CandidateInfo}
 */
proto.CandidateInfo.deserializeBinaryFromReader = function (msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
      case 1:
        var value = /** @type {string} */ (reader.readString());
        msg.setCandidate(value);
        break;
      case 2:
        var value = /** @type {number} */ (reader.readInt64());
        msg.setJobCount(value);
        break;
      default:
        reader.skipField();
        break;
    }
  }
  return msg;
};

/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.CandidateInfo.prototype.serializeBinary = function () {
  var writer = new jspb.BinaryWriter();
  proto.CandidateInfo.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};

/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.CandidateInfo} message
 * @param {!jspb.BinaryWriter} writer
 * @suppress {unusedLocalVariables} f is only used for nested messages
 */
proto.CandidateInfo.serializeBinaryToWriter = function (message, writer) {
  var f = undefined;
  f = message.getCandidate();
  if (f.length > 0) {
    writer.writeString(1, f);
  }
  f = message.getJobCount();
  if (f !== 0) {
    writer.writeInt64(2, f);
  }
};

/**
 * optional string candidate = 1;
 * @return {string}
 */
proto.CandidateInfo.prototype.getCandidate = function () {
  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ''));
};

/**
 * @param {string} value
 * @return {!proto.CandidateInfo} returns this
 */
proto.CandidateInfo.prototype.setCandidate = function (value) {
  return jspb.Message.setProto3StringField(this, 1, value);
};

/**
 * optional int64 job_count = 2;
 * @return {number}
 */
proto.CandidateInfo.prototype.getJobCount = function () {
  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
};

/**
 * @param {number} value
 * @return {!proto.CandidateInfo} returns this
 */
proto.CandidateInfo.prototype.setJobCount = function (value) {
  return jspb.Message.setProto3IntField(this, 2, value);
};

/**
 * List of repeated fields within this message type.
 * @private {!Array<number>}
 * @const
 */
proto.Snapshot.repeatedFields_ = [2];

if (jspb.Message.GENERATE_TO_OBJECT) {
  /**
   * Creates an object representation of this proto.
   * Field names that are reserved in JavaScript and will be renamed to pb_name.
   * Optional fields that are not set will be set to undefined.
   * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
   * For the list of reserved names please see:
   *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
   * @param {boolean=} opt_includeInstance Deprecated. whether to include the
   *     JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @return {!Object}
   */
  proto.Snapshot.prototype.toObject = function (opt_includeInstance) {
    return proto.Snapshot.toObject(opt_includeInstance, this);
  };

  /**
   * Static version of the {@see toObject} method.
   * @param {boolean|undefined} includeInstance Deprecated. Whether to include
   *     the JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @param {!proto.Snapshot} msg The msg instance to transform.
   * @return {!Object}
   * @suppress {unusedLocalVariables} f is only used for nested messages
   */
  proto.Snapshot.toObject = function (includeInstance, msg) {
    var f,
      obj = {
        timestamp:
          (f = msg.getTimestamp()) &&
          google_protobuf_timestamp_pb.Timestamp.toObject(includeInstance, f),
        candidatesList: jspb.Message.toObjectList(
          msg.getCandidatesList(),
          proto.CandidateInfo.toObject,
          includeInstance
        ),
      };

    if (includeInstance) {
      obj.$jspbMessageInstance = msg;
    }
    return obj;
  };
}

/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Snapshot}
 */
proto.Snapshot.deserializeBinary = function (bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Snapshot();
  return proto.Snapshot.deserializeBinaryFromReader(msg, reader);
};

/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Snapshot} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Snapshot}
 */
proto.Snapshot.deserializeBinaryFromReader = function (msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
      case 1:
        var value = new google_protobuf_timestamp_pb.Timestamp();
        reader.readMessage(
          value,
          google_protobuf_timestamp_pb.Timestamp.deserializeBinaryFromReader
        );
        msg.setTimestamp(value);
        break;
      case 2:
        var value = new proto.CandidateInfo();
        reader.readMessage(
          value,
          proto.CandidateInfo.deserializeBinaryFromReader
        );
        msg.addCandidates(value);
        break;
      default:
        reader.skipField();
        break;
    }
  }
  return msg;
};

/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Snapshot.prototype.serializeBinary = function () {
  var writer = new jspb.BinaryWriter();
  proto.Snapshot.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};

/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Snapshot} message
 * @param {!jspb.BinaryWriter} writer
 * @suppress {unusedLocalVariables} f is only used for nested messages
 */
proto.Snapshot.serializeBinaryToWriter = function (message, writer) {
  var f = undefined;
  f = message.getTimestamp();
  if (f != null) {
    writer.writeMessage(
      1,
      f,
      google_protobuf_timestamp_pb.Timestamp.serializeBinaryToWriter
    );
  }
  f = message.getCandidatesList();
  if (f.length > 0) {
    writer.writeRepeatedMessage(
      2,
      f,
      proto.CandidateInfo.serializeBinaryToWriter
    );
  }
};

/**
 * optional google.protobuf.Timestamp timestamp = 1;
 * @return {?proto.google.protobuf.Timestamp}
 */
proto.Snapshot.prototype.getTimestamp = function () {
  return /** @type{?proto.google.protobuf.Timestamp} */ (jspb.Message.getWrapperField(
    this,
    google_protobuf_timestamp_pb.Timestamp,
    1
  ));
};

/**
 * @param {?proto.google.protobuf.Timestamp|undefined} value
 * @return {!proto.Snapshot} returns this
 */
proto.Snapshot.prototype.setTimestamp = function (value) {
  return jspb.Message.setWrapperField(this, 1, value);
};

/**
 * Clears the message field making it undefined.
 * @return {!proto.Snapshot} returns this
 */
proto.Snapshot.prototype.clearTimestamp = function () {
  return this.setTimestamp(undefined);
};

/**
 * Returns whether this field is set.
 * @return {boolean}
 */
proto.Snapshot.prototype.hasTimestamp = function () {
  return jspb.Message.getField(this, 1) != null;
};

/**
 * repeated CandidateInfo candidates = 2;
 * @return {!Array<!proto.CandidateInfo>}
 */
proto.Snapshot.prototype.getCandidatesList = function () {
  return /** @type{!Array<!proto.CandidateInfo>} */ (jspb.Message.getRepeatedWrapperField(
    this,
    proto.CandidateInfo,
    2
  ));
};

/**
 * @param {!Array<!proto.CandidateInfo>} value
 * @return {!proto.Snapshot} returns this
 */
proto.Snapshot.prototype.setCandidatesList = function (value) {
  return jspb.Message.setRepeatedWrapperField(this, 2, value);
};

/**
 * @param {!proto.CandidateInfo=} opt_value
 * @param {number=} opt_index
 * @return {!proto.CandidateInfo}
 */
proto.Snapshot.prototype.addCandidates = function (opt_value, opt_index) {
  return jspb.Message.addToRepeatedWrapperField(
    this,
    2,
    opt_value,
    proto.CandidateInfo,
    opt_index
  );
};

/**
 * Clears the list making it empty but non-null.
 * @return {!proto.Snapshot} returns this
 */
proto.Snapshot.prototype.clearCandidatesList = function () {
  return this.setCandidatesList([]);
};

/**
 * List of repeated fields within this message type.
 * @private {!Array<number>}
 * @const
 */
proto.Env.repeatedFields_ = [2];

if (jspb.Message.GENERATE_TO_OBJECT) {
  /**
   * Creates an object representation of this proto.
   * Field names that are reserved in JavaScript and will be renamed to pb_name.
   * Optional fields that are not set will be set to undefined.
   * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
   * For the list of reserved names please see:
   *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
   * @param {boolean=} opt_includeInstance Deprecated. whether to include the
   *     JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @return {!Object}
   */
  proto.Env.prototype.toObject = function (opt_includeInstance) {
    return proto.Env.toObject(opt_includeInstance, this);
  };

  /**
   * Static version of the {@see toObject} method.
   * @param {boolean|undefined} includeInstance Deprecated. Whether to include
   *     the JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @param {!proto.Env} msg The msg instance to transform.
   * @return {!Object}
   * @suppress {unusedLocalVariables} f is only used for nested messages
   */
  proto.Env.toObject = function (includeInstance, msg) {
    var f,
      obj = {
        name: jspb.Message.getFieldWithDefault(msg, 1, ''),
        snapshotsList: jspb.Message.toObjectList(
          msg.getSnapshotsList(),
          proto.Snapshot.toObject,
          includeInstance
        ),
      };

    if (includeInstance) {
      obj.$jspbMessageInstance = msg;
    }
    return obj;
  };
}

/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Env}
 */
proto.Env.deserializeBinary = function (bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Env();
  return proto.Env.deserializeBinaryFromReader(msg, reader);
};

/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Env} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Env}
 */
proto.Env.deserializeBinaryFromReader = function (msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
      case 1:
        var value = /** @type {string} */ (reader.readString());
        msg.setName(value);
        break;
      case 2:
        var value = new proto.Snapshot();
        reader.readMessage(value, proto.Snapshot.deserializeBinaryFromReader);
        msg.addSnapshots(value);
        break;
      default:
        reader.skipField();
        break;
    }
  }
  return msg;
};

/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Env.prototype.serializeBinary = function () {
  var writer = new jspb.BinaryWriter();
  proto.Env.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};

/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Env} message
 * @param {!jspb.BinaryWriter} writer
 * @suppress {unusedLocalVariables} f is only used for nested messages
 */
proto.Env.serializeBinaryToWriter = function (message, writer) {
  var f = undefined;
  f = message.getName();
  if (f.length > 0) {
    writer.writeString(1, f);
  }
  f = message.getSnapshotsList();
  if (f.length > 0) {
    writer.writeRepeatedMessage(2, f, proto.Snapshot.serializeBinaryToWriter);
  }
};

/**
 * optional string name = 1;
 * @return {string}
 */
proto.Env.prototype.getName = function () {
  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ''));
};

/**
 * @param {string} value
 * @return {!proto.Env} returns this
 */
proto.Env.prototype.setName = function (value) {
  return jspb.Message.setProto3StringField(this, 1, value);
};

/**
 * repeated Snapshot snapshots = 2;
 * @return {!Array<!proto.Snapshot>}
 */
proto.Env.prototype.getSnapshotsList = function () {
  return /** @type{!Array<!proto.Snapshot>} */ (jspb.Message.getRepeatedWrapperField(
    this,
    proto.Snapshot,
    2
  ));
};

/**
 * @param {!Array<!proto.Snapshot>} value
 * @return {!proto.Env} returns this
 */
proto.Env.prototype.setSnapshotsList = function (value) {
  return jspb.Message.setRepeatedWrapperField(this, 2, value);
};

/**
 * @param {!proto.Snapshot=} opt_value
 * @param {number=} opt_index
 * @return {!proto.Snapshot}
 */
proto.Env.prototype.addSnapshots = function (opt_value, opt_index) {
  return jspb.Message.addToRepeatedWrapperField(
    this,
    2,
    opt_value,
    proto.Snapshot,
    opt_index
  );
};

/**
 * Clears the list making it empty but non-null.
 * @return {!proto.Env} returns this
 */
proto.Env.prototype.clearSnapshotsList = function () {
  return this.setSnapshotsList([]);
};

/**
 * List of repeated fields within this message type.
 * @private {!Array<number>}
 * @const
 */
proto.Project.repeatedFields_ = [2];

if (jspb.Message.GENERATE_TO_OBJECT) {
  /**
   * Creates an object representation of this proto.
   * Field names that are reserved in JavaScript and will be renamed to pb_name.
   * Optional fields that are not set will be set to undefined.
   * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
   * For the list of reserved names please see:
   *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
   * @param {boolean=} opt_includeInstance Deprecated. whether to include the
   *     JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @return {!Object}
   */
  proto.Project.prototype.toObject = function (opt_includeInstance) {
    return proto.Project.toObject(opt_includeInstance, this);
  };

  /**
   * Static version of the {@see toObject} method.
   * @param {boolean|undefined} includeInstance Deprecated. Whether to include
   *     the JSPB instance for transitional soy proto support:
   *     http://goto/soy-param-migration
   * @param {!proto.Project} msg The msg instance to transform.
   * @return {!Object}
   * @suppress {unusedLocalVariables} f is only used for nested messages
   */
  proto.Project.toObject = function (includeInstance, msg) {
    var f,
      obj = {
        name: jspb.Message.getFieldWithDefault(msg, 1, ''),
        envsList: jspb.Message.toObjectList(
          msg.getEnvsList(),
          proto.Env.toObject,
          includeInstance
        ),
      };

    if (includeInstance) {
      obj.$jspbMessageInstance = msg;
    }
    return obj;
  };
}

/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.Project}
 */
proto.Project.deserializeBinary = function (bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.Project();
  return proto.Project.deserializeBinaryFromReader(msg, reader);
};

/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.Project} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.Project}
 */
proto.Project.deserializeBinaryFromReader = function (msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
      case 1:
        var value = /** @type {string} */ (reader.readString());
        msg.setName(value);
        break;
      case 2:
        var value = new proto.Env();
        reader.readMessage(value, proto.Env.deserializeBinaryFromReader);
        msg.addEnvs(value);
        break;
      default:
        reader.skipField();
        break;
    }
  }
  return msg;
};

/**
 * Serializes the message to binary data (in protobuf wire format).
 * @return {!Uint8Array}
 */
proto.Project.prototype.serializeBinary = function () {
  var writer = new jspb.BinaryWriter();
  proto.Project.serializeBinaryToWriter(this, writer);
  return writer.getResultBuffer();
};

/**
 * Serializes the given message to binary data (in protobuf wire
 * format), writing to the given BinaryWriter.
 * @param {!proto.Project} message
 * @param {!jspb.BinaryWriter} writer
 * @suppress {unusedLocalVariables} f is only used for nested messages
 */
proto.Project.serializeBinaryToWriter = function (message, writer) {
  var f = undefined;
  f = message.getName();
  if (f.length > 0) {
    writer.writeString(1, f);
  }
  f = message.getEnvsList();
  if (f.length > 0) {
    writer.writeRepeatedMessage(2, f, proto.Env.serializeBinaryToWriter);
  }
};

/**
 * optional string name = 1;
 * @return {string}
 */
proto.Project.prototype.getName = function () {
  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ''));
};

/**
 * @param {string} value
 * @return {!proto.Project} returns this
 */
proto.Project.prototype.setName = function (value) {
  return jspb.Message.setProto3StringField(this, 1, value);
};

/**
 * repeated Env envs = 2;
 * @return {!Array<!proto.Env>}
 */
proto.Project.prototype.getEnvsList = function () {
  return /** @type{!Array<!proto.Env>} */ (jspb.Message.getRepeatedWrapperField(
    this,
    proto.Env,
    2
  ));
};

/**
 * @param {!Array<!proto.Env>} value
 * @return {!proto.Project} returns this
 */
proto.Project.prototype.setEnvsList = function (value) {
  return jspb.Message.setRepeatedWrapperField(this, 2, value);
};

/**
 * @param {!proto.Env=} opt_value
 * @param {number=} opt_index
 * @return {!proto.Env}
 */
proto.Project.prototype.addEnvs = function (opt_value, opt_index) {
  return jspb.Message.addToRepeatedWrapperField(
    this,
    2,
    opt_value,
    proto.Env,
    opt_index
  );
};

/**
 * Clears the list making it empty but non-null.
 * @return {!proto.Project} returns this
 */
proto.Project.prototype.clearEnvsList = function () {
  return this.setEnvsList([]);
};

goog.object.extend(exports, proto);
<commit_msg>Delete javascript version of the generated file.<commit_after><|endoftext|>


<commit_before>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var ti = require('./index'),
	appc = require('node-appc'),
	afs = appc.fs,
	async = require('async'),
	fs = require('fs'),
	path = require('path'),
	exec = require("child_process").exec;

exports.detect = function (projectDir, logger, callback) {
	var sdkVersion = appc.version.format(ti.manifest.version, 1, 3),
		searchPaths = (projectDir ? [projectDir] : []).concat(appc.environ.os.sdkPaths.map(function (p) {
			return afs.resolvePath(p);
		})),
		moduleZipRegExp = /^.+\-.+?\-.+?\.zip$/,
		modules = {};

	function searchModuleDir(moduleName, modulePath, platform) {
		afs.visitDirsSync(modulePath, function (version, versionPath) {
			var manifestFile = path.join(versionPath, 'manifest');
			if (afs.exists(manifestFile)) {
				var module = modules[moduleName] || (modules[moduleName] = {}),
					details = module[version] || (module[version] = {
						modulePath: versionPath,
						manifest: {},
						platforms: {}
					});

				fs.readFileSync(manifestFile).toString().split('\n').forEach(function (line) {
					var p = line.indexOf(':'),
						key,
						value;
					if (line.charAt(0) != '#' && p != -1) {
						key = line.substring(0, p);
						value = details.manifest[key] = line.substring(p + 1).trim();
						if (platform) {
							// old style
							details.platforms[platform] || (details.platforms[platform] = { originalManifest: {} });
							details.platforms[platform].originalManifest[key] = value;
						} else {
							// new style
							key == 'platforms' && value.split(',').forEach(function (p) {
								details.platforms[p.trim()] = {}; // empty for now...
							});
						}
					}
				});

				logger && logger.debug(__('Detected module for %s: %s %s @ %s', Object.keys(details.platforms).join(','), details.manifest.moduleid, details.manifest.version, details.modulePath));
			}
		});
	}

	async.parallel(searchPaths.map(function (titaniumRoot) {
		return function(cb) {
			afs.exists(titaniumRoot, function (exists) {
				if (!exists) return cb();

				var tasks = [];

				// auto-install zipped modules
				fs.readdirSync(titaniumRoot).forEach(function (file) {
					var moduleZip = path.join(titaniumRoot, file);
					if (fs.statSync(moduleZip).isFile() && moduleZipRegExp.test(file)) {
						tasks.push(function (taskDone) {
							logger && logger.info(__('Installing module: %s', file));
							// TODO: we should unzip the module to a temp directory, then manual validate the module's
							//       correctness before copying to the modules directory
							if (/osx|linux/.test(appc.environ.os.name)) {
								exec('unzip -o -qq "' + moduleZip + '" -d "' + titaniumRoot + '"', function (err, stdout, stderr) {
									fs.unlinkSync(moduleZip);
									taskDone();
								});
							} else {
								var AdmZip = require('adm-zip'),
									zip = new AdmZip(moduleZip);
								zip.extractAllTo(titaniumRoot, true);
								fs.unlinkSync(moduleZip);
								taskDone();
							}
						});
					}
				});

				async.parallel(tasks, function () {
					// search module directories
					var moduleRoot = path.join(titaniumRoot, 'modules');
					logger && logger.debug(__('Detecting modules in %s', moduleRoot));
					afs.visitDirs(moduleRoot, function (platform, modulesPath) {
						if (/^osx|win32|linux$/.test(platform)) {
							// skip old Titanium Desktop directories
						} else if (/^android|iphone|mobileweb|commonjs$/.test(platform)) {
							// old style module directory
							afs.visitDirsSync(modulesPath, function (moduleName, modulePath) {
								searchModuleDir(moduleName, modulePath, platform);
							});
						} else {
							// possibly a new style module directory
							searchModuleDir(platform, modulesPath);
						}
					}, cb);
				});
			});
		};
	}), function () {
		callback(modules);
	});
};

exports.find = function (modules, platforms, projectDir, logger, callback) {
	var result = {
			found: [],
			missing: []
		};

	// if there are modules to find, then just exit now
	if (!modules || !modules.length) return callback(result);

	Array.isArray(platforms) || (platforms = [platforms]);
	platforms.push('commonjs');

	exports.detect(projectDir, logger, function (installed) {
		modules.forEach(function (module) {
			logger && logger.debug(__('Looking for Titanium Module id: %s, version: %s, platform: %s', module.id, module.version, module.platform));
			if (module.id && installed[module.id]) {
				var mp = module.platform ? [module.platform] : platforms,
					i = 0,
					info,
					platform,
					found;
				while (!found && i < mp.length) {
					platform = mp[i++];
					if (platforms.indexOf(platform) != -1) {
						if (module.version) {
							info = installed[module.id][module.version];
							if (info && info.platforms[platform]) {
								module.info = info;
								result.found.push(module);
								found = true;
							}
						} else {
							// no version, scan newest versions for the first one to match this platform
							var versions = Object.keys(installed[module.id]).sort().reverse(),
								j = 0;
							while (j < versions.length) {
								info = installed[module.id][versions[j++]];
								if (info.platforms[platform]) {
									module.info = info;
									result.found.push(module);
									found = true;
									break;
								}
							}
						}
					}
				}
				found || result.missing.push(module);
			} else {
				logger && logger.warn(__('Could not find Titanium Module id: %s, version: %s, platform: %s', module.id, module.version, module.platform));
				result.missing.push(module);
			}
		});

		callback(result);
	});
};<commit_msg>[TIMOB-8652] Moved moduleRoot out of inner parallel task for better performance.<commit_after>/**
 * Titanium SDK Library for Node.js
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * Please see the LICENSE file for information about licensing.
 */

var ti = require('./index'),
	appc = require('node-appc'),
	afs = appc.fs,
	async = require('async'),
	fs = require('fs'),
	path = require('path'),
	exec = require("child_process").exec;

exports.detect = function (projectDir, logger, callback) {
	var sdkVersion = appc.version.format(ti.manifest.version, 1, 3),
		searchPaths = (projectDir ? [projectDir] : []).concat(appc.environ.os.sdkPaths.map(function (p) {
			return afs.resolvePath(p);
		})),
		moduleZipRegExp = /^.+\-.+?\-.+?\.zip$/,
		modules = {};

	function searchModuleDir(moduleName, modulePath, platform) {
		afs.visitDirsSync(modulePath, function (version, versionPath) {
			var manifestFile = path.join(versionPath, 'manifest');
			if (afs.exists(manifestFile)) {
				var module = modules[moduleName] || (modules[moduleName] = {}),
					details = module[version] || (module[version] = {
						modulePath: versionPath,
						manifest: {},
						platforms: {}
					});

				fs.readFileSync(manifestFile).toString().split('\n').forEach(function (line) {
					var p = line.indexOf(':'),
						key,
						value;
					if (line.charAt(0) != '#' && p != -1) {
						key = line.substring(0, p);
						value = details.manifest[key] = line.substring(p + 1).trim();
						if (platform) {
							// old style
							details.platforms[platform] || (details.platforms[platform] = { originalManifest: {} });
							details.platforms[platform].originalManifest[key] = value;
						} else {
							// new style
							key == 'platforms' && value.split(',').forEach(function (p) {
								details.platforms[p.trim()] = {}; // empty for now...
							});
						}
					}
				});

				logger && logger.debug(__('Detected module for %s: %s %s @ %s', Object.keys(details.platforms).join(','), details.manifest.moduleid, details.manifest.version, details.modulePath));
			}
		});
	}

	async.parallel(searchPaths.map(function (titaniumRoot) {
		return function(cb) {
			afs.exists(titaniumRoot, function (exists) {
				if (!exists) return cb();

				var moduleRoot = path.join(titaniumRoot, 'modules'),
					tasks = [];

				// auto-install zipped modules
				fs.readdirSync(titaniumRoot).forEach(function (file) {
					var moduleZip = path.join(titaniumRoot, file);
					if (fs.statSync(moduleZip).isFile() && moduleZipRegExp.test(file)) {
						tasks.push(function (taskDone) {
							logger && logger.info(__('Installing module: %s', file));
							// TODO: we should unzip the module to a temp directory, then manual validate the module's
							//       correctness before copying to the modules directory
							if (/osx|linux/.test(appc.environ.os.name)) {
								exec('unzip -o -qq "' + moduleZip + '" -d "' + titaniumRoot + '"', function (err, stdout, stderr) {
									fs.unlinkSync(moduleZip);
									taskDone();
								});
							} else {
								var AdmZip = require('adm-zip'),
									zip = new AdmZip(moduleZip);
								zip.extractAllTo(titaniumRoot, true);
								fs.unlinkSync(moduleZip);
								taskDone();
							}
						});
					}
				});

				async.parallel(tasks, function () {
					// search module directories
					logger && logger.debug(__('Detecting modules in %s', moduleRoot));
					afs.visitDirs(moduleRoot, function (platform, modulesPath) {
						if (/^osx|win32|linux$/.test(platform)) {
							// skip old Titanium Desktop directories
						} else if (/^android|iphone|mobileweb|commonjs$/.test(platform)) {
							// old style module directory
							afs.visitDirsSync(modulesPath, function (moduleName, modulePath) {
								searchModuleDir(moduleName, modulePath, platform);
							});
						} else {
							// possibly a new style module directory
							searchModuleDir(platform, modulesPath);
						}
					}, cb);
				});
			});
		};
	}), function () {
		callback(modules);
	});
};

exports.find = function (modules, platforms, projectDir, logger, callback) {
	var result = {
			found: [],
			missing: []
		};

	// if there are modules to find, then just exit now
	if (!modules || !modules.length) return callback(result);

	Array.isArray(platforms) || (platforms = [platforms]);
	platforms.push('commonjs');

	exports.detect(projectDir, logger, function (installed) {
		modules.forEach(function (module) {
			logger && logger.debug(__('Looking for Titanium Module id: %s, version: %s, platform: %s', module.id, module.version, module.platform));
			if (module.id && installed[module.id]) {
				var mp = module.platform ? [module.platform] : platforms,
					i = 0,
					info,
					platform,
					found;
				while (!found && i < mp.length) {
					platform = mp[i++];
					if (platforms.indexOf(platform) != -1) {
						if (module.version) {
							info = installed[module.id][module.version];
							if (info && info.platforms[platform]) {
								module.info = info;
								result.found.push(module);
								found = true;
							}
						} else {
							// no version, scan newest versions for the first one to match this platform
							var versions = Object.keys(installed[module.id]).sort().reverse(),
								j = 0;
							while (j < versions.length) {
								info = installed[module.id][versions[j++]];
								if (info.platforms[platform]) {
									module.info = info;
									result.found.push(module);
									found = true;
									break;
								}
							}
						}
					}
				}
				found || result.missing.push(module);
			} else {
				logger && logger.warn(__('Could not find Titanium Module id: %s, version: %s, platform: %s', module.id, module.version, module.platform));
				result.missing.push(module);
			}
		});

		callback(result);
	});
};<|endoftext|>