用Chart.js代表条纹费用金额和日期

时间:2016-04-30 14:50:35

标签: ruby-on-rails reactjs

我的代码来自this,我在React组件中显示chart.js的数据。我使用Rails 4.在控制器中,charge props出现为:@charges = charges_by_date = {}.as_json

JSX:

var ctx = document.getElementById("moneyHistory");
  var hash = this.props.charges;
  var amount = [];
  var d = [];
  var chargeDate = Object.keys(hash).forEach(function(k) {
    var cost = hash[k];
    var date = moment(k).format("Do MMM");
    amount.push(cost);
    d.push(date);
  });
  var myChart = new Chart(ctx, {
      type: 'line',
      data: {
          labels: d.sort(),
          datasets: [{
              label: 'Amount',
              data: amount.sort(),
              backgroundColor: 'rgba(0, 126, 255, 0.72)',
              borderColor: '#1b6ac9',
              width: 100
          }]
      },
      options: {
          scales: {
              yAxes: [{
                  ticks: {
                      beginAtZero:true
                  }
              }]
          }
      }
  });
},

render: function() {
  return(
    <div>
      <canvas id="moneyHistory" width="400" height="150"></canvas>
    </div>
  )
}

图表显示效果不错,但我希望图表上有7天(今天+ 6天前)。我想将hash日期替换为:

var staticDates = [
      moment().subtract(6, 'days').format("Do MMM"),
      moment().subtract(5, 'days').format("Do MMM"),
      moment().subtract(4, 'days').format("Do MMM"),
      moment().subtract(3, 'days').format("Do MMM"),
      moment().subtract(2, 'days').format("Do MMM"),
      moment().subtract(1, 'days').format("Do MMM"),
      moment().subtract(0, 'days').format("Do MMM")
    ];

...
 data: {
   labels: staticDates,
...

现在,我需要将这些费用与这些日期相关联。怎么做到这一点?

编辑:

我希望图表上的日期与今天的日期(4月30日)总是在右边:

enter image description here

1 个答案:

答案 0 :(得分:1)

我不认为你想在Javascript中进行所有这些日期处理。让Ruby / Rails为您做繁重的工作。

假设您有一个将费用映射到日期的方法,其中哈希中的每个键都是一天,而值是一个计数:

def each_stripe_charge_for_customer(customer_id, created)
  starting_after = nil
  loop do
    customer_charges = Stripe::Charge.all customer: customer_id, 
                                          created: created, 
                                          limit: 100, 
                                          starting_after: starting_after
    break if customer_charges.none?
    customer_charges.each do |charge|
      yield charge
    end
    starting_after = customer_charges.data.last.id
  end
end

def daily_charges_for_customer(customer_id, created=nil)
  charges_by_date = Hash.new(0)

  # For each Stripe charge, store the date and amount into a hash.
  each_stripe_charge_for_customer(customer_id, created) do |stripe_charge|
    # Parses Stripe's timestamp to a Ruby date object. `to_date` converts a DateTime object to a date (daily resolution).
    charge_date = Time.at(stripe_charge.created).to_date
    charge_amount = stripe_charge.amount

    charges_by_date[charge_date] += charge_amount
  end

  charges_by_date
end

现在,daily_charges_for_customer(customer_id, 1.week.ago.to_i)返回类似于:

的内容
{
  '19 Jan' => 10,
  '20 Jan' => 20
}

您应该尽可能地缓存此结果,这样您就不会经常点击Stripe API

现在,您可以在DOM中将其作为data-attribute传递:

在您看来:

<%= content_tag :canvas, "", id: "myChart", width: "400", height: "200", data: { charges: daily_charges_for_customer(customer_id, 1.week.ago.to_i) } %>

这将大大简化您的JavaScript:

在您的JS代码中:

var ctx = $("#moneyHistory");

var cumulative_daily_charges = ctx.data("charges");
var date_labels = Object.keys(cumulative_daily_charges);
var daily_charges = date_labels.map(function(v) { return cumulative_daily_charges[v]; });

var myChart = new Chart(ctx, {
    type: 'line',
    data: {
      labels: date_labels,
      datasets: [{
        label: 'Date',
        data: daily_charges
      }]
    },
    options: {
      scales: {
        yAxes: [{
          ticks: {
            beginAtZero: true
          }
        }]
      }
    }
});

我正在写这种&#34;关闭袖口&#34;所以你可能需要修复一些拼写错误/语法错误,但逻辑和主要的螺母和螺栓应该有效。如果您遇到任何问题,请告诉我。

修改

另外,我不认为amount.sort()d.sort()会按照您的预期行事。如果他们将数组分开,他们将被独立排序。