<commit_before>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;

  var ServiceUploadDetail = window.shared.ServiceUploadDetail = React.createClass({

    propTypes: {
      data: React.PropTypes.object.isRequired,
      onClickDeleteServiceUpload: React.PropTypes.func.isRequired
    },

    getInitialState: function () {
      return {
        showStudentLinks: false,
        showDeletionConfirmation: false,
      };
    },

    render: function () {
      var data = this.props.data;

      return dom.div({ key: String(data.id), style: this.dataCellStyle() },
        dom.div({ style: { marginBottom: 18 } },
          dom.span({ style: { fontSize: 22 } }, data.file_name),
          dom.span({ style: { fontSize: 13, color: '#999', marginLeft: 15 }},
            'Uploaded ' + moment.utc((data.created_at).slice(0, 10)).format('M/D/YYYY')
          )
        ),
        this.renderServiceTypeName(),
        dom.div({},
          dom.span({ style: { color: '#333' }}, String(data.services.length) + ' students'),
          this.renderShowStudentsLink(),
          this.renderDeletionArea()
        ),
        this.renderStudentLinks()
      );
    },

    renderShowStudentsLink: function () {
      if (this.props.data.services.length === 0) return;

      return dom.span({},
        this.infoSeparator(),
        dom.a({
          style: window.shared.styles.link,
          onClick: this.toggleShowStudents
        }, this.state.showStudentLinks ? 'Hide students' : 'Show students')
      );
    },

    renderServiceTypeName: function () {
      var service = this.props.data.services[0];

      if (!service) return;

      return dom.div({ style: { marginBottom: 18, fontSize: 18, color: '#555' } },
        service.service_type.name
      )
    },

    renderDeletionArea: function () {
      if (this.state.showDeletionConfirmation) {
        return dom.div({},
          dom.br({}),
          dom.p({},
            'Are you suure you want to delete this upload and its ' +
            this.props.data.services.length +
            ' services?'),
          dom.br({}),
          dom.button({
            className: 'btn',
            onClick: this.props.onClickBulkDeleteServices.bind(null, this.props.data.id)
          }, 'Yes, confirm deletion.'),
          dom.button({
            className: 'btn',
            onClick: this.toggleDeletionConfirmation,
            style: { marginLeft: 10 }
          }, 'Cancel deletion.')
        );
      } else {
        return dom.span({},
          this.infoSeparator(),
          dom.a({
            style: merge(window.shared.styles.link, {
              color: 'red', fontSize: 15
            }),
            onClick: this.toggleDeletionConfirmation
          }, 'Delete')
        );
      };
    },

    toggleDeletionConfirmation: function () {
      this.setState({ showDeletionConfirmation: !this.state.showDeletionConfirmation })
    },

    renderStudentLinks: function () {
      if (!this.state.showStudentLinks) return null;

      var students = this.props.data.services.map(function(service) { return service.student; });

      var studentLinks = students.map(function(student) {
        return dom.div({
          key: this.props.data.file_name + ' ' + student.id,
          style: {
            marginLeft: 15
          }
        },
          dom.li({},
            dom.a({
              href: '/students/' + student.id,
              style: window.shared.styles.link
            }, [student.first_name, student.last_name].join(' '))
          )
        );
      }, this);

      return dom.div({}, dom.br({}), studentLinks);
    },

    toggleShowStudents: function () {
      this.setState({ showStudentLinks: !(this.state.showStudentLinks) })
    },

    dataCellStyle: function () {
      return {
        width: '100%',
        borderBottom: '1px solid #999',
        borderLeft: '1px solid #999',
        padding: 30,
      };
    },

    infoSeparator: function () {
      return dom.span({}, ' | ');
    },

  });

})();
<commit_msg>Fix missing function name<commit_after>(function() {
  window.shared || (window.shared = {});
  var dom = window.shared.ReactHelpers.dom;
  var createEl = window.shared.ReactHelpers.createEl;
  var merge = window.shared.ReactHelpers.merge;

  var ServiceUploadDetail = window.shared.ServiceUploadDetail = React.createClass({

    propTypes: {
      data: React.PropTypes.object.isRequired,
      onClickDeleteServiceUpload: React.PropTypes.func.isRequired
    },

    getInitialState: function () {
      return {
        showStudentLinks: false,
        showDeletionConfirmation: false,
      };
    },

    render: function () {
      var data = this.props.data;

      return dom.div({ key: String(data.id), style: this.dataCellStyle() },
        dom.div({ style: { marginBottom: 18 } },
          dom.span({ style: { fontSize: 22 } }, data.file_name),
          dom.span({ style: { fontSize: 13, color: '#999', marginLeft: 15 }},
            'Uploaded ' + moment.utc((data.created_at).slice(0, 10)).format('M/D/YYYY')
          )
        ),
        this.renderServiceTypeName(),
        dom.div({},
          dom.span({ style: { color: '#333' }}, String(data.services.length) + ' students'),
          this.renderShowStudentsLink(),
          this.renderDeletionArea()
        ),
        this.renderStudentLinks()
      );
    },

    renderShowStudentsLink: function () {
      if (this.props.data.services.length === 0) return;

      return dom.span({},
        this.infoSeparator(),
        dom.a({
          style: window.shared.styles.link,
          onClick: this.toggleShowStudents
        }, this.state.showStudentLinks ? 'Hide students' : 'Show students')
      );
    },

    renderServiceTypeName: function () {
      var service = this.props.data.services[0];

      if (!service) return;

      return dom.div({ style: { marginBottom: 18, fontSize: 18, color: '#555' } },
        service.service_type.name
      )
    },

    renderDeletionArea: function () {
      if (this.state.showDeletionConfirmation) {
        return dom.div({},
          dom.br({}),
          dom.p({},
            'Are you suure you want to delete this upload and its ' +
            this.props.data.services.length +
            ' services?'),
          dom.br({}),
          dom.button({
            className: 'btn',
            onClick: this.props.onClickDeleteServiceUpload.bind(null, this.props.data.id)
          }, 'Yes, confirm deletion.'),
          dom.button({
            className: 'btn',
            onClick: this.toggleDeletionConfirmation,
            style: { marginLeft: 10 }
          }, 'Cancel deletion.')
        );
      } else {
        return dom.span({},
          this.infoSeparator(),
          dom.a({
            style: merge(window.shared.styles.link, {
              color: 'red', fontSize: 15
            }),
            onClick: this.toggleDeletionConfirmation
          }, 'Delete')
        );
      };
    },

    toggleDeletionConfirmation: function () {
      this.setState({ showDeletionConfirmation: !this.state.showDeletionConfirmation })
    },

    renderStudentLinks: function () {
      if (!this.state.showStudentLinks) return null;

      var students = this.props.data.services.map(function(service) { return service.student; });

      var studentLinks = students.map(function(student) {
        return dom.div({
          key: this.props.data.file_name + ' ' + student.id,
          style: {
            marginLeft: 15
          }
        },
          dom.li({},
            dom.a({
              href: '/students/' + student.id,
              style: window.shared.styles.link
            }, [student.first_name, student.last_name].join(' '))
          )
        );
      }, this);

      return dom.div({}, dom.br({}), studentLinks);
    },

    toggleShowStudents: function () {
      this.setState({ showStudentLinks: !(this.state.showStudentLinks) })
    },

    dataCellStyle: function () {
      return {
        width: '100%',
        borderBottom: '1px solid #999',
        borderLeft: '1px solid #999',
        padding: 30,
      };
    },

    infoSeparator: function () {
      return dom.span({}, ' | ');
    },

  });

})();
<|endoftext|>


<commit_before>Ext.define('TM.model.Assignee', {
  extend: 'Ext.data.Model',

  fields: [
    { name: 'id', type: 'int' },
    { name: 'name' },
    { name: 'class_name' },
    { name: 'parent_id', type: 'int' }
  ],

  proxy: {
    type: 'rest',
    url: '/assignees.json',
    reader: {
      root: 'assignees',
      totalProperty: 'total'
    }
  }
});
<commit_msg>Defined methods for generating detailed ids<commit_after>Ext.define('TM.model.Assignee', {
  extend: 'Ext.data.Model',

  fields: [
    { name: 'id', type: 'int' },
    { name: 'name' },
    { name: 'class_name' },
    { name: 'parent_id', type: 'int' }
  ],

  proxy: {
    type: 'rest',
    url: '/assignees.json',
    reader: {
      root: 'assignees',
      totalProperty: 'total'
    }
  },

  getId: function(detailed) {
    if(detailed) {
      return this.get('class_name') + '-' + this.get('id');
    } else {
      return this.get('id');
    }
  },

  getParentId: function(detailed) {
    if(this.get('parent_id') && detailed) {
      return this.get('class_name') + '-' + this.get('parent_id');
    } else {
      return this.get('parent_id');
    }
  }
});
<|endoftext|>


<commit_before>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {Component, PropTypes} from 'react';
import provide from 'react-redux-provide';
import selectn from 'selectn';

import SelectField from 'material-ui/lib/SelectField';
import MenuItem from 'material-ui/lib/menus/menu-item';

@provide
export default class DirectoryList extends Component {

  static propTypes = {
    fetchDirectory: PropTypes.func.isRequired,
    computeDirectory: PropTypes.object.isRequired,
    directory: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    label: PropTypes.string.isRequired,
    fancy: PropTypes.bool,
    value: PropTypes.string
  };

  static defaultProps = {
    fancy: true
  };

  constructor(props) {
    super(props);

    this._handleChange = this._handleChange.bind(this);
    this._handleStandardSelectChange = this._handleStandardSelectChange.bind(this);
  }

  _handleChange(event, index, value) {
    this.props.onChange(value);
  }

  _handleStandardSelectChange(event) {
    this.props.onChange(event.target.value);
  }

  componentWillReceiveProps(nextProps) {
    // Ensure value is in sync -- relevant for setting default value dynamically
    if (nextProps.value != undefined) {
      this.props.onChange(nextProps.value);
    }
  }

  componentDidMount() {
    this.props.fetchDirectory(this.props.directory);
  }

  render() {

      let previewStyles = {
        padding: '10px'
      }

      const { computeDirectory } = this.props;

      let entries = selectn('directories.' + this.props.directory, computeDirectory) || [];

      return (

          {
            (this.props.fancy) ?

            <SelectField value={this.props.value} onChange={this._handleChange} floatingLabelText={'Select ' + this.props.label + ':'}>
              {entries.map((entry) =>
                <MenuItem key={entry.value} value={entry.value} primaryText={entry.text} />
              )}
            </SelectField>

            :

            <select value={this.props.value} onChange={this._handleStandardSelectChange}>
              {entries.map((entry) =>
                <option key={entry.value} value={entry.value}>{entry.text}</option>
              )}
            </select>
          }

      );
    }
}
<commit_msg>Fix bug with select field overflow<commit_after>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {Component, PropTypes} from 'react';
import provide from 'react-redux-provide';
import selectn from 'selectn';

import SelectField from 'material-ui/lib/SelectField';
import MenuItem from 'material-ui/lib/menus/menu-item';

@provide
export default class DirectoryList extends Component {

  static propTypes = {
    fetchDirectory: PropTypes.func.isRequired,
    computeDirectory: PropTypes.object.isRequired,
    directory: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    label: PropTypes.string.isRequired,
    fancy: PropTypes.bool,
    value: PropTypes.string
  };

  static defaultProps = {
    fancy: true
  };

  constructor(props) {
    super(props);

    this._handleChange = this._handleChange.bind(this);
    this._handleStandardSelectChange = this._handleStandardSelectChange.bind(this);
  }

  _handleChange(event, index, value) {
    this.props.onChange(value);
  }

  _handleStandardSelectChange(event) {
    this.props.onChange(event.target.value);
  }

  componentWillReceiveProps(nextProps) {
    // Ensure value is in sync -- relevant for setting default value dynamically
    if (nextProps.value != undefined) {
      this.props.onChange(nextProps.value);
    }
  }

  componentDidMount() {
    this.props.fetchDirectory(this.props.directory);
  }

  render() {

      let previewStyles = {
        padding: '10px'
      }

      const { computeDirectory } = this.props;

      let entries = selectn('directories.' + this.props.directory, computeDirectory) || [];

      return (

          {
            (this.props.fancy) ?

            <SelectField maxHeight={300} autoWidth={true} value={this.props.value} onChange={this._handleChange} floatingLabelText={'Select ' + this.props.label + ':'}>
              {entries.map((entry) =>
                <MenuItem key={entry.value} value={entry.value} primaryText={entry.text} />
              )}
            </SelectField>

            :

            <select value={this.props.value} onChange={this._handleStandardSelectChange}>
              {entries.map((entry) =>
                <option key={entry.value} value={entry.value}>{entry.text}</option>
              )}
            </select>
          }

      );
    }
}
<|endoftext|>


<commit_before>import React from 'react';
import Logo from 'flavours/glitch/components/logo';
import { Link, withRouter } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { registrationsOpen, me } from 'flavours/glitch/initial_state';
import Avatar from 'flavours/glitch/components/avatar';
import Permalink from 'flavours/glitch/components/permalink';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

const Account = connect(state => ({
  account: state.getIn(['accounts', me]),
}))(({ account }) => (
  <Permalink href={account.get('url')} to={`/@${account.get('acct')}`} title={account.get('acct')}>
    <Avatar account={account} size={35} />
  </Permalink>
));

export default @withRouter
class Header extends React.PureComponent {

  static contextTypes = {
    identity: PropTypes.object,
  };

  static propTypes = {
    location: PropTypes.object,
  };

  render () {
    const { signedIn } = this.context.identity;
    const { location } = this.props;

    let content;

    if (signedIn) {
      content = (
        <>
          {location.pathname !== '/publish' && <Link to='/publish' className='button'><FormattedMessage id='compose_form.publish' defaultMessage='Publish' /></Link>}
          <Account />
        </>
      );
    } else {
      content = (
        <>
          <FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' />
          <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
        </>
      );
    }

    return (

        <Link to='/' className='ui__header__logo'><Logo /></Link>

          {content}

    );
  }

}
<commit_msg>[Glitch] Make the button that expands the publish form differentiable from the button that publishes a post<commit_after>import React from 'react';
import Logo from 'flavours/glitch/components/logo';
import { Link, withRouter } from 'react-router-dom';
import { FormattedMessage } from 'react-intl';
import { registrationsOpen, me } from 'flavours/glitch/initial_state';
import Avatar from 'flavours/glitch/components/avatar';
import Permalink from 'flavours/glitch/components/permalink';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

const Account = connect(state => ({
  account: state.getIn(['accounts', me]),
}))(({ account }) => (
  <Permalink href={account.get('url')} to={`/@${account.get('acct')}`} title={account.get('acct')}>
    <Avatar account={account} size={35} />
  </Permalink>
));

export default @withRouter
class Header extends React.PureComponent {

  static contextTypes = {
    identity: PropTypes.object,
  };

  static propTypes = {
    location: PropTypes.object,
  };

  render () {
    const { signedIn } = this.context.identity;
    const { location } = this.props;

    let content;

    if (signedIn) {
      content = (
        <>
          {location.pathname !== '/publish' && <Link to='/publish' className='button'><FormattedMessage id='compose_form.publish_form' defaultMessage='Publish' /></Link>}
          <Account />
        </>
      );
    } else {
      content = (
        <>
          <FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' />
          <FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
        </>
      );
    }

    return (

        <Link to='/' className='ui__header__logo'><Logo /></Link>

          {content}

    );
  }

}
<|endoftext|>


<commit_before>/*
 * jquery.portlet 1.1.0
 *
 * Copyright (c) 2012
 *   咖啡兔 (http://www.kafeitu.me)
 *
 * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
 * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
 *
 * See Detail: http://www.kafeitu.me/jquery-ui-portlet.html
 */
(function($) {
    $.widget("kft.portlet", {
        options: {
            columns: {},
            sortable: true,
            singleView: true,
            removeItem: null
        },

        /**
         * create portlet widget
         */
        _create: function() {
            this.element.addClass("ui-portlet");
            var _this = this;
            var _ele = _this.element;
            var o = _this.options;

            $.each(o.columns, function(ci, c) {

                var $column = $('
', {
                    'class': 'ui-portlet-column',
                    width: c.width
                }).appendTo(_ele);

                $.each(c.portlets, function(pi, p) {

                    var item = $('
', {
                        'class': 'ui-portlet-item ui-widget ui-widget-content ui-helper-clearfix ui-corner-all',
                    }).data('option', p).appendTo($column);
                    if(p.attrs) {
                        item.attr(p.attrs);
                    }

                    // title
                    var title = $('
', {
                        'class': 'ui-portlet-header ui-widget-header ui-corner-all',
                        html: function() {
                            if($.isFunction(p.title)) {
                                return p.title;
                            }
                            return "" + p.title;
                        }
                    }).appendTo(item);

                    // add icon for title
                    if (p.icon) {
                        title.prepend("");
                    }

                    // event element
                    title.prepend("");
                    title.prepend("");
                    title.prepend("");

                    // content
                    var ct = $('
', {
                        'class': 'ui-portlet-content'
                    }).appendTo(item);

                    // set content style
                    if(p.content.style) {
                        $(ct).css(p.content.style);
                    }

                    // set attrs
                    if(p.content.attrs) {
                        $.each(p.content.attrs, function(k, v) {
                            var attr = ct.attr(k);
                            if(attr) {
                                if(k == 'style' && v.substr(v.length - 1) != ';') {
                                    attr += ';';
                                }
                                if(k == 'class') {
                                    attr += ' ';
                                }
                                attr += v;
                            }
                            ct.attr(k, attr);
                        });
                    }

                    // load content
                    _this._content.call(_ele, item, p, function(data) {
                        // load scripts
                        _this._loadScripts(p.scripts);
                    });
                });
            });

            // init events
            _this._initEvents();

            // bind single view
            _this._regSingleView();

            // enable/disable sortable
            _this._sortable(o.sortable);
        },

        /**
         * set option for plugin
         * @param {[type]} key   key
         * @param {[type]} value value
         */
        _setOption: function(key, value) {
            // static options
            if(this.options[key]) {
                this.options[key] = value;
            }

            // need handle speical
            switch(key) {
            case "sortable":
                this._sortable(value);
                break;
            }
        },

        /**
         * single view
         */
        _regSingleView: function() {
            var _ele = this.element;
            $(_ele).find('.ui-portlet-header').dblclick(function() {
                var $item = $(this).parents('.ui-portlet-item');
                var p = $item.data('option');

                // recovery normal model
                if($item.hasClass('ui-portlet-single-view')) {
                    $(_ele).find('.ui-portlet-item').show();
                    $item.removeClass('ui-portlet-single-view').animate({
                        width: $item.data('width'),
                        height: $item.data('height')
                    }).css({
                        position: 'static'
                    }).removeData('width').removeData('height');

                    // callback
                    if (p.singleView) {
                        if ($.isFunction(p.singleView.recovery)) {
                            p.singleView.recovery.call($item, p);
                        }
                    }
                } else {
                    // enable single view
                    $(_ele).find('.ui-portlet-item').hide();
                    // move left:0 top:0, set width use body's width
                    $item.show().addClass('ui-portlet-single-view').data({
                        width: $item.width(),
                        height: $item.height()
                    }).css({
                        position: 'absolute',
                        left: 0,
                        top: 0
                    });

                    // set width and height when enable single view
                    var wh = {};
                    if (p.singleView) {
                        // use custom width and height
                        if (p.singleView.width) {
                            if ($.isFunction(p.singleView.width)) {
                                wh.width = p.singleView.width.call($item, p);
                            } else {
                                wh.width = p.singleView.width;
                            }
                        }
                        if (p.singleView.height) {
                            if ($.isFunction(p.singleView.height)) {
                                wh.height = p.singleView.height.call($item, p);
                            } else {
                                wh.height = p.singleView.height;
                            }
                        }

                    } else {
                        // use default width
                        wh.width = $(_ele).width() + 14;
                    }

                    $item.animate({
                        width: wh.width,
                        height: wh.height
                    });

                    // callback
                    if (p.singleView && $.isFunction(p.singleView.enable)) {
                        p.singleView.enable.call($item, p);
                    }
                }
            });
        },

        /**
         * load java scripts
         * @param  {[string]} scripts [description]
         */
        _loadScripts: function(scripts) {
            if(scripts) {
                $.each(scripts, function() {
                    var head = $('head').remove('#loadScript');
                    $("").attr({
                        src: this,
                        type: 'text/javascript',
                        id: 'loadScript'
                    }).appendTo(head);
                });
            }
        },

        /**
         * enable/disable sortable
         * @param  {[type]} value [true|false]
         */
        _sortable: function(value) {
            var st = $(".ui-portlet-column", this.element).sortable({
                connectWith: ".ui-portlet-column"
            }).disableSelection();
            if(value === true) {
                $(this.element).find('.ui-portlet-header').css('cursor', 'move');
                st.sortable('enable');
            } else {
                $(this.element).find('.ui-portlet-header').css('cursor', 'default');
                st.sortable('disable');
            }
        },

        /**
         * events and handlers
         * @return {[type]} [description]
         */
        _initEvents: function() {
            var _this = this;

            // toggle contents
            var toggle = $(".ui-portlet-toggle", this.element).click(function() {
                $(this).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
                $(this).parents(".ui-portlet-item:first").find(".ui-portlet-content").toggle();
            });

            var refresh = $(".ui-portlet-refresh", this.element).click(function(event) {
                _this.refresh.call(_this, event);
            });

            var close = $(".ui-portlet-close", this.element).click(function(event) {
                _this._destoryItem.call(_this, event);
            });

            this._hoverable(toggle.parent());
            this._hoverable(refresh.parent());
        },

        /**
         * hoverable
         */
        _hoverable: function(element) {
            $(element).hover(function() {
                $(this).addClass('ui-state-hover');
            }, function() {
                $(this).removeClass('ui-state-hover');
            });
        },

        /**
         * destory single portlet
         */
        _destoryItem: function(event) {
            var o = this.options;
            var item = $(event.target).parents('.ui-portlet-item');
            item.remove();
            if($.isFunction(o.removeItem)) {
                o.removeItem();
            }
        },

        /**
         * refresh contents
         */
        refresh: function(event) {
            var o = this.options;
            var portlet = $(event.target).parents('.ui-portlet');
            var item = $(event.target).parents('.ui-portlet-item');
            var pio = item.data('option');
            var ct = item.find('.ui-portlet-content');
            var pt = item.parents('.ui-portlet');

            // callback
            if($.isFunction(pio.beforeRefresh)) {
                pio.beforeRefresh.call(pt, pio);
            }

            // set contents
            this._content.call(portlet, item, pio, function(data) {
                // callback
                if($.isFunction(pio.afterRefresh)) {
                    pio.afterRefresh.call(pt, data, pio);
                }
            });

            // load scripts
            this._loadScripts(pio.scripts);
        },

        /**
         * get content from multi styles
         * @param  {[type]} item [.ui-portlet-item]
         * @param  {[type]} pio  [portlet configs]
         * @param  {[type]} cl   [callback after load]
         */
        _content: function(item, pio, cl) {
            var o = this.options;
            var that = this;
            var type = pio.content.type;
            var content = null;
            var ct = item.find('.ui-portlet-content');

            // before show callback
            if($.isFunction(pio.content.beforeShow)) {
                pio.content.beforeShow.call(this, pio.content.text);
            }

            if(type == 'text') {
                content = pio.content.text;

                // get content from function
                if($.isFunction(content)) {
                    content = content(that, item, pio);
                }

                if($.isFunction(cl)) {
                    cl.call(that, content);
                }
                ct.html(content);
                _callAfterShow(pio.content.text);
            } else if(type == 'ajax') {
                var dataType = pio.content.dataType || 'html';
                $.ajax({
                    url: pio.content.url,
                    dataType: dataType,
                    beforeSend: function() {
                        $(ct).html('Loading...');
                    },
                    success: function(data, textStatus, jqXHR) {
                        if(dataType == 'html') {
                            content = data;
                            $(ct).html(data);
                        } else if(dataType == 'json') {
                            content = pio.content.formatter(o, pio, data);
                            $(ct).html(content);
                        }
                        _callAfterShow(content);
                        if($.isFunction(cl)) {
                            cl.call(that, data);
                        }
                    }
                });
            }

            /**
             * after show callback
             */

            function _callAfterShow(content) {
                if($.isFunction(pio.content.afterShow)) {
                    pio.content.afterShow.call(that, content);
                }
            }

        },

        /**
         * destory portlet
         */
        _destroy: function() {
            this.element.removeClass("ui-portlet").text("");

            // call the base destroy function
            $.Widget.prototype.destroy.call(this);
            return this;
        }
    });

})(jQuery);<commit_msg>Fixed：内容区域拖动（例如滚动条的拖动）依然可以移动单个portlet<commit_after>/*
 * jquery.portlet 1.1.1
 *
 * Copyright (c) 2012
 *   咖啡兔 (http://www.kafeitu.me)
 *
 * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
 * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
 *
 * See Detail: http://www.kafeitu.me/jquery-ui-portlet.html
 */
(function($) {
    $.widget("kft.portlet", {
        options: {
            columns: {},
            sortable: true,
            singleView: true,
            removeItem: null
        },

        /**
         * create portlet widget
         */
        _create: function() {
            this.element.addClass("ui-portlet");
            var _this = this;
            var _ele = _this.element;
            var o = _this.options;

            $.each(o.columns, function(ci, c) {

                var $column = $('
', {
                    'class': 'ui-portlet-column',
                    width: c.width
                }).appendTo(_ele);

                $.each(c.portlets, function(pi, p) {

                    var item = $('
', {
                        'class': 'ui-portlet-item ui-widget ui-widget-content ui-helper-clearfix ui-corner-all',
                    }).data('option', p).appendTo($column);
                    if(p.attrs) {
                        item.attr(p.attrs);
                    }

                    // title
                    var title = $('
', {
                        'class': 'ui-portlet-header ui-widget-header ui-corner-all',
                        html: function() {
                            if($.isFunction(p.title)) {
                                return p.title;
                            }
                            return "" + p.title;
                        }
                    }).appendTo(item);

                    // add icon for title
                    if(p.icon) {
                        title.prepend("");
                    }

                    // event element
                    title.prepend("");
                    title.prepend("");
                    title.prepend("");

                    // content
                    var ct = $('
', {
                        'class': 'ui-portlet-content'
                    }).appendTo(item);

                    // set content style
                    if(p.content.style) {
                        $(ct).css(p.content.style);
                    }

                    // set attrs
                    if(p.content.attrs) {
                        $.each(p.content.attrs, function(k, v) {
                            var attr = ct.attr(k);
                            if(attr) {
                                if(k == 'style' && v.substr(v.length - 1) != ';') {
                                    attr += ';';
                                }
                                if(k == 'class') {
                                    attr += ' ';
                                }
                                attr += v;
                            }
                            ct.attr(k, attr);
                        });
                    }

                    // load content
                    _this._content.call(_ele, item, p, function(data) {
                        // load scripts
                        _this._loadScripts(p.scripts);
                    });
                });
            });

            // init events
            _this._initEvents();

            // bind single view
            _this._regSingleView();

            // enable/disable sortable
            _this._sortable(o.sortable);
        },

        /**
         * set option for plugin
         * @param {[type]} key   key
         * @param {[type]} value value
         */
        _setOption: function(key, value) {
            // static options
            if(this.options[key]) {
                this.options[key] = value;
            }

            // need handle speical
            switch(key) {
            case "sortable":
                this._sortable(value);
                break;
            }
        },

        /**
         * single view
         */
        _regSingleView: function() {
            var _ele = this.element;
            $(_ele).find('.ui-portlet-header').dblclick(function() {
                var $item = $(this).parents('.ui-portlet-item');
                var p = $item.data('option');

                // recovery normal model
                if($item.hasClass('ui-portlet-single-view')) {
                    $(_ele).find('.ui-portlet-item').show();
                    $item.removeClass('ui-portlet-single-view').animate({
                        width: $item.data('width'),
                        height: $item.data('height')
                    }).css({
                        position: 'static'
                    }).removeData('width').removeData('height');

                    // callback
                    if(p.singleView) {
                        if($.isFunction(p.singleView.recovery)) {
                            p.singleView.recovery.call($item, p);
                        }
                    }
                } else {
                    // enable single view
                    $(_ele).find('.ui-portlet-item').hide();
                    // move left:0 top:0, set width use body's width
                    $item.show().addClass('ui-portlet-single-view').data({
                        width: $item.width(),
                        height: $item.height()
                    }).css({
                        position: 'absolute',
                        left: 0,
                        top: 0
                    });

                    // set width and height when enable single view
                    var wh = {};
                    if(p.singleView) {
                        // use custom width and height
                        if(p.singleView.width) {
                            if($.isFunction(p.singleView.width)) {
                                wh.width = p.singleView.width.call($item, p);
                            } else {
                                wh.width = p.singleView.width;
                            }
                        }
                        if(p.singleView.height) {
                            if($.isFunction(p.singleView.height)) {
                                wh.height = p.singleView.height.call($item, p);
                            } else {
                                wh.height = p.singleView.height;
                            }
                        }

                    } else {
                        // use default width
                        wh.width = $(_ele).width() + 14;
                    }

                    $item.animate({
                        width: wh.width,
                        height: wh.height
                    });

                    // callback
                    if(p.singleView && $.isFunction(p.singleView.enable)) {
                        p.singleView.enable.call($item, p);
                    }
                }
            });
        },

        /**
         * load java scripts
         * @param  {[string]} scripts [description]
         */
        _loadScripts: function(scripts) {
            if(scripts) {
                $.each(scripts, function() {
                    var head = $('head').remove('#loadScript');
                    $("").attr({
                        src: this,
                        type: 'text/javascript',
                        id: 'loadScript'
                    }).appendTo(head);
                });
            }
        },

        /**
         * enable/disable sortable
         * @param  {[type]} value [true|false]
         */
        _sortable: function(value) {
            var st = $(".ui-portlet-column", this.element).sortable({
                connectWith: ".ui-portlet-column"
            }).disableSelection();
            if(value === true) {
                $(this.element).find('.ui-portlet-header').css('cursor', 'move');
                st.sortable('enable');
                $(".ui-portlet-content", this.element).draggable({
                    start: function(e, ui) {
                        return false;
                    }
                });
        } else {
            $(this.element).find('.ui-portlet-header').css('cursor', 'default');
            st.sortable('disable');
        }
    },

    /**
     * events and handlers
     * @return {[type]} [description]
     */
    _initEvents: function() {
        var _this = this;

        // toggle contents
        var toggle = $(".ui-portlet-toggle", this.element).click(function() {
            $(this).toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
            $(this).parents(".ui-portlet-item:first").find(".ui-portlet-content").toggle();
        });

        var refresh = $(".ui-portlet-refresh", this.element).click(function(event) {
            _this.refresh.call(_this, event);
        });

        var close = $(".ui-portlet-close", this.element).click(function(event) {
            _this._destoryItem.call(_this, event);
        });

        this._hoverable(toggle.parent());
        this._hoverable(refresh.parent());
    },

    /**
     * hoverable
     */
    _hoverable: function(element) {
        $(element).hover(function() {
            $(this).addClass('ui-state-hover');
        }, function() {
            $(this).removeClass('ui-state-hover');
        });
    },

    /**
     * destory single portlet
     */
    _destoryItem: function(event) {
        var o = this.options;
        var item = $(event.target).parents('.ui-portlet-item');
        item.remove();
        if($.isFunction(o.removeItem)) {
            o.removeItem();
        }
    },

    /**
     * refresh contents
     */
    refresh: function(event) {
        var o = this.options;
        var portlet = $(event.target).parents('.ui-portlet');
        var item = $(event.target).parents('.ui-portlet-item');
        var pio = item.data('option');
        var ct = item.find('.ui-portlet-content');
        var pt = item.parents('.ui-portlet');

        // callback
        if($.isFunction(pio.beforeRefresh)) {
            pio.beforeRefresh.call(pt, pio);
        }

        // set contents
        this._content.call(portlet, item, pio, function(data) {
            // callback
            if($.isFunction(pio.afterRefresh)) {
                pio.afterRefresh.call(pt, data, pio);
            }
        });

        // load scripts
        this._loadScripts(pio.scripts);
    },

    /**
     * get content from multi styles
     * @param  {[type]} item [.ui-portlet-item]
     * @param  {[type]} pio  [portlet configs]
     * @param  {[type]} cl   [callback after load]
     */
    _content: function(item, pio, cl) {
        var o = this.options;
        var that = this;
        var type = pio.content.type;
        var content = null;
        var ct = item.find('.ui-portlet-content');

        // before show callback
        if($.isFunction(pio.content.beforeShow)) {
            pio.content.beforeShow.call(this, pio.content.text);
        }

        if(type == 'text') {
            content = pio.content.text;

            // get content from function
            if($.isFunction(content)) {
                content = content(that, item, pio);
            }

            if($.isFunction(cl)) {
                cl.call(that, content);
            }
            ct.html(content);
            _callAfterShow(pio.content.text);
        } else if(type == 'ajax') {
            var dataType = pio.content.dataType || 'html';
            $.ajax({
                url: pio.content.url,
                dataType: dataType,
                beforeSend: function() {
                    $(ct).html('Loading...');
                },
                success: function(data, textStatus, jqXHR) {
                    if(dataType == 'html') {
                        content = data;
                        $(ct).html(data);
                    } else if(dataType == 'json') {
                        content = pio.content.formatter(o, pio, data);
                        $(ct).html(content);
                    }
                    _callAfterShow(content);
                    if($.isFunction(cl)) {
                        cl.call(that, data);
                    }
                }
            });
        }

        /**
         * after show callback
         */

        function _callAfterShow(content) {
            if($.isFunction(pio.content.afterShow)) {
                pio.content.afterShow.call(that, content);
            }
        }

    },

    /**
     * destory portlet
     */
    _destroy: function() {
        this.element.removeClass("ui-portlet").text("");

        // call the base destroy function
        $.Widget.prototype.destroy.call(this);
        return this;
    }
    });

})(jQuery);<|endoftext|>


<commit_before>import styles from './Footer.less';

import React, { Component } from 'react';

export default class Footer extends Component {
  render() {
    return (

              Brought to you by:

                Misha Moroshko

                Vedran Arnautović

              Have feature ideas?

                Chat to us on Slack

    );
  }
}
<commit_msg>Update Slack link<commit_after>import styles from './Footer.less';

import React, { Component } from 'react';

export default class Footer extends Component {
  render() {
    return (

              Brought to you by:

                Misha Moroshko

                Vedran Arnautović

              Have feature ideas?

                Chat to us on Slack

    );
  }
}
<|endoftext|>


<commit_before>import React, { Fragment } from 'react'
import propPath from 'crocks/Maybe/propPath'
import { RichText } from 'prismic-reactjs'
import styled, { keyframes } from 'styled-components'
import { key } from 'styled-theme'

import { Lazy } from 'Components'
import {
  Section,
  SectionRowCenteredWide,
  SectionHeader,
  SectionBlock,
} from 'Styled'
import { linkResolver, s4 } from 'Helpers'
import patternWaves from '../../assets/PatternWavesWhite.svg'

const ColoredBackSection = Section.extend`
  margin: ${key(['space', 9])}px 0 ${key(['space', 10])}px;
  padding: ${key(['space', 10])}px 0;
  background-color: ${key('colors.pink')};
  background-image: url(${patternWaves});
  background-repeat: repeat-x;
  background-position-y: calc(100% + 225px);
`

const TextBlock = SectionBlock.extend`
  flex-direction: column;
  color: ${key('colors.white')};
  font-weight: ${key('fontWeights.medium')};
  & h3, h4 {
    color: ${key('colors.white')};
    font-family: ${key('fonts.base')};
    font-size: ${key(['fontSizes', 2])}px;
    line-height: ${key(['lineHeights', 1])};
  }
`

export const ResultColoredBack = ({ section }) => {
  const { primary, items } = section
  const header = propPath(['primary', 'header'])
  const head = propPath([0])
  const text = propPath(['text'])
  const getHeader = header(section).chain(head).chain(text).option('')

  return (
    <ColoredBackSection id={primary.anchor || null} >
      {getHeader.length > 0 &&
        <SectionRowCenteredWide>
          <Lazy height={50}>
            <SectionHeader color='text' shade='white' >
            { RichText.asText(primary.header) }
            </SectionHeader>
          </Lazy>
        </SectionRowCenteredWide>
      }
      <SectionRowCenteredWide style={{textAlign: 'center'}} >
        {items.map(item =>
          <Lazy key={s4()} height={300}>
            <TextBlock key={s4()} >
            { RichText.render(item.text, linkResolver) }
            </TextBlock>
          </Lazy>
        )}
      </SectionRowCenteredWide>
    </ColoredBackSection>
  )
}<commit_msg>small fix<commit_after>import React, { Fragment } from 'react'
import propPath from 'crocks/Maybe/propPath'
import { RichText } from 'prismic-reactjs'
import styled, { keyframes } from 'styled-components'
import { key } from 'styled-theme'

import { Lazy } from 'Components'
import {
  Section,
  SectionRowCenteredWide,
  SectionHeader,
  SectionBlock,
} from 'Styled'
import { linkResolver, s4 } from 'Helpers'
import patternWaves from '../../assets/PatternWavesWhite.svg'

const ColoredBackSection = Section.extend`
  margin: ${key(['space', 9])}px 0 ${key(['space', 10])}px;
  padding: ${key(['space', 10])}px 0;
  background-color: ${key('colors.pink')};
  background-image: url(${patternWaves});
  background-repeat: repeat-x;
  background-position-y: calc(100% + 225px);
`

const SectionRow = SectionRowCenteredWide.extend`
  justify-content: center;
  text-align: center;
`

const TextBlock = SectionBlock.extend`
  flex-direction: column;
  color: ${key('colors.white')};
  font-weight: ${key('fontWeights.medium')};
  & h3, h4 {
    color: ${key('colors.white')};
    font-family: ${key('fonts.base')};
    font-size: ${key(['fontSizes', 2])}px;
    line-height: ${key(['lineHeights', 1])};
  }
`

export const ResultColoredBack = ({ section }) => {
  const { primary, items } = section
  const header = propPath(['primary', 'header'])
  const head = propPath([0])
  const text = propPath(['text'])
  const getHeader = header(section).chain(head).chain(text).option('')

  return (
    <ColoredBackSection id={primary.anchor || null} >
      {getHeader.length > 0 &&
        <SectionRow>
          <Lazy height={50}>
            <SectionHeader color='text' shade='white' >
            { RichText.asText(primary.header) }
            </SectionHeader>
          </Lazy>
        </SectionRow>
      }
      <SectionRow >
        {items.map(item =>
          <Lazy key={s4()} height={300}>
            <TextBlock key={s4()} >
            { RichText.render(item.text, linkResolver) }
            </TextBlock>
          </Lazy>
        )}
      </SectionRow>
    </ColoredBackSection>
  )
}<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular
    .module('app.user.userLandingController')
    .controller('UserLandingController', Controller);

  Controller.$inject = [
    '$routeParams',
    '$http',
    '$cookies',
    '$location',
    '$router',
    '$mdDialog',
    '$window',
    'loomApi',
    'lodash',
    'moment',
    'recruitUnitUtil',
    '$resource'
  ];

  function Controller($routeParams,$http,$cookies,$location,$router,$mdDialog,$window,loomApi,lodash,moment,recruitUnitUtil) {
    console.log("in UserLandingController");

    recruitUnitUtil.Util.setTitle("User Landing Page");

    //this.usercreated = $location.search().usercreated; //ref to get param from url
    this.useremail = $routeParams.email;
    this.username = "";
    this.role = "";
    this.id = "";
    this.status = "";
    this.myContentListArray = [];
    this.myContentListPassCount = 0;
    this.myContentListFailCount = 0;

    Controller.prototype.showFormDetailDialog = function($event, id, isPass, isPartialPass){
      console.log("in showFormDetailDialog");
      console.log("   form id:" + id);
      $mdDialog.show({
        controller: 'FormReadController',
        controllerAs: 'formRead',
        locals: {'jobDetailFormId':id, 'isItemPass': isPartialPass || isPass ? true : false},
        bindToController: true,
        templateUrl: 'src/angular/components/formRead/formReadDialog.html',
        parent: angular.element(document.body),
        targetEvent: $event,
        clickOutsideToClose:true,
        fullscreen: false
      }).then(function(answer) {
        //this.status = 'You said the information was "' + answer + '".';
      }, function() {
        //this.status = 'You cancelled the dialog.';
      });
    }

    Controller.prototype.deleteItem = function(docId, index){
      console.log("delete id:" + docId + ",index:" + index);
      //todo: ensure the update can only change the users own document
      loomApi.Article.updateArticle(docId, controllerId, jobItemModel, {"published": false}, token).then(angular.bind(this,function(result){
        console.log("Delete result:");
        console.log(result);
        if (result.success){
          this.myContentListArray.splice(index, 1);
        }
      }));
    }

    Controller.prototype.formatUnixDateToNow = function(unixTime){
      return moment.unix(unixTime).from();
    }

    Controller.prototype.viewItem = function(id){
      //console.log("view id:" + id);
      $location.path("/user/" + this.useremail + "/form/" + id);
    }

    Controller.prototype.searchDeveloper = function(searchJson){
      var comparisonRulesDocId = "";
      var controllerId = "server/services/recruitunit/articles/recruitUnitContentService.controller.js";
      var rulesModel = "server/models/RecruitUnit.ComparisonTest.js";
      //var jobItemModel = "server/models/RecruitUnit.Job.All.js";
      var localToken = recruitUnitUtil.Util.getLocalUser().token;

      loomApi.Article.search(controllerId, rulesModel, searchJson, localToken).then(function (result) {
        console.log("get search:");
        console.log(result);
        if (result.length > 0) {
          comparisonRulesDocId = result[0].id;//todo: handle no id
          return loomApi.Article.listMyTestContent(controllerId, comparisonRulesDocId, localToken);
        }
      }).then(angular.bind(this, function (listMyTestContentResult) {
        if (typeof listMyTestContentResult !== 'undefined') {
          this.myContentListArray = lodash.sortBy(listMyTestContentResult, 'document.createdDate').reverse();
          this.myContentListPassCount = lodash.filter(listMyTestContentResult, {'testResult': {'isPass': true}}).length + lodash.filter(listMyTestContentResult, {'testResult': {'isPartialPass': true}}).length;
          this.myContentListFailCount = listMyTestContentResult.length - this.myContentListPassCount;

          return true; //return canActivate state once results are available
        }
      }));
    }

    Controller.prototype.searchRecruiter = function(searchJson){
      var comparisonRulesDocId = "";
      var controllerId = "server/services/recruitunit/articles/recruitUnitContentService.controller.js";
      //var rulesModel = "server/models/RecruitUnit.ComparisonTest.js";
      var jobItemModel = "server/models/RecruitUnit.Job.All.js";
      var localToken = recruitUnitUtil.Util.getLocalUser().token;

      loomApi.Article.search(controllerId, jobItemModel, searchJson, localToken).then(function (result) {
        console.log("get search:");
        console.log(result);
        if (result.length > 0) {
          comparisonRulesDocId = result[0].id;//todo: handle no id
          return loomApi.Article.listMyTestContent(controllerId, comparisonRulesDocId, localToken);//ToDo: replace this with an alternative for 1 recruiter to many developers
        }
      }).then(angular.bind(this, function (listMyTestContentResult) {
        if (typeof listMyTestContentResult !== 'undefined') {
          this.myContentListArray = lodash.sortBy(listMyTestContentResult, 'document.createdDate').reverse();
          this.myContentListPassCount = lodash.filter(listMyTestContentResult, {'testResult': {'isPass': true}}).length + lodash.filter(listMyTestContentResult, {'testResult': {'isPartialPass': true}}).length;
          this.myContentListFailCount = listMyTestContentResult.length - this.myContentListPassCount;

          return true; //return canActivate state once results are available
        }
      }));
    }
  }

  Controller.prototype.canActivate = function($routeParams, recruitUnitUtil, jwtHelper) {
    console.log("in UserLandingController canActivate");

    if (recruitUnitUtil.Util.isLocalUserAvailable()) {
      var token = jwtHelper.decodeToken(recruitUnitUtil.Util.getLocalUser().token);
      var tokenUsername = token.username;
      var tokenJobRole = token.jobRole;
      var requestedUsername = $routeParams.email;

      return recruitUnitUtil.Util.isUserAuthenticated(tokenUsername, recruitUnitUtil.Util.getLocalUser().token).then(angular.bind(this, function (result) {
        if (result == false) {
          recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_HOME);// todo: get path from constant;
          recruitUnitUtil.Util.deleteUserAuth();
        } else if (tokenUsername != requestedUsername) {
          recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_USER + tokenUsername);
        } else if (result.success) {
            this.role = result.data.jobRole;
            this.id = result.data.id;
            this.username = result.data.displayName;
            if (tokenJobRole == "recruiter"){
              var searchJson = {
                "authorEmail": requestedUsername
              };
              return this.searchRecruiter(searchJson);
            } else if (tokenJobRole == "developer"){
              var searchJson = {
                "authorName": requestedUsername
              };
              return this.searchDeveloper(searchJson);
            }
        }

      }));
    } else {
      recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_HOME);
    }
  }

})();<commit_msg>integrating new getUserTestResults endpoint into recruiters landingpage<commit_after>(function() {
  'use strict';

  angular
    .module('app.user.userLandingController')
    .controller('UserLandingController', Controller);

  Controller.$inject = [
    '$routeParams',
    '$http',
    '$cookies',
    '$location',
    '$router',
    '$mdDialog',
    '$window',
    'loomApi',
    'lodash',
    'moment',
    'recruitUnitUtil',
    '$resource'
  ];

  function Controller($routeParams,$http,$cookies,$location,$router,$mdDialog,$window,loomApi,lodash,moment,recruitUnitUtil) {
    console.log("in UserLandingController");

    recruitUnitUtil.Util.setTitle("User Landing Page");

    //this.usercreated = $location.search().usercreated; //ref to get param from url
    this.useremail = $routeParams.email;
    this.username = "";
    this.role = "";
    this.id = "";
    this.status = "";
    this.myContentListArray = [];
    this.myContentListPassCount = 0;
    this.myContentListFailCount = 0;

    Controller.prototype.showFormDetailDialog = function($event, id, isPass, isPartialPass){
      console.log("in showFormDetailDialog");
      console.log("   form id:" + id);
      $mdDialog.show({
        controller: 'FormReadController',
        controllerAs: 'formRead',
        locals: {'jobDetailFormId':id, 'isItemPass': isPartialPass || isPass ? true : false},
        bindToController: true,
        templateUrl: 'src/angular/components/formRead/formReadDialog.html',
        parent: angular.element(document.body),
        targetEvent: $event,
        clickOutsideToClose:true,
        fullscreen: false
      }).then(function(answer) {
        //this.status = 'You said the information was "' + answer + '".';
      }, function() {
        //this.status = 'You cancelled the dialog.';
      });
    }

    Controller.prototype.deleteItem = function(docId, index){
      console.log("delete id:" + docId + ",index:" + index);
      //todo: ensure the update can only change the users own document
      loomApi.Article.updateArticle(docId, controllerId, jobItemModel, {"published": false}, token).then(angular.bind(this,function(result){
        console.log("Delete result:");
        console.log(result);
        if (result.success){
          this.myContentListArray.splice(index, 1);
        }
      }));
    }

    Controller.prototype.formatUnixDateToNow = function(unixTime){
      return moment.unix(unixTime).from();
    }

    Controller.prototype.viewItem = function(id){
      //console.log("view id:" + id);
      $location.path("/user/" + this.useremail + "/form/" + id);
    }

    Controller.prototype.searchDeveloper = function(searchJson){
      var comparisonRulesDocId = "";
      var controllerId = "server/services/recruitunit/articles/recruitUnitContentService.controller.js";
      var rulesModel = "server/models/RecruitUnit.ComparisonTest.js";
      //var jobItemModel = "server/models/RecruitUnit.Job.All.js";
      var localToken = recruitUnitUtil.Util.getLocalUser().token;

      loomApi.Article.search(controllerId, rulesModel, searchJson, localToken).then(function (result) {
        console.log("get search:");
        console.log(result);
        if (result.length > 0) {
          comparisonRulesDocId = result[0].id;//todo: handle no id
          return loomApi.Article.listMyTestContent(controllerId, comparisonRulesDocId, localToken);
        }
      }).then(angular.bind(this, function (listMyTestContentResult) {
        if (typeof listMyTestContentResult !== 'undefined') {
          this.myContentListArray = lodash.sortBy(listMyTestContentResult, 'document.createdDate').reverse();
          this.myContentListPassCount = lodash.filter(listMyTestContentResult, {'testResult': {'isPass': true}}).length + lodash.filter(listMyTestContentResult, {'testResult': {'isPartialPass': true}}).length;
          this.myContentListFailCount = listMyTestContentResult.length - this.myContentListPassCount;

          return true; //return canActivate state once results are available
        }
      }));
    }

    Controller.prototype.searchRecruiter = function(searchJson){
      var comparisonRulesDocId = "";
      var controllerId = "server/services/recruitunit/articles/recruitUnitContentService.controller.js";
      var rulesModel = "server/models/RecruitUnit.ComparisonTest.js";
      //var jobItemModel = "server/models/RecruitUnit.Job.All.js";
      var localToken = recruitUnitUtil.Util.getLocalUser().token;

      loomApi.Article.getUserTestResults(controllerId, searchJson.authorEmail, localToken).then(angular.bind(this, function (listMyTestContentResult) {
        console.log("getUserTestResults:");
        console.log(listMyTestContentResult);
        if (typeof listMyTestContentResult !== 'undefined') {
          this.myContentListArray = lodash.sortBy(listMyTestContentResult, 'document.createdDate').reverse();
          this.myContentListPassCount = lodash.filter(listMyTestContentResult, {'testResult': {'isPass': true}}).length + lodash.filter(listMyTestContentResult, {'testResult': {'isPartialPass': true}}).length;
          this.myContentListFailCount = listMyTestContentResult.length - this.myContentListPassCount;

          return true; //return canActivate state once results are available
        }
      }));
    }
  }

  Controller.prototype.canActivate = function($routeParams, recruitUnitUtil, jwtHelper) {
    console.log("in UserLandingController canActivate");

    if (recruitUnitUtil.Util.isLocalUserAvailable()) {
      var token = jwtHelper.decodeToken(recruitUnitUtil.Util.getLocalUser().token);
      var tokenUsername = token.username;
      var tokenJobRole = token.jobRole;
      var requestedUsername = $routeParams.email;

      return recruitUnitUtil.Util.isUserAuthenticated(tokenUsername, recruitUnitUtil.Util.getLocalUser().token).then(angular.bind(this, function (result) {
        if (result == false) {
          recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_HOME);// todo: get path from constant;
          recruitUnitUtil.Util.deleteUserAuth();
        } else if (tokenUsername != requestedUsername) {
          recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_USER + tokenUsername);
        } else if (result.success) {
            this.role = result.data.jobRole;
            this.id = result.data.id;
            this.username = result.data.displayName;
            if (tokenJobRole == "recruiter"){
              var searchJson = {
                "authorEmail": requestedUsername
              };
              return this.searchRecruiter(searchJson);
            } else if (tokenJobRole == "developer"){
              var searchJson = {
                "authorName": requestedUsername
              };
              return this.searchDeveloper(searchJson);
            }
        }

      }));
    } else {
      recruitUnitUtil.Util.redirectUserToPath(recruitUnitUtil.Constants.PATH_HOME);
    }
  }

})();<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { routeActions } from 'redux-simple-router'
import { RELATIONSHIP_PRIORITY } from '../../constants/relationship_types'
import { openModal, closeModal } from '../../actions/modals'
import { updateRelationship } from '../../actions/relationships'
import { trackEvent } from '../../actions/tracking'
import BlockMuteDialog from '../dialogs/BlockMuteDialog'
import RegistrationRequestDialog from '../dialogs/RegistrationRequestDialog'
import BlockMuteButton from '../relationships/BlockMuteButton'
import RelationshipButton from '../relationships/RelationshipButton'
import StarshipButton from '../relationships/StarshipButton'

class RelationsGroup extends Component {
  constructor(props, context) {
    super(props, context)
    this.handleMuteUser = ::this.handleMuteUser
    this.handleBlockUser = ::this.handleBlockUser
    this.launchBlockMutePrompt = ::this.launchBlockMutePrompt
    this.handleLaunchSignUpModal = ::this.handleLaunchSignUpModal
  }

  getNextPriority(props, btnId) {
    const { user } = props
    const priority = user.relationshipPriority
    switch (priority) {
      case RELATIONSHIP_PRIORITY.BLOCK:
      case RELATIONSHIP_PRIORITY.MUTE:
        return RELATIONSHIP_PRIORITY.INACTIVE
      default:
        switch (btnId) {
          case 'block':
            return RELATIONSHIP_PRIORITY.BLOCK
          case 'mute':
            return RELATIONSHIP_PRIORITY.MUTE
          default:
            return RELATIONSHIP_PRIORITY.INACTIVE
        }
    }
  }

  closeModal() {
    const { dispatch } = this.props
    dispatch(closeModal())
  }

  handleRelationshipUpdate(vo) {
    const { userId, priority, existing } = vo
    const { dispatch, pathname } = this.props

    if (pathname && (/^\/onboarding/).test(pathname)) {
      return dispatch(updateRelationship(userId, priority, existing, true))
    }
    return dispatch(updateRelationship(userId, priority, existing))
  }

  isBlockedOrMuted() {
    const { user } = this.props
    const status = user.relationshipPriority
    return status && status === RELATIONSHIP_PRIORITY.BLOCK || status === RELATIONSHIP_PRIORITY.MUTE
  }

  handleBlockUser() {
    const { dispatch, previousPath } = this.props
    const { user } = this.props
    const priority = user.relationshipPriority
    this.handleRelationshipUpdate({
      userId: user.id,
      priority: this.getNextPriority(this.props, 'block'),
      existing: priority,
    })
    this.closeModal()
    dispatch(routeActions.replace(previousPath || '/'))
  }

  handleMuteUser() {
    const { user } = this.props
    const priority = user.relationshipPriority
    this.handleRelationshipUpdate({
      userId: user.id,
      priority: this.getNextPriority(this.props, 'mute'),
      existing: priority,
    })
    this.closeModal()
  }

  launchBlockMutePrompt() {
    const { dispatch, user } = this.props
    const priority = user.relationshipPriority
    dispatch(openModal(
      <BlockMuteDialog
        onBlock={ this.handleBlockUser }
        onMute={ this.handleMuteUser }
        blockIsActive={ priority === RELATIONSHIP_PRIORITY.BLOCK }
        muteIsActive={ priority === RELATIONSHIP_PRIORITY.MUTE }
        username = { user.username }
      />
    , 'asDangerZone'))
  }

  handleLaunchSignUpModal() {
    const { dispatch } = this.props
    dispatch(openModal(<RegistrationRequestDialog />, 'asDecapitated'))
    return dispatch(trackEvent('open-registration-request-follow-button'))
  }

  shouldRenderBlockMute() {
    const { isLoggedIn, showBlockMuteButton, user } = this.props
    const { relationshipPriority } = user
    return isLoggedIn && showBlockMuteButton && relationshipPriority !== RELATIONSHIP_PRIORITY.SELF
  }

  renderBlockMuteButton() {
    const { user } = this.props
    return (
      <BlockMuteButton
        onClick={ this.launchBlockMutePrompt }
        priority={ user.relationshipPriority }
        userId={ user.id }
      />
    )
  }

  render() {
    const { isLoggedIn, user } = this.props
    const callback = this.isBlockedOrMuted() ?
                     (this.launchBlockMutePrompt) :
                     (this.handleRelationshipUpdate)

    return (

        { this.shouldRenderBlockMute() ? this.renderBlockMuteButton() : null }
        <RelationshipButton
          buttonWasClicked={ isLoggedIn ? callback : this.handleLaunchSignUpModal }
          priority={ user.relationshipPriority }
          ref="RelationshipButton"
          userId={ user.id }
        />
        <StarshipButton
          buttonWasClicked={ isLoggedIn ? callback : this.handleLaunchSignUpModal }
          priority={ user.relationshipPriority }
          ref="StarshipButton"
          userId={ user.id }
        />

    )
  }
}

RelationsGroup.propTypes = {
  dispatch: PropTypes.func.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  pathname: PropTypes.string,
  previousPath: PropTypes.string,
  showBlockMuteButton: PropTypes.bool,
  user: PropTypes.shape({
    id: PropTypes.string,
    relationshipPriority: PropTypes.string,
  }).isRequired,
}

RelationsGroup.defaultProps = {
  showBlockMuteButton: false,
}

function mapStateToProps(state) {
  return {
    isLoggedIn: state.authentication.isLoggedIn,
    pathname: state.routing.location.pathname,
    previousPath: state.routing.previousPath,
  }
}

export default connect(mapStateToProps, null, null, { withRef: true })(RelationsGroup)

<commit_msg>Fix scope issue with relations group.<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { routeActions } from 'redux-simple-router'
import { RELATIONSHIP_PRIORITY } from '../../constants/relationship_types'
import { openModal, closeModal } from '../../actions/modals'
import { updateRelationship } from '../../actions/relationships'
import { trackEvent } from '../../actions/tracking'
import BlockMuteDialog from '../dialogs/BlockMuteDialog'
import RegistrationRequestDialog from '../dialogs/RegistrationRequestDialog'
import BlockMuteButton from '../relationships/BlockMuteButton'
import RelationshipButton from '../relationships/RelationshipButton'
import StarshipButton from '../relationships/StarshipButton'

class RelationsGroup extends Component {
  constructor(props, context) {
    super(props, context)
    this.handleMuteUser = ::this.handleMuteUser
    this.handleBlockUser = ::this.handleBlockUser
    this.launchBlockMutePrompt = ::this.launchBlockMutePrompt
    this.handleLaunchSignUpModal = ::this.handleLaunchSignUpModal
    this.handleRelationshipUpdate = ::this.handleRelationshipUpdate
  }

  getNextPriority(props, btnId) {
    const { user } = props
    const priority = user.relationshipPriority
    switch (priority) {
      case RELATIONSHIP_PRIORITY.BLOCK:
      case RELATIONSHIP_PRIORITY.MUTE:
        return RELATIONSHIP_PRIORITY.INACTIVE
      default:
        switch (btnId) {
          case 'block':
            return RELATIONSHIP_PRIORITY.BLOCK
          case 'mute':
            return RELATIONSHIP_PRIORITY.MUTE
          default:
            return RELATIONSHIP_PRIORITY.INACTIVE
        }
    }
  }

  closeModal() {
    const { dispatch } = this.props
    dispatch(closeModal())
  }

  handleRelationshipUpdate(vo) {
    const { userId, priority, existing } = vo
    const { dispatch, pathname } = this.props

    if (pathname && (/^\/onboarding/).test(pathname)) {
      return dispatch(updateRelationship(userId, priority, existing, true))
    }
    return dispatch(updateRelationship(userId, priority, existing))
  }

  isBlockedOrMuted() {
    const { user } = this.props
    const status = user.relationshipPriority
    return status && status === RELATIONSHIP_PRIORITY.BLOCK || status === RELATIONSHIP_PRIORITY.MUTE
  }

  handleBlockUser() {
    const { dispatch, previousPath } = this.props
    const { user } = this.props
    const priority = user.relationshipPriority
    this.handleRelationshipUpdate({
      userId: user.id,
      priority: this.getNextPriority(this.props, 'block'),
      existing: priority,
    })
    this.closeModal()
    dispatch(routeActions.replace(previousPath || '/'))
  }

  handleMuteUser() {
    const { user } = this.props
    const priority = user.relationshipPriority
    this.handleRelationshipUpdate({
      userId: user.id,
      priority: this.getNextPriority(this.props, 'mute'),
      existing: priority,
    })
    this.closeModal()
  }

  launchBlockMutePrompt() {
    const { dispatch, user } = this.props
    const priority = user.relationshipPriority
    dispatch(openModal(
      <BlockMuteDialog
        onBlock={ this.handleBlockUser }
        onMute={ this.handleMuteUser }
        blockIsActive={ priority === RELATIONSHIP_PRIORITY.BLOCK }
        muteIsActive={ priority === RELATIONSHIP_PRIORITY.MUTE }
        username = { user.username }
      />
    , 'asDangerZone'))
  }

  handleLaunchSignUpModal() {
    const { dispatch } = this.props
    dispatch(openModal(<RegistrationRequestDialog />, 'asDecapitated'))
    return dispatch(trackEvent('open-registration-request-follow-button'))
  }

  shouldRenderBlockMute() {
    const { isLoggedIn, showBlockMuteButton, user } = this.props
    const { relationshipPriority } = user
    return isLoggedIn && showBlockMuteButton && relationshipPriority !== RELATIONSHIP_PRIORITY.SELF
  }

  renderBlockMuteButton() {
    const { user } = this.props
    return (
      <BlockMuteButton
        onClick={ this.launchBlockMutePrompt }
        priority={ user.relationshipPriority }
        userId={ user.id }
      />
    )
  }

  render() {
    const { isLoggedIn, user } = this.props
    const callback = this.isBlockedOrMuted() ?
                     (this.launchBlockMutePrompt) :
                     (this.handleRelationshipUpdate)

    return (

        { this.shouldRenderBlockMute() ? this.renderBlockMuteButton() : null }
        <RelationshipButton
          buttonWasClicked={ isLoggedIn ? callback : this.handleLaunchSignUpModal }
          priority={ user.relationshipPriority }
          ref="RelationshipButton"
          userId={ user.id }
        />
        <StarshipButton
          buttonWasClicked={ isLoggedIn ? callback : this.handleLaunchSignUpModal }
          priority={ user.relationshipPriority }
          ref="StarshipButton"
          userId={ user.id }
        />

    )
  }
}

RelationsGroup.propTypes = {
  dispatch: PropTypes.func.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  pathname: PropTypes.string,
  previousPath: PropTypes.string,
  showBlockMuteButton: PropTypes.bool,
  user: PropTypes.shape({
    id: PropTypes.string,
    relationshipPriority: PropTypes.string,
  }).isRequired,
}

RelationsGroup.defaultProps = {
  showBlockMuteButton: false,
}

function mapStateToProps(state) {
  return {
    isLoggedIn: state.authentication.isLoggedIn,
    pathname: state.routing.location.pathname,
    previousPath: state.routing.previousPath,
  }
}

export default connect(mapStateToProps, null, null, { withRef: true })(RelationsGroup)

<|endoftext|>