<commit_before>import React from "react";
import Radium from "radium";
// import _ from 'lodash';
// import { connect } from 'react-redux';
// import { FOO } from '../actions';
import * as globals from "../../util/globals";

// @connect(state => {
//   return state.FOO;
// })
@Radium
class TreeNode extends React.Component {
  constructor(props) {
    super(props);
    this.state = {

    };
  }
  static propTypes = {
    /* react */
    // dispatch: React.PropTypes.func,
    params: React.PropTypes.object,
    routes: React.PropTypes.array,
    /* component api */
    style: React.PropTypes.object,
    controls: React.PropTypes.object,
    strain: React.PropTypes.string,
    hasChildren: React.PropTypes.bool,
    nuc_muts: React.PropTypes.string,
    showBranchLabels: React.PropTypes.bool,
    node: React.PropTypes.object
    // foo: React.PropTypes.string
  }
  static defaultProps = {
    // foo: "bar"
  }

  getNodeText() {
    let nodeText = "";
    if (this.props.strain) {
      nodeText = this.props.strain;
    } else if (this.props.hasChildren && this.props.showBranchLabels) {
      nodeText = this.props.nuc_muts;
    }

    return nodeText;
  }
  determineLegendMatch(node) {
    const colorBy = this.props.controls.colorBy;
    const c = this.props.controls;
    // construct a dictionary that maps a legend entry to the preceding interval
    let bool;
    // equates a tip and a legend element
    // exact match is required for categorical qunantities such as genotypes, regions
    // continuous variables need to fall into the interal (lower_bound[leg], leg]
    if (
      (colorBy === "lbi") ||
      (colorBy === "date") ||
      (colorBy === "dfreq") ||
      (colorBy === "HI_dist") ||
      (colorBy === "cHI")
    ) {
      bool = (node.coloring <= c.legendBoundsMap.upper_bound[c.selectedLegendItem]) &&
        (node.coloring > c.legendBoundsMap.lower_bound[c.selectedLegendItem]);
    } else {
      bool = node[this.props.controls.colorBy] === c.selectedLegendItem;
    }
    return bool;
  }
  tipRadius(node) {
    if (
      typeof node.pred_distance !== "undefined" &&
      this.props.controls.colorBy === "fitness"
    ) {
      return globals.distanceScale(node.pred_distance);
    } else {
      return globals.tipRadius;
    }
  }
  chooseTipRadius(node) {
    let r;

    if (this.determineLegendMatch(node)) {
      r = this.tipRadius(node) *
        globals.tipRadiusOnLegendMatchMultiplier;
    } else {
      r = this.tipRadius(node, this.props.controls.colorBy);
    }
    return r;
  }
  render() {
    return (
      <g transform={"translate(" + this.props.x + "," + this.props.y + ")"}>
        <circle
          fill={this.props.fill}
          r={
            this.props.hasChildren ?
              globals.nonTipNodeRadius :
              this.chooseTipRadius(this.props.node)} />
        <text
          dx={this.props.hasChildren ? -6 : 6}
          dy={this.props.hasChildren ? -2 : 3}
            style={{
              fontFamily: "Helvetica",
              fontSize: 8,
              fontWeight: 300
            }}
          textAnchor={this.props.hasChildren ? "end" : "start"}>
          {this.getNodeText()}
        </text>
      </g>
    )
  }
}

export default TreeNode;

// if ((typeof tip_labels !== "undefined") && (tip_labels)) {
//   treeplot.selectAll(".tipLabel").data(tips)
//     .enter()
//     .append("text")
//     .attr("class", "tipLabel")
//     .style("font-size", (d) => {return tipLabelSize(d) + "px"; })
//     .text(tipLabelText);
// }
//
// var tipCircles = treeplot.selectAll(".tip")
//   .data(tips)
//   .enter()
//   .append("circle")
//   .attr("class", "tip")
//   .attr("id", (d) => { return (d.strain).replace(/\//g, ""); })
//   .attr("r", tipRadius)
//   .style("visibility", tipVisibility)
//   .style("fill", tipFillColor)
//   .style("stroke", tipStrokeColor);

// const serumCircles = treeplot.selectAll(".serum") /* bug does this need to be stored or just executed? */
//   .data(sera)
//   .enter()
//   .append("text")
//   .attr("class", "serum")
//   .attr("text-anchor", "middle")
//   .attr("dominant-baseline", "central")
//   .style("font-family", "FontAwesome")
//   .style("fill", (d) => {if (d === focusNode) {return "#FF3300";} else {return "#555555";}})
//   .style("font-size", (d) => {if (d === focusNode) {return "30px";} else {return "12px";}})
//   .text((d) => {
//     if (d === focusNode) {return "\uf05b";} else {return serumSymbol;}
//   })
//   .style("visibility", serumVisibility)
//   .style("cursor", "crosshair");
//
//
//   var vaccineCircles = treeplot.selectAll(".vaccine")
//     .data(vaccines)
//     .enter()
//     .append("text")
//     .attr("class", "vaccine")
//     .attr("text-anchor", "middle")
//     .attr("dominant-baseline", "central")
//     .style("font-size", "28px")
//     .style("font-family", "FontAwesome")
//     .style("fill", "#555555")
//     .text(() => { return "\uf00d"; })
//     .style("cursor", "default");
<commit_msg>hover logic on node<commit_after>import React from "react";
import Radium from "radium";
// import _ from 'lodash';
import { connect } from 'react-redux';
// import { FOO } from '../actions';
import * as globals from "../../util/globals";
import { NODE_MOUSEENTER, NODE_MOUSELEAVE } from "../../actions/controls";

@connect()
@Radium
class TreeNode extends React.Component {
  constructor(props) {
    super(props);
    this.state = {

    };
  }
  static propTypes = {
    /* react */
    // dispatch: React.PropTypes.func,
    params: React.PropTypes.object,
    routes: React.PropTypes.array,
    /* component api */
    style: React.PropTypes.object,
    controls: React.PropTypes.object,
    strain: React.PropTypes.string,
    hasChildren: React.PropTypes.bool,
    nuc_muts: React.PropTypes.string,
    showBranchLabels: React.PropTypes.bool,
    node: React.PropTypes.object
    // foo: React.PropTypes.string
  }
  static defaultProps = {
    // foo: "bar"
  }

  getNodeText() {
    /*
      this is a bit of trickiness. we'll see if it's too clever.
      if a node is a tip, we show the strain, and if it's not, we
      append a branch label (but only if show branch label is checked),
      and the placement of the branch label is based on the
      position of the node.

      What we're doing here is overloading the idea of node text
      to also include branch label, rather than making that its
      own thing.
    */
    let nodeText = "";
    if (this.props.strain) {
      /* this is a tip label */
      nodeText = this.props.strain;
    } else if (this.props.hasChildren && this.props.showBranchLabels) {
      /* this is a branch label */
      nodeText = this.props.nuc_muts;
    }

    return nodeText;
  }
  determineLegendMatch(node) {
    const colorBy = this.props.controls.colorBy;
    const c = this.props.controls;
    // construct a dictionary that maps a legend entry to the preceding interval
    let bool;
    // equates a tip and a legend element
    // exact match is required for categorical qunantities such as genotypes, regions
    // continuous variables need to fall into the interal (lower_bound[leg], leg]
    if (
      (colorBy === "lbi") ||
      (colorBy === "date") ||
      (colorBy === "dfreq") ||
      (colorBy === "HI_dist") ||
      (colorBy === "cHI")
    ) {
      bool = (node.coloring <= c.legendBoundsMap.upper_bound[c.selectedLegendItem]) &&
        (node.coloring > c.legendBoundsMap.lower_bound[c.selectedLegendItem]);
    } else {
      bool = node[this.props.controls.colorBy] === c.selectedLegendItem;
    }
    return bool;
  }
  tipRadius(node) {
    if (
      typeof node.pred_distance !== "undefined" &&
      this.props.controls.colorBy === "fitness"
    ) {
      return globals.distanceScale(node.pred_distance);
    } else {
      return globals.tipRadius;
    }
  }
  chooseTipRadius(node) {
    let r;

    if (this.determineLegendMatch(node)) {
      r = this.tipRadius(node) *
        globals.tipRadiusOnLegendMatchMultiplier;
    } else {
      r = this.tipRadius(node, this.props.controls.colorBy);
    }
    return r;
  }
  render() {
    return (
      <g
        onMouseEnter={() => {
          this.props.dispatch({
            type: NODE_MOUSEENTER,
            /*
              send the source and target nodes in the action,
              use x and y values in them to place tooltip
            */
            data: this.props.node
          });
        }}
        onMouseLeave={() => {
          this.props.dispatch({ type: NODE_MOUSELEAVE });
        }}
        transform={"translate(" + this.props.x + "," + this.props.y + ")"}>
        <circle
          fill={this.props.fill}
          r={
            this.props.hasChildren ?
              globals.nonTipNodeRadius :
              this.chooseTipRadius(this.props.node)} />
        <text
          dx={this.props.hasChildren ? -6 : 6}
          dy={this.props.hasChildren ? -2 : 3}
            style={{
              fontFamily: "Helvetica",
              fontSize: 8,
              fontWeight: 300
            }}
          textAnchor={this.props.hasChildren ? "end" : "start"}>
          {this.getNodeText()}
        </text>
      </g>
    )
  }
}

export default TreeNode;

// if ((typeof tip_labels !== "undefined") && (tip_labels)) {
//   treeplot.selectAll(".tipLabel").data(tips)
//     .enter()
//     .append("text")
//     .attr("class", "tipLabel")
//     .style("font-size", (d) => {return tipLabelSize(d) + "px"; })
//     .text(tipLabelText);
// }
//
// var tipCircles = treeplot.selectAll(".tip")
//   .data(tips)
//   .enter()
//   .append("circle")
//   .attr("class", "tip")
//   .attr("id", (d) => { return (d.strain).replace(/\//g, ""); })
//   .attr("r", tipRadius)
//   .style("visibility", tipVisibility)
//   .style("fill", tipFillColor)
//   .style("stroke", tipStrokeColor);

// const serumCircles = treeplot.selectAll(".serum") /* bug does this need to be stored or just executed? */
//   .data(sera)
//   .enter()
//   .append("text")
//   .attr("class", "serum")
//   .attr("text-anchor", "middle")
//   .attr("dominant-baseline", "central")
//   .style("font-family", "FontAwesome")
//   .style("fill", (d) => {if (d === focusNode) {return "#FF3300";} else {return "#555555";}})
//   .style("font-size", (d) => {if (d === focusNode) {return "30px";} else {return "12px";}})
//   .text((d) => {
//     if (d === focusNode) {return "\uf05b";} else {return serumSymbol;}
//   })
//   .style("visibility", serumVisibility)
//   .style("cursor", "crosshair");
//
//
//   var vaccineCircles = treeplot.selectAll(".vaccine")
//     .data(vaccines)
//     .enter()
//     .append("text")
//     .attr("class", "vaccine")
//     .attr("text-anchor", "middle")
//     .attr("dominant-baseline", "central")
//     .style("font-size", "28px")
//     .style("font-family", "FontAwesome")
//     .style("fill", "#555555")
//     .text(() => { return "\uf00d"; })
//     .style("cursor", "default");

// const addBranchLabels = () => {
//   /* bug mutations is not necessary just execute treeplot.selectAll */
//   const mutations = treeplot.selectAll(".branchLabel")
//     .data(nodes)
//     .enter()
//     .append("text")
//     .attr("class", "branchLabel")
//     .style("font-size", branchLabelSize)
//     .style("text-anchor", "end")
//     .text(branchLabelText)
//     .style("visibility", "hidden");
// };

// d3.select("#branchlabels")
//   .on("change", (d) => {
//     branchLabels = document.getElementById("branchlabels").checked;
//     treeplot.selectAll(".branchLabel").data(nodes)
//       .text(branchLabelText)
//       .style("visibility", (branchLabels) ? "visible" : "hidden");
//     treeplot.selectAll(".annotation").data(clades)
//       .style("visibility", (branchLabels) ? "hidden" : "visible");
//   });
//
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { push } from 'react-router-redux'
import bindAll from 'lodash/bindAll'
import filter from 'lodash/filter'
import head from 'lodash/head'
import each from 'lodash/each'
import map from 'lodash/map'
import DocumentTitle from 'react-document-title'
import { loadUserByUsername } from '../actions/auth'
import { loadModelByUsernameAndSlug, updateModelReadme, deleteModel } from '../actions/model'
import { loadFilesByUsernameAndSlug } from '../actions/file'
import NavHeader from './NavHeader'
import ModelList from '../components/ModelList'
import FileList from '../components/FileList'
import ReadmeEditor from '../components/ReadmeEditor'
import Footer from '../components/Footer'
import Radium from 'radium'
import styles from '../styles'
import Markdown from 'react-remarkable'
import 'isomorphic-fetch'

import hljs from 'highlight.js/lib/highlight'
import hljs_javascript from 'highlight.js/lib/languages/javascript'
import hljs_python from 'highlight.js/lib/languages/python'
hljs.registerLanguage('javascript', hljs_javascript)
hljs.registerLanguage('python', hljs_python)

const remarkableConfig = {
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(lang, str).value;
      } catch (err) {}
    }

    try {
      return hljs.highlightAuto(str).value;
    } catch (err) {}

    return '' // use external default escaping
  }
}

const kerasIntegration = `
\`\`\`python
from keras_gradientzoo import KerasGradientzoo
# Note: For better security, pass this auth token id as an environment variable
#       or read it from a file whose access can be restricted.
zoo = KerasGradientzoo('{username}/{slug}', auth_token_id='{authTokenId}')

# Load latest weights from Gradientzoo
zoo.load_weights(your_keras_model)

# Save updated weights to Gradientzoo after each epoch
save_weights = zoo.make_save_callback(your_keras_model)
your_keras_model.fit(/* ... */, callbacks=[save_weights])
\`\`\`
`

class ModelPage extends Component {
  constructor(props) {
    super(props)
    this.state = {readmeLater: false, editReadme: false}
    bindAll(this, 'handleReadmeChange', 'handleReadmeLater', 'handleEditClick',
      'handleDeleteClick', 'handleFileClick')
  }

  componentWillReceiveProps(nextProps) {
    // If we've deleted successfully, send them back to their profile page
    if (this.props.deleting && !nextProps.deleting && !nextProps.deleteError) {
      const { push, routeParams: { username } } = this.props
      push('/' + username)
    }
  }

  componentWillMount() {
    const { routeParams: { username, slug }} = this.props
    this.props.loadModelByUsernameAndSlug(username, slug)
    this.props.loadFilesByUsernameAndSlug(username, slug)
    this.props.loadUserByUsername(username)
  }

  handleReadmeChange(readme) {
    this.setState({editReadme: false});
    this.props.updateModelReadme(this.props.model.id, readme)
  }

  handleReadmeLater(ev) {
    this.setState({readmeLater: true, editReadme: false})
  }

  handleEditClick(ev) {
    this.setState({editReadme: true});
  }

  handleDeleteClick(ev) {
    ev.preventDefault()
    if (this.props.deleting) {
      return
    }
    if (!confirm('Warning: This cannot be undone! Now, are you absolutely sure you want to delete this model?')) {
      return
    }
    this.props.deleteModel(this.props.model.id)
  }

  handleFileClick(file, ev) {
    ev.preventDefault()
    const { routeParams: { username, slug }, authTokenId} = this.props
    const path = `/api/file-id/${file.id}`
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    }
    if (authTokenId) {
      headers['X-Auth-Token-Id'] = authTokenId
    }
    fetch(path, {headers: headers})
      .then(response => response.json().then(json => ({ json, response })))
      .then(({ json, response }) => {
        if (json && json.url) {
          window.location.assign(json.url)
        }
      })
  }

  render() {
    const { routeParams: { username, slug }, user, authTokenId} = this.props
    const { model, modelFetching, modelFetchError } = this.props
    const { files, filesFetching, filesFetchError } = this.props
    const { deleting, deleteError } = this.props
    const { readmeLater, editReadme } = this.state
    const modelLoaded = !modelFetching && model
    const keras = kerasIntegration
      .replace(/\{username\}/g, username)
      .replace(/\{slug\}/g, slug)
      .replace(/\{authTokenId\}/g, authTokenId);
    return (
      <DocumentTitle title={username + '/' + slug + ' - Gradientzoo'}>

        <NavHeader activeTab='none' />

          <Link to={'/' + username}>{username}</Link> /{' '}
          {slug}{' '}
          {model ? {model.name}: null}

        {/*model && ? {model.createdTime} : null*/}
        {model ?
{model.description}
 : null}
        {model && user && model.userId === user.id ?

Keras Integration

            <Markdown source={keras} options={remarkableConfig} />

: null}

        <FileList files={files}
                  filesFetching={filesFetching}
                  error={filesFetchError}
                  username={username}
                  modelSlug={slug}
                  showDetails={false}
                  onFileClick={this.handleFileClick} />

        {/* If the model is loaded, but doesn't have a readme, and the user hasn't
            clicked the 'later' button, then show the readme creation dialog. */}
        { modelLoaded && !model.readme && !readmeLater ?

            Next step: Next step: let’s create a readme for your model!

: null}
        { modelLoaded && ((!model.readme && !readmeLater) || editReadme) ?
          <ReadmeEditor onChange={this.handleReadmeChange}
                        onLaterClick={this.handleReadmeLater} /> : null}

        {/* If the model is loaded and does have a readme, show it */}
        { modelLoaded && model.readme && !editReadme ?

Readme Edit

              <Markdown source={model.readme} options={remarkableConfig} />

 : null}

        { modelLoaded && model.readme && !editReadme ?

              Delete Model

              { deleteError ?
{deleteError}
 : null}

 : null}

      </DocumentTitle>
    )
  }
}

ModelPage.propTypes = {
  authTokenId: PropTypes.string,
  authUser: PropTypes.object,
  user: PropTypes.object,
  userFetching: PropTypes.bool,
  userFetchError: PropTypes.string,
  model: PropTypes.object,
  modelFetching: PropTypes.bool,
  modelFetchError: PropTypes.string,
  files: PropTypes.arrayOf(PropTypes.object),
  filesFetching: PropTypes.bool,
  filesFetchError: PropTypes.string,
  deleting: PropTypes.bool,
  deleteError: PropTypes.string,
  routeParams: PropTypes.object,
  loadUserByUsername: PropTypes.func.isRequired,
  loadModelByUsernameAndSlug: PropTypes.func.isRequired,
  loadFilesByUsernameAndSlug: PropTypes.func.isRequired,
  updateModelReadme: PropTypes.func.isRequired,
  deleteModel: PropTypes.func.isRequired,
  push: PropTypes.func.isRequired
}

function mapStateToProps(state, props) {
  const { routeParams: { username, slug }} = props
  const authUser = state.authUserId ? state.entities.users[state.authUserId] : null

  const user = head(filter(
    state.entities.users,
    (u) => u.username === username
  ))

  const model = user ? head(filter(
    state.entities.models,
    (m) => m.userId === user.id && m.slug === slug
  )) : null

  const files = []
  if (model) {
    each(state.entities.files, (file) => {
      if (file.status === 'latest' &&
          file.modelId === model.id &&
          file.userId === user.id) {
        files.push(file)
      }
    })
  }

  return {
    authTokenId: state.authTokenId,
    userFetching: state.userByUsername.fetching,
    userFetchError: state.userByUsername.fetchError,
    modelFetching: state.modelByUsernameAndSlug.fetching,
    modelFetchError: state.modelByUsernameAndSlug.fetchError,
    filesFetching: state.filesByUsernameAndSlug.fetching,
    filesFetchError: state.filesByUsernameAndSlug.fetchError,
    deleting: state.deleteModel.deleting,
    deleteError: state.deleteModel.deleteError,
    authUser,
    user,
    model,
    files
  }
}

export default Radium(connect(mapStateToProps, {
  loadUserByUsername,
  loadModelByUsernameAndSlug,
  loadFilesByUsernameAndSlug,
  updateModelReadme,
  deleteModel,
  push
})(ModelPage))
<commit_msg>Only show edit readme button if viewer is owner<commit_after>import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { push } from 'react-router-redux'
import bindAll from 'lodash/bindAll'
import filter from 'lodash/filter'
import head from 'lodash/head'
import each from 'lodash/each'
import map from 'lodash/map'
import DocumentTitle from 'react-document-title'
import { loadUserByUsername } from '../actions/auth'
import { loadModelByUsernameAndSlug, updateModelReadme, deleteModel } from '../actions/model'
import { loadFilesByUsernameAndSlug } from '../actions/file'
import NavHeader from './NavHeader'
import ModelList from '../components/ModelList'
import FileList from '../components/FileList'
import ReadmeEditor from '../components/ReadmeEditor'
import Footer from '../components/Footer'
import Radium from 'radium'
import styles from '../styles'
import Markdown from 'react-remarkable'
import 'isomorphic-fetch'

import hljs from 'highlight.js/lib/highlight'
import hljs_javascript from 'highlight.js/lib/languages/javascript'
import hljs_python from 'highlight.js/lib/languages/python'
hljs.registerLanguage('javascript', hljs_javascript)
hljs.registerLanguage('python', hljs_python)

const remarkableConfig = {
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(lang, str).value;
      } catch (err) {}
    }

    try {
      return hljs.highlightAuto(str).value;
    } catch (err) {}

    return '' // use external default escaping
  }
}

const kerasIntegration = `
\`\`\`python
from keras_gradientzoo import KerasGradientzoo
# Note: For better security, pass this auth token id as an environment variable
#       or read it from a file whose access can be restricted.
zoo = KerasGradientzoo('{username}/{slug}', auth_token_id='{authTokenId}')

# Load latest weights from Gradientzoo
zoo.load_weights(your_keras_model)

# Save updated weights to Gradientzoo after each epoch
save_weights = zoo.make_save_callback(your_keras_model)
your_keras_model.fit(/* ... */, callbacks=[save_weights])
\`\`\`
`

class ModelPage extends Component {
  constructor(props) {
    super(props)
    this.state = {readmeLater: false, editReadme: false}
    bindAll(this, 'handleReadmeChange', 'handleReadmeLater', 'handleEditClick',
      'handleDeleteClick', 'handleFileClick')
  }

  componentWillReceiveProps(nextProps) {
    // If we've deleted successfully, send them back to their profile page
    if (this.props.deleting && !nextProps.deleting && !nextProps.deleteError) {
      const { push, routeParams: { username } } = this.props
      push('/' + username)
    }
  }

  componentWillMount() {
    const { routeParams: { username, slug }} = this.props
    this.props.loadModelByUsernameAndSlug(username, slug)
    this.props.loadFilesByUsernameAndSlug(username, slug)
    this.props.loadUserByUsername(username)
  }

  handleReadmeChange(readme) {
    this.setState({editReadme: false});
    this.props.updateModelReadme(this.props.model.id, readme)
  }

  handleReadmeLater(ev) {
    this.setState({readmeLater: true, editReadme: false})
  }

  handleEditClick(ev) {
    this.setState({editReadme: true});
  }

  handleDeleteClick(ev) {
    ev.preventDefault()
    if (this.props.deleting) {
      return
    }
    if (!confirm('Warning: This cannot be undone! Now, are you absolutely sure you want to delete this model?')) {
      return
    }
    this.props.deleteModel(this.props.model.id)
  }

  handleFileClick(file, ev) {
    ev.preventDefault()
    const { routeParams: { username, slug }, authTokenId} = this.props
    const path = `/api/file-id/${file.id}`
    const headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    }
    if (authTokenId) {
      headers['X-Auth-Token-Id'] = authTokenId
    }
    fetch(path, {headers: headers})
      .then(response => response.json().then(json => ({ json, response })))
      .then(({ json, response }) => {
        if (json && json.url) {
          window.location.assign(json.url)
        }
      })
  }

  render() {
    const { routeParams: { username, slug }, authTokenId} = this.props
    const { user, authUser } = this.props
    const { model, modelFetching, modelFetchError } = this.props
    const { files, filesFetching, filesFetchError } = this.props
    const { deleting, deleteError } = this.props
    const { readmeLater, editReadme } = this.state
    const isOwner = user && authUser && user.id === authUser.id
    const modelLoaded = !modelFetching && model
    const keras = kerasIntegration
      .replace(/\{username\}/g, username)
      .replace(/\{slug\}/g, slug)
      .replace(/\{authTokenId\}/g, authTokenId);
    return (
      <DocumentTitle title={username + '/' + slug + ' - Gradientzoo'}>

        <NavHeader activeTab='none' />

          <Link to={'/' + username}>{username}</Link> /{' '}
          {slug}{' '}
          {model ? {model.name}: null}

        {/*model && ? {model.createdTime} : null*/}
        {model ?
{model.description}
 : null}
        {model && user && model.userId === user.id ?

Keras Integration

            <Markdown source={keras} options={remarkableConfig} />

: null}

        <FileList files={files}
                  filesFetching={filesFetching}
                  error={filesFetchError}
                  username={username}
                  modelSlug={slug}
                  showDetails={false}
                  onFileClick={this.handleFileClick} />

        {/* If the model is loaded, but doesn't have a readme, and the user hasn't
            clicked the 'later' button, then show the readme creation dialog. */}
        { modelLoaded && !model.readme && !readmeLater ?

            Next step: Next step: let’s create a readme for your model!

: null}
        { modelLoaded && ((!model.readme && !readmeLater) || editReadme) ?
          <ReadmeEditor onChange={this.handleReadmeChange}
                        onLaterClick={this.handleReadmeLater} /> : null}

        {/* If the model is loaded and does have a readme, show it */}
        { modelLoaded && model.readme && !editReadme ?

Readme{isOwner ? Edit : null}

              <Markdown source={model.readme} options={remarkableConfig} />

 : null}

        { modelLoaded && model.readme && !editReadme ?

              Delete Model

              { deleteError ?
{deleteError}
 : null}

 : null}

      </DocumentTitle>
    )
  }
}

ModelPage.propTypes = {
  authTokenId: PropTypes.string,
  authUser: PropTypes.object,
  user: PropTypes.object,
  userFetching: PropTypes.bool,
  userFetchError: PropTypes.string,
  model: PropTypes.object,
  modelFetching: PropTypes.bool,
  modelFetchError: PropTypes.string,
  files: PropTypes.arrayOf(PropTypes.object),
  filesFetching: PropTypes.bool,
  filesFetchError: PropTypes.string,
  deleting: PropTypes.bool,
  deleteError: PropTypes.string,
  routeParams: PropTypes.object,
  loadUserByUsername: PropTypes.func.isRequired,
  loadModelByUsernameAndSlug: PropTypes.func.isRequired,
  loadFilesByUsernameAndSlug: PropTypes.func.isRequired,
  updateModelReadme: PropTypes.func.isRequired,
  deleteModel: PropTypes.func.isRequired,
  push: PropTypes.func.isRequired
}

function mapStateToProps(state, props) {
  const { routeParams: { username, slug }} = props
  const authUser = state.authUserId ? state.entities.users[state.authUserId] : null

  const user = head(filter(
    state.entities.users,
    (u) => u.username === username
  ))

  const model = user ? head(filter(
    state.entities.models,
    (m) => m.userId === user.id && m.slug === slug
  )) : null

  const files = []
  if (model) {
    each(state.entities.files, (file) => {
      if (file.status === 'latest' &&
          file.modelId === model.id &&
          file.userId === user.id) {
        files.push(file)
      }
    })
  }

  return {
    authTokenId: state.authTokenId,
    userFetching: state.userByUsername.fetching,
    userFetchError: state.userByUsername.fetchError,
    modelFetching: state.modelByUsernameAndSlug.fetching,
    modelFetchError: state.modelByUsernameAndSlug.fetchError,
    filesFetching: state.filesByUsernameAndSlug.fetching,
    filesFetchError: state.filesByUsernameAndSlug.fetchError,
    deleting: state.deleteModel.deleting,
    deleteError: state.deleteModel.deleteError,
    authUser,
    user,
    model,
    files
  }
}

export default Radium(connect(mapStateToProps, {
  loadUserByUsername,
  loadModelByUsernameAndSlug,
  loadFilesByUsernameAndSlug,
  updateModelReadme,
  deleteModel,
  push
})(ModelPage))
<|endoftext|>


<commit_before>/*
 * ************************************************************************
 * Copyright (c), 2013 Next Century Corporation. All Rights Reserved.
 *
 * This software code is the exclusive property of Next Century Corporation and is
 * protected by United States and International laws relating to the protection
 * of intellectual property.  Distribution of this software code by or to an
 * unauthorized party, or removal of any of these notices, is strictly
 * prohibited and punishable by law.
 *
 * UNLESS PROVIDED OTHERWISE IN A LICENSE AGREEMENT GOVERNING THE USE OF THIS
 * SOFTWARE, TO WHICH YOU ARE AN AUTHORIZED PARTY, THIS SOFTWARE CODE HAS BEEN
 * ACQUIRED BY YOU "AS IS" AND WITHOUT WARRANTY OF ANY KIND.  ANY USE BY YOU OF
 * THIS SOFTWARE CODE IS AT YOUR OWN RISK.  ALL WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE HEREBY EXPRESSLY
 * DISCLAIMED.
 *
 * PROPRIETARY AND CONFIDENTIAL TRADE SECRET MATERIAL NOT FOR DISCLOSURE OUTSIDE
 * OF NEXT CENTURY CORPORATION EXCEPT BY PRIOR WRITTEN PERMISSION AND WHEN
 * RECIPIENT IS UNDER OBLIGATION TO MAINTAIN SECRECY.
 *
 * @author tbrooks
 */

describe('map', function () {
    var mapId = "map";

    beforeEach(function () {
        setFixtures("

");
    });

    it('has a default layer and can toggle layers', function () {
        var map = new coreMap.Map(mapId);
        map.draw();
        expect(map.currentLayer.name).toEqual("Points Layer");
        map.toggleLayers();
        expect(map.currentLayer.name).toEqual("Heatmap Layer");
        map.toggleLayers();
        expect(map.currentLayer.name).toEqual("Points Layer");
    });

    it('has default data mapping of latitude and longitude', function () {
        var data = [{latitude: 50, longitude: 20}, {longitude: 40, latitude: -30}];
        var map = new coreMap.Map(mapId);
        map.setData(data);

        expect(map.getValueFromDataElement(map.latitudeMapping, data[0])).toEqual(50);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[0])).toEqual(20);
        expect(map.getValueFromDataElement(map.latitudeMapping, data[1])).toEqual(-30);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[1])).toEqual(40);
    });

    it('default latitude and longitude mapping can be overridden', function () {
        var data = [[50,20], [-30, 40]];

        var opts = {
            data: data,
            latitudeMapping: function(element){
                return element[0];
            },
            longitudeMapping: function(element){
                return element[1];
            }
        };

        var map = new coreMap.Map(mapId, opts);

        expect(map.getValueFromDataElement(map.latitudeMapping, data[0])).toEqual(50);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[0])).toEqual(20);
        expect(map.getValueFromDataElement(map.latitudeMapping, data[1])).toEqual(-30);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[1])).toEqual(40);
    });

    it('has default width and height', function () {
        var opts = {
            responsive: false
        }
        var map = new coreMap.Map(mapId, opts);

        expect(map.width).toEqual(1024);
        expect(map.height).toEqual(680);
    });

    it('default width and height can be overridden', function () {
        var opts = {
            responsive: false,
            width: 200,
            height: 100
        }
        var map = new coreMap.Map(mapId, opts);

        expect(map.width).toEqual(200);
        expect(map.height).toEqual(100);
    });

    it('has default radius of 3', function () {
        var data = [{latitude: 50, longitude: 20}, {longitude: 40, latitude: -30}];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[1].style.pointRadius).toEqual(3);

    });

    it('has radius depending on count', function () {
        var data = [{latitude: 50, longitude: 20, count_: 10},
            {longitude: 40, latitude: -30, count_: 1},
            {longitude: 40, latitude: -30, count_: 0},
            {longitude: 40, latitude: -30, count_: -5},
            {longitude: 40, latitude: -30, count_: null}
        ];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toBeCloseTo(13);
        expect(map.currentLayer.features[1].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[2].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[3].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[4].style.pointRadius).toEqual(3);
    });

    it('has radius ranging between 3 and 13', function () {
        var data = [{latitude: 50, longitude: 20, count_: -5000},
            {longitude: 10, latitude: -30, count_: 5},
            {longitude: 20, latitude: -30, count_: 50 * 1000},
            {longitude: 50, latitude: -30, count_: 5 * 1000 * 1000}
        ];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[1].style.pointRadius).toBeCloseTo(4.043);
        expect(map.currentLayer.features[2].style.pointRadius).toBeCloseTo(10.014);
        expect(map.currentLayer.features[3].style.pointRadius).toBeCloseTo(13);
    });

    it('gets correct minimum and maximum', function () {
        var data = [{latitude: 50, longitude: 20},
            {longitude: 10, latitude: -30},
            {longitude: 20, latitude: 0},
            {longitude: 50, latitude: null}
        ];
        var map = new coreMap.Map(mapId);

        expect(map.minValue(data, 'latitude')).toEqual(-30);
        expect(map.maxValue(data, 'latitude')).toEqual(50);
    });

    it('gets correct minimum and maximum when using function', function () {
        var data = [[50,20], [-30, 40]];

        var latMap = function(element){
            return element[0];
        };

        var map = new coreMap.Map(mapId);

        expect(map.minValue(data, latMap)).toEqual(-30);
        expect(map.maxValue(data, latMap)).toEqual(50);
    });
});
<commit_msg>Changes based on code review<commit_after>/*
 * ************************************************************************
 * Copyright (c), 2013 Next Century Corporation. All Rights Reserved.
 *
 * This software code is the exclusive property of Next Century Corporation and is
 * protected by United States and International laws relating to the protection
 * of intellectual property.  Distribution of this software code by or to an
 * unauthorized party, or removal of any of these notices, is strictly
 * prohibited and punishable by law.
 *
 * UNLESS PROVIDED OTHERWISE IN A LICENSE AGREEMENT GOVERNING THE USE OF THIS
 * SOFTWARE, TO WHICH YOU ARE AN AUTHORIZED PARTY, THIS SOFTWARE CODE HAS BEEN
 * ACQUIRED BY YOU "AS IS" AND WITHOUT WARRANTY OF ANY KIND.  ANY USE BY YOU OF
 * THIS SOFTWARE CODE IS AT YOUR OWN RISK.  ALL WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE HEREBY EXPRESSLY
 * DISCLAIMED.
 *
 * PROPRIETARY AND CONFIDENTIAL TRADE SECRET MATERIAL NOT FOR DISCLOSURE OUTSIDE
 * OF NEXT CENTURY CORPORATION EXCEPT BY PRIOR WRITTEN PERMISSION AND WHEN
 * RECIPIENT IS UNDER OBLIGATION TO MAINTAIN SECRECY.
 *
 * @author tbrooks
 */

describe('map', function () {
    var mapId = "map";

    beforeEach(function () {
        setFixtures("

");
    });

    it('has a default layer and can toggle layers', function () {
        var map = new coreMap.Map(mapId);
        map.draw();
        expect(map.currentLayer.name).toEqual("Points Layer");
        expect(map.heatmapLayer.heatmap.get("visible")).toEqual(false);
        map.toggleLayers();
        expect(map.currentLayer.name).toEqual("Heatmap Layer");
        expect(map.pointsLayer.getVisibility()).toEqual(false);
        expect(map.heatmapLayer.heatmap.get("visible")).toEqual(true);
        map.toggleLayers();
        expect(map.currentLayer.name).toEqual("Points Layer");
        expect(map.heatmapLayer.heatmap.get("visible")).toEqual(false);

    });

    it('has default data mapping of latitude and longitude', function () {
        var data = [{latitude: 50, longitude: 20}, {longitude: 40, latitude: -30}];
        var map = new coreMap.Map(mapId);
        map.setData(data);

        expect(map.getValueFromDataElement(map.latitudeMapping, data[0])).toEqual(50);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[0])).toEqual(20);
        expect(map.getValueFromDataElement(map.latitudeMapping, data[1])).toEqual(-30);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[1])).toEqual(40);
    });

    it('default latitude and longitude mapping can be overridden', function () {
        var data = [[50,20], [-30, 40]];

        var opts = {
            data: data,
            latitudeMapping: function(element){
                return element[0];
            },
            longitudeMapping: function(element){
                return element[1];
            }
        };

        var map = new coreMap.Map(mapId, opts);

        expect(map.getValueFromDataElement(map.latitudeMapping, data[0])).toEqual(50);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[0])).toEqual(20);
        expect(map.getValueFromDataElement(map.latitudeMapping, data[1])).toEqual(-30);
        expect(map.getValueFromDataElement(map.longitudeMapping, data[1])).toEqual(40);
    });

    it('has default width and height', function () {
        var opts = {
            responsive: false
        }
        var map = new coreMap.Map(mapId, opts);

        expect(map.width).toEqual(1024);
        expect(map.height).toEqual(680);
    });

    it('default width and height can be overridden', function () {
        var opts = {
            responsive: false,
            width: 200,
            height: 100
        }
        var map = new coreMap.Map(mapId, opts);

        expect(map.width).toEqual(200);
        expect(map.height).toEqual(100);
    });

    it('has default radius of 3', function () {
        var data = [{latitude: 50, longitude: 20}, {longitude: 40, latitude: -30}];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[1].style.pointRadius).toEqual(3);

    });

    it('has radius depending on count', function () {
        var data = [{latitude: 50, longitude: 20, count_: 10},
            {longitude: 40, latitude: -30, count_: 1},
            {longitude: 40, latitude: -30, count_: 0},
            {longitude: 40, latitude: -30, count_: -5},
            {longitude: 40, latitude: -30, count_: null}
        ];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toBeCloseTo(13);
        expect(map.currentLayer.features[1].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[2].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[3].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[4].style.pointRadius).toEqual(3);
    });

    it('has radius ranging between 3 and 13', function () {
        var data = [{latitude: 50, longitude: 20, count_: -5000},
            {longitude: 10, latitude: -30, count_: 5},
            {longitude: 20, latitude: -30, count_: 50 * 1000},
            {longitude: 50, latitude: -30, count_: 5 * 1000 * 1000}
        ];
        var map = new coreMap.Map(mapId);
        map.setData(data);
        map.draw();

        expect(map.currentLayer.features[0].style.pointRadius).toEqual(3);
        expect(map.currentLayer.features[1].style.pointRadius).toBeCloseTo(4.043);
        expect(map.currentLayer.features[2].style.pointRadius).toBeCloseTo(10.014);
        expect(map.currentLayer.features[3].style.pointRadius).toBeCloseTo(13);
    });

    it('gets correct minimum and maximum', function () {
        var data = [{longitude: 20, latitude: 45},
            {longitude: 10, latitude: -30},
            {longitude: 20, latitude: 0},
            {longitude: 50, latitude: null}
        ];
        var map = new coreMap.Map(mapId);

        expect(map.minValue(data, 'latitude')).toEqual(-30);
        expect(map.maxValue(data, 'latitude')).toEqual(45);
    });

    it('gets correct minimum and maximum when using function', function () {
        var data = [[50,20], [-30, 40]];

        var latMap = function(element){
            return element[0];
        };

        var map = new coreMap.Map(mapId);

        expect(map.minValue(data, latMap)).toEqual(-30);
        expect(map.maxValue(data, latMap)).toEqual(50);
    });
});
<|endoftext|>


<commit_before>'use strict';

var  forEach = require('lodash/collection/forEach'),
    filter = require('lodash/collection/filter'),
    pick = require('lodash/object/pick'),
    assign = require('lodash/object/assign');

var REPLACE_OPTIONS = require ('./ReplaceOptions');

var startEventReplace =  REPLACE_OPTIONS.START_EVENT,
    intermediateEventReplace =  REPLACE_OPTIONS.INTERMEDIATE_EVENT,
    endEventReplace =  REPLACE_OPTIONS.END_EVENT,
    gatewayReplace =  REPLACE_OPTIONS.GATEWAY,
    taskReplace =  REPLACE_OPTIONS.TASK,
    subProcessExpandedReplace = REPLACE_OPTIONS.SUBPROCESS_EXPANDED,
    transactionReplace = REPLACE_OPTIONS.TRANSACTION,
    boundaryEventReplace =  REPLACE_OPTIONS.BOUNDARY_EVENT;

var is = require('./../util/ModelUtil').is,
    getBusinessObject = require('./../util/ModelUtil').getBusinessObject,
    isExpanded = require('./../util/DiUtil').isExpanded;

var CUSTOM_PROPERTIES = [
  'cancelActivity',
  'instantiate',
  'eventGatewayType'
];

/**
 * A replace menu provider that gives users the controls to choose
 * and replace BPMN elements with each other.
 *
 * @param {BpmnFactory} bpmnFactory
 * @param {Moddle} moddle
 * @param {PopupMenu} popupMenu
 * @param {Replace} replace
 */
function CustomBpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modeling, eventBus) {

  var self = this,
      currentElement;

    /**
     * Prepares a new business object for the replacement element
     * and triggers the replace operation.
     *
     * @param  {djs.model.Base} element
     * @param  {Object} target
     * @return {djs.model.Base} the newly created element
     */
    function replaceElement(element, target) {

        var type = target.type,
            oldBusinessObject = element.businessObject,
            businessObject = bpmnFactory.create(type);

        var newElement = {
            type: type,
            businessObject: businessObject
        };

        // initialize custom BPMN extensions

        if (target.eventDefinition) {
            var eventDefinitions = businessObject.get('eventDefinitions'),
                eventDefinition = moddle.create(target.eventDefinition);

            eventDefinitions.push(eventDefinition);
        }

    // initialize special properties defined in target definition

    assign(businessObject, pick(target, CUSTOM_PROPERTIES));

        // copy size (for activities only)
    if (is(oldBusinessObject, 'bpmn:Activity')) {

            // TODO: need also to respect min/max Size

            newElement.width = element.width;
            newElement.height = element.height;
        }

    if (is(oldBusinessObject, 'bpmn:SubProcess')) {
      newElement.isExpanded = isExpanded(oldBusinessObject);
    }

        var oldProps=moddle.getElementDescriptor(oldBusinessObject).propertiesByName;
        var newProps=moddle.getElementDescriptor(businessObject).propertiesByName;
        forEach(oldProps, function(prop,key){
            if(oldBusinessObject.hasOwnProperty(key) && newProps.hasOwnProperty(key)){
                if(['id'].indexOf(key)==-1){
                    businessObject[key]=oldBusinessObject[key];
                }
            }

        });

        newElement = replace.replaceElement(element, newElement);

        selection.select(newElement);

        return newElement;
    }

  function toggleLoopEntry(event, entry) {
    var loopEntries = self.getLoopEntries(currentElement);

    var loopCharacteristics;

    if (entry.active) {
      loopCharacteristics = undefined;
    } else {
      forEach(loopEntries, function(action) {
        var options = action.options;

        if (entry.id === action.id) {
          loopCharacteristics = moddle.create(options.loopCharacteristics);

          if (options.isSequential) {
            loopCharacteristics.isSequential = options.isSequential;
          }
        }
      });
    }
    modeling.updateProperties(currentElement, { loopCharacteristics: loopCharacteristics });
  }

  function getLoopEntries(element) {

    currentElement = element;

    var businessObject = getBusinessObject(element),
        loopCharacteristics = businessObject.loopCharacteristics;

    var isSequential,
        isLoop,
        isParallel;

    if (loopCharacteristics) {
      isSequential = loopCharacteristics.isSequential;
      isLoop = loopCharacteristics.isSequential === undefined;
      isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
    }

    var loopEntries = [
      {
        id: 'toggle-parallel-mi',
        className: 'icon-parallel-mi-marker',
        active: isParallel,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
          isSequential: false
        }
      },
      {
        id: 'toggle-sequential-mi',
        className: 'icon-sequential-mi-marker',
        active: isSequential,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
          isSequential: true
        }
      },
      {
        id: 'toggle-loop',
        className: 'icon-loop-marker',
        active: isLoop,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
        }
      }
    ];
    return loopEntries;
  }

  function getAdHocEntry(element) {
    var businessObject = getBusinessObject(element);

    var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess');

    var adHocEntry = {
      id: 'toggle-adhoc',
      className: 'icon-ad-hoc-marker',
      active: isAdHoc,
      action: function(event, entry) {
        if (isAdHoc) {
          return replaceElement(element, { type: 'bpmn:SubProcess' });
        } else {
          return replaceElement(element, { type: 'bpmn:AdHocSubProcess' });
        }
      }
    };

    return adHocEntry;
  }

    function getReplaceOptions(element) {

        var menuEntries = [];
        var businessObject = element.businessObject;

    if (is(businessObject, 'bpmn:StartEvent')) {
            addEntries(startEventReplace, filterEvents);
        } else

    if (is(businessObject, 'bpmn:IntermediateCatchEvent') ||
        is(businessObject, 'bpmn:IntermediateThrowEvent')) {

            addEntries(intermediateEventReplace, filterEvents);
        } else

    if (is(businessObject, 'bpmn:EndEvent')) {

            addEntries(endEventReplace, filterEvents);
        } else

    if (is(businessObject, 'bpmn:Gateway')) {

            addEntries(gatewayReplace, function(entry) {

                return entry.target.type  !== businessObject.$type;
            });
        } else

    if (is(businessObject, 'bpmn:Transaction')) {

      addEntries(transactionReplace, filterEvents);
    } else

    if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {

      addEntries(subProcessExpandedReplace, filterEvents);
    } else

    if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {

      addEntries(taskReplace, function(entry) {
        return entry.target.type !== 'bpmn:SubProcess';
      });
    } else

    if (is(businessObject, 'bpmn:BoundaryEvent')) {
      addEntries(boundaryEventReplace, filterEvents);
    } else

    if (is(businessObject, 'bpmn:FlowNode')) {
      addEntries(taskReplace,filterFlowNodes);
        }

        function filterEvents(entry) {

            var target = entry.target;

      var eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0].$type,
          cancelActivity;

      if (businessObject.$type === 'bpmn:BoundaryEvent') {
        cancelActivity = target.cancelActivity !== false;
      }

      var isEventDefinitionEqual = target.eventDefinition == eventDefinition,
          isEventTypeEqual = businessObject.$type == target.type,
          isInterruptingEqual = businessObject.cancelActivity == cancelActivity;

            return ((!isEventDefinitionEqual && isEventTypeEqual) ||
                !isEventTypeEqual) ||
              !(isEventDefinitionEqual && isEventTypeEqual && isInterruptingEqual);
        }
// Added to filter task types
        function filterFlowNodes(entry){
            //return entry.target.type  !== businessObject.$type;
            if(entry.target.type=="bpmn:ManualTask" || entry.target.type=="bpmn:UserTask")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        function addEntries(entries, filterFun) {
            // Filter selected type from the array
            var filteredEntries = filter(entries, filterFun);

            // Add entries to replace menu
            forEach(filteredEntries, function(definition) {

                var entry = addMenuEntry(definition);
                menuEntries.push(entry);
            });
        }

        function addMenuEntry(definition) {

            return {
                label: definition.label,
                className: definition.className,
        id: definition.actionName,
        action: function() {
          return replaceElement(element, definition.target);
                }
            };
        }

        return menuEntries;
    }

  /**
   * [function description]
   * @param  {Object} position
   * @param  {Object} element
   */
    this.openChooser = function(position, element) {
    var entries = this.getReplaceOptions(element),
        headerEntries = [];

    if (is(element, 'bpmn:Activity')) {
      headerEntries = headerEntries.concat(this.getLoopEntries(element));
    }

    if (is(element, 'bpmn:SubProcess') && !is(element, 'bpmn:Transaction')) {
      headerEntries.push(this.getAdHocEntry(element));
    }

    popupMenu.open({
      className: 'replace-menu',
      element: element,
      position: position,
      headerEntries: headerEntries,
      entries: entries
    });
    };

    this.getReplaceOptions = getReplaceOptions;

  this.getLoopEntries = getLoopEntries;

  this.getAdHocEntry = getAdHocEntry;

    this.replaceElement = replaceElement;
}

CustomBpmnReplace.$inject = [ 'bpmnFactory', 'moddle', 'popupMenu', 'replace', 'selection', 'modeling', 'eventBus' ];

module.exports = CustomBpmnReplace;<commit_msg>Enabled different Tasktypes in differenz Participants<commit_after>'use strict';

var  forEach = require('lodash/collection/forEach'),
    filter = require('lodash/collection/filter'),
    pick = require('lodash/object/pick'),
    assign = require('lodash/object/assign');

var REPLACE_OPTIONS = require ('./ReplaceOptions');

var startEventReplace =  REPLACE_OPTIONS.START_EVENT,
    intermediateEventReplace =  REPLACE_OPTIONS.INTERMEDIATE_EVENT,
    endEventReplace =  REPLACE_OPTIONS.END_EVENT,
    gatewayReplace =  REPLACE_OPTIONS.GATEWAY,
    taskReplace =  REPLACE_OPTIONS.TASK,
    subProcessExpandedReplace = REPLACE_OPTIONS.SUBPROCESS_EXPANDED,
    transactionReplace = REPLACE_OPTIONS.TRANSACTION,
    boundaryEventReplace =  REPLACE_OPTIONS.BOUNDARY_EVENT;

var is = require('./../util/ModelUtil').is,
    getBusinessObject = require('./../util/ModelUtil').getBusinessObject,
    isExpanded = require('./../util/DiUtil').isExpanded;

var CUSTOM_PROPERTIES = [
  'cancelActivity',
  'instantiate',
  'eventGatewayType'
];

/**
 * A replace menu provider that gives users the controls to choose
 * and replace BPMN elements with each other.
 *
 * @param {BpmnFactory} bpmnFactory
 * @param {Moddle} moddle
 * @param {PopupMenu} popupMenu
 * @param {Replace} replace
 */
function CustomBpmnReplace(bpmnFactory, moddle, popupMenu, replace, selection, modeling, eventBus, elementRegistry) {

  var self = this,
      currentElement;

    /**
     * Prepares a new business object for the replacement element
     * and triggers the replace operation.
     *
     * @param  {djs.model.Base} element
     * @param  {Object} target
     * @return {djs.model.Base} the newly created element
     */
    function replaceElement(element, target) {

        var type = target.type,
            oldBusinessObject = element.businessObject,
            businessObject = bpmnFactory.create(type);

        var newElement = {
            type: type,
            businessObject: businessObject
        };

        // initialize custom BPMN extensions

        if (target.eventDefinition) {
            var eventDefinitions = businessObject.get('eventDefinitions'),
                eventDefinition = moddle.create(target.eventDefinition);

            eventDefinitions.push(eventDefinition);
        }

    // initialize special properties defined in target definition

    assign(businessObject, pick(target, CUSTOM_PROPERTIES));

        // copy size (for activities only)
    if (is(oldBusinessObject, 'bpmn:Activity')) {

            // TODO: need also to respect min/max Size

            newElement.width = element.width;
            newElement.height = element.height;
        }

    if (is(oldBusinessObject, 'bpmn:SubProcess')) {
      newElement.isExpanded = isExpanded(oldBusinessObject);
    }

        var oldProps=moddle.getElementDescriptor(oldBusinessObject).propertiesByName;
        var newProps=moddle.getElementDescriptor(businessObject).propertiesByName;
        forEach(oldProps, function(prop,key){
            if(oldBusinessObject.hasOwnProperty(key) && newProps.hasOwnProperty(key)){
                if(['id'].indexOf(key)==-1){
                    businessObject[key]=oldBusinessObject[key];
                }
            }

        });

        newElement = replace.replaceElement(element, newElement);

        selection.select(newElement);

        return newElement;
    }

  function toggleLoopEntry(event, entry) {
    var loopEntries = self.getLoopEntries(currentElement);

    var loopCharacteristics;

    if (entry.active) {
      loopCharacteristics = undefined;
    } else {
      forEach(loopEntries, function(action) {
        var options = action.options;

        if (entry.id === action.id) {
          loopCharacteristics = moddle.create(options.loopCharacteristics);

          if (options.isSequential) {
            loopCharacteristics.isSequential = options.isSequential;
          }
        }
      });
    }
    modeling.updateProperties(currentElement, { loopCharacteristics: loopCharacteristics });
  }

  function getLoopEntries(element) {

    currentElement = element;

    var businessObject = getBusinessObject(element),
        loopCharacteristics = businessObject.loopCharacteristics;

    var isSequential,
        isLoop,
        isParallel;

    if (loopCharacteristics) {
      isSequential = loopCharacteristics.isSequential;
      isLoop = loopCharacteristics.isSequential === undefined;
      isParallel = loopCharacteristics.isSequential !== undefined && !loopCharacteristics.isSequential;
    }

    var loopEntries = [
      {
        id: 'toggle-parallel-mi',
        className: 'icon-parallel-mi-marker',
        active: isParallel,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
          isSequential: false
        }
      },
      {
        id: 'toggle-sequential-mi',
        className: 'icon-sequential-mi-marker',
        active: isSequential,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:MultiInstanceLoopCharacteristics',
          isSequential: true
        }
      },
      {
        id: 'toggle-loop',
        className: 'icon-loop-marker',
        active: isLoop,
        action: toggleLoopEntry,
        options: {
          loopCharacteristics: 'bpmn:StandardLoopCharacteristics'
        }
      }
    ];
    return loopEntries;
  }

  function getAdHocEntry(element) {
    var businessObject = getBusinessObject(element);

    var isAdHoc = is(businessObject, 'bpmn:AdHocSubProcess');

    var adHocEntry = {
      id: 'toggle-adhoc',
      className: 'icon-ad-hoc-marker',
      active: isAdHoc,
      action: function(event, entry) {
        if (isAdHoc) {
          return replaceElement(element, { type: 'bpmn:SubProcess' });
        } else {
          return replaceElement(element, { type: 'bpmn:AdHocSubProcess' });
        }
      }
    };

    return adHocEntry;
  }

    function getReplaceOptions(element) {

        var menuEntries = [];
        var businessObject = element.businessObject;

        if (is(businessObject, 'bpmn:StartEvent')) {
                addEntries(startEventReplace, filterEvents);
            } else

        if (is(businessObject, 'bpmn:IntermediateCatchEvent') ||
            is(businessObject, 'bpmn:IntermediateThrowEvent')) {

                addEntries(intermediateEventReplace, filterEvents);
            } else

        if (is(businessObject, 'bpmn:EndEvent')) {

                addEntries(endEventReplace, filterEvents);
            } else

        if (is(businessObject, 'bpmn:Gateway')) {

                addEntries(gatewayReplace, function(entry) {

                    return entry.target.type  !== businessObject.$type;
                });
            } else

        if (is(businessObject, 'bpmn:Transaction')) {

          addEntries(transactionReplace, filterEvents);
        } else

        if (is(businessObject, 'bpmn:SubProcess') && isExpanded(businessObject)) {

          addEntries(subProcessExpandedReplace, filterEvents);
        } else

        if (is(businessObject, 'bpmn:AdHocSubProcess') && !isExpanded(businessObject)) {

          addEntries(taskReplace, function(entry) {
            return entry.target.type !== 'bpmn:SubProcess';
          });
        } else

        if (is(businessObject, 'bpmn:BoundaryEvent')) {
          addEntries(boundaryEventReplace, filterEvents);
        } else

        if (is(businessObject, 'bpmn:FlowNode')) {

            /* get the parent shape */
            var inElement=false;
            var containingElement;
            elementRegistry.filter(function(element,gfx){
                forEach(element.children,function(child){
                    if(child.id==businessObject.id){inElement=true;}
                });
                if(inElement){containingElement=element;inElement=false;}
            });

            /* if the parent shape is a appEnsemble Participant enable the right filter */
            if(containingElement.businessObject.isAppEnsemble) addEntries(taskReplace,filterFlowNodes_inAppEnsemble);
            else addEntries(taskReplace,filterFlowNodes);
        }

        function filterEvents(entry) {

            var target = entry.target;

      var eventDefinition = businessObject.eventDefinitions && businessObject.eventDefinitions[0].$type,
          cancelActivity;

      if (businessObject.$type === 'bpmn:BoundaryEvent') {
        cancelActivity = target.cancelActivity !== false;
      }

      var isEventDefinitionEqual = target.eventDefinition == eventDefinition,
          isEventTypeEqual = businessObject.$type == target.type,
          isInterruptingEqual = businessObject.cancelActivity == cancelActivity;

            return ((!isEventDefinitionEqual && isEventTypeEqual) ||
                !isEventTypeEqual) ||
              !(isEventDefinitionEqual && isEventTypeEqual && isInterruptingEqual);
        }
// Added to filter task types
        function filterFlowNodes(entry){
            //return entry.target.type  !== businessObject.$type;
            if(entry.target.type=="bpmn:UserTask") return false;
            else   return true;

        }

        function filterFlowNodes_inAppEnsemble(entry){
            //return entry.target.type  !== businessObject.$type;
            if(entry.target.type=="bpmn:ManualTask" || entry.target.type=="bpmn:UserTask") return true;
            else   return false;

        }

        function addEntries(entries, filterFun) {
            // Filter selected type from the array
            var filteredEntries = filter(entries, filterFun);

            // Add entries to replace menu
            forEach(filteredEntries, function(definition) {

                var entry = addMenuEntry(definition);
                menuEntries.push(entry);
            });
        }

        function addMenuEntry(definition) {

            return {
                label: definition.label,
                className: definition.className,
        id: definition.actionName,
        action: function() {
          return replaceElement(element, definition.target);
                }
            };
        }

        return menuEntries;
    }

  /**
   * [function description]
   * @param  {Object} position
   * @param  {Object} element
   */
    this.openChooser = function(position, element) {
    var entries = this.getReplaceOptions(element),
        headerEntries = [];

    if (is(element, 'bpmn:Activity')) {
      headerEntries = headerEntries.concat(this.getLoopEntries(element));
    }

    if (is(element, 'bpmn:SubProcess') && !is(element, 'bpmn:Transaction')) {
      headerEntries.push(this.getAdHocEntry(element));
    }

    popupMenu.open({
      className: 'replace-menu',
      element: element,
      position: position,
      headerEntries: headerEntries,
      entries: entries
    });
    };

    this.getReplaceOptions = getReplaceOptions;

  this.getLoopEntries = getLoopEntries;

  this.getAdHocEntry = getAdHocEntry;

    this.replaceElement = replaceElement;
}

CustomBpmnReplace.$inject = [ 'bpmnFactory', 'moddle', 'popupMenu', 'replace', 'selection', 'modeling', 'eventBus','elementRegistry' ];

module.exports = CustomBpmnReplace;<|endoftext|>


<commit_before>import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import 'storybook-addon-jsx/register';
import '@storybook/addon-knobs/register';
<commit_msg>chore(bonde-styleguide): reorder storybook addons<commit_after>import '@storybook/addon-knobs/register';
import 'storybook-addon-jsx/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
<|endoftext|>


<commit_before>/*
 * grunt-yaml-to-swagger
 *
 *
 * Copyright (c) 2014 Cyril GIACOPINO
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

    // Please see the Grunt documentation for more information regarding task
    // creation: http://gruntjs.com/creating-tasks
    Array.prototype.getUnique = function () {
        var u = {}, a = [];
        for (var i = 0, l = this.length; i < l; ++i) {
            if (u.hasOwnProperty(this[i])) {
                continue;
            }
            a.push(this[i]);
            u[this[i]] = 1;
        }
        return a;
    }

    var primitives = [
        "array",
        "boolean",
        "integer",
        "number",
        "null",
        "object",
        "string"
    ];

    function contains(a, obj) {
        var i = a.length;
        while (i--) {
            if (a[i] === obj) {
                return true;
            }
        }
        return false;
    }

    function extend(target) {
        var sources = [].slice.call(arguments, 1);
        sources.forEach(function (source) {
            for (var prop in source) {
                target[prop] = source[prop];
            }
        });
        return target;
    }

    function isEmpty(obj) {
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop))
                return false;
        }

        return true;
    }

    function execSync(cmd, args, callback) {
        var options = {
            // The command to execute. It should be in the system path.
            cmd: cmd,
            args: args
        };
        grunt.util.spawn(options, callback)
    }

    function parseFiles(files, options, callback) {
        var fs = require('fs');
        var path = require('path').resolve(options.route_path + '/');
        var working = false;
        var interval = setInterval(function () {
            if (files.length > 0) {
                if (working == false) {
                    working = true;
                    var file = files[0];
                    var file_path = require('path').resolve(path + '/' + file);
                    try {
                        var route_definitions = require('yamljs').load(file_path);
                    } catch (e) {
                        console.log("error");
                        grunt.fatal(e.message);
                    }

                    var base_filename = file.split(".yml")[0];
                    var outputFilename = options.output_docs_path + "/" + base_filename + ".json";

                    var returnData = {};
                    //console.log(JSON.stringify(route_definitions));
                    var models = [];
                    for (var j = 0; j < route_definitions.apis.length; j++) {
                        var operations = route_definitions.apis[j].operations;
                        for (var i = 0; i < operations.length; i++) {
                            if (!contains(primitives, operations[i].type)) {
                                models.push(operations[i].type);
                            }

                        }
                    }
                    models = models.getUnique();
                    parseModels(models, options, function (data) {
                        route_definitions.models = data;

                        var pretty_route_definitions = JSON.stringify(route_definitions, undefined, 2);

                        var matches = pretty_route_definitions.match(/:(\w)+/g);
                        if (matches != null && matches.length > 0) {
                            for (var replace = 0; replace < matches.length; replace++) {
                                var field = matches[replace].split(":").join("");
                                pretty_route_definitions = pretty_route_definitions.split(matches[replace]).join("{" + field + "}");
                            }
                        }

                        fs.writeFileSync(outputFilename, pretty_route_definitions);
                        grunt.log.ok(base_filename + ".json created");
                        files.splice(0, 1);
                        working = false;
                    });

                }
            } else {
                clearInterval(interval);
                callback();
            }
        }, 100);
    }

    function parseModels(models, options, callback) {
        var fs = require('fs');
        var returnData = {};
        var working = false;
        var interval = setInterval(function () {
            if (models.length > 0) {
                if (working == false) {
                    working = true;
                    var args = ['schema', require("path").resolve(options.models_path + '/' + models[0] + '.ts')];
                    execSync('typson', args, function (error, result, code) {
                        if (error == null) {
                            var schemaJson = JSON.parse(result);
                            schemaJson.basePath = options.base_url_ws;
                            var result = JSON.stringify();
                            var pattern = new RegExp('\[MockType=(\w)+\]', "g");
                            var matches = result.match(/\[MockType=(\w)+\]/g);
                            if (matches != null && matches.length > 0) {
                                for (var replace = 0; replace < matches.length; replace++) {
                                    result = result.split(matches[replace]).join("");
                                }
                            }
                            returnData = extend(returnData, JSON.parse(result));
                            models.splice(0, 1);
                            working = false;
                        } else {
                            grunt.log.error('typson ' + args.join(" "));
                            grunt.fatal(error);
                        }

                    });

                }
            } else {
                clearInterval(interval);
                callback(returnData);
            }
        }, 100);

    }

    function createMockSchema(options, callback) {
        var fs = require('fs');

        var models_files = fs.readdirSync(options.models_path);
        var models = [];
        for (var i = 0; i < models_files.length; i++) {
            var file = models_files[i];
            var extension = file.split('.').pop();
            if (extension == "ts") {
                models.push(file);
            }

        }
        var returnData = {};
        var working = false;
        var interval = setInterval(function () {
            if (models.length > 0) {
                if (working == false) {
                    working = true;
                    var args = ['schema', require("path").resolve(options.models_path + '/' + models[0])];
                    execSync('typson', args, function (error, result, code) {
                        if (error == null) {
                            var pretty_schema = JSON.stringify(JSON.parse(result), undefined, 2);
                            fs.writeFileSync(options.models_path + 'schema/' + models[0].split(".ts").join('.json'), pretty_schema);
                            models.splice(0, 1);
                            working = false;
                        } else {
                            grunt.log.error('typson ' + args.join(" "));
                            grunt.fatal(error);
                        }

                    });

                }
            } else {
                clearInterval(interval);
                callback();
            }
        }, 100);
    }

    grunt.registerMultiTask('yaml_to_swagger', 'Convert YAML files into swagger compatible JSON Schema format', function () {

        var fs = require('fs');
        var options = this.options();

        var done = this.async();
        createMockSchema(options, function () {
            var path_api = require('path').resolve(options.route_path + '/api.yml');
            var api_definitions = require('yamljs').load(path_api);
            var files = [];
            for (var i = 0; i < api_definitions.apis.length; i++) {
                var path = api_definitions.apis[i].path.split("/").join("");
                files.push(api_definitions.apis[i].path + '.yml');
            }
            var outputFilename = options.output_docs_path + "/api.json";
            var pretty_route_definitions = JSON.stringify(api_definitions, undefined, 2);
            fs.writeFileSync(outputFilename, pretty_route_definitions);
            grunt.log.ok("/api.json created");
            parseFiles(files, options, function () {
                done();
            });
        });

    });

};
<commit_msg>Adding basePath to route by config file<commit_after>/*
 * grunt-yaml-to-swagger
 *
 *
 * Copyright (c) 2014 Cyril GIACOPINO
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function (grunt) {

    // Please see the Grunt documentation for more information regarding task
    // creation: http://gruntjs.com/creating-tasks
    Array.prototype.getUnique = function () {
        var u = {}, a = [];
        for (var i = 0, l = this.length; i < l; ++i) {
            if (u.hasOwnProperty(this[i])) {
                continue;
            }
            a.push(this[i]);
            u[this[i]] = 1;
        }
        return a;
    }

    var primitives = [
        "array",
        "boolean",
        "integer",
        "number",
        "null",
        "object",
        "string"
    ];

    function contains(a, obj) {
        var i = a.length;
        while (i--) {
            if (a[i] === obj) {
                return true;
            }
        }
        return false;
    }

    function extend(target) {
        var sources = [].slice.call(arguments, 1);
        sources.forEach(function (source) {
            for (var prop in source) {
                target[prop] = source[prop];
            }
        });
        return target;
    }

    function isEmpty(obj) {
        for (var prop in obj) {
            if (obj.hasOwnProperty(prop))
                return false;
        }

        return true;
    }

    function execSync(cmd, args, callback) {
        var options = {
            // The command to execute. It should be in the system path.
            cmd: cmd,
            args: args
        };
        grunt.util.spawn(options, callback)
    }

    function parseFiles(files, options, callback) {
        var fs = require('fs');
        var path = require('path').resolve(options.route_path + '/');
        var working = false;
        var interval = setInterval(function () {
            if (files.length > 0) {
                if (working == false) {
                    working = true;
                    var file = files[0];
                    var file_path = require('path').resolve(path + '/' + file);
                    try {
                        var route_definitions = require('yamljs').load(file_path);
                    } catch (e) {
                        console.log("error");
                        grunt.fatal(e.message);
                    }

                    var base_filename = file.split(".yml")[0];
                    var outputFilename = options.output_docs_path + "/" + base_filename + ".json";

                    var returnData = {};
                    //console.log(JSON.stringify(route_definitions));
                    var models = [];
                    for (var j = 0; j < route_definitions.apis.length; j++) {
                        var operations = route_definitions.apis[j].operations;
                        for (var i = 0; i < operations.length; i++) {
                            if (!contains(primitives, operations[i].type)) {
                                models.push(operations[i].type);
                            }

                        }
                    }
                    models = models.getUnique();
                    parseModels(models, options, function (data) {
                        route_definitions.models = data;

                        var pretty_route_definitions = JSON.stringify(route_definitions, undefined, 2);

                        var matches = pretty_route_definitions.match(/:(\w)+/g);
                        if (matches != null && matches.length > 0) {
                            for (var replace = 0; replace < matches.length; replace++) {
                                var field = matches[replace].split(":").join("");
                                pretty_route_definitions = pretty_route_definitions.split(matches[replace]).join("{" + field + "}");
                            }
                        }

                        fs.writeFileSync(outputFilename, pretty_route_definitions);
                        grunt.log.ok(base_filename + ".json created");
                        files.splice(0, 1);
                        working = false;
                    });

                }
            } else {
                clearInterval(interval);
                callback();
            }
        }, 100);
    }

    function parseModels(models, options, callback) {
        var fs = require('fs');
        var returnData = {};
        var working = false;
        var interval = setInterval(function () {
            if (models.length > 0) {
                if (working == false) {
                    working = true;
                    var args = ['schema', require("path").resolve(options.models_path + '/' + models[0] + '.ts')];
                    execSync('typson', args, function (error, result, code) {
                        if (error == null) {
                            var schemaJson = JSON.parse(result);
                            schemaJson.basePath = options.base_url_ws;
                            var result = JSON.stringify(schemaJson);
                            var pattern = new RegExp('\[MockType=(\w)+\]', "g");
                            var matches = result.match(/\[MockType=(\w)+\]/g);
                            if (matches != null && matches.length > 0) {
                                for (var replace = 0; replace < matches.length; replace++) {
                                    result = result.split(matches[replace]).join("");
                                }
                            }
                            returnData = extend(returnData, JSON.parse(result));
                            models.splice(0, 1);
                            working = false;
                        } else {
                            grunt.log.error('typson ' + args.join(" "));
                            grunt.fatal(error);
                        }

                    });

                }
            } else {
                clearInterval(interval);
                callback(returnData);
            }
        }, 100);

    }

    function createMockSchema(options, callback) {
        var fs = require('fs');

        var models_files = fs.readdirSync(options.models_path);
        var models = [];
        for (var i = 0; i < models_files.length; i++) {
            var file = models_files[i];
            var extension = file.split('.').pop();
            if (extension == "ts") {
                models.push(file);
            }

        }
        var returnData = {};
        var working = false;
        var interval = setInterval(function () {
            if (models.length > 0) {
                if (working == false) {
                    working = true;
                    var args = ['schema', require("path").resolve(options.models_path + '/' + models[0])];
                    execSync('typson', args, function (error, result, code) {
                        if (error == null) {
                            var pretty_schema = JSON.stringify(JSON.parse(result), undefined, 2);
                            fs.writeFileSync(options.models_path + 'schema/' + models[0].split(".ts").join('.json'), pretty_schema);
                            models.splice(0, 1);
                            working = false;
                        } else {
                            grunt.log.error('typson ' + args.join(" "));
                            grunt.fatal(error);
                        }

                    });

                }
            } else {
                clearInterval(interval);
                callback();
            }
        }, 100);
    }

    grunt.registerMultiTask('yaml_to_swagger', 'Convert YAML files into swagger compatible JSON Schema format', function () {

        var fs = require('fs');
        var options = this.options();

        var done = this.async();
        createMockSchema(options, function () {
            var path_api = require('path').resolve(options.route_path + '/api.yml');
            var api_definitions = require('yamljs').load(path_api);
            var files = [];
            for (var i = 0; i < api_definitions.apis.length; i++) {
                var path = api_definitions.apis[i].path.split("/").join("");
                files.push(api_definitions.apis[i].path + '.yml');
            }
            var outputFilename = options.output_docs_path + "/api.json";
            var pretty_route_definitions = JSON.stringify(api_definitions, undefined, 2);
            fs.writeFileSync(outputFilename, pretty_route_definitions);
            grunt.log.ok("/api.json created");
            parseFiles(files, options, function () {
                done();
            });
        });

    });

};
<|endoftext|>


<commit_before>var observable = require("data/observable");
var frame = require("ui/frame");
var fileSystemService = require("~/data/fileSystemService");
var camera = require("camera");
var geolocation = require("nativescript-geolocation");

exports.onLoaded = function(args) {
    var page = args.object;
    var scrapbookPage = page.navigationContext.model;

    page.bindingContext = scrapbookPage;
};

exports.onDoneTap = function(args) {
    var page = args.object;
    var scrapbookPage = page.bindingContext;

    fileSystemService.fileSystemService.savePage(scrapbookPage);

    frame.topmost().navigate({
        moduleName: "views/scrapbook-page"
    });
};

exports.onAddImageTap = function (args) {
    var page = args.object;
    var scrapbookPage = page.bindingContext;

    camera.takePicture({ width: 100, height: 100, keepAspectRatio: true }).then(function (picture) {
        scrapbookPage.set("image", picture);

        if (!geolocation.isEnabled()) {
            geolocation.enableLocationRequest();
        }

        geolocation.getCurrentLocation().then(function (location) {
            scrapbookPage.set("lat", location.latitude);
            scrapbookPage.set("long", location.longitude);
        });
    });
};<commit_msg>updated flow of when to enable location services<commit_after>var observable = require("data/observable");
var frame = require("ui/frame");
var fileSystemService = require("~/data/fileSystemService");
var camera = require("camera");
var geolocation = require("nativescript-geolocation");

exports.onLoaded = function(args) {
    var page = args.object;
    var scrapbookPage = page.navigationContext.model;

    page.bindingContext = scrapbookPage;
};

exports.onDoneTap = function(args) {
    var page = args.object;
    var scrapbookPage = page.bindingContext;

    fileSystemService.fileSystemService.savePage(scrapbookPage);

    frame.topmost().navigate({
        moduleName: "views/scrapbook-page"
    });
};

exports.onAddImageTap = function (args) {
    var page = args.object;
    var scrapbookPage = page.bindingContext;

    if (!geolocation.isEnabled()) {
        geolocation.enableLocationRequest();
    }

    camera.takePicture({ width: 100, height: 100, keepAspectRatio: true }).then(function (picture) {
        scrapbookPage.set("image", picture);

        geolocation.getCurrentLocation().then(function (location) {
            scrapbookPage.set("lat", location.latitude);
            scrapbookPage.set("long", location.longitude);
        });
    });
};<|endoftext|>