<commit_before>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function()
{
	var setters = {};
	var getters = {};
	var validators = {};

	var up = function(name) {
		return name.charAt(0).toUpperCase() + name.slice(1);
	};

	var undef;

	/**
	 * Generic setter/getter support for property API.
	 *
	 * Include this if your class uses properties and want to be able to generically
	 * set/get them based on the property names
	 */
	core.Class("core.property.MGeneric",
	{
		members :
		{
			/**
			 * {var} Generic setter. Supports two possible use cases for @property {String|Map} and @value {var?}:
			 *
			 *     set("property", value);
			 *     set({
			 *       property1: value1,
			 *       property2: value2
			 *     });
			 *
			 * Returns the value from the setter (if single property is used)
			 */
			set : function(property, value)
			{
				if (arguments.length == 2)
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "String");
					}

					var method = setters[property];
					if (!method) {
						method = setters[property] = "set" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to set: " + property);
					}

					return this[method](value);
				}
				else
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "Map");
					}

					for (var name in property)
					{
						var method = setters[name];
						if (!method) {
							method = setters[name] = "set" + up(name);
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to set: " + name);
						}

						this[method](property[name]);
					}
				}
			},

			/**
			 * {var} Generic getter for @property {String|Array}. Supports two possible use cases:
			 *
			 *     var value = get("property");
			 *     var values = get(["property1", "property2"]);
			 */
			get : function(property)
			{
				if (typeof property == "string")
				{
					var method = getters[property];
					if (!method) {
						method = getters[property] = "get" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to get: " + property);
					}

					return this[method]();
				}
				else
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "Array");
					}

					var ret = {};

					for (var i=0, l=property.length; i<l; i++)
					{
						var name = property[i];
						var method = getters[name];
						if (!method) {
							method = getters[name] = "get" + up(name);
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to get: " + name);
						}

						ret[name] = this[method]();
					}

					return ret;
				}
			},

			/**
			 * {var} Generic checker for @property {String|Array} being valid. Supports two possible use cases:
			 *
			 *     var singleIsValid = isValid("property");
			 *     var givenAreValid = isValid(["property1", "property2"]);
			 *     var allAreValid = isValid();
			 */
			isValid : function(property)
			{
				if (typeof property == "string")
				{
					var method = validators[property];
					if (!method) {
						method = validators[property] = "isValid" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to validate: " + property);
					}

					return this[method]();
				}
				else if (property === undef || core.Assert.isType(property, "Array"))
				{
					if (!property)
					{
						property = core.Class.getProperties(this.constructor);
						var all = true;
					}

					for (var i=0, l=property.length; i<l; i++)
					{
						var name = property[i];
						var method = validators[name];
						if (!method) {
							method = validators[name] = "isValid" + up(name);
						}

						if (all && !this[method]) {
							continue;
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to validate: " + name);
						}

						if (!this[method]()) {
							return false;
						}
					}

					return true;
				}
				else if (jasy.Env.isSet("debug"))
				{
					throw new Error("Invalid value for validation: " + property);
				}
			}
		}
	});
})();

<commit_msg>Minor fix<commit_after>/*
==================================================================================================
  Core - JavaScript Foundation
  Copyright 2010-2012 Zynga Inc.
  Copyright 2012-2013 Sebastian Werner
==================================================================================================
*/

(function()
{
	var setters = {};
	var getters = {};
	var validators = {};

	var up = function(name) {
		return name.charAt(0).toUpperCase() + name.slice(1);
	};

	var undef;

	/**
	 * Generic setter/getter support for property API.
	 *
	 * Include this if your class uses properties and want to be able to generically
	 * set/get them based on the property names
	 */
	core.Class("core.property.MGeneric",
	{
		members :
		{
			/**
			 * {var} Generic setter. Supports two possible use cases for @property {String|Map} and @value {var?}:
			 *
			 *     set("property", value);
			 *     set({
			 *       property1: value1,
			 *       property2: value2
			 *     });
			 *
			 * Returns the value from the setter (if single property is used)
			 */
			set : function(property, value)
			{
				if (arguments.length == 2)
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "String");
					}

					var method = setters[property];
					if (!method) {
						method = setters[property] = "set" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to set: " + property);
					}

					return this[method](value);
				}
				else
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "Map");
					}

					for (var name in property)
					{
						var method = setters[name];
						if (!method) {
							method = setters[name] = "set" + up(name);
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to set: " + name);
						}

						this[method](property[name]);
					}
				}
			},

			/**
			 * {var} Generic getter for @property {String|Array}. Supports two possible use cases:
			 *
			 *     var value = get("property");
			 *     var values = get(["property1", "property2"]);
			 */
			get : function(property)
			{
				if (typeof property == "string")
				{
					var method = getters[property];
					if (!method) {
						method = getters[property] = "get" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to get: " + property);
					}

					return this[method]();
				}
				else
				{
					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(property, "Array");
					}

					var ret = {};

					for (var i=0, l=property.length; i<l; i++)
					{
						var name = property[i];
						var method = getters[name];
						if (!method) {
							method = getters[name] = "get" + up(name);
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to get: " + name);
						}

						ret[name] = this[method]();
					}

					return ret;
				}
			},

			/**
			 * {var} Generic checker for @property {String|Array} being valid. Supports two possible use cases:
			 *
			 *     var singleIsValid = isValid("property");
			 *     var givenAreValid = isValid(["property1", "property2"]);
			 *     var allAreValid = isValid();
			 */
			isValid : function(property)
			{
				if (typeof property == "string")
				{
					var method = validators[property];
					if (!method) {
						method = validators[property] = "isValid" + up(property);
					}

					if (jasy.Env.isSet("debug")) {
						core.Assert.isType(this[method], "Function", "Invalid property to validate: " + property);
					}

					return this[method]();
				}
				else if (property === undef || core.Assert.isType(property, "Array"))
				{
					if (!property)
					{
						property = Object.keys(core.Class.getProperties(this.constructor));
						var all = true;
					}

					for (var i=0, l=property.length; i<l; i++)
					{
						var name = property[i];
						var method = validators[name];
						if (!method) {
							method = validators[name] = "isValid" + up(name);
						}

						if (all && !this[method]) {
							continue;
						}

						if (jasy.Env.isSet("debug")) {
							core.Assert.isType(this[method], "Function", "Invalid property to validate: " + name);
						}

						if (!this[method]()) {
							return false;
						}
					}

					return true;
				}
				else if (jasy.Env.isSet("debug"))
				{
					throw new Error("Invalid value for validation: " + property);
				}
			}
		}
	});
})();

<|endoftext|>


<commit_before>/* global FileReader */

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ProfilePic from 'components/ProfilePic'
import Button from 'components/Button'
import ImageEditModal from 'components/Modals/ImageEditModal'
import BioEditModal from 'components/Modals/BioEditModal'
import {
  removeStatusMsg,
  updateStatusMsg,
  uploadProfilePic,
  uploadBio
} from 'redux/actions/UserActions'
import { openDirectMessageChannel } from 'redux/actions/ChatActions'
import AlertModal from 'components/Modals/AlertModal'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import { borderRadius, Color, mobileMaxWidth } from 'constants/css'
import { css } from 'emotion'
import { loadComments } from 'helpers/requestHelpers'
import { timeSince } from 'helpers/timeStampHelpers'
import RankBar from 'components/RankBar'
import Icon from 'components/Icon'
import Comments from 'components/Comments'
import Link from 'components/Link'
import UserDetails from 'components/UserDetails'

class ProfilePanel extends Component {
  static propTypes = {
    expandable: PropTypes.bool,
    history: PropTypes.object,
    isCreator: PropTypes.bool,
    isProfilePage: PropTypes.bool,
    updateStatusMsg: PropTypes.func,
    openDirectMessageChannel: PropTypes.func,
    profile: PropTypes.object,
    removeStatusMsg: PropTypes.func,
    userId: PropTypes.number,
    uploadBio: PropTypes.func,
    uploadProfilePic: PropTypes.func
  }

  state = {
    comments: [],
    commentsShown: false,
    commentsLoadMoreButton: false,
    confirmModalShown: false,
    imageUri: null,
    processing: false,
    imageEditModalShown: false,
    mouseEnteredProfile: false,
    bioEditModalShown: false,
    alertModalShown: false
  }

  async componentDidMount() {
    const { profile } = this.props
    try {
      const { comments } = await loadComments({
        id: profile.id,
        type: 'user',
        limit: 1
      })
      this.setState({ comments })
    } catch (error) {
      console.error(error)
    }
  }

  render() {
    const {
      comments,
      commentsShown,
      commentsLoadMoreButton,
      imageUri,
      imageEditModalShown,
      bioEditModalShown,
      alertModalShown,
      mouseEnteredProfile,
      processing
    } = this.state
    const {
      history,
      profile,
      userId,
      expandable,
      isCreator,
      isProfilePage,
      openDirectMessageChannel,
      updateStatusMsg,
      uploadBio
    } = this.props
    const canEdit = userId === profile.id || isCreator
    const { profileFirstRow, profileSecondRow, profileThirdRow } = profile
    const noProfile = !profileFirstRow && !profileSecondRow && !profileThirdRow
    return (

        <div
          className={css`
            background: #fff;
            padding: 1rem;
            border: #e7e7e7 1px solid;
            border-top-left-radius: ${borderRadius};
            border-top-right-radius: ${borderRadius};
            ${
              profile.twinkleXP
                ? 'border-bottom: none;'
                : `
                border-bottom-left-radius: ${borderRadius};
                border-bottom-right-radius: ${borderRadius};
              `
            }
            @media (max-width: ${mobileMaxWidth}) {
              border-radius: 0;
              border-left: none;
              border-right: none;
            }
          `}
        >

                  this.setState({ mouseEnteredProfile: true })
                }
                onMouseLeave={() =>
                  this.setState({ mouseEnteredProfile: false })
                }
              >
                <Link to={isProfilePage ? null : `/users/${profile.username}`}>
                  <ProfilePic
                    style={{ width: '18rem', height: '18rem' }}
                    userId={profile.id}
                    profilePicId={profile.profilePicId}
                    online={userId === profile.id || !!profile.online}
                    large
                  />
                </Link>

              {!isProfilePage && (

                  <Button
                    warning
                    transparent
                    style={{ color: mouseEnteredProfile && Color.orange() }}
                    onClick={() => history.push(`/users/${profile.username}`)}
                  >
                    View Profile
                  </Button>

              )}

              <UserDetails
                profile={profile}
                isProfilePage={isProfilePage}
                updateStatusMsg={updateStatusMsg}
                uploadBio={uploadBio}
                userId={userId}
              />
              {canEdit && (

                    <Button
                      transparent
                      onClick={this.onChangeProfilePictureClick}
                    >
                      Change Pic
                    </Button>
                    <Button
                      transparent
                      onClick={() => this.setState({ bioEditModalShown: true })}
                      style={{ marginLeft: '0.5rem' }}
                    >
                      Edit Bio
                    </Button>
                    {profile.id === userId &&
                      comments.length > 0 &&
                      this.renderMessagesButton({
                        style: { marginLeft: '0.5rem' }
                      })}

              )}
              {expandable &&
                userId !== profile.id && (

                    {this.renderMessagesButton()}
                    <Button
                      style={{ marginLeft: '0.5rem' }}
                      success
                      onClick={() =>
                        openDirectMessageChannel(
                          { userId },
                          { userId: profile.id, username: profile.username },
                          false
                        )
                      }
                    >
                      <Icon icon="comments" />
                      Talk
                    </Button>

                )}
              {profile.lastActive &&
                !profile.online &&
                profile.id !== userId && (

last online {timeSince(profile.lastActive)}

                )}

            <input
              ref={ref => {
                this.fileInput = ref
              }}
              style={{ display: 'none' }}
              type="file"
              onChange={this.handlePicture}
              accept="image/*"
            />
            {bioEditModalShown && (
              <BioEditModal
                firstLine={profileFirstRow}
                secondLine={profileSecondRow}
                thirdLine={profileThirdRow}
                onSubmit={this.uploadBio}
                onHide={() =>
                  this.setState({
                    bioEditModalShown: false
                  })
                }
              />
            )}
            {imageEditModalShown && (
              <ImageEditModal
                imageUri={imageUri}
                onHide={() =>
                  this.setState({
                    imageUri: null,
                    imageEditModalShown: false,
                    processing: false
                  })
                }
                processing={processing}
                onConfirm={this.uploadImage}
              />
            )}

          <Comments
            autoFocus
            comments={comments}
            commentsLoadLimit={20}
            commentsShown={commentsShown}
            contentId={profile.id}
            inputAreaInnerRef={ref => (this.CommentInputArea = ref)}
            inputTypeLabel={`message to ${profile.username}`}
            loadMoreButton={commentsLoadMoreButton}
            loadMoreComments={this.onLoadMoreComments}
            noInput={profile.id === userId}
            numPreviews={3}
            onAttachStar={this.onAttachStar}
            onCommentSubmit={this.onCommentSubmit}
            onDelete={this.onDeleteComment}
            onEditDone={this.onEditComment}
            onLikeClick={this.onLikeComment}
            onLoadMoreReplies={this.onLoadMoreReplies}
            onReplySubmit={this.onReplySubmit}
            onRewardCommentEdit={this.onEditRewardComment}
            parent={{ ...profile, type: 'user' }}
            style={{ marginTop: '1rem' }}
            userId={userId}
          />

        {!!profile.twinkleXP && <RankBar profile={profile} />}
        {alertModalShown && (
          <AlertModal
            title="Image is too large (limit: 5mb)"
            content="Please select a smaller image"
            onHide={() => this.setState({ alertModalShown: false })}
          />
        )}

    )
  }

  handlePicture = event => {
    const reader = new FileReader()
    const maxSize = 5000
    const file = event.target.files[0]
    if (file.size / 1000 > maxSize) {
      return this.setState({ alertModalShown: true })
    }
    reader.onload = upload => {
      this.setState({
        imageEditModalShown: true,
        imageUri: upload.target.result
      })
    }

    reader.readAsDataURL(file)
    event.target.value = null
  }

  onAttachStar = star => {
    this.setState(state => ({
      comments: state.comments.map(comment => {
        return {
          ...comment,
          stars:
            comment.id === star.contentId
              ? (comment.stars || []).concat(star)
              : comment.stars || [],
          replies: comment.replies.map(reply => ({
            ...reply,
            stars:
              reply.id === star.contentId
                ? (reply.stars || []).concat(star)
                : reply.stars || []
          }))
        }
      })
    }))
  }

  onCommentSubmit = comment => {
    this.setState(state => ({
      comments: [comment].concat(state.comments)
    }))
  }

  onChangeProfilePictureClick = () => {
    this.fileInput.click()
  }

  onDeleteComment = commentId => {
    this.setState(state => {
      const comments = state.comments.filter(
        comment => comment.id !== commentId
      )
      return {
        comments: comments.map(comment => ({
          ...comment,
          replies: (comment.replies || []).filter(
            reply => reply.id !== commentId
          )
        }))
      }
    })
  }

  onEditComment = ({ editedComment, commentId }) => {
    this.setState(state => {
      return {
        comments: state.comments.map(comment => ({
          ...comment,
          content: comment.id === commentId ? editedComment : comment.content,
          replies: comment.replies
            ? comment.replies.map(
                reply =>
                  reply.id === commentId
                    ? {
                        ...reply,
                        content: editedComment
                      }
                    : reply
              )
            : []
        }))
      }
    })
  }

  onEditRewardComment = ({ id, text }) => {
    this.setState(state => ({
      comments: state.comments.map(comment => ({
        ...comment,
        stars: comment.stars
          ? comment.stars.map(star => ({
              ...star,
              rewardComment: star.id === id ? text : star.rewardComment
            }))
          : [],
        replies: comment.replies.map(reply => ({
          ...reply,
          stars: reply.stars
            ? reply.stars.map(star => ({
                ...star,
                rewardComment: star.id === id ? text : star.rewardComment
              }))
            : []
        }))
      }))
    }))
  }

  onExpandComments = async() => {
    const { profile, userId } = this.props
    const { comments, loadMoreButton } = await loadComments({
      id: profile.id,
      type: 'user',
      limit: 5
    })
    this.setState({
      comments,
      commentsShown: true,
      commentsLoadMoreButton: loadMoreButton
    })
    if (profile.id !== userId) this.CommentInputArea.focus()
  }

  onLikeComment = ({ commentId, likes }) => {
    this.setState(state => {
      return {
        comments: state.comments.map(comment => ({
          ...comment,
          likes: comment.id === commentId ? likes : comment.likes,
          replies: comment.replies
            ? comment.replies.map(
                reply =>
                  reply.id === commentId
                    ? {
                        ...reply,
                        likes
                      }
                    : reply
              )
            : []
        }))
      }
    })
  }

  onLoadMoreComments = ({ comments, loadMoreButton }) => {
    this.setState(state => ({
      comments: state.comments.concat(comments),
      commentsLoadMoreButton: loadMoreButton
    }))
  }

  onLoadMoreReplies = ({ commentId, replies, loadMoreButton }) => {
    this.setState(state => ({
      comments: state.comments.map(comment => ({
        ...comment,
        replies:
          comment.id === commentId
            ? replies.concat(comment.replies)
            : comment.replies,
        loadMoreButton:
          comment.id === commentId ? loadMoreButton : comment.loadMoreButton
      }))
    }))
  }

  onReplySubmit = data => {
    this.setState(state => ({
      comments: state.comments.map(comment => {
        let match = false
        let commentId = data.replyId || data.commentId
        if (comment.id === commentId) {
          match = true
        } else {
          for (let reply of comment.replies || []) {
            if (reply.id === commentId) {
              match = true
              break
            }
          }
        }
        return {
          ...comment,
          replies: match ? comment.replies.concat([data]) : comment.replies
        }
      })
    }))
  }

  renderMessagesButton = (props = {}) => {
    const {
      profile: { id, numMessages },
      userId
    } = this.props
    const { commentsShown } = this.state
    return (
      <Button
        {...props}
        disabled={commentsShown && id === userId}
        logo
        onClick={this.onExpandComments}
      >
        <Icon icon="comment-alt" />

          Message
          {Number(numMessages) > 0 && !commentsShown
            ? `${numMessages > 1 ? 's' : ''} (${numMessages})`
            : ''}

      </Button>
    )
  }

  uploadBio = async params => {
    const { profile, uploadBio } = this.props
    await uploadBio({ ...params, profileId: profile.id })
    this.setState({
      bioEditModalShown: false
    })
  }

  uploadImage = async image => {
    const { uploadProfilePic } = this.props
    this.setState({
      processing: true
    })
    await uploadProfilePic(image)
    this.setState({
      imageUri: null,
      processing: false,
      imageEditModalShown: false
    })
  }
}

export default connect(
  state => ({
    isCreator: state.UserReducer.isCreator,
    userId: state.UserReducer.userId
  }),
  {
    removeStatusMsg,
    updateStatusMsg,
    uploadProfilePic,
    uploadBio,
    openDirectMessageChannel
  }
)(withRouter(ProfilePanel))
<commit_msg>update profile panel comments when change<commit_after>/* global FileReader */

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ProfilePic from 'components/ProfilePic'
import Button from 'components/Button'
import ImageEditModal from 'components/Modals/ImageEditModal'
import BioEditModal from 'components/Modals/BioEditModal'
import {
  removeStatusMsg,
  updateStatusMsg,
  uploadProfilePic,
  uploadBio
} from 'redux/actions/UserActions'
import { openDirectMessageChannel } from 'redux/actions/ChatActions'
import AlertModal from 'components/Modals/AlertModal'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import { borderRadius, Color, mobileMaxWidth } from 'constants/css'
import { css } from 'emotion'
import { loadComments } from 'helpers/requestHelpers'
import { timeSince } from 'helpers/timeStampHelpers'
import RankBar from 'components/RankBar'
import Icon from 'components/Icon'
import Comments from 'components/Comments'
import Link from 'components/Link'
import UserDetails from 'components/UserDetails'

class ProfilePanel extends Component {
  static propTypes = {
    expandable: PropTypes.bool,
    history: PropTypes.object,
    isCreator: PropTypes.bool,
    isProfilePage: PropTypes.bool,
    updateStatusMsg: PropTypes.func,
    openDirectMessageChannel: PropTypes.func,
    profile: PropTypes.object,
    removeStatusMsg: PropTypes.func,
    userId: PropTypes.number,
    uploadBio: PropTypes.func,
    uploadProfilePic: PropTypes.func
  }

  state = {
    comments: [],
    commentsShown: false,
    commentsLoadMoreButton: false,
    confirmModalShown: false,
    imageUri: null,
    processing: false,
    imageEditModalShown: false,
    mouseEnteredProfile: false,
    bioEditModalShown: false,
    alertModalShown: false
  }

  async componentDidMount() {
    const { profile } = this.props
    try {
      const { comments } = await loadComments({
        id: profile.id,
        type: 'user',
        limit: 1
      })
      this.setState({ comments })
    } catch (error) {
      console.error(error)
    }
  }

  render() {
    const {
      comments,
      commentsShown,
      commentsLoadMoreButton,
      imageUri,
      imageEditModalShown,
      bioEditModalShown,
      alertModalShown,
      mouseEnteredProfile,
      processing
    } = this.state
    const {
      history,
      profile,
      userId,
      expandable,
      isCreator,
      isProfilePage,
      openDirectMessageChannel,
      updateStatusMsg,
      uploadBio
    } = this.props
    const canEdit = userId === profile.id || isCreator
    const { profileFirstRow, profileSecondRow, profileThirdRow } = profile
    const noProfile = !profileFirstRow && !profileSecondRow && !profileThirdRow
    return (

        <div
          className={css`
            background: #fff;
            padding: 1rem;
            border: #e7e7e7 1px solid;
            border-top-left-radius: ${borderRadius};
            border-top-right-radius: ${borderRadius};
            ${
              profile.twinkleXP
                ? 'border-bottom: none;'
                : `
                border-bottom-left-radius: ${borderRadius};
                border-bottom-right-radius: ${borderRadius};
              `
            }
            @media (max-width: ${mobileMaxWidth}) {
              border-radius: 0;
              border-left: none;
              border-right: none;
            }
          `}
        >

                  this.setState({ mouseEnteredProfile: true })
                }
                onMouseLeave={() =>
                  this.setState({ mouseEnteredProfile: false })
                }
              >
                <Link to={isProfilePage ? null : `/users/${profile.username}`}>
                  <ProfilePic
                    style={{ width: '18rem', height: '18rem' }}
                    userId={profile.id}
                    profilePicId={profile.profilePicId}
                    online={userId === profile.id || !!profile.online}
                    large
                  />
                </Link>

              {!isProfilePage && (

                  <Button
                    warning
                    transparent
                    style={{ color: mouseEnteredProfile && Color.orange() }}
                    onClick={() => history.push(`/users/${profile.username}`)}
                  >
                    View Profile
                  </Button>

              )}

              <UserDetails
                profile={profile}
                isProfilePage={isProfilePage}
                updateStatusMsg={updateStatusMsg}
                uploadBio={uploadBio}
                userId={userId}
              />
              {canEdit && (

                    <Button
                      transparent
                      onClick={this.onChangeProfilePictureClick}
                    >
                      Change Pic
                    </Button>
                    <Button
                      transparent
                      onClick={() => this.setState({ bioEditModalShown: true })}
                      style={{ marginLeft: '0.5rem' }}
                    >
                      Edit Bio
                    </Button>
                    {profile.id === userId &&
                      comments.length > 0 &&
                      this.renderMessagesButton({
                        style: { marginLeft: '0.5rem' }
                      })}

              )}
              {expandable &&
                userId !== profile.id && (

                    {this.renderMessagesButton()}
                    <Button
                      style={{ marginLeft: '0.5rem' }}
                      success
                      onClick={() =>
                        openDirectMessageChannel(
                          { userId },
                          { userId: profile.id, username: profile.username },
                          false
                        )
                      }
                    >
                      <Icon icon="comments" />
                      Talk
                    </Button>

                )}
              {profile.lastActive &&
                !profile.online &&
                profile.id !== userId && (

last online {timeSince(profile.lastActive)}

                )}

            <input
              ref={ref => {
                this.fileInput = ref
              }}
              style={{ display: 'none' }}
              type="file"
              onChange={this.handlePicture}
              accept="image/*"
            />
            {bioEditModalShown && (
              <BioEditModal
                firstLine={profileFirstRow}
                secondLine={profileSecondRow}
                thirdLine={profileThirdRow}
                onSubmit={this.uploadBio}
                onHide={() =>
                  this.setState({
                    bioEditModalShown: false
                  })
                }
              />
            )}
            {imageEditModalShown && (
              <ImageEditModal
                imageUri={imageUri}
                onHide={() =>
                  this.setState({
                    imageUri: null,
                    imageEditModalShown: false,
                    processing: false
                  })
                }
                processing={processing}
                onConfirm={this.uploadImage}
              />
            )}

          <Comments
            autoFocus
            comments={comments}
            commentsLoadLimit={20}
            commentsShown={commentsShown}
            contentId={profile.id}
            inputAreaInnerRef={ref => (this.CommentInputArea = ref)}
            inputTypeLabel={`message to ${profile.username}`}
            loadMoreButton={commentsLoadMoreButton}
            loadMoreComments={this.onLoadMoreComments}
            noInput={profile.id === userId}
            numPreviews={3}
            onAttachStar={this.onAttachStar}
            onCommentSubmit={this.onCommentSubmit}
            onDelete={this.onDeleteComment}
            onEditDone={this.onEditComment}
            onLikeClick={this.onLikeComment}
            onLoadMoreReplies={this.onLoadMoreReplies}
            onReplySubmit={this.onReplySubmit}
            onRewardCommentEdit={this.onEditRewardComment}
            parent={{ ...profile, type: 'user' }}
            style={{ marginTop: '1rem' }}
            userId={userId}
          />

        {!!profile.twinkleXP && <RankBar profile={profile} />}
        {alertModalShown && (
          <AlertModal
            title="Image is too large (limit: 5mb)"
            content="Please select a smaller image"
            onHide={() => this.setState({ alertModalShown: false })}
          />
        )}

    )
  }

  handlePicture = event => {
    const reader = new FileReader()
    const maxSize = 5000
    const file = event.target.files[0]
    if (file.size / 1000 > maxSize) {
      return this.setState({ alertModalShown: true })
    }
    reader.onload = upload => {
      this.setState({
        imageEditModalShown: true,
        imageUri: upload.target.result
      })
    }

    reader.readAsDataURL(file)
    event.target.value = null
  }

  onAttachStar = star => {
    this.setState(state => ({
      comments: state.comments.map(comment => {
        return {
          ...comment,
          stars:
            comment.id === star.contentId
              ? (comment.stars || []).concat(star)
              : comment.stars || [],
          replies: comment.replies.map(reply => ({
            ...reply,
            stars:
              reply.id === star.contentId
                ? (reply.stars || []).concat(star)
                : reply.stars || []
          }))
        }
      })
    }))
  }

  onCommentSubmit = comment => {
    this.setState(state => ({
      comments: [comment].concat(state.comments)
    }))
  }

  onChangeProfilePictureClick = () => {
    this.fileInput.click()
  }

  onDeleteComment = commentId => {
    this.setState(state => {
      const comments = state.comments.filter(
        comment => comment.id !== commentId
      )
      return {
        comments: comments.map(comment => ({
          ...comment,
          replies: (comment.replies || []).filter(
            reply => reply.id !== commentId
          )
        }))
      }
    })
  }

  onEditComment = ({ editedComment, commentId }) => {
    this.setState(state => {
      return {
        comments: state.comments.map(comment => ({
          ...comment,
          content: comment.id === commentId ? editedComment : comment.content,
          replies: comment.replies
            ? comment.replies.map(
                reply =>
                  reply.id === commentId
                    ? {
                        ...reply,
                        content: editedComment
                      }
                    : reply
              )
            : []
        }))
      }
    })
  }

  onEditRewardComment = ({ id, text }) => {
    this.setState(state => ({
      comments: state.comments.map(comment => ({
        ...comment,
        stars: comment.stars
          ? comment.stars.map(star => ({
              ...star,
              rewardComment: star.id === id ? text : star.rewardComment
            }))
          : [],
        replies: comment.replies.map(reply => ({
          ...reply,
          stars: reply.stars
            ? reply.stars.map(star => ({
                ...star,
                rewardComment: star.id === id ? text : star.rewardComment
              }))
            : []
        }))
      }))
    }))
  }

  onExpandComments = async() => {
    const { profile, userId } = this.props
    const { comments, loadMoreButton } = await loadComments({
      id: profile.id,
      type: 'user',
      limit: 5
    })
    this.setState({
      comments,
      commentsShown: true,
      commentsLoadMoreButton: loadMoreButton
    })
    if (profile.id !== userId) this.CommentInputArea.focus()
  }

  onLikeComment = ({ commentId, likes }) => {
    this.setState(state => {
      return {
        comments: state.comments.map(comment => ({
          ...comment,
          likes: comment.id === commentId ? likes : comment.likes,
          replies: comment.replies
            ? comment.replies.map(
                reply =>
                  reply.id === commentId
                    ? {
                        ...reply,
                        likes
                      }
                    : reply
              )
            : []
        }))
      }
    })
  }

  onLoadMoreComments = ({ comments, loadMoreButton }) => {
    this.setState(state => ({
      comments: state.comments.concat(comments),
      commentsLoadMoreButton: loadMoreButton
    }))
  }

  onLoadMoreReplies = ({ commentId, replies, loadMoreButton }) => {
    this.setState(state => ({
      comments: state.comments.map(comment => ({
        ...comment,
        replies:
          comment.id === commentId
            ? replies.concat(comment.replies)
            : comment.replies,
        loadMoreButton:
          comment.id === commentId ? loadMoreButton : comment.loadMoreButton
      }))
    }))
  }

  onReplySubmit = data => {
    this.setState(state => ({
      comments: state.comments.map(comment => {
        let match = false
        let commentId = data.replyId || data.commentId
        if (comment.id === commentId) {
          match = true
        } else {
          for (let reply of comment.replies || []) {
            if (reply.id === commentId) {
              match = true
              break
            }
          }
        }
        return {
          ...comment,
          replies: match ? comment.replies.concat([data]) : comment.replies
        }
      })
    }))
  }

  renderMessagesButton = (props = {}) => {
    const {
      profile: { id, numMessages },
      userId
    } = this.props
    const { commentsShown } = this.state
    return (
      <Button
        {...props}
        disabled={commentsShown && id === userId}
        logo
        onClick={this.onExpandComments}
      >
        <Icon icon="comment-alt" />

          Message
          {Number(numMessages) > 0 && !commentsShown
            ? `${numMessages > 1 ? 's' : ''} (${numMessages})`
            : ''}

      </Button>
    )
  }

  uploadBio = async params => {
    const { profile, uploadBio } = this.props
    await uploadBio({ ...params, profileId: profile.id })
    this.setState({
      bioEditModalShown: false
    })
  }

  uploadImage = async image => {
    const { uploadProfilePic } = this.props
    this.setState({
      processing: true
    })
    await uploadProfilePic(image)
    this.setState({
      imageUri: null,
      processing: false,
      imageEditModalShown: false
    })
  }
}

export default connect(
  state => ({
    isCreator: state.UserReducer.isCreator,
    userId: state.UserReducer.userId
  }),
  {
    removeStatusMsg,
    updateStatusMsg,
    uploadProfilePic,
    uploadBio,
    openDirectMessageChannel
  }
)(withRouter(ProfilePanel))
<|endoftext|>


<commit_before><commit_msg>Created a replacement for RulesContainer.<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2017 Banco Bilbao Vizcaya Argentaria, S.A.
 *
 * 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.
 */

var Utils = (function() {
  'use strict';

  var breakFavIconTimeout;
  var colorMapping = {
    'daa038' : 'yellow', // Warning status color for Slack
    'd00000': 'red', // Danger status color for Slack
    'red': 'red',
    'yellow': 'yellow'
  };

  var notification;

  document.addEventListener('Message', checkNotification);
  document.addEventListener('HeadsUp', checkNotification);
  document.addEventListener('Message', notifyFavIcon);
  document.addEventListener('HeadsUp', notifyFavIcon);

  function checkNotification(data) {
    if (Notification.permission === "granted") {
      if (data && data.detail) {
        if(notification) {
          notification.close();
        }
        notification = new Notification('MirrorGate Notification: ' + (data.detail.title || ''), {
          body: data.detail.description || '',
          icon: 'img/favicon-' + (colorMapping[data.detail.color] || 'blue') + '.png'
        });
      }
    }
  }

  function notifyFavIcon(event) {
    if(event && event.detail) {
      var icon = document.querySelector('link[rel*="icon"]');

      icon.href = 'img/favicon-' + (colorMapping[event.detail.color] || 'blue') + '.png';
      if(breakFavIconTimeout) {
        clearTimeout(breakFavIconTimeout);
      }
      breakFavIconTimeout = setTimeout(function() {
        icon.href = 'img/favicon.png';
        breakFavIconTimeout = undefined;
      }, 60000);
    }
  }

  function clone(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null === obj || 'object' != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
      copy = new Date();
      copy.setTime(obj.getTime());
      return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
      copy = [];
      for (var i = 0, len = obj.length; i < len; i++) {
        copy[i] = clone(obj[i]);
      }
      return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
      copy = {};
      Object.setPrototypeOf(copy, Object.getPrototypeOf(obj));
      for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
      }
      return copy;
    }

    throw new Error('Unable to copy obj! Its type isn\'t supported.');
  }

  return {

    clone: clone,

    getDashboardId: function() {
      var dashboard = document.location.hash;
      if (dashboard && dashboard.length > 1) {
        dashboard = dashboard.substring(1);
      } else {
        var searchParams = new URLSearchParams(window.location.search);
        dashboard = searchParams.get('board');
      }
      return dashboard || '';
    },

    getSkin: function () {
      return this._skin || 'classic';
    },

    initSkin: function () {
      var self = this;
      return new Promise(function (resolve) {
        Service
          .get(Service.types.dashboard, Utils.getDashboardId())
          .addListener(function(details) {
            details = details && JSON.parse(details);
            self._skin = (details && details.skin) || 'classic';
            resolve(self._skin);
          });
      });
    },

    getWorkingDays: function(start, end) {
      var diff = 0;
      start = moment(start);
      end = moment(end);
      if (start.isBefore(end)) {
        end.add(-1, 'days');
        diff = moment().isoWeekdayCalc({
          rangeStart: start,
          rangeEnd: end,
          weekdays: [1, 2, 3, 4, 5],
          exclusions: [],
          inclusions: []
        });
      }
      return diff;
    },

    raiseEvent: function(source, detail) {
      source.dispatchEvent(
          new CustomEvent('dashboard-updated', {bubbles: true, detail: detail}));
    },

    toClassName: function(s) { return (s || s === 0) && ('' + s).toLowerCase().replace(' ', '-').replace('_','-'); },

    openDashboard : function(type, boardId) {
      document.location.href = type + '.html?board=' + encodeURIComponent( boardId || Utils.getDashboardId());
      return false;
    },

    openFeedbackForm: function () {
      window.mirrorGateConfig().then(function (config) {
        document.location.href = config.backOfficeUrl + 'index.html#/feedback';
      });
      return false;
    },

    openBackOffice: function (boardId) {
      window.mirrorGateConfig().then(function (config) {
        document.location.href = config.backOfficeUrl + (boardId ?
          'index.html#/edit/' + encodeURIComponent(boardId) + "?backToDashboard=true" :
          'index.html#/list');
      });
      return false;
    },

    compareVersions: function (version1, version2, regExp) {

      var v1parts = regExp.exec(version1) || [];
      var v2parts = regExp.exec(version2) || [];

      for (var i = 1; i < Math.max(v1parts.length, v2parts.length); ++i) {
        var part1 = parseInt(v1parts[i]) || 0;
        var part2 = parseInt(v2parts[i]) || 0;

        if (part1 !== part2) {
          return part1 - part2;
        }
      }

      return v1parts.length - v2parts.length;
    },

    rephraseVersion: function (version, regExp) {
      var parts = regExp.exec(version);
      return parts && (parts.length > 1) ? 'v' + parts.slice(1).join('.') : version;
    },

    normalEstimation: function (serie, confidence) {
      serie = serie || [];
      var z = {'80%': 0.84,'90%':1.29, '95%': 1.65, '99%': 2.33}[confidence || '80%'];

      var r = {
          count: 0,
          total: 0,
          avg: 0,
          sigma: 0,
          estimate: 0
      };

      serie.forEach(function(value) {
          r.count++;
          r.total += value;
      }, this);
      r.avg = r.total / r.count;

      serie.forEach(function(value) {
          r.sigma += Math.pow(value - r.avg,2);
      }, this);

      r.sigma = Math.sqrt(r.sigma / (r.total - 1));
      r.estimate = r.sigma * z + r.avg;
      return r;
    },
  };

})();

rivets.formatters.dateFrom = function(value, now) {
  return moment(value).from(now);
};

rivets.formatters.date = function(value, now) {
  return moment(value).calendar(now);
};

rivets.formatters.textCleanUp = function(value) {
  return decodeURIComponent(decodeURIComponent(value));
};

rivets.formatters.duration = function(value) {
  if(!value) {
    return "";
  }
  var duration = moment.duration(value);
  var rt = "" + duration.seconds() + " sec";
  if(duration.asMinutes() >= 1) {
    if(duration.seconds() < 1) {
      rt = "";
    } else {
      rt = " " + rt;
    }
    rt = "" + Math.round(duration.asMinutes()) + " min" + rt;
  }
  return rt;
};

rivets.formatters.round = function(value) {
  return Math.round(value);
};

rivets.formatters.bigNumber = function(value) {
  if(value < 10000) {
    return value;
  } else if(value < 10000000) {
    return Math.round(value / 1000) + 'K';
  } else {
    return Math.round(value / 1000000) + 'M';
  }
};

rivets.formatters.length = function(value) {
  return value ? (value.length || 0) : 0;
};

rivets.formatters['>='] = function (value, arg) {
  return value >= arg;
};

rivets.formatters['='] = function (value, arg) {
  return value === arg;
};

rivets.binders['pclass-*'] = function(el, value) {
  var prefix = this.args[0] + '-';
  var $el = $(el);
  var classList = el.className.split(/\s+/);
  classList.forEach(function(name) {
    if (name.startsWith(prefix)) {
      $el.removeClass(name);
    }
  });
  if (value !== null && value !== undefined) {
    $(el).addClass(prefix + Utils.toClassName(value));
  }
};

rivets.binders['setclass-*'] = function(el, value) {
  var cls = this.args[0];
  var $el = $(el);
  var classList = el.className.split(/\s+/);
  classList.forEach(function(name) {
    if (name === cls) {
      $el.removeClass(name);
    }
  });
  if (value) {
    $(el).addClass(cls);
  }
};

function styleBuilder(style, suffix) {
  suffix = suffix || '';

  return function(el, value) {
    $(el).css(style, '' + value + suffix);
  };
}

rivets.binders.ignore = {
    block: true,
    routine: function () { /* do nothing */ }
};

rivets.binders.width = styleBuilder('width','%');
rivets.binders.left = styleBuilder('left','%');
rivets.binders.right = styleBuilder('right','%');

rivets.binders.color = function(el, value) {
  $(el).css('color', '#' + value);
};
<commit_msg>refactor(notitications): check if favicon exists before change it<commit_after>/*
 * Copyright 2017 Banco Bilbao Vizcaya Argentaria, S.A.
 *
 * 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.
 */

var Utils = (function() {
  'use strict';

  var breakFavIconTimeout;
  var colorMapping = {
    'daa038' : 'yellow', // Warning status color for Slack
    'd00000': 'red', // Danger status color for Slack
    'red': 'red',
    'yellow': 'yellow'
  };

  var notification;

  document.addEventListener('Message', checkNotification);
  document.addEventListener('HeadsUp', checkNotification);
  document.addEventListener('Message', notifyFavIcon);
  document.addEventListener('HeadsUp', notifyFavIcon);

  function checkNotification(data) {
    if (Notification.permission === "granted") {
      if (data && data.detail) {
        if(notification) {
          notification.close();
        }
        notification = new Notification('MirrorGate Notification: ' + (data.detail.title || ''), {
          body: data.detail.description || '',
          icon: 'img/favicon-' + (colorMapping[data.detail.color] || 'blue') + '.png'
        });
      }
    }
  }

  function notifyFavIcon(event) {
    if(event && event.detail) {
      var icon = document.querySelector('link[rel*="icon"]');

      if(icon) {
        icon.href = 'img/favicon-' + (colorMapping[event.detail.color] || 'blue') + '.png';
        if(breakFavIconTimeout) {
          clearTimeout(breakFavIconTimeout);
        }
        breakFavIconTimeout = setTimeout(function() {
          icon.href = 'img/favicon.png';
          breakFavIconTimeout = undefined;
        }, 60000);
      }
    }
  }

  function clone(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null === obj || 'object' != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
      copy = new Date();
      copy.setTime(obj.getTime());
      return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
      copy = [];
      for (var i = 0, len = obj.length; i < len; i++) {
        copy[i] = clone(obj[i]);
      }
      return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
      copy = {};
      Object.setPrototypeOf(copy, Object.getPrototypeOf(obj));
      for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
      }
      return copy;
    }

    throw new Error('Unable to copy obj! Its type isn\'t supported.');
  }

  return {

    clone: clone,

    getDashboardId: function() {
      var dashboard = document.location.hash;
      if (dashboard && dashboard.length > 1) {
        dashboard = dashboard.substring(1);
      } else {
        var searchParams = new URLSearchParams(window.location.search);
        dashboard = searchParams.get('board');
      }
      return dashboard || '';
    },

    getSkin: function () {
      return this._skin || 'classic';
    },

    initSkin: function () {
      var self = this;
      return new Promise(function (resolve) {
        Service
          .get(Service.types.dashboard, Utils.getDashboardId())
          .addListener(function(details) {
            details = details && JSON.parse(details);
            self._skin = (details && details.skin) || 'classic';
            resolve(self._skin);
          });
      });
    },

    getWorkingDays: function(start, end) {
      var diff = 0;
      start = moment(start);
      end = moment(end);
      if (start.isBefore(end)) {
        end.add(-1, 'days');
        diff = moment().isoWeekdayCalc({
          rangeStart: start,
          rangeEnd: end,
          weekdays: [1, 2, 3, 4, 5],
          exclusions: [],
          inclusions: []
        });
      }
      return diff;
    },

    raiseEvent: function(source, detail) {
      source.dispatchEvent(
          new CustomEvent('dashboard-updated', {bubbles: true, detail: detail}));
    },

    toClassName: function(s) { return (s || s === 0) && ('' + s).toLowerCase().replace(' ', '-').replace('_','-'); },

    openDashboard : function(type, boardId) {
      document.location.href = type + '.html?board=' + encodeURIComponent( boardId || Utils.getDashboardId());
      return false;
    },

    openFeedbackForm: function () {
      window.mirrorGateConfig().then(function (config) {
        document.location.href = config.backOfficeUrl + 'index.html#/feedback';
      });
      return false;
    },

    openBackOffice: function (boardId) {
      window.mirrorGateConfig().then(function (config) {
        document.location.href = config.backOfficeUrl + (boardId ?
          'index.html#/edit/' + encodeURIComponent(boardId) + "?backToDashboard=true" :
          'index.html#/list');
      });
      return false;
    },

    compareVersions: function (version1, version2, regExp) {

      var v1parts = regExp.exec(version1) || [];
      var v2parts = regExp.exec(version2) || [];

      for (var i = 1; i < Math.max(v1parts.length, v2parts.length); ++i) {
        var part1 = parseInt(v1parts[i]) || 0;
        var part2 = parseInt(v2parts[i]) || 0;

        if (part1 !== part2) {
          return part1 - part2;
        }
      }

      return v1parts.length - v2parts.length;
    },

    rephraseVersion: function (version, regExp) {
      var parts = regExp.exec(version);
      return parts && (parts.length > 1) ? 'v' + parts.slice(1).join('.') : version;
    },

    normalEstimation: function (serie, confidence) {
      serie = serie || [];
      var z = {'80%': 0.84,'90%':1.29, '95%': 1.65, '99%': 2.33}[confidence || '80%'];

      var r = {
          count: 0,
          total: 0,
          avg: 0,
          sigma: 0,
          estimate: 0
      };

      serie.forEach(function(value) {
          r.count++;
          r.total += value;
      }, this);
      r.avg = r.total / r.count;

      serie.forEach(function(value) {
          r.sigma += Math.pow(value - r.avg,2);
      }, this);

      r.sigma = Math.sqrt(r.sigma / (r.total - 1));
      r.estimate = r.sigma * z + r.avg;
      return r;
    },
  };

})();

rivets.formatters.dateFrom = function(value, now) {
  return moment(value).from(now);
};

rivets.formatters.date = function(value, now) {
  return moment(value).calendar(now);
};

rivets.formatters.textCleanUp = function(value) {
  return decodeURIComponent(decodeURIComponent(value));
};

rivets.formatters.duration = function(value) {
  if(!value) {
    return "";
  }
  var duration = moment.duration(value);
  var rt = "" + duration.seconds() + " sec";
  if(duration.asMinutes() >= 1) {
    if(duration.seconds() < 1) {
      rt = "";
    } else {
      rt = " " + rt;
    }
    rt = "" + Math.round(duration.asMinutes()) + " min" + rt;
  }
  return rt;
};

rivets.formatters.round = function(value) {
  return Math.round(value);
};

rivets.formatters.bigNumber = function(value) {
  if(value < 10000) {
    return value;
  } else if(value < 10000000) {
    return Math.round(value / 1000) + 'K';
  } else {
    return Math.round(value / 1000000) + 'M';
  }
};

rivets.formatters.length = function(value) {
  return value ? (value.length || 0) : 0;
};

rivets.formatters['>='] = function (value, arg) {
  return value >= arg;
};

rivets.formatters['='] = function (value, arg) {
  return value === arg;
};

rivets.binders['pclass-*'] = function(el, value) {
  var prefix = this.args[0] + '-';
  var $el = $(el);
  var classList = el.className.split(/\s+/);
  classList.forEach(function(name) {
    if (name.startsWith(prefix)) {
      $el.removeClass(name);
    }
  });
  if (value !== null && value !== undefined) {
    $(el).addClass(prefix + Utils.toClassName(value));
  }
};

rivets.binders['setclass-*'] = function(el, value) {
  var cls = this.args[0];
  var $el = $(el);
  var classList = el.className.split(/\s+/);
  classList.forEach(function(name) {
    if (name === cls) {
      $el.removeClass(name);
    }
  });
  if (value) {
    $(el).addClass(cls);
  }
};

function styleBuilder(style, suffix) {
  suffix = suffix || '';

  return function(el, value) {
    $(el).css(style, '' + value + suffix);
  };
}

rivets.binders.ignore = {
    block: true,
    routine: function () { /* do nothing */ }
};

rivets.binders.width = styleBuilder('width','%');
rivets.binders.left = styleBuilder('left','%');
rivets.binders.right = styleBuilder('right','%');

rivets.binders.color = function(el, value) {
  $(el).css('color', '#' + value);
};
<|endoftext|>


<commit_before>// Based on:
// https://github.com/babel/babel/blob/8b096ac7057379fd698eea3a33a2f77a8311a363/src/babel/transformation/helpers/build-react-transformer.js

var esutils = require('esutils');
var isIdentifierNameES6 = esutils.keyword.isIdentifierNameES6;

// this.scope.hasBinding("name")` checks for local bindings
// this.scope.hasOwnBinding("name")` only checks the current scope
// this.scope.hasGlobal("name")`

module.exports = function(babel) {
  var t = babel.types;

  return new babel.Transformer('jsx-ir', {
    // @done
    JSXIdentifier: function (node) {
      if (node.name === 'this' && this.isReferenced()) {
        return t.thisExpression();
      } else if (isIdentifierNameES6(node.name)) {
        node.type = 'Identifier';
      } else {
        return t.literal(node.name);
      }
    },
    // @done
    JSXNamespacedName: function(node) {
      return t.literal(node.namespace.name + ':' + node.name.name);
    },
    // @done
    JSXMemberExpression: {
      exit: function(node) {
        node.computed = t.isLiteral(node.property);
        node.type = 'MemberExpression';
      }
    },
    // @done
    JSXEmptyExpression: function (node) {
      node.type = 'Literal';
      node.value = null;
    },
    // @done
    JSXExpressionContainer: function(node) {
      return node.expression;
    },
    // @done
    JSXAttribute: {
      enter: function(node) {
        var value = node.value;

        if (t.isLiteral(value) && typeof value.value === 'string') {
          value.value = value.value.replace(/\n\s+/g, ' ');
        }
      },

      exit: function(node) {
        var name = node.name;
        var value = node.value || t.literal(true);

        return t.inherits(t.property('init', name, value), node);
      }
    },
    // @done
    JSXOpeningElement: {
      exit: function(node, parent, scope, file) {
        var props = node.attributes;

        if (props.length) {
          // props = handleProps(props, scope, file, t);
          props = handleSpreadProps(props, scope, file, t);
        } else {
          props = t.literal(null);
        }

        var tag;

        if (t.isMemberExpression(node.name)) {
          node = node.name;
          tag = [];

          do {
            tag.push(node.property.name);
          } while (t.isMemberExpression(node = node.object));

          tag.push(node.name);
          tag = t.literal(tag.join('.'));
        } else {
          tag = t.literal(node.name.name || node.name.value);
        }

        var item = t.objectExpression([
          t.property('init', t.identifier('tag'), tag),
          t.property('init', t.identifier('props'), props)
        ]);

        return item;
      }
    },
    // @done
    JSXElement: {
      exit: function(node) {
        var item = node.openingElement;
        var children = buildChildren(node.children, t);

        children = children.length ? t.arrayExpression(children) : t.literal(null);
        item.properties.push(
          t.property('init', t.identifier('children'), children)
        );

        return t.inherits(item, node);
      }
    },

    Expression: function(node, parent) {
      if (this.isCompletionRecord()) {
        // console.log(parent);
      }
    },
    Program: function(node) {
      // console.log(node);
    }
  });
};

function cleanChildren(child) {
  var lines = child.value.split(/\r\n|\n|\r/);
  var lastNonEmptyLine = 0;

  for (var i = 0; i < lines.length; i++) {
    if (lines[i].match(/[^ \t]/)) {
      lastNonEmptyLine = i;
    }
  }

  var str = '';

  for (var i = 0; i < lines.length; i++) {
    var line = lines[i];

    var isFirstLine = i === 0;
    var isLastLine = i === lines.length - 1;
    var isLastNonEmptyLine = i === lastNonEmptyLine;

    // replace rendered whitespace tabs with spaces
    var trimmedLine = line.replace(/\t/g, ' ');

    // trim whitespace touching a newline
    if (!isFirstLine) {
      trimmedLine = trimmedLine.replace(/^[ ]+/, '');
    }

    // trim whitespace touching an endline
    if (!isLastLine) {
      trimmedLine = trimmedLine.replace(/[ ]+$/, '');
    }

    if (trimmedLine) {
      if (!isLastNonEmptyLine) {
        trimmedLine += ' ';
      }

      str += trimmedLine;
    }
  }

  return str;
}

function buildChildren(children, t) {
  var elems = [];

  for (var i = 0; i < children.length; i++) {
    var child = children[i];

    if (t.isLiteral(child) && typeof child.value === 'string') {
      var str = cleanChildren(child, t);
      if (str) elems.push(t.literal(str));

      continue;
    }

    elems.push(child);
  }

  return elems;
}

function handleProps(props, scope, file, t) {
  // scope.push({ id: t.identifier("id"), init: t.identifier("init") });
  props = props.map(function(prop) {
    var propName = prop.key.name || prop.key.value;

    if (isIdentifierNameES6(propName)) {
      propName = t.identifier(propName);
    } else {
      propName = t.literal(propName);
    }

    return t.property('init', propName, prop.value);
  });

  return t.objectExpression(props);
}

function handleSpreadProps(props, scope, file, t) {
  var propsStack = [];
  var objectsStack = [];

  var pushProps = function () {
    if (!propsStack.length) return;

    objectsStack.push(t.objectExpression(propsStack));
    propsStack = [];
  };

  var makeProp = function(prop) {
    var propName = prop.key.name || prop.key.value;

    if (isIdentifierNameES6(propName)) {
      propName = t.identifier(propName);
    } else {
      propName = t.literal(propName);
    }

    return t.property('init', propName, prop.value);
  };

  for (var i = 0, len = props.length; i < len; i++) {
    var prop = props[i];

    if (t.isJSXSpreadAttribute(prop)) {
      pushProps();
      objectsStack.push(prop.argument);
    } else {
      propsStack.push(makeProp(prop));
    }
  }

  pushProps();

  if (objectsStack.length === 1) {
    // only one object
    props = objectsStack[0];
  } else {
    // looks like we have multiple objects
    if (!t.isObjectExpression(objectsStack[0])) {
      objectsStack.unshift(t.objectExpression([]));
    }

    // spread it
    props = t.callExpression(
      file.addHelper('extends'),
      objectsStack
    );

    /*var propsKey = scope.generateUidIdentifier('props');

    scope.push({
      id: propsKey,
      init: props
    });

    props = t.identifier(propsKey.name);*/
  }

  return props;
};<commit_msg>Remove comments<commit_after>// Based on:
// https://github.com/babel/babel/blob/8b096ac7057379fd698eea3a33a2f77a8311a363/src/babel/transformation/helpers/build-react-transformer.js

var esutils = require('esutils');
var isIdentifierNameES6 = esutils.keyword.isIdentifierNameES6;

// this.scope.hasBinding("name")` checks for local bindings
// this.scope.hasOwnBinding("name")` only checks the current scope
// this.scope.hasGlobal("name")`

module.exports = function(babel) {
  var t = babel.types;

  return new babel.Transformer('jsx-ir', {
    JSXIdentifier: function (node) {
      if (node.name === 'this' && this.isReferenced()) {
        return t.thisExpression();
      } else if (isIdentifierNameES6(node.name)) {
        node.type = 'Identifier';
      } else {
        return t.literal(node.name);
      }
    },
    JSXNamespacedName: function(node) {
      return t.literal(node.namespace.name + ':' + node.name.name);
    },
    JSXMemberExpression: {
      exit: function(node) {
        node.computed = t.isLiteral(node.property);
        node.type = 'MemberExpression';
      }
    },
    JSXEmptyExpression: function (node) {
      node.type = 'Literal';
      node.value = null;
    },
    JSXExpressionContainer: function(node) {
      return node.expression;
    },
    JSXAttribute: {
      enter: function(node) {
        var value = node.value;

        if (t.isLiteral(value) && typeof value.value === 'string') {
          value.value = value.value.replace(/\n\s+/g, ' ');
        }
      },

      exit: function(node) {
        var name = node.name;
        var value = node.value || t.literal(true);

        return t.inherits(t.property('init', name, value), node);
      }
    },
    JSXOpeningElement: {
      exit: function(node, parent, scope, file) {
        var props = node.attributes;

        if (props.length) {
          // props = handleProps(props, scope, file, t);
          props = handleSpreadProps(props, scope, file, t);
        } else {
          props = t.literal(null);
        }

        var tag;

        if (t.isMemberExpression(node.name)) {
          node = node.name;
          tag = [];

          do {
            tag.push(node.property.name);
          } while (t.isMemberExpression(node = node.object));

          tag.push(node.name);
          tag = t.literal(tag.join('.'));
        } else {
          tag = t.literal(node.name.name || node.name.value);
        }

        var item = t.objectExpression([
          t.property('init', t.identifier('tag'), tag),
          t.property('init', t.identifier('props'), props)
        ]);

        return item;
      }
    },
    JSXElement: {
      exit: function(node) {
        var item = node.openingElement;
        var children = buildChildren(node.children, t);

        children = children.length ? t.arrayExpression(children) : t.literal(null);
        item.properties.push(
          t.property('init', t.identifier('children'), children)
        );

        return t.inherits(item, node);
      }
    },

    Expression: function(node, parent) {
      if (this.isCompletionRecord()) {
        // console.log(parent);
      }
    },
    Program: function(node) {
      // console.log(node);
    }
  });
};

function cleanChildren(child) {
  var lines = child.value.split(/\r\n|\n|\r/);
  var lastNonEmptyLine = 0;

  for (var i = 0; i < lines.length; i++) {
    if (lines[i].match(/[^ \t]/)) {
      lastNonEmptyLine = i;
    }
  }

  var str = '';

  for (var i = 0; i < lines.length; i++) {
    var line = lines[i];

    var isFirstLine = i === 0;
    var isLastLine = i === lines.length - 1;
    var isLastNonEmptyLine = i === lastNonEmptyLine;

    // replace rendered whitespace tabs with spaces
    var trimmedLine = line.replace(/\t/g, ' ');

    // trim whitespace touching a newline
    if (!isFirstLine) {
      trimmedLine = trimmedLine.replace(/^[ ]+/, '');
    }

    // trim whitespace touching an endline
    if (!isLastLine) {
      trimmedLine = trimmedLine.replace(/[ ]+$/, '');
    }

    if (trimmedLine) {
      if (!isLastNonEmptyLine) {
        trimmedLine += ' ';
      }

      str += trimmedLine;
    }
  }

  return str;
}

function buildChildren(children, t) {
  var elems = [];

  for (var i = 0; i < children.length; i++) {
    var child = children[i];

    if (t.isLiteral(child) && typeof child.value === 'string') {
      var str = cleanChildren(child, t);
      if (str) elems.push(t.literal(str));

      continue;
    }

    elems.push(child);
  }

  return elems;
}

function handleProps(props, scope, file, t) {
  // scope.push({ id: t.identifier("id"), init: t.identifier("init") });
  props = props.map(function(prop) {
    var propName = prop.key.name || prop.key.value;

    if (isIdentifierNameES6(propName)) {
      propName = t.identifier(propName);
    } else {
      propName = t.literal(propName);
    }

    return t.property('init', propName, prop.value);
  });

  return t.objectExpression(props);
}

function handleSpreadProps(props, scope, file, t) {
  var propsStack = [];
  var objectsStack = [];

  var pushProps = function () {
    if (!propsStack.length) return;

    objectsStack.push(t.objectExpression(propsStack));
    propsStack = [];
  };

  var makeProp = function(prop) {
    var propName = prop.key.name || prop.key.value;

    if (isIdentifierNameES6(propName)) {
      propName = t.identifier(propName);
    } else {
      propName = t.literal(propName);
    }

    return t.property('init', propName, prop.value);
  };

  for (var i = 0, len = props.length; i < len; i++) {
    var prop = props[i];

    if (t.isJSXSpreadAttribute(prop)) {
      pushProps();
      objectsStack.push(prop.argument);
    } else {
      propsStack.push(makeProp(prop));
    }
  }

  pushProps();

  if (objectsStack.length === 1) {
    // only one object
    props = objectsStack[0];
  } else {
    // looks like we have multiple objects
    if (!t.isObjectExpression(objectsStack[0])) {
      objectsStack.unshift(t.objectExpression([]));
    }

    // spread it
    props = t.callExpression(
      file.addHelper('extends'),
      objectsStack
    );

    /*var propsKey = scope.generateUidIdentifier('props');

    scope.push({
      id: propsKey,
      init: props
    });

    props = t.identifier(propsKey.name);*/
  }

  return props;
};<|endoftext|>


<commit_before>Vps.Binding.AbstractPanel = function(config) {
    if (!config || !config.actions) this.actions = {}; //muss hier sein
    Vps.Binding.AbstractPanel.superclass.constructor.apply(this, arguments);
};
Ext.extend(Vps.Binding.AbstractPanel, Ext.Panel,
{
    checkDirty: true,

    loadBindingsOnSelectionChange: true, //wenn false muss loadBindings() selbst aufgerufen werden

    initComponent: function() {
        this.activeId = null;

        this.addEvents(
            /**
            * @event datachange
            * Daten wurden geändert, zB um grid neu zu laden
            * @param {Object} result from server
            */
            'datachange',
            'selectionchange',
            'beforeselectionchange',
            'loaded'
        );
        var binds = this.bindings;
        this.bindings = new Ext.util.MixedCollection();
        if (binds) {
            this.addBinding.apply(this, binds);
        }
        if (this.loadBindingsOnSelectionChange) {
            this.on('selectionchange', function() {
                this.loadBindings();
            }, this, {buffer: 500});
            this.on('beforeselectionchange', function(id) {
                var ret = true;
                this.bindings.each(function(b) {
                    if (!b.item.mabySubmit({
                        callback: function() {
                            b.item.reset();
                            this.selectId(id);
                        },
                        scope: this
                    })) {
                        ret = false;
                        return false; //break each
                    }
                }, this)
                return ret;
            }, this);
        }

        if (this.baseParams) {
            this.setBaseParams(this.baseParams); //damit baseParams in applyBaseParams modifiziert werden können
        }
        if (!this.baseParams) {
            this.baseParams = {};
        }

        Vps.Binding.AbstractPanel.superclass.initComponent.call(this);
    },

    /**
     * Lädt alle Bindings, wird normalerweise im selectionchange event aufgerufen
     */
    loadBindings: function(id)
    {
        if (!id) id = this.getSelectedId();
        if (id) {
            this.activeId = id;
            this.bindings.each(function(b) {
                b.item.enable();
                if (b.item.ownerCt && b.item.ownerCt.getLayout && b.item.ownerCt.getLayout() instanceof Ext.layout.CardLayout) {
                    if (b.item.ownerCt.getLayout().activeItem != b.item) {
                        //dieses binding überspringen, liegt in einem
                        //tab der nicht aktiv ist
                        return;
                    }
                }
                this._loadBinding(b);
            }, this);
        }
    },

    //private
    _loadBinding: function(b)
    {
        var params = {};
        if (b.componentIdSuffix) {
            params.componentId =
                this.getBaseParams()['componentId'] +
                String.format(b.componentIdSuffix, this.activeId);
        } else if (b.componentId) {
            params.componentId =
                String.format(b.componentId, this.activeId);
        } else {
			//this.getGrid().getSelectionModel().getSelections()[0].data[b.valueParam];
            params[b.queryParam] = this.activeId;
        }
        if (!b.item.hasBaseParams(params)) {
            b.item.applyBaseParams(params);
            b.item.load();
        }
    },
    addBinding: function() {
        for(var i = 0; i < arguments.length; i++){
            var b = arguments[i];
            if (b instanceof Vps.Binding.AbstractPanel) {
                b = {item: b};
            }
            if (!b.queryParam) b.queryParam = 'id';
            b.item.disable();
            b.item.setAutoLoad(false);
            this.bindings.add(b);

            b.item.on('datachange', function(result)
            {
                if (result && result.data && result.data.addedId) {

                    //nachdem ein neuer eintrag hinzugefügt wurde die anderen reloaden
                    this.activeId = result.data.addedId;

                    //neuladen und wenn geladen den neuen auswählen
                    this.reload({
                        callback: function() {
                            this.selectId(this.activeId);
                        },
                        scope: this
                    });

                    //die anderen auch neu laden
                    this.bindings.each(function(b) {
                        b.item.enable();
                        if (b.item.ownerCt && b.item.ownerCt.getLayout && b.item.ownerCt.getLayout() instanceof Ext.layout.CardLayout) {
                            if (b.item.ownerCt.getLayout().activeItem != b.item) {
                                //dieses binding überspringen, liegt in einem
                                //tab der nicht aktiv ist
                                return;
                            }
                        }
                        this._loadBinding(b);
                    }, this);
                } else {
                    this.reload();
                }
            }, this);

            if (b.item instanceof Vps.Auto.FormPanel) {
                b.item.on('addaction', function(form) {
                    this.activeId = 0;
                    this.selectId(0);
                    //bei addaction die anderen disablen
                    this.bindings.each(function(i) {
                        if (i.item != form) {
                            i.item.disable();
                        }
                    }, this);
                }, this);

                b.item.on('deleteaction', function(form) {
                    this.activeId = null;
                    this.selectId(null);
                    //wenn gelöscht alle anderen disablen
                    this.bindings.each(function(i) {
                        i.item.disable();
                    }, this);
                }, this);
            }
            b.item.on('activate', function(item) {
                this.bindings.each(function(i) {
                    if (i.item == item) {
                        if (!item.disabled) {
                            this._loadBinding(i);
                        }
                        return false;
                    }
                }, this);
            }, this);
        }
    },
    removeBinding: function(autoPanel) {
        //todo
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];
    },

    //deprecated
    mabySave : function(callback, callCallbackIfNotDirty)
    {
        var ret = this.mabySubmit(callback.callback, callback.scope || this);
        if(typeof callCallbackIfNotDirty == 'undefined') callCallbackIfNotDirty = true;
        if (ret && callCallbackIfNotDirty) {
            callback.callback.call(callback.scope);
        }
        return ret;
    },

    mabySubmit : function(cb, options)
    {
        if (this.checkDirty && !this.disabled && this.isDirty()) {
            Ext.Msg.show({
            title:trlVps('Save'),
            msg: trlVps('Do you want to save the changes?'),
            buttons: Ext.Msg.YESNOCANCEL,
            scope: this,
            fn: function(button) {
                if (button == 'yes') {
                    if (!options) options = {};
                    options.success = cb.callback;
                    options.scope = cb.scope;
                    this.submit(options);
                } else if (button == 'no') {
                    cb.callback.call(cb.scope || this);
                } else if (button == 'cancel') {
                    //nothing to do, action allread canceled
                }
            }});
            return false;
        }
        return true;
    },

    submit: function(options) {
    },
    reset: function() {
    },
    load: function(params, options) {
    },
    reload : function(options) {
        if (!this.disabled) {
            this.load(null, options);
        }
    },
    getSelectedId: function() {
    },
    selectId: function(id) {
    },
    isDirty: function() {
        return false;
    },
    setBaseParams : function(baseParams) {
        this.baseParams = {};
        this.applyBaseParams(baseParams);
    },
    applyBaseParams : function(baseParams) {
        if (!this.baseParams) { this.baseParams = {}; }
        Ext.apply(this.baseParams, baseParams);
    },
    getBaseParams : function() {
        return this.baseParams || {};
    },

    //um herauszufinden ob params neue baseParams sind
    //wird zB in ComponentPanel überschrieben
    //getBaseParams von aussen holen und mit den neuen vergleichen geht im ComponentPanel
    //nicht, da diese anders gespeichert werden
    hasBaseParams : function(params) {
        var baseParams = this.getBaseParams();
        for (var i in params) {
            if (params[i] != baseParams[i]) return false;
        }
        return true;
    },

    setAutoLoad: function(v) {
        this.autoLoad = v;
    },
    getAutoLoad: function() {
        return this.autoLoad;
    }
});
<commit_msg>kein fehler wenn keine autoform geladen<commit_after>Vps.Binding.AbstractPanel = function(config) {
    if (!config || !config.actions) this.actions = {}; //muss hier sein
    Vps.Binding.AbstractPanel.superclass.constructor.apply(this, arguments);
};
Ext.extend(Vps.Binding.AbstractPanel, Ext.Panel,
{
    checkDirty: true,

    loadBindingsOnSelectionChange: true, //wenn false muss loadBindings() selbst aufgerufen werden

    initComponent: function() {
        this.activeId = null;

        this.addEvents(
            /**
            * @event datachange
            * Daten wurden geändert, zB um grid neu zu laden
            * @param {Object} result from server
            */
            'datachange',
            'selectionchange',
            'beforeselectionchange',
            'loaded'
        );
        var binds = this.bindings;
        this.bindings = new Ext.util.MixedCollection();
        if (binds) {
            this.addBinding.apply(this, binds);
        }
        if (this.loadBindingsOnSelectionChange) {
            this.on('selectionchange', function() {
                this.loadBindings();
            }, this, {buffer: 500});
            this.on('beforeselectionchange', function(id) {
                var ret = true;
                this.bindings.each(function(b) {
                    if (!b.item.mabySubmit({
                        callback: function() {
                            b.item.reset();
                            this.selectId(id);
                        },
                        scope: this
                    })) {
                        ret = false;
                        return false; //break each
                    }
                }, this)
                return ret;
            }, this);
        }

        if (this.baseParams) {
            this.setBaseParams(this.baseParams); //damit baseParams in applyBaseParams modifiziert werden können
        }
        if (!this.baseParams) {
            this.baseParams = {};
        }

        Vps.Binding.AbstractPanel.superclass.initComponent.call(this);
    },

    /**
     * Lädt alle Bindings, wird normalerweise im selectionchange event aufgerufen
     */
    loadBindings: function(id)
    {
        if (!id) id = this.getSelectedId();
        if (id) {
            this.activeId = id;
            this.bindings.each(function(b) {
                b.item.enable();
                if (b.item.ownerCt && b.item.ownerCt.getLayout && b.item.ownerCt.getLayout() instanceof Ext.layout.CardLayout) {
                    if (b.item.ownerCt.getLayout().activeItem != b.item) {
                        //dieses binding überspringen, liegt in einem
                        //tab der nicht aktiv ist
                        return;
                    }
                }
                this._loadBinding(b);
            }, this);
        }
    },

    //private
    _loadBinding: function(b)
    {
        var params = {};
        if (b.componentIdSuffix) {
            params.componentId =
                this.getBaseParams()['componentId'] +
                String.format(b.componentIdSuffix, this.activeId);
        } else if (b.componentId) {
            params.componentId =
                String.format(b.componentId, this.activeId);
        } else {
			//this.getGrid().getSelectionModel().getSelections()[0].data[b.valueParam];
            params[b.queryParam] = this.activeId;
        }
        if (!b.item.hasBaseParams(params)) {
            b.item.applyBaseParams(params);
            b.item.load();
        }
    },
    addBinding: function() {
        for(var i = 0; i < arguments.length; i++){
            var b = arguments[i];
            if (b instanceof Vps.Binding.AbstractPanel) {
                b = {item: b};
            }
            if (!b.queryParam) b.queryParam = 'id';
            b.item.disable();
            b.item.setAutoLoad(false);
            this.bindings.add(b);

            b.item.on('datachange', function(result)
            {
                if (result && result.data && result.data.addedId) {

                    //nachdem ein neuer eintrag hinzugefügt wurde die anderen reloaden
                    this.activeId = result.data.addedId;

                    //neuladen und wenn geladen den neuen auswählen
                    this.reload({
                        callback: function() {
                            this.selectId(this.activeId);
                        },
                        scope: this
                    });

                    //die anderen auch neu laden
                    this.bindings.each(function(b) {
                        b.item.enable();
                        if (b.item.ownerCt && b.item.ownerCt.getLayout && b.item.ownerCt.getLayout() instanceof Ext.layout.CardLayout) {
                            if (b.item.ownerCt.getLayout().activeItem != b.item) {
                                //dieses binding überspringen, liegt in einem
                                //tab der nicht aktiv ist
                                return;
                            }
                        }
                        this._loadBinding(b);
                    }, this);
                } else {
                    this.reload();
                }
            }, this);

            if (Vps.Auto.FormPanel && b.item instanceof Vps.Auto.FormPanel) {
                b.item.on('addaction', function(form) {
                    this.activeId = 0;
                    this.selectId(0);
                    //bei addaction die anderen disablen
                    this.bindings.each(function(i) {
                        if (i.item != form) {
                            i.item.disable();
                        }
                    }, this);
                }, this);

                b.item.on('deleteaction', function(form) {
                    this.activeId = null;
                    this.selectId(null);
                    //wenn gelöscht alle anderen disablen
                    this.bindings.each(function(i) {
                        i.item.disable();
                    }, this);
                }, this);
            }
            b.item.on('activate', function(item) {
                this.bindings.each(function(i) {
                    if (i.item == item) {
                        if (!item.disabled) {
                            this._loadBinding(i);
                        }
                        return false;
                    }
                }, this);
            }, this);
        }
    },
    removeBinding: function(autoPanel) {
        //todo
    },

    getAction : function(type)
    {
        if (this.actions[type]) return this.actions[type];
    },

    //deprecated
    mabySave : function(callback, callCallbackIfNotDirty)
    {
        var ret = this.mabySubmit(callback.callback, callback.scope || this);
        if(typeof callCallbackIfNotDirty == 'undefined') callCallbackIfNotDirty = true;
        if (ret && callCallbackIfNotDirty) {
            callback.callback.call(callback.scope);
        }
        return ret;
    },

    mabySubmit : function(cb, options)
    {
        if (this.checkDirty && !this.disabled && this.isDirty()) {
            Ext.Msg.show({
            title:trlVps('Save'),
            msg: trlVps('Do you want to save the changes?'),
            buttons: Ext.Msg.YESNOCANCEL,
            scope: this,
            fn: function(button) {
                if (button == 'yes') {
                    if (!options) options = {};
                    options.success = cb.callback;
                    options.scope = cb.scope;
                    this.submit(options);
                } else if (button == 'no') {
                    cb.callback.call(cb.scope || this);
                } else if (button == 'cancel') {
                    //nothing to do, action allread canceled
                }
            }});
            return false;
        }
        return true;
    },

    submit: function(options) {
    },
    reset: function() {
    },
    load: function(params, options) {
    },
    reload : function(options) {
        if (!this.disabled) {
            this.load(null, options);
        }
    },
    getSelectedId: function() {
    },
    selectId: function(id) {
    },
    isDirty: function() {
        return false;
    },
    setBaseParams : function(baseParams) {
        this.baseParams = {};
        this.applyBaseParams(baseParams);
    },
    applyBaseParams : function(baseParams) {
        if (!this.baseParams) { this.baseParams = {}; }
        Ext.apply(this.baseParams, baseParams);
    },
    getBaseParams : function() {
        return this.baseParams || {};
    },

    //um herauszufinden ob params neue baseParams sind
    //wird zB in ComponentPanel überschrieben
    //getBaseParams von aussen holen und mit den neuen vergleichen geht im ComponentPanel
    //nicht, da diese anders gespeichert werden
    hasBaseParams : function(params) {
        var baseParams = this.getBaseParams();
        for (var i in params) {
            if (params[i] != baseParams[i]) return false;
        }
        return true;
    },

    setAutoLoad: function(v) {
        this.autoLoad = v;
    },
    getAutoLoad: function() {
        return this.autoLoad;
    }
});
<|endoftext|>