<commit_before>( function() {
    "use strict";

    var app = angular.module('entityReferenceApp', ['sky', 'ui.bootstrap', 'LocalStorageModule']);

    app.controller('EntityReferenceCtrl', ['$window', '$http', '$sce', '$timeout', 'bbWait', 'localStorageService', '$rootScope', EntityReferenceCtrl]);

    app.component('bbEntityReference', {
        templateUrl: '/assets/views/entities.html',
        controller: 'EntityReferenceCtrl as ctrl',
        bindings: {
            apiTitle: '@',
            lastUpdatedDate: '@',
            getStartedUrl: '@',
            swaggerUrl: '@',
            swaggerUrlDev: '@',
            whiteList: '@',
            blackList: '@',
            showDescriptions: '@'
        }
    });

    function EntityReferenceCtrl($window, $http, $sce, $timeout, bbWait, localStorageService, $rootScope) {
        var self = this;
        this.showErrorMessage = false;

        if (this.showDescriptions == null)
        {
            // default showDescriptions to false, since not all APIs have user friendly descriptions
            this.showDescriptions = false;
        }
        this.$onInit = onInit;

        function onInit() {
            var isDev = window.location.search.includes('ENV=DEV') && self.swaggerUrlDev;
            this.swaggerCacheName = 'swaggerResponseCache-' + (isDev ? 'DEV-' : '') + this.apiTitle;
            var swaggerResponseCache = localStorageService.get(self.swaggerCacheName);
            bbWait.beginPageWait({});

            // Get a new swagger response if one is not cached or the cache has expired
            if (!swaggerResponseCache || Date.now() >= swaggerResponseCache.expirationDate) {
              $http.get(isDev ? self.swaggerUrlDev : self.swaggerUrl)
                  .then(handleSuccess, handleError)
                  .finally(function() { bbWait.endPageWait(); });
            }
            else {
              handleSwaggerResponseData(swaggerResponseCache.swaggerResponseData);
              bbWait.endPageWait();
            }
        }

        function handleSuccess(response) {
            // Represents the number of hours until the cache expires
            var swaggerCacheHourLimit = 12;

            localStorageService.set(self.swaggerCacheName, {
              'swaggerResponseData': response.data,
              'expirationDate': Date.now() + (swaggerCacheHourLimit * 36e5)
            });
            handleSwaggerResponseData(response.data);
        }

        function handleSwaggerResponseData(swagger) {
            self.swagger = swagger;
            var whiteList = self.whiteList ? self.whiteList.split(',') : [];
            var blackList = self.blackList ? self.blackList.split(',') : [];
            self.entities = getEntitiesFromSwagger(swagger, whiteList, blackList);

            // Need to delay allowing digest cycle to run and additionally
            // give a little extra time to prevent rescrolling back to top due to
            // angular loading sequence.
            return $timeout(function() {
              scrollToHash();
            });
        }

        $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
            scrollToHash();
        });

        function handleError(response) {
            self.showErrorMessage = true;
        }

        function getEntitiesFromSwagger(swagger, whiteList, blackList) {
            return Object.keys(swagger.definitions)
                .sort(function(a, b) {
                    var keyA = getRefDisplayName(a, swagger.definitions);
                    var keyB = getRefDisplayName(b, swagger.definitions);

                    if (keyA < keyB) {
                        return -1;
                    }

                    if (keyA > keyB) {
                        return 1;
                    }

                    // keys are equal (shouldn't happen in our swagger)
                    return 0;
                })
                .map(function(name) {
                    var definition = swagger.definitions[name];
                    return {
                        name: name,
                        displayName: definition['x-display-name'] || name,
                        displayId: definition['x-display-id'] || name,
                        details: definition,
                        description: self.showDescriptions ? definition.description : null,
                        additionalInfoHtml: $sce.trustAsHtml(definition['x-additional-info'])
                    };
                })
                .filter(function(entity) {
                    if (whiteList.length > 0) {
                        return whiteList.find(function(name) {
                            return entity.name == name;
                        });
                    }
                    if (blackList.length > 0) {
                        return !blackList.find(function(name) {
                            return entity.name == name;
                        });
                    }
                    return !!entity.details.properties && !entity.details['x-hidden'];
                })
                .map(function(entity)
                {
                    return setDisplayTypesOnEntity(entity, swagger.definitions);
                });
        }

        function setDisplayTypesOnEntity(entity, definitions) {
            Object.keys(entity.details.properties).forEach(function(propertyName) {
                var property = entity.details.properties[propertyName];
                property.isArray = (property.type === "array");

                if (property.isArray) {
                    property.ref = (property.items.$ref && property.items.$ref.replace("#/definitions/", ""));
                    property.displayType = getRefDisplayName(property.ref, definitions) || getTypeFormattedName(property);
                    property.displayId = getRefDisplayId(property.ref, definitions) || getTypeFormattedName(property);
                } else {
                    property.ref = property.$ref && property.$ref.replace("#/definitions/", "");
                    property.displayType = getRefDisplayName(property.ref, definitions) || getTypeFormattedName(property);
                    property.displayId = getRefDisplayId(property.ref, definitions) || getTypeFormattedName(property);
                }

                property.descriptionHtml = $sce.trustAsHtml(property.description);
            });
            return entity;
        }

        function getRefDisplayName(ref, definitions) {
            if (ref) {
                return (definitions[ref]['x-display-name'] || ref).toLowerCase();
            }
        }

        function getRefDisplayId(ref, definitions) {
            if (ref) {
                return (definitions[ref]['x-display-id'] || ref);
            }
        }

        function getTypeFormattedName(property) {

            // Conversion table for swagger format to display text.
            var formatDisplayNames = {
                'date-time': 'dateTime'
            };

            if (property.format) {
                return formatDisplayNames[property.format] || property.type;
            } else {
                return property.type;
            }
        }

        function scrollToHash() {
            // Cannot use $location with anchors or links will be broken without html5Mode.
            // Cannot $autoScroll due to it requiring $location without html5Mode.
            // Cannot enable html5Mode or external links will be broken.

            // Unfortunately, this means we need to manually scroll window to element.
            // See https://github.com/angular/angular.js/issues/114

            var document = $window.document;
            var hash = getHash($window.location);

            var elem = document.getElementsByName(hash)[0];

            if (elem) {
                elem.scrollIntoView();
            } else {
                $window.scrollTo(0, 0);
            }
        }

        function getHash(location) {
            var hash = location.hash || '';
            var index = hash.indexOf('#!#'); // This was indexOf('#') before the angular 1.6 upgrade.
            return index === -1 ? hash : hash.substr(index+3); // This was +1 before 1.6. If we do something to remove the #! prefix, change this back
        }
    }
})();
<commit_msg>fixing bug in ie where entity ref was not displaying<commit_after>( function() {
    "use strict";

    var app = angular.module('entityReferenceApp', ['sky', 'ui.bootstrap', 'LocalStorageModule']);

    app.controller('EntityReferenceCtrl', ['$window', '$http', '$sce', '$timeout', 'bbWait', 'localStorageService', '$rootScope', EntityReferenceCtrl]);

    app.component('bbEntityReference', {
        templateUrl: '/assets/views/entities.html',
        controller: 'EntityReferenceCtrl as ctrl',
        bindings: {
            apiTitle: '@',
            lastUpdatedDate: '@',
            getStartedUrl: '@',
            swaggerUrl: '@',
            swaggerUrlDev: '@',
            whiteList: '@',
            blackList: '@',
            showDescriptions: '@'
        }
    });

    function EntityReferenceCtrl($window, $http, $sce, $timeout, bbWait, localStorageService, $rootScope) {
        var self = this;
        this.showErrorMessage = false;

        if (this.showDescriptions == null)
        {
            // default showDescriptions to false, since not all APIs have user friendly descriptions
            this.showDescriptions = false;
        }
        this.$onInit = onInit;

        function onInit() {
            var isDev = window.location.search.indexOf('ENV=DEV') >= 0 && self.swaggerUrlDev;
            this.swaggerCacheName = 'swaggerResponseCache-' + (isDev ? 'DEV-' : '') + this.apiTitle;
            var swaggerResponseCache = localStorageService.get(self.swaggerCacheName);
            bbWait.beginPageWait({});

            // Get a new swagger response if one is not cached or the cache has expired
            if (!swaggerResponseCache || Date.now() >= swaggerResponseCache.expirationDate) {
              $http.get(isDev ? self.swaggerUrlDev : self.swaggerUrl)
                  .then(handleSuccess, handleError)
                  .finally(function() { bbWait.endPageWait(); });
            }
            else {
              handleSwaggerResponseData(swaggerResponseCache.swaggerResponseData);
              bbWait.endPageWait();
            }
        }

        function handleSuccess(response) {
            // Represents the number of hours until the cache expires
            var swaggerCacheHourLimit = 12;

            localStorageService.set(self.swaggerCacheName, {
              'swaggerResponseData': response.data,
              'expirationDate': Date.now() + (swaggerCacheHourLimit * 36e5)
            });
            handleSwaggerResponseData(response.data);
        }

        function handleSwaggerResponseData(swagger) {
            self.swagger = swagger;
            var whiteList = self.whiteList ? self.whiteList.split(',') : [];
            var blackList = self.blackList ? self.blackList.split(',') : [];
            self.entities = getEntitiesFromSwagger(swagger, whiteList, blackList);

            // Need to delay allowing digest cycle to run and additionally
            // give a little extra time to prevent rescrolling back to top due to
            // angular loading sequence.
            return $timeout(function() {
              scrollToHash();
            });
        }

        $rootScope.$on('$locationChangeSuccess', function (event, newUrl, oldUrl) {
            scrollToHash();
        });

        function handleError(response) {
            self.showErrorMessage = true;
        }

        function getEntitiesFromSwagger(swagger, whiteList, blackList) {
            return Object.keys(swagger.definitions)
                .sort(function(a, b) {
                    var keyA = getRefDisplayName(a, swagger.definitions);
                    var keyB = getRefDisplayName(b, swagger.definitions);

                    if (keyA < keyB) {
                        return -1;
                    }

                    if (keyA > keyB) {
                        return 1;
                    }

                    // keys are equal (shouldn't happen in our swagger)
                    return 0;
                })
                .map(function(name) {
                    var definition = swagger.definitions[name];
                    return {
                        name: name,
                        displayName: definition['x-display-name'] || name,
                        displayId: definition['x-display-id'] || name,
                        details: definition,
                        description: self.showDescriptions ? definition.description : null,
                        additionalInfoHtml: $sce.trustAsHtml(definition['x-additional-info'])
                    };
                })
                .filter(function(entity) {
                    if (whiteList.length > 0) {
                        return whiteList.find(function(name) {
                            return entity.name == name;
                        });
                    }
                    if (blackList.length > 0) {
                        return !blackList.find(function(name) {
                            return entity.name == name;
                        });
                    }
                    return !!entity.details.properties && !entity.details['x-hidden'];
                })
                .map(function(entity)
                {
                    return setDisplayTypesOnEntity(entity, swagger.definitions);
                });
        }

        function setDisplayTypesOnEntity(entity, definitions) {
            Object.keys(entity.details.properties).forEach(function(propertyName) {
                var property = entity.details.properties[propertyName];
                property.isArray = (property.type === "array");

                if (property.isArray) {
                    property.ref = (property.items.$ref && property.items.$ref.replace("#/definitions/", ""));
                    property.displayType = getRefDisplayName(property.ref, definitions) || getTypeFormattedName(property);
                    property.displayId = getRefDisplayId(property.ref, definitions) || getTypeFormattedName(property);
                } else {
                    property.ref = property.$ref && property.$ref.replace("#/definitions/", "");
                    property.displayType = getRefDisplayName(property.ref, definitions) || getTypeFormattedName(property);
                    property.displayId = getRefDisplayId(property.ref, definitions) || getTypeFormattedName(property);
                }

                property.descriptionHtml = $sce.trustAsHtml(property.description);
            });
            return entity;
        }

        function getRefDisplayName(ref, definitions) {
            if (ref) {
                return (definitions[ref]['x-display-name'] || ref).toLowerCase();
            }
        }

        function getRefDisplayId(ref, definitions) {
            if (ref) {
                return (definitions[ref]['x-display-id'] || ref);
            }
        }

        function getTypeFormattedName(property) {

            // Conversion table for swagger format to display text.
            var formatDisplayNames = {
                'date-time': 'dateTime'
            };

            if (property.format) {
                return formatDisplayNames[property.format] || property.type;
            } else {
                return property.type;
            }
        }

        function scrollToHash() {
            // Cannot use $location with anchors or links will be broken without html5Mode.
            // Cannot $autoScroll due to it requiring $location without html5Mode.
            // Cannot enable html5Mode or external links will be broken.

            // Unfortunately, this means we need to manually scroll window to element.
            // See https://github.com/angular/angular.js/issues/114

            var document = $window.document;
            var hash = getHash($window.location);

            var elem = document.getElementsByName(hash)[0];

            if (elem) {
                elem.scrollIntoView();
            } else {
                $window.scrollTo(0, 0);
            }
        }

        function getHash(location) {
            var hash = location.hash || '';
            var index = hash.indexOf('#!#'); // This was indexOf('#') before the angular 1.6 upgrade.
            return index === -1 ? hash : hash.substr(index+3); // This was +1 before 1.6. If we do something to remove the #! prefix, change this back
        }
    }
})();
<|endoftext|>


<commit_before>/* eslint max-nested-callbacks: ["error", 7] */
/* eslint-env browser */

(function(exports) {
  'use strict';

  const Toast = document.querySelector('chromedash-toast');

  let toastReady = new Promise(function(resolve, reject) {
    // If the page is using async imports, wait for them to load so toast custom
    // element is upgraded and has its methods.
    if (window.asyncImportsLoadPromise) {
      return window.asyncImportsLoadPromise.then(resolve, reject);
    }
    resolve();
  });

  /**
   * Returns a promise for the total size of assets precached by service worker.
   * @return {Promise} Promises that fulfills with the total size.
   */
  function precachedAssetTotalSize() {
    // Note that any opaque (i.e. cross-domain, without CORS) responses in the
    // cache will return a size of 0.
    return caches.keys().then(cacheNames => {
      let total = 0;

      return Promise.all(
        cacheNames.map(cacheName => {
          // Filter for assets cached by precache.
          if (!cacheName.includes('sw-precache')) {
            // eslint-disable-next-line array-callback-return
            return;
          }

          return caches.open(cacheName).then(cache => {
            return cache.keys().then(keys => {
              return Promise.all(
                keys.map(key => {
                  return cache.match(key)
                    .then(response => response.arrayBuffer())
                    .then(function(buffer) {
                      total += buffer.byteLength;
                    });
                })
              );
            });
          });
        })
      ).then(function() {
        return total;
      }).catch(function() {
        // noop!
      });
    });
  }

  /**
   * Registers a service worker.
   */
  function registerServiceWorker() {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/service-worker.js').then(reg => {
        reg.onupdatefound = function() {
          // The updatefound event implies that registration.installing is set.
          const installingWorker = reg.installing;
          installingWorker.onstatechange = function() {
            switch (installingWorker.state) {
              case 'installed':
                if (!navigator.serviceWorker.controller) {
                  if (Toast) {
                    toastReady.then(precachedAssetTotalSize().then(bytes => {
                      let kb = Math.round(bytes / 1000);
                      console.info('[ServiceWorker] precached', kb, 'KB');

                      // Send precached bytes to GA.
                      let metric = new Metric('sw_precache');
                      metric.sendToAnalytics(
                          'service worker', 'precache size', bytes);

                      Toast.showMessage(
                          'This site is cached and ready to use offline!' +
                           ` (${kb}KB)`);
                    }));
                  }
                }
                break;
              case 'redundant':
                throw Error('The installing service worker became redundant.');
              default:
                break;
            }
          };
        };
      }).catch(function(e) {
        console.error('Error during service worker registration:', e);
      });
    }
  }

  if (!window.asyncImportsLoadPromise) {
    registerServiceWorker();
  }

  // Check to see if the service worker controlling the page at initial load
  // has become redundant, since this implies there's a new service worker with =
  // fresh content.
  if (navigator.serviceWorker && navigator.serviceWorker.controller) {
    navigator.serviceWorker.controller.onstatechange = function(e) {
      if (e.target.state === 'redundant') {
        const tapHandler = function() {
          window.location.reload();
        };

        if (Toast) {
          toastReady.then(function() {
            Toast.showMessage('A new version of this app is available.',
                              'Refresh', tapHandler, -1);
          });
        } else {
          tapHandler(); // Force reload if toast never loads.
        }
      }
    };
  }

  exports.registerServiceWorker = registerServiceWorker;
})(window);
<commit_msg>Shorten SW toast message (for mobile)<commit_after>/* eslint max-nested-callbacks: ["error", 7] */
/* eslint-env browser */

(function(exports) {
  'use strict';

  const Toast = document.querySelector('chromedash-toast');

  let toastReady = new Promise(function(resolve, reject) {
    // If the page is using async imports, wait for them to load so toast custom
    // element is upgraded and has its methods.
    if (window.asyncImportsLoadPromise) {
      return window.asyncImportsLoadPromise.then(resolve, reject);
    }
    resolve();
  });

  /**
   * Returns a promise for the total size of assets precached by service worker.
   * @return {Promise} Promises that fulfills with the total size.
   */
  function precachedAssetTotalSize() {
    // Note that any opaque (i.e. cross-domain, without CORS) responses in the
    // cache will return a size of 0.
    return caches.keys().then(cacheNames => {
      let total = 0;

      return Promise.all(
        cacheNames.map(cacheName => {
          // Filter for assets cached by precache.
          if (!cacheName.includes('sw-precache')) {
            // eslint-disable-next-line array-callback-return
            return;
          }

          return caches.open(cacheName).then(cache => {
            return cache.keys().then(keys => {
              return Promise.all(
                keys.map(key => {
                  return cache.match(key)
                    .then(response => response.arrayBuffer())
                    .then(function(buffer) {
                      total += buffer.byteLength;
                    });
                })
              );
            });
          });
        })
      ).then(function() {
        return total;
      }).catch(function() {
        // noop!
      });
    });
  }

  /**
   * Registers a service worker.
   */
  function registerServiceWorker() {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/service-worker.js').then(reg => {
        reg.onupdatefound = function() {
          // The updatefound event implies that registration.installing is set.
          const installingWorker = reg.installing;
          installingWorker.onstatechange = function() {
            switch (installingWorker.state) {
              case 'installed':
                if (!navigator.serviceWorker.controller) {
                  if (Toast) {
                    toastReady.then(precachedAssetTotalSize().then(bytes => {
                      let kb = Math.round(bytes / 1000);
                      console.info('[ServiceWorker] precached', kb, 'KB');

                      // Send precached bytes to GA.
                      let metric = new Metric('sw_precache');
                      metric.sendToAnalytics(
                          'service worker', 'precache size', bytes);

                      Toast.showMessage(`This site is cached (${kb}KB). Ready to use offline!`);
                    }));
                  }
                }
                break;
              case 'redundant':
                throw Error('The installing service worker became redundant.');
              default:
                break;
            }
          };
        };
      }).catch(function(e) {
        console.error('Error during service worker registration:', e);
      });
    }
  }

  if (!window.asyncImportsLoadPromise) {
    registerServiceWorker();
  }

  // Check to see if the service worker controlling the page at initial load
  // has become redundant, since this implies there's a new service worker with =
  // fresh content.
  if (navigator.serviceWorker && navigator.serviceWorker.controller) {
    navigator.serviceWorker.controller.onstatechange = function(e) {
      if (e.target.state === 'redundant') {
        const tapHandler = function() {
          window.location.reload();
        };

        if (Toast) {
          toastReady.then(function() {
            Toast.showMessage('A new version of this app is available.',
                              'Refresh', tapHandler, -1);
          });
        } else {
          tapHandler(); // Force reload if toast never loads.
        }
      }
    };
  }

  exports.registerServiceWorker = registerServiceWorker;
})(window);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import * as Actions from '../actions';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import Tag from './Tag';
import { RECORDS_LIST, RECORD_FORM } from '../constants/WidgetNames';
import { EXP, INC } from '../constants/TransactionTypes';

import RecordModel from '../models/Record';

class RecordForm extends Component {
    static propTypes = {
        isVisible: PropTypes.bool.isRequired,
        tags: PropTypes.array.isRequired,
    };

    constructor(props) {
        super(props);

        this.calculateButton = React.createRef();
        this.amountInput = React.createRef();
    }

    get record() {
        return this.props.recordForm.record;
    }

    calculate() {
        this.props.actions.calculateRecordFormAmount();
        this.focus();
    }

    get tags() {
        return this.props.tags.map(name => (
            <Tag
                name={name}
                key={name}
                toggle={this.props.actions.toggleRecordFormTag}
                isSelected={this.record.selectedTags.has(name)}
            />
        ));
    }

    async submit(returnTo) {
        const success = await this.props.actions.submitRecordForm(returnTo);
        // TODO: show valdation errors if any

        if (success) {
            this.reset();
        }
    }

    save() {
        return this.submit(RECORDS_LIST);
    }

    saveAddAnother() {
        return this.submit(RECORD_FORM);
    }

    reset() {
        this.setState(RecordModel.default());
        this.focus();
    }

    handleAmountChange(event) {
        this.props.actions.setRecordFormAmount(event.target.value);
    }

    handleTypeChange(event) {
        this.props.actions.setRecordFormTransactionType(event.target.value);
    }

    componentDidUpdate(prevProps) {
        const justShowedUp = prevProps.isVisible === false && this.props.isVisible === true;
        const amountChanged =
            prevProps.recordForm.record.amount.amount !== this.record.amount.amount;

        if (justShowedUp || amountChanged) {
            this.focus();
        }
    }

    componentDidMount() {
        this.focus();
    }

    focus() {
        this.amountInput.current.focus();
    }

    cancel() {
        this.props.actions.selectWidget(RECORDS_LIST);
    }

    get isPersisted() {
        return Boolean(this.record.id);
    }

    render() {
        return (

Add New Record

                <form>

                            Amount

                            <input
                                value={this.record.amount.amount}
                                onChange={this.handleAmountChange.bind(this)}
                                ref={this.amountInput}
                                type="tel"
                                className="form-control"
                                autoComplete="off"
                                autoFocus
                            />

                                <button
                                    ref={this.calculateButton}
                                    onClick={this.props.actions.calculateRecordFormAmount}
                                    className="btn btn-default"
                                    type="button">
                                    calculate
                                </button>

                        Tags

                            {this.tags}

                            Transaction type

                            <select
                                name="transaction_type"
                                className="form-control"
                                value={this.record.transaction_type}
                                onChange={this.handleTypeChange.bind(this)}>
                                <option value={EXP}>Expences</option>
                                <option value={INC}>Income</option>
                            </select>

                </form>

                    <button onClick={this.save.bind(this)} className="btn btn-success btn-default">
                        Save
                    </button>
                    <button
                        onClick={this.saveAddAnother.bind(this)}
                        className="btn btn-default"
                        hidden={!this.isPersisted}>
                        Save & Add
                    </button>
                    <button className="btn btn-danger" hidden={!this.isPersisted}>
                        Delete
                    </button>
                    <button onClick={this.cancel.bind(this)} className="btn btn-info">
                        Cancel
                    </button>

        );
    }
}

const mapStateToProps = state => ({ recordForm: state.recordForm });

const mapDispatchToProps = dispatch => ({
    actions: bindActionCreators(Actions, dispatch),
});

export default connect(mapStateToProps, mapDispatchToProps)(RecordForm);
<commit_msg>remove delete button for now<commit_after>import React, { Component } from 'react';
import * as Actions from '../actions';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';

import Tag from './Tag';
import { RECORDS_LIST, RECORD_FORM } from '../constants/WidgetNames';
import { EXP, INC } from '../constants/TransactionTypes';

import RecordModel from '../models/Record';

class RecordForm extends Component {
    static propTypes = {
        isVisible: PropTypes.bool.isRequired,
        tags: PropTypes.array.isRequired,
    };

    constructor(props) {
        super(props);

        this.calculateButton = React.createRef();
        this.amountInput = React.createRef();
    }

    get record() {
        return this.props.recordForm.record;
    }

    calculate() {
        this.props.actions.calculateRecordFormAmount();
        this.focus();
    }

    get tags() {
        return this.props.tags.map(name => (
            <Tag
                name={name}
                key={name}
                toggle={this.props.actions.toggleRecordFormTag}
                isSelected={this.record.selectedTags.has(name)}
            />
        ));
    }

    async submit(returnTo) {
        const success = await this.props.actions.submitRecordForm(returnTo);
        // TODO: show valdation errors if any

        if (success) {
            this.reset();
        }
    }

    save() {
        return this.submit(RECORDS_LIST);
    }

    saveAddAnother() {
        return this.submit(RECORD_FORM);
    }

    reset() {
        this.setState(RecordModel.default());
        this.focus();
    }

    handleAmountChange(event) {
        this.props.actions.setRecordFormAmount(event.target.value);
    }

    handleTypeChange(event) {
        this.props.actions.setRecordFormTransactionType(event.target.value);
    }

    componentDidUpdate(prevProps) {
        const justShowedUp = prevProps.isVisible === false && this.props.isVisible === true;
        const amountChanged =
            prevProps.recordForm.record.amount.amount !== this.record.amount.amount;

        if (justShowedUp || amountChanged) {
            this.focus();
        }
    }

    componentDidMount() {
        this.focus();
    }

    focus() {
        this.amountInput.current.focus();
    }

    cancel() {
        this.props.actions.selectWidget(RECORDS_LIST);
    }

    get isPersisted() {
        return Boolean(this.record.id);
    }

    render() {
        return (

Add New Record

                <form>

                            Amount

                            <input
                                value={this.record.amount.amount}
                                onChange={this.handleAmountChange.bind(this)}
                                ref={this.amountInput}
                                type="tel"
                                className="form-control"
                                autoComplete="off"
                                autoFocus
                            />

                                <button
                                    ref={this.calculateButton}
                                    onClick={this.props.actions.calculateRecordFormAmount}
                                    className="btn btn-default"
                                    type="button">
                                    calculate
                                </button>

                        Tags

                            {this.tags}

                            Transaction type

                            <select
                                name="transaction_type"
                                className="form-control"
                                value={this.record.transaction_type}
                                onChange={this.handleTypeChange.bind(this)}>
                                <option value={EXP}>Expences</option>
                                <option value={INC}>Income</option>
                            </select>

                </form>

                    <button onClick={this.save.bind(this)} className="btn btn-success btn-default">
                        Save
                    </button>
                    <button
                        onClick={this.saveAddAnother.bind(this)}
                        className="btn btn-default"
                        hidden={!this.isPersisted}>
                        Save & Add
                    </button>
                    {/* <button className="btn btn-danger" hidden={!this.isPersisted}> */}
                    {/*     Delete */}
                    {/* </button> */}
                    <button onClick={this.cancel.bind(this)} className="btn btn-info">
                        Cancel
                    </button>

        );
    }
}

const mapStateToProps = state => ({ recordForm: state.recordForm });

const mapDispatchToProps = dispatch => ({
    actions: bindActionCreators(Actions, dispatch),
});

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(RecordForm);
<|endoftext|>


<commit_before>document.addEventListener("DOMContentLoaded", function () {
    "use strict";
    initialSetup();
    reload();
});

var emailGitHubIssuesClassName = "emailGitHubIssues";

function initialSetup() {
    var s = document.createElement('script');
    s.src = chrome.extension.getURL('scripts/injectedcode.js');
    s.onload = function () {
        this.parentNode.removeChild(this);
    };

    (document.head || document.documentElement).appendChild(s);

    document.addEventListener('_pjax:end', function () {
        reload();
    }, false);
}

function reload() {
    $('.' + emailGitHubIssuesClassName).remove();

    addIndividualIssueButton();
    addButtonsToIssuesList();

    openJenkinsDetailsInNewTab();
    makeBuildStatusWindowsBig();

    addTestFailureButtonsAndDescriptions();
    addJenkinsTestRunTimes();
}

function addIndividualIssueButton() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["emailIssue"] }, function (response) {
        if (response.data["emailIssue"]) {
            var titleElement = document.getElementsByClassName("js-issue-title")[0]

            if (typeof titleElement !== 'undefined') {
                var button = document.createElement("input");
                button.setAttribute("type", "button");
                button.setAttribute("value", "Email Issue");
                button.setAttribute("name", "buttonname");
                var issueNumber = document.getElementsByClassName("gh-header-number")[0].innerHTML.substring(1);
                var issueTitle = document.getElementsByClassName("js-issue-title")[0].innerHTML;
                button.onclick = (function () {
                    var currentTitle = issueTitle;
                    var currentNumber = issueNumber;
                    return function () {
                        sendmail(currentNumber, currentTitle);
                    };
                });

                button.className = "btn " + emailGitHubIssuesClassName;
                titleElement.parentNode.insertBefore(button, document.getElementsByClassName("js-issue-title")[0].parentNode.firstChild);
            }
        }
    });
}

// TODO: Only scrape once between this and addTestFailureButtonsAndDescriptions
function addJenkinsTestRunTimes() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsShowRunTime"] }, function (response) {
        if (response.data["jenkinsShowRunTime"]) {

            var testRuns = document.getElementsByClassName("build-status-item");
            for (var i = 0; i < testRuns.length; i++) {
                var run = testRuns[i];
                var detailsLink = run.getElementsByClassName("build-status-details")[0];
                if (typeof detailsLink === 'undefined') {
                    continue;
                }

                var textToUpdate = run.getElementsByClassName("text-muted")[0];

                var loading = document.createElement("img");
                var imgUrl = chrome.extension.getURL("images/loading.gif");
                loading.src = imgUrl;
                var specificClassName = emailGitHubIssuesClassName + "_TestRunTime_" + i;
                loading.className = emailGitHubIssuesClassName + " " + specificClassName;
                textToUpdate.appendChild(loading);

                (function (_run, _url, _specificClassName) {
                    chrome.runtime.sendMessage({
                        method: 'GET',
                        action: 'xhttp',
                        url: _url,
                        data: ''
                    }, function (responseText) {
                        var parser = new DOMParser();
                        var doc = parser.parseFromString(responseText, "text/html");
                        var header = doc.getElementsByClassName("build-caption page-headline")[0];
                        if (typeof header === "undefined") {
                          $('.' + _specificClassName).remove();
                          return;
                        }

                        var timestamp = header.innerText.split("(")[1].split(")")[0];
                        var timestampDisplay = " [Run on " + timestamp + ". "

                        // TODO: time zones?
                        var date = new Date(Date.parse(timestamp));
                        var currentdate = new Date();

                        var delta = currentdate - date;
                        var dayCount = delta / (1000 * 60 * 60 * 24);
                        var minuteCount = delta / (1000 * 60);

                        var backgroundColor = "#000000";
                        var timeAgo = Math.round(dayCount * 10) / 10 + " days ago";

                        if (dayCount <= 2) { backgroundColor = "#AAFFAA"; } // green
                        else if (dayCount <= 5) { backgroundColor = "#FFC85A"; } // yellow
                        else { backgroundColor = "#FFAAAA"; } // red

			$('.' + _specificClassName).remove();

                        var textToUpdate = _run.getElementsByClassName("text-muted")[0];

                        var span = document.createElement("span");
                        span.innerHTML = timestampDisplay;
                        span.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span);

                        var span2 = document.createElement("span");
                        span2.innerHTML = "(" + timeAgo + ")";
                        span2.style.backgroundColor = backgroundColor;
                        span2.setAttribute("title", "Green: < 2 days\nYellow: 2 to 5 days\nRed: > 5 days");
                        span2.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span2);

                        var span3 = document.createElement("span");
                        span3.innerHTML = "]";
                        span3.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span3);
                    });
                })(run, detailsLink.href, specificClassName);
            }
        }
    });
}

function addTestFailureButtonsAndDescriptions() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsShowBugFilingButton", "jenkinsShowFailureIndications", "jenkinsShowTestFailures"] }, function (response) {
        if (response.data["jenkinsShowBugFilingButton"] || response.data["jenkinsShowFailureIndications"]) {
                var testFailures = document.getElementsByClassName("octicon-x build-status-icon");

                for (var i = 0; i < testFailures.length; i++) {
                    var isDropdown = false;

                    var ancestor = testFailures[i];
                    while ((ancestor = ancestor.parentElement) != null) {
                        if (ancestor.classList.contains("dropdown-menu")) {
                            isDropdown = true;
                            break;
                        }
                    }

                    if (isDropdown) {
                        continue;
                    }

                    var testFailure = testFailures[i];
                    var testFailUrl = testFailure.parentNode.getElementsByClassName("build-status-details")[0].href;

                    var loading = document.createElement("img");
                    var imgUrl = chrome.extension.getURL("images/loading.gif");
                    loading.src = imgUrl;
                    var specificClassName = emailGitHubIssuesClassName + "_TestFailures_" + i;
                    loading.className = emailGitHubIssuesClassName + " " + specificClassName;
                    testFailure.parentNode.insertBefore(loading, testFailure.parentNode.firstChild);

                    (function (_testFailure, _testFailUrl, _specificClassName) {
                        chrome.runtime.sendMessage({
                            method: 'GET',
                            action: 'xhttp',
                            url: _testFailUrl,
                            data: ''
                        }, function (responseText) {
                            var parser = new DOMParser();
                            var doc = parser.parseFromString(responseText, "text/html");
                            var h2elements = doc.getElementsByTagName("h2");
                            var aelements = doc.getElementsByTagName("a");

                            var issueBody = "*See " + _testFailUrl + " for more details.*\r\n\r\n";
                            var htmlDescription = "";
                            var count = 1;

                            if (response.data["jenkinsShowTestFailures"]) {
                                for (var i = 0; i < aelements.length; i++) {
                                    var aelement = aelements[i];
                                    if (aelement.innerText == "Test Result" && aelement.parentNode.tagName == "TD") {
                                        var unitTestFailures = aelement.parentNode.getElementsByTagName("li");

                                        if (unitTestFailures.length > 0) {
                                            htmlDescription = htmlDescription + "Test Failures:
";
                                            issueBody = issueBody + "**Test Failures:**\r\n";
                                        }

                                        for (var j = 0; j < unitTestFailures.length; j++) {
                                            var unitTestFailure = unitTestFailures[j];
                                            htmlDescription = htmlDescription + "    " + unitTestFailure.innerText + "
";
                                            issueBody = issueBody + unitTestFailure.innerText + "\r\n";
                                        }

                                        htmlDescription = htmlDescription + "
";
                                        issueBody = issueBody + "\r\n";
                                    }
                                }
                            }

                            for (var i = 0; i < h2elements.length; i++) {
                                var h2 = h2elements[i];

                                if (h2.innerHTML == "HTTP ERROR 404") {
                                    htmlDescription = htmlDescription + "404: Build details page could not be found.";
                                }

                                if (h2.innerHTML == "Identified problems") {
                                    var nodeWithErrorSiblings = h2.parentNode.parentNode;
                                    var errorRow = nodeWithErrorSiblings;
                                    while ((errorRow = errorRow.nextSibling) != null) {
                                        if (count > 1) {
                                            issueBody = issueBody + "\r\n\r\n";
                                            htmlDescription = htmlDescription + "

";
                                        }

                                        var failureTitle = "";
                                        var failureDescription = "";

                                        var h3s = errorRow.getElementsByTagName("h3");
                                        var h4s = errorRow.getElementsByTagName("h4");
                                        if (h3s.length > 0) {
                                            failureTitle = h3s[0].innerHTML.split("
 0) {
                                            failureTitle = h4s[0].innerHTML.trim();
                                            failureDescription = h4s[1].innerHTML.trim();
                                        }

                                        issueBody = issueBody + "**Issue " + count + ": " + failureTitle + "**\r\n";
                                        issueBody = issueBody + failureDescription;
                                        htmlDescription = htmlDescription + "Issue " + count + ": " + failureTitle + "
" + failureDescription;

                                        count++;
                                    }
                                }
                            }

                            if (count == 1) {
                                // we failed to find the failure, or there was none.
                                // should we add special handling here?
                            }

                            var issueTitle = "PR Test Failure: <explanation>";

                            var url = "https://github.com/dotnet/roslyn/issues/new?title=" + encodeURI(issueTitle) + "&body=" + encodeURI(issueBody) + "&labels[]=Area-Infrastructure&labels[]=Contributor%20Pain";

                            $('.' + _specificClassName).remove();

                            if (response.data["jenkinsShowBugFilingButton"]) {
                                var button = document.createElement("input");
                                button.setAttribute("type", "button");
                                button.setAttribute("value", "File bug");
                                button.setAttribute("name", "buttonname");
                                button.onclick = (function () {
                                    var thisUrl = url;
                                    return function () {
                                        window.open(thisUrl);
                                    };
                                })();

                                button.className = "btn btn-sm " + emailGitHubIssuesClassName;
                                button.style.margin = "0px 0px 3px 0px";

                                _testFailure.parentNode.insertBefore(button, _testFailure.parentNode.firstChild);
                            }

                            if (response.data["jenkinsShowFailureIndications"]) {
                                var div = document.createElement("div");
                                div.innerHTML = htmlDescription;
                                div.style.backgroundColor = "#FFAAAA";
                                div.className = emailGitHubIssuesClassName;
                                _testFailure.parentNode.appendChild(div);
                            }
                        });
                    })(testFailure, testFailUrl, specificClassName);
                }
        }
    });
}

function makeBuildStatusWindowsBig() {
    var lists = document.getElementsByClassName("build-statuses-list");
    for (var i = 0; i < lists.length; i++) {
        lists[i].style.maxHeight = "5000px";
    }
}

function addButtonsToIssuesList() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["emailIssuesList"] }, function (response) {
        if (response.data["emailIssuesList"]) {
            var issuesList = document.getElementsByClassName("table-list-issues")[0];

            if (typeof issuesList !== 'undefined') {
                var issues = issuesList.children;

                for (var i = 0; i < issues.length; i++) {
                    var issue = issues[i];
                    var title = issue.getElementsByClassName("issue-title")[0];

                    var button = document.createElement("input");
                    button.setAttribute("type", "button");
                    button.setAttribute("value", "Email Issue");
                    button.setAttribute("name", "buttonname");

                    var urlParts = title.getElementsByClassName("issue-title-link")[0].href.split("/");
                    var issueNumber = urlParts[urlParts.length - 1];
                    var issueTitle = title.getElementsByClassName("issue-title-link")[0].innerHTML;

                    button.onclick = (function () {
                        var currentTitle = issueTitle;
                        var currentNumber = issueNumber;
                        return function () {
                            sendmail(currentNumber, currentTitle);
                        };
                    })();
                    button.className = "btn btn-sm " + emailGitHubIssuesClassName;

                    title.insertBefore(button, title.firstChild);
                }
            }
        }
    });
}

function openJenkinsDetailsInNewTab() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsOpenDetailsLinksInNewTab"] }, function (response) {
        if (response.data["jenkinsOpenDetailsLinksInNewTab"]) {
            var detailsLinks = document.getElementsByClassName("build-status-details");
            for (var i = 0; i < detailsLinks.length; i++) {
                var detailsLink = detailsLinks[i];
                detailsLink.target = "_blank";
            }
        }
    });
}

function sendmail(issueNumber, issueTitle) {
    issueTitle = issueTitle.trim();
    issueNumber = issueNumber.trim();

    var baseUrl = document.getElementsByClassName("entry-title public")[0].getElementsByTagName('strong')[0].getElementsByTagName('a')[0].href + "/issues/";

    var owner = document.getElementsByClassName("entry-title public")[0].getElementsByClassName("author")[0].getElementsByTagName("span")[0].innerHTML;
    var repo = document.getElementsByClassName("entry-title public")[0].getElementsByTagName("strong")[0].getElementsByTagName("a")[0].innerHTML;

    var subject = owner + "/" + repo + " #" + issueNumber + ": " + issueTitle;

    var body = baseUrl + issueNumber + "\r\n\r\n"; // TODO: Assigned to, etc.

    window.location.href = "mailto:?subject=" + encodeURI(subject) + "&body=" + encodeURI(body);
}<commit_msg>Only show first 10 Jenkins test failures<commit_after>document.addEventListener("DOMContentLoaded", function () {
    "use strict";
    initialSetup();
    reload();
});

var emailGitHubIssuesClassName = "emailGitHubIssues";

function initialSetup() {
    var s = document.createElement('script');
    s.src = chrome.extension.getURL('scripts/injectedcode.js');
    s.onload = function () {
        this.parentNode.removeChild(this);
    };

    (document.head || document.documentElement).appendChild(s);

    document.addEventListener('_pjax:end', function () {
        reload();
    }, false);
}

function reload() {
    $('.' + emailGitHubIssuesClassName).remove();

    addIndividualIssueButton();
    addButtonsToIssuesList();

    openJenkinsDetailsInNewTab();
    makeBuildStatusWindowsBig();

    addTestFailureButtonsAndDescriptions();
    addJenkinsTestRunTimes();
}

function addIndividualIssueButton() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["emailIssue"] }, function (response) {
        if (response.data["emailIssue"]) {
            var titleElement = document.getElementsByClassName("js-issue-title")[0]

            if (typeof titleElement !== 'undefined') {
                var button = document.createElement("input");
                button.setAttribute("type", "button");
                button.setAttribute("value", "Email Issue");
                button.setAttribute("name", "buttonname");
                var issueNumber = document.getElementsByClassName("gh-header-number")[0].innerHTML.substring(1);
                var issueTitle = document.getElementsByClassName("js-issue-title")[0].innerHTML;
                button.onclick = (function () {
                    var currentTitle = issueTitle;
                    var currentNumber = issueNumber;
                    return function () {
                        sendmail(currentNumber, currentTitle);
                    };
                });

                button.className = "btn " + emailGitHubIssuesClassName;
                titleElement.parentNode.insertBefore(button, document.getElementsByClassName("js-issue-title")[0].parentNode.firstChild);
            }
        }
    });
}

// TODO: Only scrape once between this and addTestFailureButtonsAndDescriptions
function addJenkinsTestRunTimes() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsShowRunTime"] }, function (response) {
        if (response.data["jenkinsShowRunTime"]) {

            var testRuns = document.getElementsByClassName("build-status-item");
            for (var i = 0; i < testRuns.length; i++) {
                var run = testRuns[i];
                var detailsLink = run.getElementsByClassName("build-status-details")[0];
                if (typeof detailsLink === 'undefined') {
                    continue;
                }

                var textToUpdate = run.getElementsByClassName("text-muted")[0];

                var loading = document.createElement("img");
                var imgUrl = chrome.extension.getURL("images/loading.gif");
                loading.src = imgUrl;
                var specificClassName = emailGitHubIssuesClassName + "_TestRunTime_" + i;
                loading.className = emailGitHubIssuesClassName + " " + specificClassName;
                textToUpdate.appendChild(loading);

                (function (_run, _url, _specificClassName) {
                    chrome.runtime.sendMessage({
                        method: 'GET',
                        action: 'xhttp',
                        url: _url,
                        data: ''
                    }, function (responseText) {
                        var parser = new DOMParser();
                        var doc = parser.parseFromString(responseText, "text/html");
                        var header = doc.getElementsByClassName("build-caption page-headline")[0];
                        if (typeof header === "undefined") {
                          $('.' + _specificClassName).remove();
                          return;
                        }

                        var timestamp = header.innerText.split("(")[1].split(")")[0];
                        var timestampDisplay = " [Run on " + timestamp + ". "

                        // TODO: time zones?
                        var date = new Date(Date.parse(timestamp));
                        var currentdate = new Date();

                        var delta = currentdate - date;
                        var dayCount = delta / (1000 * 60 * 60 * 24);
                        var minuteCount = delta / (1000 * 60);

                        var backgroundColor = "#000000";
                        var timeAgo = Math.round(dayCount * 10) / 10 + " days ago";

                        if (dayCount <= 2) { backgroundColor = "#AAFFAA"; } // green
                        else if (dayCount <= 5) { backgroundColor = "#FFC85A"; } // yellow
                        else { backgroundColor = "#FFAAAA"; } // red

			$('.' + _specificClassName).remove();

                        var textToUpdate = _run.getElementsByClassName("text-muted")[0];

                        var span = document.createElement("span");
                        span.innerHTML = timestampDisplay;
                        span.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span);

                        var span2 = document.createElement("span");
                        span2.innerHTML = "(" + timeAgo + ")";
                        span2.style.backgroundColor = backgroundColor;
                        span2.setAttribute("title", "Green: < 2 days\nYellow: 2 to 5 days\nRed: > 5 days");
                        span2.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span2);

                        var span3 = document.createElement("span");
                        span3.innerHTML = "]";
                        span3.className = emailGitHubIssuesClassName;
                        textToUpdate.appendChild(span3);
                    });
                })(run, detailsLink.href, specificClassName);
            }
        }
    });
}

function addTestFailureButtonsAndDescriptions() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsShowBugFilingButton", "jenkinsShowFailureIndications", "jenkinsShowTestFailures"] }, function (response) {
        if (response.data["jenkinsShowBugFilingButton"] || response.data["jenkinsShowFailureIndications"]) {
                var testFailures = document.getElementsByClassName("octicon-x build-status-icon");

                for (var i = 0; i < testFailures.length; i++) {
                    var isDropdown = false;

                    var ancestor = testFailures[i];
                    while ((ancestor = ancestor.parentElement) != null) {
                        if (ancestor.classList.contains("dropdown-menu")) {
                            isDropdown = true;
                            break;
                        }
                    }

                    if (isDropdown) {
                        continue;
                    }

                    var testFailure = testFailures[i];
                    var testFailUrl = testFailure.parentNode.getElementsByClassName("build-status-details")[0].href;

                    var loading = document.createElement("img");
                    var imgUrl = chrome.extension.getURL("images/loading.gif");
                    loading.src = imgUrl;
                    var specificClassName = emailGitHubIssuesClassName + "_TestFailures_" + i;
                    loading.className = emailGitHubIssuesClassName + " " + specificClassName;
                    testFailure.parentNode.insertBefore(loading, testFailure.parentNode.firstChild);

                    (function (_testFailure, _testFailUrl, _specificClassName) {
                        chrome.runtime.sendMessage({
                            method: 'GET',
                            action: 'xhttp',
                            url: _testFailUrl,
                            data: ''
                        }, function (responseText) {
                            var parser = new DOMParser();
                            var doc = parser.parseFromString(responseText, "text/html");
                            var h2elements = doc.getElementsByTagName("h2");
                            var aelements = doc.getElementsByTagName("a");

                            var issueBody = "*See " + _testFailUrl + " for more details.*\r\n\r\n";
                            var htmlDescription = "";
                            var count = 1;

                            if (response.data["jenkinsShowTestFailures"]) {
                                for (var i = 0; i < aelements.length; i++) {
                                    var aelement = aelements[i];
                                    if (aelement.innerText == "Test Result" && aelement.parentNode.tagName == "TD") {
                                        var unitTestFailures = aelement.parentNode.getElementsByTagName("li");

                                        if (unitTestFailures.length > 0) {
                                            if (unitTestFailures.length <= 10) {
                                                htmlDescription = htmlDescription + "" + unitTestFailures.length + " Test Failures:
";
                                                issueBody = issueBody + "**" + unitTestFailures.length + " Test Failures:**\r\n";
                                            }
                                            else {
                                                htmlDescription = htmlDescription + "" + unitTestFailures.length + " Test Failures: (showing first 10)
";
                                                issueBody = issueBody + "**" + unitTestFailures.length + " Test Failures:** (showing first 10)\r\n";
                                            }
                                        }

                                        for (var j = 0; j < unitTestFailures.length && j < 10; j++) {
                                            var unitTestFailure = unitTestFailures[j];
                                            htmlDescription = htmlDescription + "    " + unitTestFailure.innerText + "
";
                                            issueBody = issueBody + unitTestFailure.innerText + "\r\n";
                                        }

                                        htmlDescription = htmlDescription + "
";
                                        issueBody = issueBody + "\r\n";
                                    }
                                }
                            }

                            for (var i = 0; i < h2elements.length; i++) {
                                var h2 = h2elements[i];

                                if (h2.innerHTML == "HTTP ERROR 404") {
                                    htmlDescription = htmlDescription + "404: Build details page could not be found.";
                                }

                                if (h2.innerHTML == "Identified problems") {
                                    var nodeWithErrorSiblings = h2.parentNode.parentNode;
                                    var errorRow = nodeWithErrorSiblings;
                                    while ((errorRow = errorRow.nextSibling) != null) {
                                        if (count > 1) {
                                            issueBody = issueBody + "\r\n\r\n";
                                            htmlDescription = htmlDescription + "

";
                                        }

                                        var failureTitle = "";
                                        var failureDescription = "";

                                        var h3s = errorRow.getElementsByTagName("h3");
                                        var h4s = errorRow.getElementsByTagName("h4");
                                        if (h3s.length > 0) {
                                            failureTitle = h3s[0].innerHTML.split("
 0) {
                                            failureTitle = h4s[0].innerHTML.trim();
                                            failureDescription = h4s[1].innerHTML.trim();
                                        }

                                        issueBody = issueBody + "**Issue " + count + ": " + failureTitle + "**\r\n";
                                        issueBody = issueBody + failureDescription;
                                        htmlDescription = htmlDescription + "Issue " + count + ": " + failureTitle + "
" + failureDescription;

                                        count++;
                                    }
                                }
                            }

                            if (count == 1) {
                                // we failed to find the failure, or there was none.
                                // should we add special handling here?
                            }

                            var issueTitle = "PR Test Failure: <explanation>";

                            var url = "https://github.com/dotnet/roslyn/issues/new?title=" + encodeURI(issueTitle) + "&body=" + encodeURI(issueBody) + "&labels[]=Area-Infrastructure&labels[]=Contributor%20Pain";

                            $('.' + _specificClassName).remove();

                            if (response.data["jenkinsShowBugFilingButton"]) {
                                var button = document.createElement("input");
                                button.setAttribute("type", "button");
                                button.setAttribute("value", "File bug");
                                button.setAttribute("name", "buttonname");
                                button.onclick = (function () {
                                    var thisUrl = url;
                                    return function () {
                                        window.open(thisUrl);
                                    };
                                })();

                                button.className = "btn btn-sm " + emailGitHubIssuesClassName;
                                button.style.margin = "0px 0px 3px 0px";

                                _testFailure.parentNode.insertBefore(button, _testFailure.parentNode.firstChild);
                            }

                            if (response.data["jenkinsShowFailureIndications"]) {
                                var div = document.createElement("div");
                                div.innerHTML = htmlDescription;
                                div.style.backgroundColor = "#FFAAAA";
                                div.className = emailGitHubIssuesClassName;
                                _testFailure.parentNode.appendChild(div);
                            }
                        });
                    })(testFailure, testFailUrl, specificClassName);
                }
        }
    });
}

function makeBuildStatusWindowsBig() {
    var lists = document.getElementsByClassName("build-statuses-list");
    for (var i = 0; i < lists.length; i++) {
        lists[i].style.maxHeight = "5000px";
    }
}

function addButtonsToIssuesList() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["emailIssuesList"] }, function (response) {
        if (response.data["emailIssuesList"]) {
            var issuesList = document.getElementsByClassName("table-list-issues")[0];

            if (typeof issuesList !== 'undefined') {
                var issues = issuesList.children;

                for (var i = 0; i < issues.length; i++) {
                    var issue = issues[i];
                    var title = issue.getElementsByClassName("issue-title")[0];

                    var button = document.createElement("input");
                    button.setAttribute("type", "button");
                    button.setAttribute("value", "Email Issue");
                    button.setAttribute("name", "buttonname");

                    var urlParts = title.getElementsByClassName("issue-title-link")[0].href.split("/");
                    var issueNumber = urlParts[urlParts.length - 1];
                    var issueTitle = title.getElementsByClassName("issue-title-link")[0].innerHTML;

                    button.onclick = (function () {
                        var currentTitle = issueTitle;
                        var currentNumber = issueNumber;
                        return function () {
                            sendmail(currentNumber, currentTitle);
                        };
                    })();
                    button.className = "btn btn-sm " + emailGitHubIssuesClassName;

                    title.insertBefore(button, title.firstChild);
                }
            }
        }
    });
}

function openJenkinsDetailsInNewTab() {
    chrome.runtime.sendMessage({ method: "getSettings", keys: ["jenkinsOpenDetailsLinksInNewTab"] }, function (response) {
        if (response.data["jenkinsOpenDetailsLinksInNewTab"]) {
            var detailsLinks = document.getElementsByClassName("build-status-details");
            for (var i = 0; i < detailsLinks.length; i++) {
                var detailsLink = detailsLinks[i];
                detailsLink.target = "_blank";
            }
        }
    });
}

function sendmail(issueNumber, issueTitle) {
    issueTitle = issueTitle.trim();
    issueNumber = issueNumber.trim();

    var baseUrl = document.getElementsByClassName("entry-title public")[0].getElementsByTagName('strong')[0].getElementsByTagName('a')[0].href + "/issues/";

    var owner = document.getElementsByClassName("entry-title public")[0].getElementsByClassName("author")[0].getElementsByTagName("span")[0].innerHTML;
    var repo = document.getElementsByClassName("entry-title public")[0].getElementsByTagName("strong")[0].getElementsByTagName("a")[0].innerHTML;

    var subject = owner + "/" + repo + " #" + issueNumber + ": " + issueTitle;

    var body = baseUrl + issueNumber + "\r\n\r\n"; // TODO: Assigned to, etc.

    window.location.href = "mailto:?subject=" + encodeURI(subject) + "&body=" + encodeURI(body);
}<|endoftext|>


<commit_before>const OLD_ADDON_PREF_NAME = "extensions.jid1-NeEaf3sAHdKHPA@jetpack.deviceIdInfo";
const OLD_ADDON_ID = "jid1-NeEaf3sAHdKHPA@jetpack";
const ADDON_ID = "screenshots@mozilla.org";
const TELEMETRY_ENABLED_PREF = "datareporting.healthreport.uploadEnabled";
const PREF_BRANCH = "extensions.screenshots.";
const USER_DISABLE_PREF = "extensions.screenshots.disabled";
const SYSTEM_DISABLE_PREF = "extensions.screenshots.system-disabled";

const { interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                  "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Console",
                                  "resource://gre/modules/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                  "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LegacyExtensionsUtils",
                                  "resource://gre/modules/LegacyExtensionsUtils.jsm");

let addonResourceURI;
let appStartupDone;
const appStartupPromise = new Promise((resolve, reject) => {
  appStartupDone = resolve;
});

const prefs = Services.prefs;
const prefObserver = {
  register() {
    prefs.addObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  unregister() {
    prefs.removeObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  observe(aSubject, aTopic, aData) {
    // aSubject is the nsIPrefBranch we're observing (after appropriate QI)
    // aData is the name of the pref that's been changed (relative to aSubject)
    if (aData == USER_DISABLE_PREF || aData == SYSTEM_DISABLE_PREF) {
      // eslint-disable-next-line promise/catch-or-return
      appStartupPromise.then(handleStartup);
    }
  }
};

function startup(data, reason) { // eslint-disable-line no-unused-vars
  appStartupDone();
  prefObserver.register();
  addonResourceURI = data.resourceURI;
  // eslint-disable-next-line promise/catch-or-return
  appStartupPromise.then(handleStartup);
}

function shutdown(data, reason) { // eslint-disable-line no-unused-vars
  prefObserver.unregister();
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });
  if (webExtension.started) {
    stop(webExtension);
  }
}

function install(data, reason) {} // eslint-disable-line no-unused-vars

function uninstall(data, reason) {} // eslint-disable-line no-unused-vars

function getBoolPref(pref) {
  return prefs.getPrefType(pref) && prefs.getBoolPref(pref);
}

function shouldDisable() {
  return getBoolPref(USER_DISABLE_PREF) || getBoolPref(SYSTEM_DISABLE_PREF);
}

function handleStartup() {
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });

  if (!shouldDisable() && !webExtension.started) {
    start(webExtension);
  } else if (shouldDisable()) {
    stop(webExtension);
  }
}

function start(webExtension) {
  webExtension.startup().then((api) => {
    api.browser.runtime.onMessage.addListener(handleMessage);
  }).catch((err) => {
    // The startup() promise will be rejected if the webExtension was
    // already started (a harmless error), or if initializing the
    // WebExtension failed and threw (an important error).
    console.error(err);
    if (err.message !== "This embedded extension has already been started") {
      // TODO: Should we send these errors to Sentry? #2420
    }
  });
}

function stop(webExtension) {
  webExtension.shutdown();
}

function handleMessage(msg, sender, sendReply) {
  if (!msg) {
    return;
  }

  if (msg.funcName === "getTelemetryPref") {
    let telemetryEnabled = getBoolPref(TELEMETRY_ENABLED_PREF);
    sendReply({type: "success", value: telemetryEnabled});
  } else if (msg.funcName === "getOldDeviceInfo") {
    let oldDeviceInfo = prefs.prefHasUserValue(OLD_ADDON_PREF_NAME) && prefs.getCharPref(OLD_ADDON_PREF_NAME);
    sendReply({type: "success", value: oldDeviceInfo || null});
  } else if (msg.funcName === "removeOldAddon") {
    AddonManager.getAddonByID(OLD_ADDON_ID, (addon) => {
      prefs.clearUserPref(OLD_ADDON_PREF_NAME);
      if (addon) {
        addon.uninstall();
      }
      sendReply({type: "success", value: !!addon});
    });
    return true;
  }
}
<commit_msg>Revert "Start WebExtension immediately"<commit_after>const OLD_ADDON_PREF_NAME = "extensions.jid1-NeEaf3sAHdKHPA@jetpack.deviceIdInfo";
const OLD_ADDON_ID = "jid1-NeEaf3sAHdKHPA@jetpack";
const ADDON_ID = "screenshots@mozilla.org";
const TELEMETRY_ENABLED_PREF = "datareporting.healthreport.uploadEnabled";
const PREF_BRANCH = "extensions.screenshots.";
const USER_DISABLE_PREF = "extensions.screenshots.disabled";
const SYSTEM_DISABLE_PREF = "extensions.screenshots.system-disabled";

const { interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager",
                                  "resource://gre/modules/AddonManager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Console",
                                  "resource://gre/modules/Console.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                  "resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LegacyExtensionsUtils",
                                  "resource://gre/modules/LegacyExtensionsUtils.jsm");

let addonResourceURI;
let appStartupDone;
const appStartupPromise = new Promise((resolve, reject) => {
  appStartupDone = resolve;
});

const prefs = Services.prefs;
const prefObserver = {
  register() {
    prefs.addObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  unregister() {
    prefs.removeObserver(PREF_BRANCH, this, false); // eslint-disable-line mozilla/no-useless-parameters
  },

  observe(aSubject, aTopic, aData) {
    // aSubject is the nsIPrefBranch we're observing (after appropriate QI)
    // aData is the name of the pref that's been changed (relative to aSubject)
    if (aData == USER_DISABLE_PREF || aData == SYSTEM_DISABLE_PREF) {
      // eslint-disable-next-line promise/catch-or-return
      appStartupPromise.then(handleStartup);
    }
  }
};

const appStartupObserver = {
  register() {
    Services.obs.addObserver(this, "sessionstore-windows-restored", false); // eslint-disable-line mozilla/no-useless-parameters
  },

  unregister() {
    Services.obs.removeObserver(this, "sessionstore-windows-restored", false); // eslint-disable-line mozilla/no-useless-parameters
  },

  observe() {
    appStartupDone();
    this.unregister();
  }
}

const APP_STARTUP = 1;
function startup(data, reason) { // eslint-disable-line no-unused-vars
  if (reason === APP_STARTUP) {
    appStartupObserver.register();
  } else {
    appStartupDone();
  }
  prefObserver.register();
  addonResourceURI = data.resourceURI;
  // eslint-disable-next-line promise/catch-or-return
  appStartupPromise.then(handleStartup);
}

function shutdown(data, reason) { // eslint-disable-line no-unused-vars
  prefObserver.unregister();
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });
  if (webExtension.started) {
    stop(webExtension);
  }
}

function install(data, reason) {} // eslint-disable-line no-unused-vars

function uninstall(data, reason) {} // eslint-disable-line no-unused-vars

function getBoolPref(pref) {
  return prefs.getPrefType(pref) && prefs.getBoolPref(pref);
}

function shouldDisable() {
  return getBoolPref(USER_DISABLE_PREF) || getBoolPref(SYSTEM_DISABLE_PREF);
}

function handleStartup() {
  const webExtension = LegacyExtensionsUtils.getEmbeddedExtensionFor({
    id: ADDON_ID,
    resourceURI: addonResourceURI
  });

  if (!shouldDisable() && !webExtension.started) {
    start(webExtension);
  } else if (shouldDisable()) {
    stop(webExtension);
  }
}

function start(webExtension) {
  webExtension.startup().then((api) => {
    api.browser.runtime.onMessage.addListener(handleMessage);
  }).catch((err) => {
    // The startup() promise will be rejected if the webExtension was
    // already started (a harmless error), or if initializing the
    // WebExtension failed and threw (an important error).
    console.error(err);
    if (err.message !== "This embedded extension has already been started") {
      // TODO: Should we send these errors to Sentry? #2420
    }
  });
}

function stop(webExtension) {
  webExtension.shutdown();
}

function handleMessage(msg, sender, sendReply) {
  if (!msg) {
    return;
  }

  if (msg.funcName === "getTelemetryPref") {
    let telemetryEnabled = getBoolPref(TELEMETRY_ENABLED_PREF);
    sendReply({type: "success", value: telemetryEnabled});
  } else if (msg.funcName === "getOldDeviceInfo") {
    let oldDeviceInfo = prefs.prefHasUserValue(OLD_ADDON_PREF_NAME) && prefs.getCharPref(OLD_ADDON_PREF_NAME);
    sendReply({type: "success", value: oldDeviceInfo || null});
  } else if (msg.funcName === "removeOldAddon") {
    AddonManager.getAddonByID(OLD_ADDON_ID, (addon) => {
      prefs.clearUserPref(OLD_ADDON_PREF_NAME);
      if (addon) {
        addon.uninstall();
      }
      sendReply({type: "success", value: !!addon});
    });
    return true;
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name         Ads DOM Remover
// @namespace    sagiegurari
// @version      0.50
// @author       Sagie Gur-Ari
// @description  Removes Ad Containers from DOM (doesn't replace adblocker extension, but blocks dynamic content which the adblocker fails to block by removing whole sections from the HTML DOM.)
// @homepage     https://github.com/sagiegurari/userscripts-ads-dom-remover
// @supportURL   https://github.com/sagiegurari/userscripts-ads-dom-remover/issues
// @match        http://www.ynet.co.il/home/*
// @match        http://www.ynet.co.il/articles/*
// @match        http://www.calcalist.co.il/*
// @match        http://www.globes.co.il/*
// @require      https://code.jquery.com/jquery-2.2.2.min.js
// @require      https://raw.githubusercontent.com/sagiegurari/userscripts-ads-dom-remover/fc378743a66f0a4350c72bd700537eaed82382ad/ads-dom-remover-runner.js
// @grant        none
// @license      MIT License
// ==/UserScript==
/* jshint -W097 */

(function run($, runner) {
    'use strict';

    var selectorDefinitions = {
        ynet: [
            '#colorbox',
            '#cboxOverlay',
            '#ads.premium',
            'img[src*="dynamicyield"]',
            'div.MSCmainContent',
            '[id*="arketingCarouse"]',
            '[id*="arketingRecommended"]',
            '.mainVerticalArticleSharingLinks',
            '.OUTBRAIN',
            '.topBannerWrap',
            '.block.B3 .B3.ghcite.dyother.dyMonitor div',
            '.bigdealhomepage',
            '#ww6s_Main',
            '.buyandsavedy',
            '.area.footer.ghcite',
            '.hdr_set_homepage',
            '#c1_Hor',
            '#c2_Hor',
            '#c3_Hor',
            '#c4_Hor',
            '#c5_Hor',
            '#c6_Hor',
            '.homepagevideo-x6',
            '.buyandsave',
            '[name="ExternalWebpageIframe"]',
            {
                selector: 'iframe',
                filter: function ($element) {
                    return !$element.parent().hasClass('news_ticker_iframe');
                }
            },
            {
                selector: 'div.B2b.block div',
                pre: function ($element) {
                    $element.parent().css({
                        height: '1px'
                    });
                }
            }
        ],
        globes: [
            '#chromeWindow',
            {
                selector: 'iframe',
                filter: function ($element) {
                    var id = $element.attr('id');
                    var src = $element.attr('src') || '';
                    return (id !== 'GlobalFinanceData_home') && (src.indexOf('/news/') !== -1);
                }
            }
        ]
    };

    runner($, {
        getSelectors: function (hostName) {
            var selectors;
            if (hostName.indexOf('globes') !== -1) {
                selectors = selectorDefinitions.globes;
            } else { //ynet/calcalist
                selectors = selectorDefinitions.ynet;
            }

            return selectors;
        }
    });
}(window.$, window.adrRunner));
<commit_msg>minor changes<commit_after>// ==UserScript==
// @name         Ads DOM Remover
// @namespace    sagiegurari
// @version      0.51
// @author       Sagie Gur-Ari
// @description  Removes Ad Containers from DOM (doesn't replace adblocker extension, but blocks dynamic content which the adblocker fails to block by removing whole sections from the HTML DOM.)
// @homepage     https://github.com/sagiegurari/userscripts-ads-dom-remover
// @supportURL   https://github.com/sagiegurari/userscripts-ads-dom-remover/issues
// @match        http://www.ynet.co.il/home/*
// @match        http://www.ynet.co.il/articles/*
// @match        http://www.calcalist.co.il/*
// @match        http://www.globes.co.il/*
// @require      https://code.jquery.com/jquery-2.2.2.min.js
// @require      https://raw.githubusercontent.com/sagiegurari/userscripts-ads-dom-remover/c9a160f6b95236937c530a835a8cc6c7ddeba53b/ads-dom-remover-runner.js
// @grant        none
// @license      MIT License
// ==/UserScript==
/* jshint -W097 */

(function run($, runner) {
    'use strict';

    var selectorDefinitions = {
        ynet: [
            '#colorbox',
            '#cboxOverlay',
            '#ads.premium',
            'img[src*="dynamicyield"]',
            'div.MSCmainContent',
            '[id*="arketingCarouse"]',
            '[id*="arketingRecommended"]',
            '.mainVerticalArticleSharingLinks',
            '.OUTBRAIN',
            '.topBannerWrap',
            '.block.B3 .B3.ghcite.dyother.dyMonitor div',
            '.bigdealhomepage',
            '#ww6s_Main',
            '.buyandsavedy',
            '.area.footer.ghcite',
            '.hdr_set_homepage',
            '#c1_Hor',
            '#c2_Hor',
            '#c3_Hor',
            '#c4_Hor',
            '#c5_Hor',
            '#c6_Hor',
            '.homepagevideo-x6',
            '.buyandsave',
            '[name="ExternalWebpageIframe"]',
            {
                selector: 'iframe',
                filter: function ($element) {
                    return !$element.parent().hasClass('news_ticker_iframe');
                }
            },
            {
                selector: 'div.B2b.block div',
                pre: function ($element) {
                    $element.parent().css({
                        height: '1px'
                    });
                }
            }
        ],
        globes: [
            '#chromeWindow',
            {
                selector: 'iframe',
                filter: function ($element) {
                    var id = $element.attr('id');
                    var src = $element.attr('src') || '';
                    return (id !== 'GlobalFinanceData_home') && (src.indexOf('/news/') !== -1);
                }
            }
        ]
    };

    runner($, {
        getSelectors: function (hostName) {
            var selectors;
            if (hostName.indexOf('globes') !== -1) {
                selectors = selectorDefinitions.globes;
            } else { //ynet/calcalist
                selectors = selectorDefinitions.ynet;
            }

            return selectors;
        }
    });
}(window.$, window.adrRunner));
<|endoftext|>