<commit_before>import _ from 'lodash';
import pubsub from 'pubsub-js';
import React from 'react';
import update from 'react-addons-update';
import { parseString } from 'gcode-parser';
import GCodeStats from './GCodeStats';
import GCodeTable from './GCodeTable';
import controller from '../../../lib/controller';
import log from '../../../lib/log';
import {
    IMPERIAL_UNIT,
    METRIC_UNIT,
    GCODE_STATUS
} from './constants';

class GCode extends React.Component {
    state = {
        port: '',
        unit: METRIC_UNIT,
        lines: [], // List of G-code lines
        alertMessage: '',

        // G-code Status
        remain: 0,
        sent: 0,
        total: 0,
        createdTime: 0,
        startedTime: 0,
        finishedTime: 0
    };
    controllerEvents = {
        'gcode:statuschange': (data) => {
            const { remain, sent, total, createdTime, startedTime, finishedTime } = data;
            const from = this.state.sent;
            const to = sent;

            const list = {};

            // Reset obsolete queue items
            for (let i = to; i < from; ++i) {
                list[i] = {
                    status: {
                        $set: GCODE_STATUS.NOT_STARTED
                    }
                };
            }

            // Update completed queue items
            for (let i = from; i < to; ++i) {
                list[i] = {
                    status: {
                        $set: GCODE_STATUS.COMPLETED
                    }
                };
            }

            const lines = update(this.state.lines, list);
            this.setState({
                lines,
                remain,
                sent,
                total,
                createdTime,
                startedTime,
                finishedTime
            });
        },
        'grbl:parserstate': (parserstate) => {
            let unit = this.state.unit;

            // Imperial
            if (parserstate.modal.units === 'G20') {
                unit = IMPERIAL_UNIT;
            }

            // Metric
            if (parserstate.modal.units === 'G21') {
                unit = METRIC_UNIT;
            }

            if (this.state.unit !== unit) {
                this.setState({ unit });
            }
        }
    };

    componentDidMount() {
        this.subscribe();
        this.addControllerEvents();
    }
    componentWillUnmount() {
        this.removeControllerEvents();
        this.unsubscribe();
    }
    subscribe() {
        this.pubsubTokens = [];

        { // port
            const token = pubsub.subscribe('port', (msg, port) => {
                port = port || '';
                this.setState({ port });
            });
            this.pubsubTokens.push(token);<commit_msg>Fix an uncaught TypeError: Cannot read property 'status' of undefined (#52)<commit_after>import _ from 'lodash';
import pubsub from 'pubsub-js';
import React from 'react';
import update from 'react-addons-update';
import { parseString } from 'gcode-parser';
import GCodeStats from './GCodeStats';
import GCodeTable from './GCodeTable';
import controller from '../../../lib/controller';
import log from '../../../lib/log';
import {
    IMPERIAL_UNIT,
    METRIC_UNIT,
    GCODE_STATUS
} from './constants';

class GCode extends React.Component {
    state = {
        port: '',
        unit: METRIC_UNIT,
        lines: [], // List of G-code lines
        alertMessage: '',

        // G-code Status
        remain: 0,
        sent: 0,
        total: 0,
        createdTime: 0,
        startedTime: 0,
        finishedTime: 0
    };
    controllerEvents = {
        'gcode:statuschange': (data) => {
            const { remain, sent, total, createdTime, startedTime, finishedTime } = data;

            let lines = this.state.lines;
            if (this.state.lines.length > 0) {
                const from = this.state.sent;
                const to = sent;
                let list = {};

                // Reset obsolete queue items
                for (let i = to; i < from; ++i) {
                    list[i] = {
                        status: {
                            $set: GCODE_STATUS.NOT_STARTED
                        }
                    };
                }

                // Update completed queue items
                for (let i = from; i < to; ++i) {
                    list[i] = {
                        status: {
                            $set: GCODE_STATUS.COMPLETED
                        }
                    };
                }

                lines = update(this.state.lines, list);
            }

            this.setState({
                lines,
                remain,
                sent,
                total,
                createdTime,
                startedTime,
                finishedTime
            });
        },
        'grbl:parserstate': (parserstate) => {
            let unit = this.state.unit;

            // Imperial
            if (parserstate.modal.units === 'G20') {
                unit = IMPERIAL_UNIT;
            }

            // Metric
            if (parserstate.modal.units === 'G21') {
                unit = METRIC_UNIT;
            }

            if (this.state.unit !== unit) {
                this.setState({ unit });
            }
        }
    };

    componentDidMount() {
        this.subscribe();
        this.addControllerEvents();
    }
    componentWillUnmount() {
        this.removeControllerEvents();
        this.unsubscribe();
    }
    shouldComponentUpdate(nextProps, nextState) {
        return !_.isEqual(nextProps, this.props) || !_.isEqual(nextState, this.state);
    }
    subscribe() {
        this.pubsubTokens = [];

        { // port
            const token = pubsub.subscribe('port', (msg, port) => {
                port = port || '';
                this.setState({ port });
            });
            this.pubsubTokens.push(token);
{'fraction_non_alphanumeric': 0.1191806331471136, 'fraction_numerical': 0.003893685457931268, 'mean_word_length': 1.2328042328042328, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '662978', 'n_tokens_mistral': 1611, 'n_tokens_neox': 1530, 'n_words': 364}