<commit_before><!--
@license
Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../tf-imports/plottable.html">
<link rel="import" href="../tf-imports/lodash.html">

<!--
tf-chart-scaffold is responsible for providing data from TensorBoard to charts.
It has the following settable properties:
tag: (required, string) - the name of the tag to load for this chart
visibleSeries: (required, string[]) - the names of the series the chart should
    display.
dataProvider: (required, VZ.ChartHelpers.DataFn) - function that takes (tag,
    run) and returns a promise containing an array of VZ.ChartHelpers.Datum,
    compatible with TF.Backend.Datum.

It exposes the following methods:
chart() - Returns the underlying chart element.
reload() - Reloads the data and sends it to the underlying chart.

This element should have a compatible chart plugin element as it's content. The
plugin is requred to implement two functions:
- setVisibleSeries(names: string[]): a function that receives an array of series
    names as the first parameter, responsible for changing the series currently
    being displayed to only the series in this array.
- setSeriesData(name: string, data: VZ.ChartHelpers.Datum[]): sets the data of
    the series with the given name to the data given in the second parameter.
-->
<dom-module id="tf-chart-scaffold">
  <template>
    <content></content>
    <style>
      :host {
        -webkit-user-select: none;
        -moz-user-select: none;
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        flex-shrink: 1;
        position: relative;
      }
    </style>
  </template>
  <script>
    Polymer({
      is: "tf-chart-scaffold",
      properties: {
        tag: String,
        dataProvider: Function,
        visibleSeries: Array,
        _attached: {
          type: Boolean,
          value: false
        }
      },
      observers: [
        "reload(tag, dataProvider)",
        "_changeSeries(visibleSeries.*)"
      ],
      ready: function() {
        this.fire('ready');
      },
      attached: function() {
        this._attached = true;
        this._changeSeries();
      },
      detached: function() {
        this._attached = false;
      },
      reload: function() {
        if (!this._attached) {
          return;
        }
        else if (!this.dataProvider) {
          throw new Error('tf-chart-scaffold requires a dataProvider.');
        }
        else if (!this.tag) {
          throw new Error('tf-chart-scaffold requires a tag.');
        }

        this.visibleSeries.forEach(function(name) {
          this.dataProvider(this.tag, name).then(function(data) {
            this.chart().setSeriesData(name, data);
          }.bind(this));
        }.bind(this));
      },
      _changeSeries: function() {
        if (!this._attached) {
           return;
        }
        else if (!this.visibleSeries) {
          throw new Error('tf-chart-scaffold requires a visibleSeries.');
        }

        this.chart().setVisibleSeries(this.visibleSeries);
        this.reload();
      },
      chart: function() {
        var children = this.getEffectiveChildren();
        if (!children.length) {
          throw new Error('tf-chart-scaffold has no children');
        }

        var child = children[0];
        if (!child.setVisibleSeries || !child.setSeriesData) {
          throw new Error("tf-chart-scaffold's content doesn't implement the " +
              "required interface");
        }
        return child;
      }<commit_msg>Made the chart scaffold discount data responses that are outdated. Otherwise, dashboards (such as image) could show stale data. Change: 145044777<commit_after><!--
@license
Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../tf-imports/plottable.html">
<link rel="import" href="../tf-imports/lodash.html">

<!--
tf-chart-scaffold is responsible for providing data from TensorBoard to charts.
It has the following settable properties:
tag: (required, string) - the name of the tag to load for this chart
visibleSeries: (required, string[]) - the names of the series the chart should
    display.
dataProvider: (required, VZ.ChartHelpers.DataFn) - function that takes (tag,
    run) and returns a promise containing an array of VZ.ChartHelpers.Datum,
    compatible with TF.Backend.Datum.

It exposes the following methods:
chart() - Returns the underlying chart element.
reload() - Reloads the data and sends it to the underlying chart.

This element should have a compatible chart plugin element as it's content. The
plugin is requred to implement two functions:
- setVisibleSeries(names: string[]): a function that receives an array of series
    names as the first parameter, responsible for changing the series currently
    being displayed to only the series in this array.
- setSeriesData(name: string, data: VZ.ChartHelpers.Datum[]): sets the data of
    the series with the given name to the data given in the second parameter.
-->
<dom-module id="tf-chart-scaffold">
  <template>
    <content></content>
    <style>
      :host {
        -webkit-user-select: none;
        -moz-user-select: none;
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        flex-shrink: 1;
        position: relative;
      }
    </style>
  </template>
  <script>
    Polymer({
      is: "tf-chart-scaffold",
      properties: {
        tag: String,
        dataProvider: Function,
        visibleSeries: Array,
        _attached: {
          type: Boolean,
          value: false
        },

        // Storing the update ID of the previous request for data enables us to determine if a
        // data response is outdated. We rely on an increasing ID instead of timestamp because
        // successive updates often fire within the same millisecond.
        _dataUpdateIdOfLastRequest: Number,
        _nextAvailableDataUpdateId: {
          type: Number,
          value: 1,
        },
      },
      observers: [
        "reload(tag, dataProvider)",
        "_changeSeries(visibleSeries.*)"
      ],
      ready: function() {
        this.fire('ready');
      },
      attached: function() {
        this._attached = true;
        this._changeSeries();
      },
      detached: function() {
        this._attached = false;
      },
      reload: function() {
        if (!this._attached) {
          return;
        }
        else if (!this.dataProvider) {
          throw new Error('tf-chart-scaffold requires a dataProvider.');
        }
        else if (!this.tag) {
          throw new Error('tf-chart-scaffold requires a tag.');
        }

        // TODO(chizeng): At this point, notify effective children that the previous data has been
        // invalidated. For instance, the image dashboard may want to clear its images. Today, the
        // chart scaffold only informs children when the new image URLs response finishes loading.

        const dataUpdateId = this._nextAvailableDataUpdateId++;
        this._dataUpdateIdOfLastRequest = dataUpdateId;

        this.visibleSeries.forEach(function(name) {
          this.dataProvider(this.tag, name).then(function(data) {
            if (dataUpdateId != this._dataUpdateIdOfLastRequest) {
              // This response is outdated. Ignore it.
              // TODO(chizeng): Explore canceling an outdated request before we even receive its
              // response. This involves creating hooks into the request manager and might introduce
              // some complexity that may not be worth it; Tensorboard frankly does not seem
              // bottlenecked by the network (It is often run in fast corp networks or locally.).
              return;
            }
            this.chart().setSeriesData(name, data);
          }.bind(this));
        }.bind(this));
      },
      _changeSeries: function() {
        if (!this._attached) {
           return;
        }
        else if (!this.visibleSeries) {
          throw new Error('tf-chart-scaffold requires a visibleSeries.');
        }

        this.chart().setVisibleSeries(this.visibleSeries);
        this.reload();
      },
      chart: function() {
        var children = this.getEffectiveChildren();
        if (!children.length) {
          throw new Error('tf-chart-scaffold has no children');
        }

        var child = children[0];
        if (!child.setVisibleSeries || !child.setSeriesData) {
          throw new Error("tf-chart-scaffold's content doesn't implement the " +
              "required interface");
        }
        return child;
      }
{'fraction_non_alphanumeric': 0.09855399446210646, 'fraction_numerical': 0.0032817146959286227, 'mean_word_length': 2.481613709389504, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, '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': '7062117', 'n_tokens_mistral': 2609, 'n_tokens_neox': 2543, 'n_words': 934}