index.jsx 3.4 KB
Newer Older
1
import React from 'react';
2
import { connect } from 'react-redux';
J
Jason Park 已提交
3 4
import { classes } from '/common/util';
import { BaseComponent, ResizableContainer } from '/components';
5
import { actions } from '/reducers';
6
import styles from './stylesheet.scss';
7
import { Array1DData, Array2DData, ChartData, Data, GraphData, LogData, MarkdownData } from '/core/datas';
8

9
@connect(({ player }) => ({ player }), actions)
J
Jason Park 已提交
10
class VisualizationViewer extends BaseComponent {
11 12 13 14
  constructor(props) {
    super(props);

    this.state = {
15
      dataWeights: {},
16
    };
17 18

    this.datas = [];
19 20 21
  }

  componentDidMount() {
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    const { chunks, cursor } = this.props.player;
    this.update(chunks, cursor);
  }

  componentWillReceiveProps(nextProps) {
    const { chunks, cursor } = nextProps.player;
    const { chunks: oldChunks, cursor: oldCursor } = this.props.player;
    if (chunks !== oldChunks || cursor !== oldCursor) {
      this.update(chunks, cursor, oldChunks, oldCursor);
    }
  }

  update(chunks, cursor, oldChunks = [], oldCursor = 0) {
    let applyingChunks;
    if (cursor > oldCursor) {
      applyingChunks = chunks.slice(oldCursor, cursor);
    } else {
      this.datas = [];
      applyingChunks = chunks.slice(0, cursor);
    }
    applyingChunks.forEach(chunk => this.applyChunk(chunk));

    const dataWeights = chunks === oldChunks ? { ...this.state.dataWeights } : {};
    this.datas.forEach(data => {
      if (!(data.tracerKey in dataWeights)) {
        dataWeights[data.tracerKey] = 1;
      }
49
    });
50 51 52 53 54 55 56 57
    this.setState({ dataWeights });

    const lastChunk = applyingChunks[applyingChunks.length - 1];
    if (lastChunk && lastChunk.lineNumber !== undefined) {
      this.props.setLineIndicator({ lineNumber: lastChunk.lineNumber, cursor });
    } else {
      this.props.setLineIndicator(undefined);
    }
58 59
  }

60 61 62 63 64 65 66 67 68 69 70 71
  addTracer(className, tracerKey, title) {
    const DataClass = {
      Tracer: Data,
      MarkdownTracer: MarkdownData,
      LogTracer: LogData,
      Array2DTracer: Array2DData,
      Array1DTracer: Array1DData,
      ChartTracer: ChartData,
      GraphTracer: GraphData,
    }[className];
    const data = new DataClass(tracerKey, title, this.datas);
    this.datas.push(data);
72 73
  }

74 75 76 77 78 79 80 81 82 83 84
  applyTrace(trace) {
    const { tracerKey, method, args } = trace;
    try {
      if (method === 'construct') {
        const [className, title] = args;
        this.addTracer(className, tracerKey, title);
      } else {
        const data = this.datas.find(data => data.tracerKey === tracerKey);
        data[method](...args);
      }
    } catch (error) {
J
Jason Park 已提交
85
      this.handleError(error);
86 87 88 89 90 91 92 93 94 95 96 97 98
    }
  }

  applyChunk(chunk) {
    chunk.traces.forEach(trace => this.applyTrace(trace));
  }

  handleChangeWeights(weights) {
    const dataWeights = {};
    weights.forEach((weight, i) => {
      dataWeights[this.datas[i].tracerKey] = weight;
    });
    this.setState({ dataWeights });
99 100 101 102
  }

  render() {
    const { className } = this.props;
103
    const { dataWeights } = this.state;
104 105

    return (
106 107 108 109 110 111 112
      <ResizableContainer className={classes(styles.visualization_viewer, className)}
                          weights={this.datas.map(data => dataWeights[data.tracerKey])}
                          visibles={this.datas.map(() => true)}
                          onChangeWeights={weights => this.handleChangeWeights(weights)}>
        {
          this.datas.map(data => data.render())
        }
113 114 115 116 117 118
      </ResizableContainer>
    );
  }
}

export default VisualizationViewer;