unageanu/jiji2

View on GitHub
sites/src/js/view/components/agents/agent-property-editor.js

Summary

Maintainability
A
2 hrs
Test Coverage
import React                  from "react"

import AbstractComponent      from "../widgets/abstract-component"
import IconSelector           from "../icons/icon-selector"
import StringFormatter        from "../../../viewmodel/utils/string-formatter"

import TextField from "material-ui/TextField"

const keys = new Set([
  "selectedAgent"
]);

let counter = 0;

export default class AgentPropertyEditor extends AbstractComponent {

  constructor(props) {
    super(props);
    this.state = {};
  }

  componentWillMount() {
    const model = this.props.model;
    model.addObserver("beforeSeletionChange",
      this.applyAgentConfiguration.bind(this), this);
    this.registerPropertyChangeListener(model, keys);
    const state = this.collectInitialState(model, keys);
    this.setState(state);
  }

  render() {
    return (
      <div className="agent-property-editor">
        {this.createEditor()}
      </div>
    );
  }

  createEditor() {
    const selectedAgent = this.state.selectedAgent;
    if (selectedAgent == null) return null;

    const agentClass =  this.props.model.getAgentClassForSelected();
    const agentPropertyEditors =
      this.createAgentPropertyEditor(selectedAgent, agentClass);
    const agentNameEditor =
      this.createAgentNameEditor(selectedAgent, agentClass);
    return <div className="agent-details" key={counter++}>
      <div className="agent-class item">
        <span className="item-label">クラス:</span>
        <span className="item-value">{selectedAgent ? selectedAgent.agentClass : ""}</span>
      </div>
      <div className="description item">
        <span className="item-label">説明:</span>
        <div className="item-value">
          <pre>
            {agentClass ? agentClass.description : ""}
          </pre>
        </div>
      </div>
      <div className="icon-and-name item">
        <div className="icon">
          <IconSelector
            model={this.props.model.iconSelector}
            readOnly={this.props.readOnly} />
        </div>
        <div className="agent-name">{agentNameEditor}</div>
      </div>
      <div className="properties">
        {agentPropertyEditors}
      </div>
    </div>;
  }

  createAgentNameEditor(selectedAgent, agentClass) {
    if (!selectedAgent || !agentClass) return null;
    const name = selectedAgent.agentName || selectedAgent.agentClass;
    if (this.props.readOnly) {
      return <div className="agent-name item">
        <span className="item-label">エージェントの名前:</span>
        <div className="item-value">{name}</div>
      </div>;
    } else {
      return <TextField
        ref={"agent_name"}
        key={"agent_name"}
        floatingLabelText="エージェントの名前"
        defaultValue={name}
        style={{
          width: "100%"
        }} />;
    }
  }

  createAgentPropertyEditor(selectedAgent, agentClass) {
    if (!selectedAgent || !agentClass) return null;
    return agentClass.properties.map((p) => {
      const value = selectedAgent.properties[p.id]
        || selectedAgent.properties[StringFormatter.snakeCaseToCamelCase(p.id)]
           // 転送時にキャメルケースに変更される場合があるため、キャメルケースに変換
           // したキーでも取得を試みる
        || p.default;
      if (this.props.readOnly) {
        return <div key={p.id} className="property item">
          <span className="item-label">{p.name}:</span>
          <div className="item-value">{value}</div>
        </div>;
      } else {
        return <div key={p.id} className="property">
            <TextField
              ref={"agent_properties_" + p.id}
              key={p.id}
              floatingLabelText={p.name}
              defaultValue={value}
              style={{
                width: "100%"
              }}/>
          </div>;
      }
    });
  }

  applyAgentConfiguration() {
    if (this.props.readOnly) return;
    if (this.state.selectedAgent == null) return;
    const agentClass =  this.props.model.getAgentClassForSelected();
    const agentName = this.refs.agent_name.getValue();
    const iconId = this.props.model.iconSelector.selectedId;
    const configuration = agentClass.properties.reduce((r, p) => {
      r[p.id] = this.refs["agent_properties_" + p.id].getValue();
      return r;
    }, {});
    this.props.model.updateSelectedAgent(
      agentName, iconId, configuration);
  }
}
AgentPropertyEditor.propTypes = {
  model : React.PropTypes.object.isRequired,
  readOnly : React.PropTypes.bool
};
AgentPropertyEditor.defaultProps = {
  readOnly : false
};