<commit_before>/*
Copyright (C) 2017  Cloudbase Solutions SRL

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import React, { Component, PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import moment from 'moment';
import Table from '../Table';
import s from './Tasks.scss';
import TextTruncate from 'react-text-truncate';
import NotificationActions from '../../actions/NotificationActions'
import LoadingIcon from "../LoadingIcon/LoadingIcon";
import ProgressBar from '../ProgressBar';
import Helper from '../Helper';

function hasProgress(msg) {
  if (msg.indexOf('progress:') > -1) {
    let progressStr = msg.substr(msg.indexOf('progress:'))
    let value = progressStr.match(/(100|[0-9]{1,2})%/)
    return value[1]
  } else {
    return false
  }
}

class Tasks extends Component {

  static propTypes = {
    tasks: PropTypes.array,
    execution: PropTypes.object
  }


  constructor(props) {
    super(props)
    this.headers = [
      { label: "Task", key: 'task_type', width: 1 },
      { label: "Instance", key: 'instance', width: 1 },
      { label: "Latest Message", key: 'latest_message', width: 2 },
      { label: "Timestamp", key: 'timestamp', width: 1 }
    ]

    this.state = {
      listItems: [],
      execution: null
    }
  }

  componentWillMount() {
    this.componentWillReceiveProps(this.props)
  }

  componentWillReceiveProps(newProps) {
    let listItems = []
    if (newProps.tasks) {
      newProps.tasks.forEach(item => {
        let latestMessage
        if (item.progress_updates.length && item.progress_updates[item.progress_updates.length - 1]) {
          latestMessage = item.progress_updates[item.progress_updates.length - 1].message
        } else {
          latestMessage = "-"
        }

        let progressUpdates = []
        if (item.progress_updates.length) {
          let first = true

          if (item.progress_updates[0] !== null) {
            item.progress_updates.sort((a, b) => moment(a.created_at).isAfter(moment(b.created_at)))
          }
          for (let i = item.progress_updates.length - 1; i >= 0; i--) {
            let date = "-"
            if (item.progress_updates[i]) {
              let createdAt = Helper.getTimeObject(item.progress_updates[i].created_at)
              date = moment(createdAt).format("YYYY-MM-DD HH:mm:ss")

              progressUpdates.push(
                <div key={"progress_" + i} className={first ? " first" : ""}>
                  <span>{date}</span>
                  <span>
                    {item.progress_updates[i] && item.progress_updates[i].message}
                    {hasProgress(item.progress_updates[i].message) &&
                    <ProgressBar progress={hasProgress(item.progress_updates[i].message)} />
                    }
                  </span>
                </div>)
              first = false
            }
          }
          if (progressUpdates.length == 0) {
            progressUpdates = "N/A"
          }
        } else {
          progressUpdates = "N/A"
        }

        let taskDetails = (<div className={s.taskDetails}>
          <div className={s.group}>
            <div className={s.detailTitle}>Status</div>
            <div className={s.detailValue}><span className={"status-pill " + item.status}>{item.status}</span></div>
          </div>
          <div className={s.group}><commit_msg>Add a more permissive way to identify percentages in task execution progress update messages<commit_after>/*
Copyright (C) 2017  Cloudbase Solutions SRL

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import React, { Component, PropTypes } from 'react';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import moment from 'moment';
import Table from '../Table';
import s from './Tasks.scss';
import TextTruncate from 'react-text-truncate';
import NotificationActions from '../../actions/NotificationActions'
import LoadingIcon from "../LoadingIcon/LoadingIcon";
import ProgressBar from '../ProgressBar';
import Helper from '../Helper';

let getProgressPercentage = (msg) => {
  let match = msg.match(/.*progress.*?(100|\d{1,2})%/)
  return match && match[1]
}

class Tasks extends Component {

  static propTypes = {
    tasks: PropTypes.array,
    execution: PropTypes.object
  }


  constructor(props) {
    super(props)
    this.headers = [
      { label: "Task", key: 'task_type', width: 1 },
      { label: "Instance", key: 'instance', width: 1 },
      { label: "Latest Message", key: 'latest_message', width: 2 },
      { label: "Timestamp", key: 'timestamp', width: 1 }
    ]

    this.state = {
      listItems: [],
      execution: null
    }
  }

  componentWillMount() {
    this.componentWillReceiveProps(this.props)
  }

  componentWillReceiveProps(newProps) {
    let listItems = []
    if (newProps.tasks) {
      newProps.tasks.forEach(item => {
        let latestMessage
        if (item.progress_updates.length && item.progress_updates[item.progress_updates.length - 1]) {
          latestMessage = item.progress_updates[item.progress_updates.length - 1].message
        } else {
          latestMessage = "-"
        }

        let progressUpdates = []
        if (item.progress_updates.length) {
          let first = true

          if (item.progress_updates[0] !== null) {
            item.progress_updates.sort((a, b) => moment(a.created_at).isAfter(moment(b.created_at)))
          }
          for (let i = item.progress_updates.length - 1; i >= 0; i--) {
            let date = "-"
            let progressUpdate = item.progress_updates[i]
            if (progressUpdate) {
              let createdAt = Helper.getTimeObject(progressUpdate.created_at)
              date = moment(createdAt).format("YYYY-MM-DD HH:mm:ss")

              let percentage = getProgressPercentage(progressUpdate.message)
              progressUpdates.push(
                <div key={"progress_" + i} className={first ? " first" : ""}>
                  <span>{date}</span>
                  <span>
                    {progressUpdate.message}
                    {percentage && <ProgressBar progress={percentage} />}
                  </span>
                </div>)
              first = false
            }
          }
          if (progressUpdates.length == 0) {
            progressUpdates = "N/A"
          }
        } else {
          progressUpdates = "N/A"
        }

        let taskDetails = (<div className={s.taskDetails}>
          <div className={s.group}>
            <div className={s.detailTitle}>Status</div>
            <div className={s.detailValue}><span className={"status-pill " + item.status}>{item.status}</span></div>
          </div>
          <div className={s.group}>
{'fraction_non_alphanumeric': 0.12082751618225664, 'fraction_numerical': 0.005711384693489021, 'mean_word_length': 2.460693895476504, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '2242650', 'n_tokens_mistral': 2252, 'n_tokens_neox': 2176, 'n_words': 608}