<commit_before>var Backbone = require('backbone');
var cdb = require('cartodb.js');
var Model = require('../../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-form-models/closest-form-model');
var BaseAnalysisFormModel = require('../../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-form-models/base-analysis-form-model');
var analyses = require('../../../../../../../../javascripts/cartodb3/data/analyses');

describe('editor/layers/layer-content-views/analyses/analysis-form-models/closest-form-model', function () {
  var cdbSQLBackup;

  beforeEach(function () {
    this.configModel = new Backbone.Model({});

    this.layerDefinitionModel = new Backbone.Model({});
    this.layerDefinitionModel.findAnalysisDefinitionNodeModel = function () {
      var node = {
        id: 808,
        letter: function () { return 'A'; },
        querySchemaModel: new Backbone.Model({
          query: 'SELECT * FROM somewhere;'
        })
      };
      return node;
    };
    this.layerDefinitionModel.getName = function () { return 'Metro Madrid'; };

    this.analysisSourceOptionsModel = new Backbone.Model({
      fetching: false
    });
    this.analysisSourceOptionsModel.getSelectOptions = function () {
      return [];
    };
    this.analysisSourceOptionsModel.createSourceNodeUnlessExisting = function () {};

    cdbSQLBackup = cdb.SQL;
    cdb.SQL = function () {
      return {
        execute: function () {}
      };
    };

    this.initializeOptions = {
      analyses: analyses,
      configModel: this.configModel,
      layerDefinitionModel: this.layerDefinitionModel,
      analysisSourceOptionsModel: this.analysisSourceOptionsModel
    };

    this.model = new Model(null, this.initializeOptions);
  });

  afterEach(function () {
    cdb.SQL = cdbSQLBackup;
  });

  describe('initialize', function () {
    it('should call proper function and hook events', function () {
      spyOn(BaseAnalysisFormModel.prototype, 'initialize');
      spyOn(this.model, '_resetColumnOptions');
      spyOn(this.model, '_initBinds');
      spyOn(this.model, '_setSchema');
      spyOn(this.model, '_fetchColumns');

      this.model.initialize(null, this.initializeOptions);

      expect(BaseAnalysisFormModel.prototype.initialize).toHaveBeenCalled();
      expect(this.model._resetColumnOptions).toHaveBeenCalled();
      expect(this.model._initBinds).toHaveBeenCalled();
      expect(this.model._setSchema).toHaveBeenCalled();
      expect(this.model._fetchColumns).toHaveBeenCalled();
    });
  });

  describe('_initBinds', function () {
    it('should hook up change:fetching and change:target events', function () {
      spyOn(this.model, '_onSourceOptionsFetched');

      this.model._initBinds();
      this.model._analysisSourceOptionsModel.set('fetching', true);

      expect(this.model._events['change:target']).toBeDefined();
      expect(this.model._onSourceOptionsFetched).toHaveBeenCalled();
    });
  });

  describe('.getTemplate', function () {
    it('should return the template', function () {
      var template = this.model.getTemplate();

      var templateContent = template();
      expect(templateContent.indexOf('<form>')).toBeGreaterThan(-1);
      expect(templateContent.indexOf('data-fields="source,target"')).toBeGreaterThan(-1);
      expect(templateContent.indexOf('data-fields="category,responses"')).toBeGreaterThan(-1);
    });
  });

  describe('.getTemplateData', function () {
    it('should return an empty object', function () {
      var templateData = this.model.getTemplateData();

      expect(templateData).toEqual({});
    });
  });

  describe('._resetColumnOptions', function () {
    it('should reset _columnOptions and hook up "columnsFetched" event', function () {
      this.model._columnOptions.set('aProperty', 'some value');
      spyOn(this.model, '_onColumnsFetched');

      this.model._resetColumnOptions();
      this.model._columnOptions.trigger('columnsFetched');

      expect(this.model._columnOptions.aProperty).not.toBeDefined();
      expect(this.model._onColumnsFetched).toHaveBeenCalled();
    });
  });

  describe('._onSourceOptionsFetched', function () {
    it('should call _setSchema', function () {
      spyOn(this.model, '_setSchema');

      this.model._onSourceOptionsFetched();

      expect(this.model._setSchema).toHaveBeenCalled();
    });
  });

  describe('._setSchema', function () {
    it('should call _setSchema of BaseAnalysisFormModel with proper schema', function () {
      spyOn(BaseAnalysisFormModel.prototype, '_setSchema');
      spyOn(this.model, '_primarySourceSchemaItem').and.callFake(function (title) {
        return title;
      });
      spyOn(this.model, '_getSourceOptionsForSource').and.callFake(function (sourceAttrName) {
        return sourceAttrName;
      });
      spyOn(this.model, '_isSourceDisabled').and.callFake(function (source) {
        return 'called with ' + source;
      });
      spyOn(this.model._columnOptions, 'filterByType').and.callFake(function (type) { return type; });

      var expectedSchema = {
        source: 'editor.layers.analysis-form.find-nearest.input',
        target: {
          type: 'NodeDataset',
          title: 'editor.layers.analysis-form.find-nearest.target',
          options: {sourceAttrName: 'target'},
          dialogMode: 'float',
          validators: ['required'],
          editorAttrs: {
            disabled: 'called with target'
          }
        },
        category: {
          type: 'EnablerEditor',
          title: '',
          label: 'editor.layers.analysis-form.find-nearest.categorized',
          editor: {
            type: 'Select',
            options: 'string',
            dialogMode: 'float',
            editorAttrs: {
              showLabel: false
            }
          }
        },
        responses: {
          type: 'Number',
          title: 'editor.layers.analysis-form.find-nearest.max-results',
          value: 1,
          validators: ['required', {
            type: 'interval',
            min: 1,
            max: 32
          }]
        }
      };

      this.model._setSchema();

      expect(BaseAnalysisFormModel.prototype._setSchema).toHaveBeenCalledWith(expectedSchema);
    });
  });

  describe('._isSourceDisabled', function () {
    it('should return if attr is primary source or it is fetching, combination 1', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(true);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(false);

      var result = this.model._isSourceDisabled('target');

      expect(this.model._isPrimarySource).toHaveBeenCalledWith('target');
      expect(result).toBe(true);
    });

    it('should return if attr is primary source or it is fetching, combination 2', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(false);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(true);

      var result = this.model._isSourceDisabled('target');

      expect(this.model._isFetchingOptions).toHaveBeenCalled();
      expect(result).toBe(true);
    });

    it('should return if attr is primary source or it is fetching, combination 3', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(false);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(false);

      var result = this.model._isSourceDisabled('target');

      expect(result).toBe(false);
    });
  });

  describe('._onChangeTarget', function () {
    it('should reset category and fetch columnds', function () {
      this.model.set('target', 'madrid');
      spyOn(this.model, '_setSchema');
      spyOn(this.model, '_fetchColumns');
      spyOn(this.model._analysisSourceOptionsModel, 'createSourceNodeUnlessExisting');

      this.model._onChangeTarget();

      expect(this.model.get('category')).toEqual('');
      expect(this.model._setSchema).toHaveBeenCalled();
      expect(this.model._analysisSourceOptionsModel.createSourceNodeUnlessExisting).toHaveBeenCalledWith('madrid');
      expect(this.model._fetchColumns).toHaveBeenCalled();
    });
  });

  describe('._fetchColumns', function () {
    beforeEach(function () {
      this.model.set('target', 'a layer');
      this.layerDefinitionModel.findAnalysisDefinitionNodeModel = function () {};
    });

    it('should set node in columnOptions if target is a node', function () {
      spyOn(this.model._layerDefinitionModel, 'findAnalysisDefinitionNodeModel').and.returnValue('node');
      spyOn(this.model._columnOptions, 'setNode');

      this.model._fetchColumns();

      expect(this.model._layerDefinitionModel.findAnalysisDefinitionNodeModel).toHaveBeenCalledWith('a layer');
      expect(this.model._columnOptions.setNode).toHaveBeenCalledWith('node');
    });

    it('should set target dataset in columnOptions if target is a dataset', function () {
      spyOn(this.model._layerDefinitionModel, 'findAnalysisDefinitionNodeModel').and.returnValue(null);
      spyOn(this.model._columnOptions, 'setDataset');

      this.model._fetchColumns();

      expect(this.model._layerDefinitionModel.findAnalysisDefinitionNodeModel).toHaveBeenCalledWith('a layer');
      expect(this.model._columnOptions.setDataset).toHaveBeenCalledWith('a layer');
    });
  });

  describe('._onColumnsFetched', function () {
    it('should call _setSchema', function () {
      spyOn(this.model, '_setSchema');

      this.model._onColumnsFetched();

      expect(this.model._setSchema).toHaveBeenCalled();
    });
  });
});
<commit_msg>Added missing spec<commit_after>var Backbone = require('backbone');
var cdb = require('cartodb.js');
var Model = require('../../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-form-models/closest-form-model');
var BaseAnalysisFormModel = require('../../../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-form-models/base-analysis-form-model');
var analyses = require('../../../../../../../../javascripts/cartodb3/data/analyses');

describe('editor/layers/layer-content-views/analyses/analysis-form-models/closest-form-model', function () {
  var cdbSQLBackup;

  beforeEach(function () {
    this.configModel = new Backbone.Model({});

    this.layerDefinitionModel = new Backbone.Model({});
    this.layerDefinitionModel.findAnalysisDefinitionNodeModel = function () {
      var node = {
        id: 808,
        letter: function () { return 'A'; },
        querySchemaModel: new Backbone.Model({
          query: 'SELECT * FROM somewhere;'
        })
      };
      return node;
    };
    this.layerDefinitionModel.getName = function () { return 'Metro Madrid'; };

    this.analysisSourceOptionsModel = new Backbone.Model({
      fetching: false
    });
    this.analysisSourceOptionsModel.getSelectOptions = function () {
      return [];
    };
    this.analysisSourceOptionsModel.createSourceNodeUnlessExisting = function () {};

    cdbSQLBackup = cdb.SQL;
    cdb.SQL = function () {
      return {
        execute: function () {}
      };
    };

    this.initializeOptions = {
      analyses: analyses,
      configModel: this.configModel,
      layerDefinitionModel: this.layerDefinitionModel,
      analysisSourceOptionsModel: this.analysisSourceOptionsModel
    };

    this.model = new Model(null, this.initializeOptions);
  });

  afterEach(function () {
    cdb.SQL = cdbSQLBackup;
  });

  describe('parse', function () {
    it('should set default value to responses property', function () {
      var parsed = this.model.parse({});

      expect(parsed.responses).toBe(1);
    });

    it('should not modify responses propertyif present', function () {
      var parsed = this.model.parse({responses: 32});

      expect(parsed.responses).toBe(32);
    });
  });

  describe('initialize', function () {
    it('should call proper function and hook events', function () {
      spyOn(BaseAnalysisFormModel.prototype, 'initialize');
      spyOn(this.model, '_resetColumnOptions');
      spyOn(this.model, '_initBinds');
      spyOn(this.model, '_setSchema');
      spyOn(this.model, '_fetchColumns');

      this.model.initialize(null, this.initializeOptions);

      expect(BaseAnalysisFormModel.prototype.initialize).toHaveBeenCalled();
      expect(this.model._resetColumnOptions).toHaveBeenCalled();
      expect(this.model._initBinds).toHaveBeenCalled();
      expect(this.model._setSchema).toHaveBeenCalled();
      expect(this.model._fetchColumns).toHaveBeenCalled();
    });
  });

  describe('_initBinds', function () {
    it('should hook up change:fetching and change:target events', function () {
      spyOn(this.model, '_onSourceOptionsFetched');

      this.model._initBinds();
      this.model._analysisSourceOptionsModel.set('fetching', true);

      expect(this.model._events['change:target']).toBeDefined();
      expect(this.model._onSourceOptionsFetched).toHaveBeenCalled();
    });
  });

  describe('.getTemplate', function () {
    it('should return the template', function () {
      var template = this.model.getTemplate();

      var templateContent = template();
      expect(templateContent.indexOf('<form>')).toBeGreaterThan(-1);
      expect(templateContent.indexOf('data-fields="source,target"')).toBeGreaterThan(-1);
      expect(templateContent.indexOf('data-fields="category,responses"')).toBeGreaterThan(-1);
    });
  });

  describe('.getTemplateData', function () {
    it('should return an empty object', function () {
      var templateData = this.model.getTemplateData();

      expect(templateData).toEqual({});
    });
  });

  describe('._resetColumnOptions', function () {
    it('should reset _columnOptions and hook up "columnsFetched" event', function () {
      this.model._columnOptions.set('aProperty', 'some value');
      spyOn(this.model, '_onColumnsFetched');

      this.model._resetColumnOptions();
      this.model._columnOptions.trigger('columnsFetched');

      expect(this.model._columnOptions.aProperty).not.toBeDefined();
      expect(this.model._onColumnsFetched).toHaveBeenCalled();
    });
  });

  describe('._onSourceOptionsFetched', function () {
    it('should call _setSchema', function () {
      spyOn(this.model, '_setSchema');

      this.model._onSourceOptionsFetched();

      expect(this.model._setSchema).toHaveBeenCalled();
    });
  });

  describe('._setSchema', function () {
    it('should call _setSchema of BaseAnalysisFormModel with proper schema', function () {
      spyOn(BaseAnalysisFormModel.prototype, '_setSchema');
      spyOn(this.model, '_primarySourceSchemaItem').and.callFake(function (title) {
        return title;
      });
      spyOn(this.model, '_getSourceOptionsForSource').and.callFake(function (sourceAttrName) {
        return sourceAttrName;
      });
      spyOn(this.model, '_isSourceDisabled').and.callFake(function (source) {
        return 'called with ' + source;
      });
      spyOn(this.model._columnOptions, 'filterByType').and.callFake(function (type) { return type; });

      var expectedSchema = {
        source: 'editor.layers.analysis-form.find-nearest.input',
        target: {
          type: 'NodeDataset',
          title: 'editor.layers.analysis-form.find-nearest.target',
          options: {sourceAttrName: 'target'},
          dialogMode: 'float',
          validators: ['required'],
          editorAttrs: {
            disabled: 'called with target'
          }
        },
        category: {
          type: 'EnablerEditor',
          title: '',
          label: 'editor.layers.analysis-form.find-nearest.categorized',
          editor: {
            type: 'Select',
            options: 'string',
            dialogMode: 'float',
            editorAttrs: {
              showLabel: false
            }
          }
        },
        responses: {
          type: 'Number',
          title: 'editor.layers.analysis-form.find-nearest.max-results',
          value: 1,
          validators: ['required', {
            type: 'interval',
            min: 1,
            max: 32
          }]
        }
      };

      this.model._setSchema();

      expect(BaseAnalysisFormModel.prototype._setSchema).toHaveBeenCalledWith(expectedSchema);
    });
  });

  describe('._isSourceDisabled', function () {
    it('should return if attr is primary source or it is fetching, combination 1', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(true);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(false);

      var result = this.model._isSourceDisabled('target');

      expect(this.model._isPrimarySource).toHaveBeenCalledWith('target');
      expect(result).toBe(true);
    });

    it('should return if attr is primary source or it is fetching, combination 2', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(false);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(true);

      var result = this.model._isSourceDisabled('target');

      expect(this.model._isFetchingOptions).toHaveBeenCalled();
      expect(result).toBe(true);
    });

    it('should return if attr is primary source or it is fetching, combination 3', function () {
      spyOn(this.model, '_isPrimarySource').and.returnValue(false);
      spyOn(this.model, '_isFetchingOptions').and.returnValue(false);

      var result = this.model._isSourceDisabled('target');

      expect(result).toBe(false);
    });
  });

  describe('._onChangeTarget', function () {
    it('should reset category and fetch columnds', function () {
      this.model.set('target', 'madrid');
      spyOn(this.model, '_setSchema');
      spyOn(this.model, '_fetchColumns');
      spyOn(this.model._analysisSourceOptionsModel, 'createSourceNodeUnlessExisting');

      this.model._onChangeTarget();

      expect(this.model.get('category')).toEqual('');
      expect(this.model._setSchema).toHaveBeenCalled();
      expect(this.model._analysisSourceOptionsModel.createSourceNodeUnlessExisting).toHaveBeenCalledWith('madrid');
      expect(this.model._fetchColumns).toHaveBeenCalled();
    });
  });

  describe('._fetchColumns', function () {
    beforeEach(function () {
      this.model.set('target', 'a layer');
      this.layerDefinitionModel.findAnalysisDefinitionNodeModel = function () {};
    });

    it('should set node in columnOptions if target is a node', function () {
      spyOn(this.model._layerDefinitionModel, 'findAnalysisDefinitionNodeModel').and.returnValue('node');
      spyOn(this.model._columnOptions, 'setNode');

      this.model._fetchColumns();

      expect(this.model._layerDefinitionModel.findAnalysisDefinitionNodeModel).toHaveBeenCalledWith('a layer');
      expect(this.model._columnOptions.setNode).toHaveBeenCalledWith('node');
    });

    it('should set target dataset in columnOptions if target is a dataset', function () {
      spyOn(this.model._layerDefinitionModel, 'findAnalysisDefinitionNodeModel').and.returnValue(null);
      spyOn(this.model._columnOptions, 'setDataset');

      this.model._fetchColumns();

      expect(this.model._layerDefinitionModel.findAnalysisDefinitionNodeModel).toHaveBeenCalledWith('a layer');
      expect(this.model._columnOptions.setDataset).toHaveBeenCalledWith('a layer');
    });
  });

  describe('._onColumnsFetched', function () {
    it('should call _setSchema', function () {
      spyOn(this.model, '_setSchema');

      this.model._onColumnsFetched();

      expect(this.model._setSchema).toHaveBeenCalled();
    });
  });
});
<|endoftext|>


<commit_before>/**
 * AdSenseModuleStatus component.
 *
 * Site Kit by Google, Copyright 2019 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import { parse as pslParse } from 'psl';
import PropTypes from 'prop-types';
import SvgIcon from 'GoogleUtil/svg-icon';

/**
 * WordPress dependencies
 */
import { Component } from '@wordpress/element';
import { __, _x } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import AdSenseSetupInstructions from '../setup/adsense-setup-instructions';
import AdSenseInProcessStatus from './adsense-in-process-status';
import { getExistingTag, getReAuthURL, getSiteKitAdminURL } from 'GoogleUtil';
import { getAdSenseAccountStatus } from '../util';

const propsFromAccountStatus = ( accountStatus, existingTag ) => {
	/**
	 * Defines the account status variables.
	 */
	let accountTagMatch = false;
	let continueAction = false;
	let ctaLink;
	let ctaLinkText;
	let footerAppendedText;
	let footerCTA;
	let footerCTALink;
	let footerText;
	let icon;
	let incomplete = false;
	let issue;
	let profile = false;
	let required = false;
	const setupComplete = false;
	let statusHeadline;
	let statusMessage;
	let switchLabel;
	let switchOffMessage;
	let switchOnMessage;
	let tracking = false;

	const { accountURL, signupURL } = googlesitekit.modules.adsense;
	const moduleURL = getSiteKitAdminURL(
		'googlesitekit-module-adsense',
		{}
	);
	const siteURL = new URL( googlesitekit.admin.siteURL );

	switch ( accountStatus ) {
		case 'account-connected':
			if ( existingTag ) {
				issue = false;
				icon = 'alert';
				statusHeadline = __( 'Site Kit will place AdSense code to your site', 'google-site-kit' );
				statusMessage = __( 'This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
				ctaLinkText = __( 'Continue', 'google-site-kit' );
				ctaLink = moduleURL;
				accountTagMatch = true;
				switchLabel = __( 'Let Site Kit place code on your site', 'google-site-kit' );
				switchOffMessage = __( 'If you don’t let Site Kit place the code you may not get the best ads experience. You can set this up later on the Site Kit settings page.', 'google-site-kit' );
				switchOnMessage = __( 'If you’ve already set up ads on your site, it may change how they appear. You can customize this later in AdSense.', 'google-site-kit' );
			} else {
				issue = false;
				icon = false;
				statusHeadline = __( 'Looks like you’re already using AdSense', 'google-site-kit' );
				statusMessage = __( 'Site Kit will place AdSense code on your site to connect your site to AdSense and help you get the most out of ads. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
				ctaLinkText = __( 'Continue', 'google-site-kit' );
				ctaLink = moduleURL;
				tracking = {
					eventCategory: 'adsense_setup',
					eventName: 'complete_adsense_setup',
				};
				switchLabel = __( 'Let Site Kit place code on your site to get your site approved', 'google-site-kit' );
				switchOffMessage = __( 'If you’ve already got some AdSense code on your site, we recommend you use Site Kit to place code to get the most out of AdSense.', 'google-site-kit' );
			}
			break;
		case 'account-connected-nonmatching':
			issue = false;
			icon = false;
			statusHeadline = __( 'Your site has code from another AdSense account', 'google-site-kit' );
			statusMessage = __( 'We’ve found some AdSense code on your site, but it’s not linked to this AdSense account.', 'google-site-kit' );
			profile = false;
			ctaLinkText = __( 'Switch Google account', 'google-site-kit' );
			ctaLink = getReAuthURL( 'adsense', true );
			continueAction = {
				accountStatus: 'account-connected',
				continueText: __( 'Continue anyway', 'google-site-kit' ),
				statusHeadline: __( 'Site Kit will place AdSense code on your site', 'google-site-kit' ),
				statusMessage: __( 'To connect your site to your AdSense account, Site Kit will place AdSense code on your site. For a better ads experience, you should remove AdSense code that’s not linked to this AdSense account.', 'google-site-kit' ),
				profile: true,
				ctaLink: moduleURL,
				ctaLinkText: __( 'Continue', 'google-site-kit' ),
				continueAction: false,
				switchLabel: __( 'Let Site Kit place code on your site', 'google-site-kit' ),
				switchOffMessage: __( 'You can let Site Kit do this later.', 'google-site-kit' ),
			};
			break;
		case 'ads-display-pending':
			const { domain: parsedDomain } = pslParse( siteURL.hostname );

			statusHeadline = __( 'Let’s get your site ready for ads', 'google-site-kit' );
			statusMessage = __(
				'After you’ve finished setting up your account, we’ll let you know when your site is ready to show ads. This usually takes less than a day, but it can sometimes take a bit longer.',
				'google-site-kit'
			);
			ctaLinkText = __( 'Go to your AdSense account to check on your site’s status or to complete setting up', 'google-site-kit' );
			ctaLink = `https://www.google.com/adsense/new/sites?url=${ parsedDomain || siteURL.hostname }&source=site-kit`;
			break;
		case 'account-pending-review':
			statusHeadline = __( 'We’re getting your site ready for ads', 'google-site-kit' );
			statusMessage = __(
				'AdSense is reviewing your site. Meanwhile, make sure you’ve completed these steps in AdSense.',
				'google-site-kit'
			);
			ctaLinkText = __( 'Go to your AdSense account to check on your site’s status', 'google-site-kit' );
			ctaLink = `https://www.google.com/adsense/new/sites?url=${ siteURL.hostname }&source=site-kit`;
			incomplete = true;
			break;
		case 'account-required-action':
			required = true;
			break;
		case 'disapproved-account':
			ctaLink = accountURL;
			ctaLinkText = __( 'Go to AdSense to find out how to fix the issue', 'google-site-kit' );
			statusHeadline = __( 'Your site isn’t ready to show ads yet', 'google-site-kit' );
			statusMessage = __( 'You need to fix some things before we can connect Site Kit to your AdSense account.', 'google-site-kit' );
			break;
		case 'disapproved-account-afc':
			issue = __( 'There is an AdSense account, but the AFC account is disapproved', 'google-site-kit' );
			icon = 'error';
			statusHeadline = __( 'Create Account', 'google-site-kit' );
			statusMessage = __( 'Create an AdMob account, then open AdSense and try to upgrade.', 'google-site-kit' );
			ctaLinkText = __( 'Create an AdMob Account', 'google-site-kit' );
			ctaLink = 'https://google.com/admob';
			break;
		case 'no-account':
			statusHeadline = __( 'Create your AdSense account', 'google-site-kit' );
			statusMessage = __( 'Site Kit will place AdSense code on every page across your site. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
			profile = true;
			ctaLinkText = __( 'Create AdSense Account', 'google-site-kit' );
			ctaLink = signupURL;
			footerText = __( 'Already have an AdSense account?', 'google-site-kit' );
			footerAppendedText = __( 'to connect to it', 'google-site-kit' );
			footerCTA = __( 'Switch Google account', 'google-site-kit' );
			footerCTALink = getReAuthURL( 'adsense', true );
			tracking = {
				eventCategory: 'adsense_setup',
				eventName: 'create_adsense_account',
			};
			break;
		case 'no-account-tag-found':
			statusHeadline = __( 'Looks like you’re already using AdSense', 'google-site-kit' );
			statusMessage = __( 'We’ve found some AdSense code on your site, but it’s not linked to this Google account.', 'google-site-kit' );
			profile = false;
			ctaLinkText = __( 'Switch Google account', 'google-site-kit' );
			ctaLink = getReAuthURL( 'adsense', true );
			switchLabel = __( 'Let Site Kit place code on your site to get your site approved', 'google-site-kit' );
			continueAction = {
				statusHeadline: __( 'Create a new AdSense account', 'google-site-kit' ),
				statusMessage: __( 'Site Kit will place additional AdSense code on every page across your site after you create an account. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' ),
				notice: __( 'We recommend you remove the old AdSense code from this site.', 'google-site-kit' ),
				icon: 'warning',
				continueText: __( 'Continue anyway', 'google-site-kit' ),
				ctaLinkText: __( 'Create AdSense Account', 'google-site-kit' ),
				ctaLink: signupURL,
				ctaTarget: '_blank',
				continueAction: false,
			};
			break;
		default:
			break;
	}

	return {
		accountTagMatch,
		continueAction,
		ctaLink,
		ctaLinkText,
		footerAppendedText,
		footerCTA,
		footerCTALink,
		footerText,
		icon,
		incomplete,
		issue,
		profile,
		required,
		setupComplete,
		statusHeadline,
		statusMessage,
		switchLabel,
		switchOffMessage,
		switchOnMessage,
		tracking,
	};
};

class AdSenseModuleStatus extends Component {
	constructor( props ) {
		super( props );

		this.state = {
			accountStatus: undefined,
			loadingMessage: __( 'Loading…', 'google-site-kit' ),
			instructionProps: {},
		};
	}

	async componentDidMount() {
		await this.updateAccountStatus();
	}

	componentDidUpdate( previousProps, previousState ) {
		const { accountStatus } = this.state;

		if ( previousState.accountStatus !== accountStatus ) {
			const adSenseSetupInstructionsProps = propsFromAccountStatus( accountStatus );
			this.setState( { instructionProps: adSenseSetupInstructionsProps } );
		}
	}

	/**
	 * If setup requires a continue step, the method repopulates state with the new data.
	 * @param {Object} continueData
	 */
	continueSetup( continueData ) {
		const { instructionProps } = this.state;

		continueData.existingState = { ...instructionProps };
		this.setState( { instructionProps: continueData } );
	}

	/**
	 * Go back to the previous (existing) state.
	 */
	goBack() {
		const { instructionProps } = this.state;

		const { existingState } = { ...instructionProps };
		if ( existingState ) {
			existingState.existingState = false;
			this.setState( { instructionProps: existingState } );
		}
	}

	async updateAccountStatus() {
		const existingTag = await getExistingTag( 'adsense' );
		const setLoadingMessage = ( message ) => {
			this.setState( { loadingMessage: message } );
		};

		const { accountStatus, clientID } = await getAdSenseAccountStatus( existingTag, setLoadingMessage );

		this.setState( { accountStatus, clientID } );
	}

	render() {
		const { accountStatus, clientID, loadingMessage, instructionProps } = this.state;

		const showInProcess = ! accountStatus || ! googlesitekit.modules.adsense.setupComplete || [
			'ads-display-pending',
			'account-pending-review',
			'account-required-action',
		].includes( accountStatus );

		return (

						<SvgIcon id="adsense" width="33" height="33" />

						{ _x( 'AdSense', 'Service name', 'google-site-kit' ) }

					{ ! googlesitekit.canAdsRun && ! googlesitekit.modules.adsense.setupComplete && (

							<SvgIcon id="error" height="20" width="23" />
							{ __( 'Ad blocker detected, you need to disable it in order to setup AdSense.', 'google-site-kit' ) }

					) }

					{ showInProcess && 'account-connected' !== accountStatus && (
						<AdSenseInProcessStatus
							ctaLink={ instructionProps.ctaLink }
							ctaLinkText={ instructionProps.ctaLinkText }
							header={ instructionProps.statusHeadline }
							subHeader={ instructionProps.statusMessage }
							incomplete={ instructionProps.incomplete }
							required={ instructionProps.required }
							loadingMessage={ ! accountStatus && loadingMessage }
						/>
					) }

					{ googlesitekit.canAdsRun && ( googlesitekit.modules.adsense.setupComplet || 'account-connected' === accountStatus ) && accountStatus && (
						<AdSenseSetupInstructions
							{ ...instructionProps }
							accountStatus={ accountStatus }
							clientID={ clientID }
							continueSetup={ this.continueSetup }
							goBack={ this.goBack }
						/>
					) }

		);
	}
}

AdSenseModuleStatus.propTypes = {
	status: PropTypes.string,
	module: PropTypes.string,
};

export default AdSenseModuleStatus;
<commit_msg>Update assets/js/modules/adsense/dashboard/adsense-module-status.js<commit_after>/**
 * AdSenseModuleStatus component.
 *
 * Site Kit by Google, Copyright 2019 Google LLC
 *
 * 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
 *
 *     https://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.
 */

/**
 * External dependencies
 */
import { parse as pslParse } from 'psl';
import PropTypes from 'prop-types';
import SvgIcon from 'GoogleUtil/svg-icon';

/**
 * WordPress dependencies
 */
import { Component } from '@wordpress/element';
import { __, _x } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import AdSenseSetupInstructions from '../setup/adsense-setup-instructions';
import AdSenseInProcessStatus from './adsense-in-process-status';
import { getExistingTag, getReAuthURL, getSiteKitAdminURL } from 'GoogleUtil';
import { getAdSenseAccountStatus } from '../util';

const propsFromAccountStatus = ( accountStatus, existingTag ) => {
	/**
	 * Defines the account status variables.
	 */
	let accountTagMatch = false;
	let continueAction = false;
	let ctaLink;
	let ctaLinkText;
	let footerAppendedText;
	let footerCTA;
	let footerCTALink;
	let footerText;
	let icon;
	let incomplete = false;
	let issue;
	let profile = false;
	let required = false;
	const setupComplete = false;
	let statusHeadline;
	let statusMessage;
	let switchLabel;
	let switchOffMessage;
	let switchOnMessage;
	let tracking = false;

	const { accountURL, signupURL } = googlesitekit.modules.adsense;
	const moduleURL = getSiteKitAdminURL(
		'googlesitekit-module-adsense',
		{}
	);
	const siteURL = new URL( googlesitekit.admin.siteURL );

	switch ( accountStatus ) {
		case 'account-connected':
			if ( existingTag ) {
				issue = false;
				icon = 'alert';
				statusHeadline = __( 'Site Kit will place AdSense code to your site', 'google-site-kit' );
				statusMessage = __( 'This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
				ctaLinkText = __( 'Continue', 'google-site-kit' );
				ctaLink = moduleURL;
				accountTagMatch = true;
				switchLabel = __( 'Let Site Kit place code on your site', 'google-site-kit' );
				switchOffMessage = __( 'If you don’t let Site Kit place the code you may not get the best ads experience. You can set this up later on the Site Kit settings page.', 'google-site-kit' );
				switchOnMessage = __( 'If you’ve already set up ads on your site, it may change how they appear. You can customize this later in AdSense.', 'google-site-kit' );
			} else {
				issue = false;
				icon = false;
				statusHeadline = __( 'Looks like you’re already using AdSense', 'google-site-kit' );
				statusMessage = __( 'Site Kit will place AdSense code on your site to connect your site to AdSense and help you get the most out of ads. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
				ctaLinkText = __( 'Continue', 'google-site-kit' );
				ctaLink = moduleURL;
				tracking = {
					eventCategory: 'adsense_setup',
					eventName: 'complete_adsense_setup',
				};
				switchLabel = __( 'Let Site Kit place code on your site to get your site approved', 'google-site-kit' );
				switchOffMessage = __( 'If you’ve already got some AdSense code on your site, we recommend you use Site Kit to place code to get the most out of AdSense.', 'google-site-kit' );
			}
			break;
		case 'account-connected-nonmatching':
			issue = false;
			icon = false;
			statusHeadline = __( 'Your site has code from another AdSense account', 'google-site-kit' );
			statusMessage = __( 'We’ve found some AdSense code on your site, but it’s not linked to this AdSense account.', 'google-site-kit' );
			profile = false;
			ctaLinkText = __( 'Switch Google account', 'google-site-kit' );
			ctaLink = getReAuthURL( 'adsense', true );
			continueAction = {
				accountStatus: 'account-connected',
				continueText: __( 'Continue anyway', 'google-site-kit' ),
				statusHeadline: __( 'Site Kit will place AdSense code on your site', 'google-site-kit' ),
				statusMessage: __( 'To connect your site to your AdSense account, Site Kit will place AdSense code on your site. For a better ads experience, you should remove AdSense code that’s not linked to this AdSense account.', 'google-site-kit' ),
				profile: true,
				ctaLink: moduleURL,
				ctaLinkText: __( 'Continue', 'google-site-kit' ),
				continueAction: false,
				switchLabel: __( 'Let Site Kit place code on your site', 'google-site-kit' ),
				switchOffMessage: __( 'You can let Site Kit do this later.', 'google-site-kit' ),
			};
			break;
		case 'ads-display-pending':
			const { domain: parsedDomain } = pslParse( siteURL.hostname );

			statusHeadline = __( 'Let’s get your site ready for ads', 'google-site-kit' );
			statusMessage = __(
				'After you’ve finished setting up your account, we’ll let you know when your site is ready to show ads. This usually takes less than a day, but it can sometimes take a bit longer.',
				'google-site-kit'
			);
			ctaLinkText = __( 'Go to your AdSense account to check on your site’s status or to complete setting up', 'google-site-kit' );
			ctaLink = `https://www.google.com/adsense/new/sites?url=${ parsedDomain || siteURL.hostname }&source=site-kit`;
			break;
		case 'account-pending-review':
			statusHeadline = __( 'We’re getting your site ready for ads', 'google-site-kit' );
			statusMessage = __(
				'AdSense is reviewing your site. Meanwhile, make sure you’ve completed these steps in AdSense.',
				'google-site-kit'
			);
			ctaLinkText = __( 'Go to your AdSense account to check on your site’s status', 'google-site-kit' );
			ctaLink = `https://www.google.com/adsense/new/sites?url=${ siteURL.hostname }&source=site-kit`;
			incomplete = true;
			break;
		case 'account-required-action':
			required = true;
			break;
		case 'disapproved-account':
			ctaLink = accountURL;
			ctaLinkText = __( 'Go to AdSense to find out how to fix the issue', 'google-site-kit' );
			statusHeadline = __( 'Your site isn’t ready to show ads yet', 'google-site-kit' );
			statusMessage = __( 'You need to fix some things before we can connect Site Kit to your AdSense account.', 'google-site-kit' );
			break;
		case 'disapproved-account-afc':
			issue = __( 'There is an AdSense account, but the AFC account is disapproved', 'google-site-kit' );
			icon = 'error';
			statusHeadline = __( 'Create Account', 'google-site-kit' );
			statusMessage = __( 'Create an AdMob account, then open AdSense and try to upgrade.', 'google-site-kit' );
			ctaLinkText = __( 'Create an AdMob Account', 'google-site-kit' );
			ctaLink = 'https://google.com/admob';
			break;
		case 'no-account':
			statusHeadline = __( 'Create your AdSense account', 'google-site-kit' );
			statusMessage = __( 'Site Kit will place AdSense code on every page across your site. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' );
			profile = true;
			ctaLinkText = __( 'Create AdSense Account', 'google-site-kit' );
			ctaLink = signupURL;
			footerText = __( 'Already have an AdSense account?', 'google-site-kit' );
			footerAppendedText = __( 'to connect to it', 'google-site-kit' );
			footerCTA = __( 'Switch Google account', 'google-site-kit' );
			footerCTALink = getReAuthURL( 'adsense', true );
			tracking = {
				eventCategory: 'adsense_setup',
				eventName: 'create_adsense_account',
			};
			break;
		case 'no-account-tag-found':
			statusHeadline = __( 'Looks like you’re already using AdSense', 'google-site-kit' );
			statusMessage = __( 'We’ve found some AdSense code on your site, but it’s not linked to this Google account.', 'google-site-kit' );
			profile = false;
			ctaLinkText = __( 'Switch Google account', 'google-site-kit' );
			ctaLink = getReAuthURL( 'adsense', true );
			switchLabel = __( 'Let Site Kit place code on your site to get your site approved', 'google-site-kit' );
			continueAction = {
				statusHeadline: __( 'Create a new AdSense account', 'google-site-kit' ),
				statusMessage: __( 'Site Kit will place additional AdSense code on every page across your site after you create an account. This means Google will automatically place ads for you in all the best places.', 'google-site-kit' ),
				notice: __( 'We recommend you remove the old AdSense code from this site.', 'google-site-kit' ),
				icon: 'warning',
				continueText: __( 'Continue anyway', 'google-site-kit' ),
				ctaLinkText: __( 'Create AdSense Account', 'google-site-kit' ),
				ctaLink: signupURL,
				ctaTarget: '_blank',
				continueAction: false,
			};
			break;
		default:
			break;
	}

	return {
		accountTagMatch,
		continueAction,
		ctaLink,
		ctaLinkText,
		footerAppendedText,
		footerCTA,
		footerCTALink,
		footerText,
		icon,
		incomplete,
		issue,
		profile,
		required,
		setupComplete,
		statusHeadline,
		statusMessage,
		switchLabel,
		switchOffMessage,
		switchOnMessage,
		tracking,
	};
};

class AdSenseModuleStatus extends Component {
	constructor( props ) {
		super( props );

		this.state = {
			accountStatus: undefined,
			loadingMessage: __( 'Loading…', 'google-site-kit' ),
			instructionProps: {},
		};
	}

	async componentDidMount() {
		await this.updateAccountStatus();
	}

	componentDidUpdate( previousProps, previousState ) {
		const { accountStatus } = this.state;

		if ( previousState.accountStatus !== accountStatus ) {
			const adSenseSetupInstructionsProps = propsFromAccountStatus( accountStatus );
			this.setState( { instructionProps: adSenseSetupInstructionsProps } );
		}
	}

	/**
	 * If setup requires a continue step, the method repopulates state with the new data.
	 * @param {Object} continueData
	 */
	continueSetup( continueData ) {
		const { instructionProps } = this.state;

		continueData.existingState = { ...instructionProps };
		this.setState( { instructionProps: continueData } );
	}

	/**
	 * Go back to the previous (existing) state.
	 */
	goBack() {
		const { instructionProps } = this.state;

		const { existingState } = { ...instructionProps };
		if ( existingState ) {
			existingState.existingState = false;
			this.setState( { instructionProps: existingState } );
		}
	}

	async updateAccountStatus() {
		const existingTag = await getExistingTag( 'adsense' );
		const setLoadingMessage = ( message ) => {
			this.setState( { loadingMessage: message } );
		};

		const { accountStatus, clientID } = await getAdSenseAccountStatus( existingTag, setLoadingMessage );

		this.setState( { accountStatus, clientID } );
	}

	render() {
		const { accountStatus, clientID, loadingMessage, instructionProps } = this.state;

		const showInProcess = ! accountStatus || ! googlesitekit.modules.adsense.setupComplete || [
			'ads-display-pending',
			'account-pending-review',
			'account-required-action',
		].includes( accountStatus );

		return (

						<SvgIcon id="adsense" width="33" height="33" />

						{ _x( 'AdSense', 'Service name', 'google-site-kit' ) }

					{ ! googlesitekit.canAdsRun && ! googlesitekit.modules.adsense.setupComplete && (

							<SvgIcon id="error" height="20" width="23" />
							{ __( 'Ad blocker detected, you need to disable it in order to setup AdSense.', 'google-site-kit' ) }

					) }

					{ showInProcess && 'account-connected' !== accountStatus && (
						<AdSenseInProcessStatus
							ctaLink={ instructionProps.ctaLink }
							ctaLinkText={ instructionProps.ctaLinkText }
							header={ instructionProps.statusHeadline }
							subHeader={ instructionProps.statusMessage }
							incomplete={ instructionProps.incomplete }
							required={ instructionProps.required }
							loadingMessage={ ! accountStatus && loadingMessage }
						/>
					) }

					{ googlesitekit.canAdsRun && ( googlesitekit.modules.adsense.setupComplete || 'account-connected' === accountStatus ) && accountStatus && (
						<AdSenseSetupInstructions
							{ ...instructionProps }
							accountStatus={ accountStatus }
							clientID={ clientID }
							continueSetup={ this.continueSetup }
							goBack={ this.goBack }
						/>
					) }

		);
	}
}

AdSenseModuleStatus.propTypes = {
	status: PropTypes.string,
	module: PropTypes.string,
};

export default AdSenseModuleStatus;
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2010 Evin Grano
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

sc_require('models/child_record');
sc_require('models/record');
sc_require('models/record_attribute');

/** @class

  ChildAttribute is a subclass of RecordAttribute and handles to-one
  relationship for child record

  When setting ( .set() ) the value of a toMany attribute, make sure
  to pass in an array of SC.Record objects.

  There are many ways you can configure a ManyAttribute:

  {{{
    contacts: SC.ChildAttribute.attr('SC.Child');
  }}}

  @extends SC.RecordAttribute
  @since SproutCore 1.0
*/
SC.ChildAttribute = SC.RecordAttribute.extend(
  /** @scope SC.ChildAttribute.prototype */ {

  isNestedRecordTransform: YES,

  // ..........................................................
  // LOW-LEVEL METHODS
  //

  /**  @private - adapted for to one relationship */
  toType: function(record, key, value) {
    var ret   = null, rel,
        recordType  = this.get('typeClass');

    if (!record) {
      throw 'SC.Child: Error during transform: Unable to retrieve parent record.';
    }
    if (!SC.none(value)) ret = record.registerNestedRecord(value, key);

    return ret;
  },

  // Default fromType is just returning itself
  fromType: function(record, key, value){
    var sk, store, ret;
    if (record){
      ret = record.registerNestedRecord(value, key);
      if (ret) {
        sk = ret.get('storeKey');
        store = ret.get('store');
        record.writeAttribute(key, store.readDataHash(sk));
      }
      else if (value) {
        record.writeAttribute(key, value);
      }
    }

    return ret;
  },

  /**
    The core handler.  Called from the property.
    @param {SC.Record} record the record instance
    @param {String} key the key used to access this attribute on the record
    @param {Object} value the property value if called as a setter
    @returns {Object} property value
  */
  call: function(record, key, value) {
    var attrKey = this.get('key') || key, cRef,
        cacheKey = SC.keyFor('__kid__', SC.guidFor(this));
    if (value !== undefined) {
      // this.orphan(record, cacheKey, value);
      value = this.fromType(record, key, value) ; // convert to attribute.
      // record[cacheKey] = value;
    } else {
      value = record.readAttribute(attrKey);
      if (SC.none(value) && (value = this.get('defaultValue'))) {
        if (typeof value === SC.T_FUNCTION) {
          value = this.defaultValue(record, key, this);
          // write default value so it doesn't have to be executed again
          if(record.attributes()) record.writeAttribute(attrKey, value, true);
        }
      } else value = this.toType(record, key, value);
    }

    return value ;
  }
});

<commit_msg>removing dead require<commit_after>// ==========================================================================
// Project:   SproutCore - JavaScript Application Framework
// Copyright: ©2010 Evin Grano
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

sc_require('models/record');
sc_require('models/record_attribute');

/** @class

  ChildAttribute is a subclass of RecordAttribute and handles to-one
  relationship for child record

  When setting ( .set() ) the value of a toMany attribute, make sure
  to pass in an array of SC.Record objects.

  There are many ways you can configure a ManyAttribute:

  {{{
    contacts: SC.ChildAttribute.attr('SC.Child');
  }}}

  @extends SC.RecordAttribute
  @since SproutCore 1.0
*/
SC.ChildAttribute = SC.RecordAttribute.extend(
  /** @scope SC.ChildAttribute.prototype */ {

  isNestedRecordTransform: YES,

  // ..........................................................
  // LOW-LEVEL METHODS
  //

  /**  @private - adapted for to one relationship */
  toType: function(record, key, value) {
    var ret   = null, rel,
        recordType  = this.get('typeClass');

    if (!record) {
      throw 'SC.Child: Error during transform: Unable to retrieve parent record.';
    }
    if (!SC.none(value)) ret = record.registerNestedRecord(value, key);

    return ret;
  },

  // Default fromType is just returning itself
  fromType: function(record, key, value){
    var sk, store, ret;
    if (record){
      ret = record.registerNestedRecord(value, key);
      if (ret) {
        sk = ret.get('storeKey');
        store = ret.get('store');
        record.writeAttribute(key, store.readDataHash(sk));
      }
      else if (value) {
        record.writeAttribute(key, value);
      }
    }

    return ret;
  },

  /**
    The core handler.  Called from the property.
    @param {SC.Record} record the record instance
    @param {String} key the key used to access this attribute on the record
    @param {Object} value the property value if called as a setter
    @returns {Object} property value
  */
  call: function(record, key, value) {
    var attrKey = this.get('key') || key, cRef,
        cacheKey = SC.keyFor('__kid__', SC.guidFor(this));
    if (value !== undefined) {
      // this.orphan(record, cacheKey, value);
      value = this.fromType(record, key, value) ; // convert to attribute.
      // record[cacheKey] = value;
    } else {
      value = record.readAttribute(attrKey);
      if (SC.none(value) && (value = this.get('defaultValue'))) {
        if (typeof value === SC.T_FUNCTION) {
          value = this.defaultValue(record, key, this);
          // write default value so it doesn't have to be executed again
          if(record.attributes()) record.writeAttribute(attrKey, value, true);
        }
      } else value = this.toType(record, key, value);
    }

    return value ;
  }
});

<|endoftext|>


<commit_before>// ### Part of the [Rosy Framework](http://github.com/ff0000/rosy)
/* history.js */

// Custom [JSLint](http://jslint.com) settings.
/*global $: true, console: true, Class: true */
/*jslint browser: true, onevar: true */

// The RED Namespace
var RED = RED || {};

// ## RED.History
// A bootstrap to add [History.js](https://github.com/balupton/History.js/) functionality to the Rosy Framework.
RED.History = RED.Class.extend({

	// Load the required History.js dependencies.
	init : function (scope) {
		if (!scope) {
			throw "You must define a scope.";
		}

		this.scope = scope;

		Modernizr.load([{
			test : window.JSON && window.JSON.stringify,
			nope : "media/js/libs/json2.js",
			both : "media/js/libs/amplify.store.js"
		}, {
			test : $,
			yep : "media/js/libs/plugins/history.adapter.jquery.js"
		}, {
			test : Modernizr.history,
			yep : "media/js/libs/history.js",
			nope : "media/js/libs/history.html4.js",
			complete : this.delegate(this, this.setupEvents)
		}]);
	},

	// Attach `statechange` event listener
	setupEvents : function () {
		History.Adapter.bind(window, "statechange", this.delegate(this, this.onStateChange));
	},

	// On `statechange`, call RED.Class.refresh
	onStateChange : function () {
		this.scope.refresh.call(this.scope, History.getState());
	}

});

<commit_msg>Sanity check for RED.Class.refresh.<commit_after>// ### Part of the [Rosy Framework](http://github.com/ff0000/rosy)
/* history.js */

// Custom [JSLint](http://jslint.com) settings.
/*global $: true, console: true, Class: true */
/*jslint browser: true, onevar: true */

// The RED Namespace
var RED = RED || {};

// ## RED.History
// A bootstrap to add [History.js](https://github.com/balupton/History.js/) functionality to the Rosy Framework.
RED.History = RED.Class.extend({

	// Load the required History.js dependencies.
	init : function (scope) {
		if (!scope) {
			throw "You must define a scope.";
		}

		this.scope = scope;

		Modernizr.load([{
			test : window.JSON && window.JSON.stringify,
			nope : "media/js/libs/json2.js",
			both : "media/js/libs/amplify.store.js"
		}, {
			test : $,
			yep : "media/js/libs/plugins/history.adapter.jquery.js"
		}, {
			test : Modernizr.history,
			yep : "media/js/libs/history.js",
			nope : "media/js/libs/history.html4.js",
			complete : this.delegate(this, this.setupEvents)
		}]);
	},

	// Attach `statechange` event listener
	setupEvents : function () {
		History.Adapter.bind(window, "statechange", this.delegate(this, this.onStateChange));
	},

	// On `statechange`, call RED.Class.refresh
	onStateChange : function () {
		if (this.scope && this.scope.refresh) {
			this.scope.refresh.call(this.scope, History.getState());
		}
	}

});
<|endoftext|>


<commit_before>var peers = require('./peer')
var NETWORK = require('./const').NETWORK
var dns = require('dns')

var Promise = require('promise')
var dnsResolve4 = Promise.denodeify(dns.resolve4)

/* Default DNS seeds*/
var dnsSeeds = ['bitseed.xf2.org', 'dnsseed.bluematt.me', 'seed.bitcoin.sipa.be', 'dnsseed.bitcoin.dashjr.org', 'seed.bitcoinstats.com']
var dnsTestnetSeeds = ['seed.tbtc.petertodd.org']

/* Resolve DNS to get peers' IP, then connect them*/
var resolve = (network) => {
  var seeds = network === NETWORK.MAINNET ? dnsSeeds : dnsTestnetSeeds
  var seedsResolved = seeds.map((seed) => dnsResolve4(seed))
  seedsResolved.forEach((seedResolved) => seedResolved.then(peers.connect(network)).catch(console.log))
  return seedsResolved
}

module.exports = {
  resolve: resolve
}
<commit_msg>meet standardjs<commit_after>var peers = require('./peer')
var NETWORK = require('./const').NETWORK
var dns = require('dns')

var Promise = require('promise')
var dnsResolve4 = Promise.denodeify(dns.resolve4)

/* Default DNS seeds */
var dnsSeeds = ['bitseed.xf2.org', 'dnsseed.bluematt.me', 'seed.bitcoin.sipa.be', 'dnsseed.bitcoin.dashjr.org', 'seed.bitcoinstats.com']
var dnsTestnetSeeds = ['seed.tbtc.petertodd.org']

/* Resolve DNS to get peers' IP, then connect them */
var resolve = (network) => {
  var seeds = network === NETWORK.MAINNET ? dnsSeeds : dnsTestnetSeeds
  var seedsResolved = seeds.map((seed) => dnsResolve4(seed))
  seedsResolved.forEach((seedResolved) => seedResolved.then(peers.connect(network)).catch(console.log))
  return seedsResolved
}

module.exports = {
  resolve: resolve
}
<|endoftext|>


<commit_before>module.exports = {
    "extends": "airbnb",
    "plugins": [
        "react",
        "jsx-a11y",
        "import"
    ],
    "globals": {
    	"window": true,
    	"document": true
    },
    "rules": { "no-unused-vars": 0}
};
<commit_msg>Added note for addtional refactoring<commit_after>module.exports = {
    "extends": "airbnb",
    "plugins": [
        "react",
        "jsx-a11y",
        "import"
    ],
    "globals": {
    	"window": true,
    	"document": true
    },
    // Should exceptions for .css and bootstrap files as opposed to
    // turning whole thing off.
    "rules": { "no-unused-vars": 0}
};
<|endoftext|>


<commit_before>/*!
* Copyright 2002 - 2013 Webdetails, a Pentaho company.  All rights reserved.
*
* This software was developed by Webdetails and is provided under the terms
* of the Mozilla Public License, Version 2.0, or any later version. You may not use
* this file except in compliance with the license. If you need a copy of the license,
* please go to  http://mozilla.org/MPL/2.0/. The Initial Developer is Webdetails.
*
* Software distributed under the Mozilla Public License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to
* the license for the specific language governing your rights and limitations.
*/

/*==================================================
 *  Simile Timeplot API
 *
 *  Include Timeplot in your HTML file as follows:
 *    <script src="http://static.simile.mit.edu/timeplot/api/1.0/timeplot-api.js" type="text/javascript"></script>
 *
 *==================================================*/

(function() {

	var debug = false;
    var local = false;

    // obtain local mode from the document URL
    if (document.location.search.length > 0) {
        var params = document.location.search.substr(1).split("&");
        for (var i = 0; i < params.length; i++) {
            if (params[i] == "local") {
                local = true;
            }
        }
    }

    // obtain local mode from the script URL params attribute
    if (!local) {
        var heads = document.documentElement.getElementsByTagName("head");
        for (var h = 0; h < heads.length; h++) {
            var node = heads[h].firstChild;
            while (node != null) {
                if (node.nodeType == 1 && node.tagName.toLowerCase() == "script") {
                    var url = node.src;
                    if (url.indexOf("timeplot-api") >= 0) {
                        local = (url.indexOf("local") >= 0);
                    }
                }
                node = node.nextSibling;
            }
        }
    }

    // Load Timeplot if it's not already loaded (after SimileAjax and Timeline)
    var loadTimeplot = function() {

        if (typeof window.Timeplot != "undefined") {
            return;
        }

        window.Timeplot = {
            loaded:     false,
            params:     { bundle: true, autoCreate: true },
            namespace:  "http://simile.mit.edu/2007/06/timeplot#",
            importers:  {}
        };

        var javascriptFiles = [
            "timeplot.js",
            "plot.js",
            "sources.js",
            "geometry.js",
            "color.js",
            "math.js",
            "processor.js"
        ];
        var cssFiles = [
            "timeplot.css"
        ];

        var locales = [ "en" ];

        var defaultClientLocales = ("language" in navigator ? navigator.language : navigator.browserLanguage).split(";");
        for (var l = 0; l < defaultClientLocales.length; l++) {
            var locale = defaultClientLocales[l];
            if (locale != "en") {
                var segments = locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(locale);
            }
        }

        var paramTypes = { bundle:Boolean, js:Array, css:Array, autoCreate:Boolean };
        if (typeof Timeplot_urlPrefix == "string") {
            Timeplot.urlPrefix = Timeplot_urlPrefix;
            if ("Timeplot_parameters" in window) {
                SimileAjax.parseURLParameters(Timeplot_parameters, Timeplot.params, paramTypes);
            }
        } else {
            var url = SimileAjax.findScript(document, "/timeplot-api.js");
            if (url == null) {
                Timeplot.error = new Error("Failed to derive URL prefix for Simile Timeplot API code files");
                return;
            }
            Timeplot.urlPrefix = url.substr(0, url.indexOf("timeplot-api.js"));

            SimileAjax.parseURLParameters(url, Timeplot.params, paramTypes);
        }

        if (Timeplot.params.locale) { // ISO-639 language codes,
            // optional ISO-3166 country codes (2 characters)
            if (Timeplot.params.locale != "en") {
                var segments = Timeplot.params.locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(Timeplot.params.locale);
            }
        }

        var timeplotURLPrefix = (local) ? webAppPath + "/content/pentaho-cdf/js/simile/timeplot/" : Timeplot.urlPrefix;

        if (debug && local && !("console" in window)) {
            var firebug = [ timeplotURLPrefix + "lib/firebug/firebug.js" ];
            SimileAjax.includeJavascriptFiles(document, "", firebug);
        }

        var canvas = document.createElement("canvas");

        if (!canvas.getContext) {
            var excanvas = [ timeplotURLPrefix + "lib/excanvas.js" ];
            SimileAjax.includeJavascriptFiles(document, "", excanvas);
        }

        var scriptURLs = Timeplot.params.js || [];
        var cssURLs = Timeplot.params.css || [];

        // Core scripts and styles
        if (Timeplot.params.bundle && !local) {
            scriptURLs.push(timeplotURLPrefix + "timeplot-bundle.js");
            cssURLs.push(timeplotURLPrefix + "timeplot-bundle.css");
        } else {
            SimileAjax.prefixURLs(scriptURLs, timeplotURLPrefix + "scripts/", javascriptFiles);
            SimileAjax.prefixURLs(cssURLs, timeplotURLPrefix + "styles/", cssFiles);
        }

        // Localization
        //for (var i = 0; i < locales.length; i++) {
        //    scriptURLs.push(Timeplot.urlPrefix + "locales/" + locales[i] + "/locale.js");
        //};

        window.SimileAjax_onLoad = function() {
            if (debug && local && window.console.open) window.console.open();
            if (Timeplot.params.callback) {
                eval(Timeplot.params.callback + "()");
            }
        }

        SimileAjax.includeJavascriptFiles(document, "", scriptURLs);
        SimileAjax.includeCssFiles(document, "", cssURLs);
        Timeplot.loaded = true;
    };

    // Load Timeline if it's not already loaded (after SimileAjax and before Timeplot)
    var loadTimeline = function() {
        if (typeof Timeline != "undefined") {
            loadTimeplot();
        } else {
            var timelineURL = (local) ? webAppPath + "/content/pentaho-cdf/js/simile/timeline/timeline-api.js?bundle=false" : "http://static.simile.mit.edu/timeline/api-2.0/timeline-api.js";
            window.SimileAjax_onLoad = loadTimeplot;
            SimileAjax.includeJavascriptFile(document, timelineURL);
        }
    };

    // Load SimileAjax if it's not already loaded
    if (typeof SimileAjax == "undefined") {
        window.SimileAjax_onLoad = loadTimeline;

        var url = local ?
            webAppPath + "/content/pentaho-cdf/js/simile/ajax/simile-ajax-api.js?bundle=false" :
            "http://static.simile.mit.edu/ajax/api-2.0/simile-ajax-api.js?bundle=true";

        var createScriptElement = function() {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.language = "JavaScript";
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        }

        if (document.body == null) {
            try {
                document.write("<script src='" + url + "' type='text/javascript'></script>");
            } catch (e) {
                createScriptElement();
            }
        } else {
            createScriptElement();
        }
    } else {
        loadTimeline();
    }
})();
<commit_msg>[CDF-257] - Timeplot was being loaded from external location instead of local copy<commit_after>/*!
*
*   © Copyright The SIMILE Project 2003-2005.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* 3. The name of the author may not be used to endorse or promote products
*    derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*==================================================
 *  Simile Timeplot API
 *
 *  Include Timeplot in your HTML file as follows:
 *    <script src="http://static.simile.mit.edu/timeplot/api/1.0/timeplot-api.js" type="text/javascript"></script>
 *
 *==================================================*/

(function() {

	var debug = false;
    var local = true;

    // obtain local mode from the document URL
    if (document.location.search.length > 0) {
        var params = document.location.search.substr(1).split("&");
        for (var i = 0; i < params.length; i++) {
            if (params[i] == "local") {
                local = true;
            }
        }
    }

    // obtain local mode from the script URL params attribute
    if (!local) {
        var heads = document.documentElement.getElementsByTagName("head");
        for (var h = 0; h < heads.length; h++) {
            var node = heads[h].firstChild;
            while (node != null) {
                if (node.nodeType == 1 && node.tagName.toLowerCase() == "script") {
                    var url = node.src;
                    if (url.indexOf("timeplot-api") >= 0) {
                        local = (url.indexOf("local") >= 0);
                    }
                }
                node = node.nextSibling;
            }
        }
    }

    // Load Timeplot if it's not already loaded (after SimileAjax and Timeline)
    var loadTimeplot = function() {

        if (typeof window.Timeplot != "undefined") {
            return;
        }

        window.Timeplot = {
            loaded:     false,
            params:     { bundle: true, autoCreate: true },
            namespace:  "http://simile.mit.edu/2007/06/timeplot#",
            importers:  {}
        };

        var javascriptFiles = [
            "timeplot.js",
            "plot.js",
            "sources.js",
            "geometry.js",
            "color.js",
            "math.js",
            "processor.js"
        ];
        var cssFiles = [
            "timeplot.css"
        ];

        var locales = [ "en" ];

        var defaultClientLocales = ("language" in navigator ? navigator.language : navigator.browserLanguage).split(";");
        for (var l = 0; l < defaultClientLocales.length; l++) {
            var locale = defaultClientLocales[l];
            if (locale != "en") {
                var segments = locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(locale);
            }
        }

        var paramTypes = { bundle:Boolean, js:Array, css:Array, autoCreate:Boolean };
        if (typeof Timeplot_urlPrefix == "string") {
            Timeplot.urlPrefix = Timeplot_urlPrefix;
            if ("Timeplot_parameters" in window) {
                SimileAjax.parseURLParameters(Timeplot_parameters, Timeplot.params, paramTypes);
            }
        } else {
            var url = SimileAjax.findScript(document, "/timeplot-api.js");
            if (url == null) {
                Timeplot.error = new Error("Failed to derive URL prefix for Simile Timeplot API code files");
                return;
            }
            Timeplot.urlPrefix = url.substr(0, url.indexOf("timeplot-api.js"));

            SimileAjax.parseURLParameters(url, Timeplot.params, paramTypes);
        }

        if (Timeplot.params.locale) { // ISO-639 language codes,
            // optional ISO-3166 country codes (2 characters)
            if (Timeplot.params.locale != "en") {
                var segments = Timeplot.params.locale.split("-");
                if (segments.length > 1 && segments[0] != "en") {
                    locales.push(segments[0]);
                }
                locales.push(Timeplot.params.locale);
            }
        }

        var timeplotURLPrefix = (local) ? webAppPath + "/content/pentaho-cdf/js/simile/timeplot/" : Timeplot.urlPrefix;

        if (debug && local && !("console" in window)) {
            var firebug = [ timeplotURLPrefix + "lib/firebug/firebug.js" ];
            SimileAjax.includeJavascriptFiles(document, "", firebug);
        }

        var canvas = document.createElement("canvas");

        if (!canvas.getContext) {
            var excanvas = [ timeplotURLPrefix + "lib/excanvas.js" ];
            SimileAjax.includeJavascriptFiles(document, "", excanvas);
        }

        var scriptURLs = Timeplot.params.js || [];
        var cssURLs = Timeplot.params.css || [];

        // Core scripts and styles
        if (Timeplot.params.bundle && !local) {
            scriptURLs.push(timeplotURLPrefix + "timeplot-bundle.js");
            cssURLs.push(timeplotURLPrefix + "timeplot-bundle.css");
        } else {
            SimileAjax.prefixURLs(scriptURLs, timeplotURLPrefix + "scripts/", javascriptFiles);
            SimileAjax.prefixURLs(cssURLs, timeplotURLPrefix + "styles/", cssFiles);
        }

        // Localization
        //for (var i = 0; i < locales.length; i++) {
        //    scriptURLs.push(Timeplot.urlPrefix + "locales/" + locales[i] + "/locale.js");
        //};

        window.SimileAjax_onLoad = function() {
            if (debug && local && window.console.open) window.console.open();
            if (Timeplot.params.callback) {
                eval(Timeplot.params.callback + "()");
            }
        }

        SimileAjax.includeJavascriptFiles(document, "", scriptURLs);
        SimileAjax.includeCssFiles(document, "", cssURLs);
        Timeplot.loaded = true;
    };

    // Load Timeline if it's not already loaded (after SimileAjax and before Timeplot)
    var loadTimeline = function() {
        if (typeof Timeline != "undefined") {
            loadTimeplot();
        } else {
            var timelineURL = (local) ? webAppPath + "/content/pentaho-cdf/js/simile/timeline/timeline-api.js?bundle=true" : "http://static.simile.mit.edu/timeline/api-2.0/timeline-api.js";
            window.SimileAjax_onLoad = loadTimeplot;
            SimileAjax.includeJavascriptFile(document, timelineURL);
        }
    };

    // Load SimileAjax if it's not already loaded
    if (typeof SimileAjax == "undefined") {
        window.SimileAjax_onLoad = loadTimeline;

        var url = local ?
            webAppPath + "/content/pentaho-cdf/js/simile/ajax/simile-ajax-api.js?bundle=true" :
            "http://static.simile.mit.edu/ajax/api-2.0/simile-ajax-api.js?bundle=true";

        var createScriptElement = function() {
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.language = "JavaScript";
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        }

        if (document.body == null) {
            try {
                document.write("<script src='" + url + "' type='text/javascript'></script>");
            } catch (e) {
                createScriptElement();
            }
        } else {
            createScriptElement();
        }
    } else {
        loadTimeline();
    }
})();
<|endoftext|>


<commit_before>/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.
 */

'use strict';

var fs = require('fs');

var template = fs.readFileSync(__dirname + '/users.html', 'utf8');
var searchConfig = JSON.parse(
  fs.readFileSync(__dirname + '/users-search-plugin-config.json', 'utf8')
);

var angular = require('camunda-commons-ui/vendor/angular');

var Controller = [
  '$scope',
  '$location',
  'search',
  'UserResource',
  'page',
  '$translate',
  'Notifications',
  function(
    $scope,
    $location,
    search,
    UserResource,
    pageService,
    $translate,
    Notifications
  ) {
    $scope.searchConfig = angular.copy(searchConfig);

    $scope.blocked = true;
    $scope.onSearchChange = updateView;

    $scope.canSortEntries = true;

    $scope.query = $scope.pages = null;
    var sorting;

    $scope.onSortInitialized = function(_sorting) {
      sorting = _sorting;
      $scope.blocked = false;
    };

    $scope.onSortChanged = function(_sorting) {
      sorting = _sorting;
      updateView();
    };

    function updateView(query, pages) {
      if (query && pages) {
        $scope.query = query;
        $scope.pages = pages;
      }

      var page = $scope.pages.current,
        count = $scope.pages.size,
        firstResult = (page - 1) * count;

      var queryParams = {
        firstResult: firstResult,
        maxResults: count,
        sortBy: sorting.sortBy,
        sortOrder: sorting.sortOrder
      };

      $scope.userList = null;
      $scope.loadingState = 'LOADING';

      return UserResource.count(angular.extend({}, $scope.query))
        .$promise.then(function(data) {
          var total = data.count;

          return UserResource.query(
            angular.extend({}, $scope.query, queryParams)
          )
            .$promise.then(function(data) {
              $scope.userList = data;
              $scope.loadingState = data.length ? 'LOADED' : 'EMPTY';

              return total;
            })
            .catch(() => {
              // When using LDAP, sorting parameters might not work and throw errors
              // Try again with default sorting
              delete queryParams.sortBy;
              delete queryParams.sortOrder;
              return UserResource.query(
                angular.extend({}, $scope.query, queryParams)
              ).$promise.then(function(data) {
                $scope.canSortEntries = false;
                $scope.userList = data;
                $scope.loadingState = data.length ? 'LOADED' : 'EMPTY';

                Notifications.addMessage({
                  status: $translate.instant('USERS_NO_SORTING_HEADER'),
                  message: $translate.instant('USERS_NO_SORTING_BODY'),
                  exclusive: true
                });

                return total;
              });
            });
        })
        .catch(angular.noop);
    }

    $scope.availableOperations = {};
    UserResource.OPTIONS()
      .$promise.then(function(response) {
        angular.forEach(response.links, function(link) {
          $scope.availableOperations[link.rel] = true;
        });
      })
      .catch(angular.noop);

    $scope.$root.showBreadcrumbs = true;

    pageService.titleSet($translate.instant('USERS_USERS'));

    pageService.breadcrumbsClear();

    pageService.breadcrumbsAdd({
      label: $translate.instant('USERS_USERS'),
      href: '#/users/'
    });
  }
];

module.exports = [
  '$routeProvider',
  function($routeProvider) {
    $routeProvider.when('/users', {
      template: template,
      controller: Controller,
      authentication: 'required',
      reloadOnSearch: false
    });
  }
];
<commit_msg>fix(users): handle unreachable identity provider<commit_after>/*
 * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. Camunda licenses this file to you under the Apache License,
 * Version 2.0; 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.
 */

'use strict';

var fs = require('fs');

var template = fs.readFileSync(__dirname + '/users.html', 'utf8');
var searchConfig = JSON.parse(
  fs.readFileSync(__dirname + '/users-search-plugin-config.json', 'utf8')
);

var angular = require('camunda-commons-ui/vendor/angular');

var Controller = [
  '$scope',
  '$location',
  'search',
  'UserResource',
  'page',
  '$translate',
  'Notifications',
  function(
    $scope,
    $location,
    search,
    UserResource,
    pageService,
    $translate,
    Notifications
  ) {
    $scope.searchConfig = angular.copy(searchConfig);

    $scope.blocked = true;
    $scope.onSearchChange = updateView;

    $scope.canSortEntries = true;

    $scope.query = $scope.pages = null;
    var sorting;

    $scope.onSortInitialized = function(_sorting) {
      sorting = _sorting;
      $scope.blocked = false;
    };

    $scope.onSortChanged = function(_sorting) {
      sorting = _sorting;
      updateView();
    };

    function updateView(query, pages) {
      if (query && pages) {
        $scope.query = query;
        $scope.pages = pages;
      }

      var page = $scope.pages.current,
        count = $scope.pages.size,
        firstResult = (page - 1) * count;

      var queryParams = {
        firstResult: firstResult,
        maxResults: count,
        sortBy: sorting.sortBy,
        sortOrder: sorting.sortOrder
      };

      $scope.userList = null;
      $scope.loadingState = 'LOADING';

      return UserResource.count(angular.extend({}, $scope.query))
        .$promise.then(function(data) {
          var total = data.count;

          return UserResource.query(
            angular.extend({}, $scope.query, queryParams)
          )
            .$promise.then(function(data) {
              $scope.userList = data;
              $scope.loadingState = data.length ? 'LOADED' : 'EMPTY';

              return total;
            })
            .catch(() => {
              // When using LDAP, sorting parameters might not work and throw errors
              // Try again with default sorting
              delete queryParams.sortBy;
              delete queryParams.sortOrder;
              return UserResource.query(
                angular.extend({}, $scope.query, queryParams)
              )
                .$promise.then(function(data) {
                  $scope.canSortEntries = false;
                  $scope.userList = data;
                  $scope.loadingState = data.length ? 'LOADED' : 'EMPTY';

                  Notifications.addMessage({
                    status: $translate.instant('USERS_NO_SORTING_HEADER'),
                    message: $translate.instant('USERS_NO_SORTING_BODY'),
                    exclusive: true
                  });

                  return total;
                })
                .catch(function() {
                  $scope.loadingState = 'EMPTY';
                });
            });
        })
        .catch(angular.noop);
    }

    $scope.availableOperations = {};
    UserResource.OPTIONS()
      .$promise.then(function(response) {
        angular.forEach(response.links, function(link) {
          $scope.availableOperations[link.rel] = true;
        });
      })
      .catch(angular.noop);

    $scope.$root.showBreadcrumbs = true;

    pageService.titleSet($translate.instant('USERS_USERS'));

    pageService.breadcrumbsClear();

    pageService.breadcrumbsAdd({
      label: $translate.instant('USERS_USERS'),
      href: '#/users/'
    });
  }
];

module.exports = [
  '$routeProvider',
  function($routeProvider) {
    $routeProvider.when('/users', {
      template: template,
      controller: Controller,
      authentication: 'required',
      reloadOnSearch: false
    });
  }
];
<|endoftext|>


<commit_before>/**
* @Author: Yingya Zhang <zyy>
* @Date:   2016-07-08 11:29:00
* @Email:  zyy7259@gmail.com
* @Last modified by:   zyy
* @Last modified time: 2016-07-10 22:29:41
*/

import {
  isFunction,
  exist
} from './type'

export function calHeight (node) {
  node = node.cloneNode(true)
  node.style.display = 'block'
  node.style.opacity = 0
  node.style.height = 'auto'
  document.body.appendChild(node)
  const height = node.offsetHeight
  document.body.removeChild(node)
  return height
}

export function remove (node) {
  if (node.parentNode) {
    node.parentNode.removeChild(node)
  }
}

export function dataset (node, key, value) {
  if (exist(value)) {
    node.setAttribute('data-' + key, value)
  } else {
    return node.getAttribute('data-' + key)
  }
}

export const addEventListener = (node, type, callback) => {
  if (node.addEventListener) {
    node.addEventListener(type, callback, false)
  } else if (node.attachEvent) {
    node.attachEvent('on' + type, callback)
  }
}
export const on = addEventListener

export const removeEventListener = (node, type, callback) => {
  if (node.removeEventListener) {
    node.removeEventListener(type, callback, false)
  } else if (node.detachEvent) {
    node.detachEvent('on' + type, callback)
  }
}
export const off = removeEventListener

export function target (event) {
  return event.target || event.srcElement
}

export function createIframe (options) {
  options = options || {}
  var iframe = document.createElement('iframe')
  iframe.frameBorder = 0
  if (options.name) {
    iframe.name = options.name
  }
  if (!options.visible) {
    iframe.style.display = 'none'
  }
  if (isFunction(options.onload)) {
    var onIframeLoad = function (event) {
      if (!iframe.src) {
        return
      }
      if (!options.multi) {
        off(iframe, 'load', onIframeLoad)
      }
      options.onload(event)
    }
    on(iframe, 'load', onIframeLoad)
  }
    // will trigger onload
  var parent = options.parent;
  (parent || document.body).appendChild(iframe)
    // ensure trigger onload async
  var src = options.src || 'about:blank'
  setTimeout(() => {
    iframe.src = src
  }, 0)
  return iframe
}

export function html2node (html) {
  const div = window.document.createElement('div')
  div.innerHTML = html
  const children = []
  let i
  let l
  if (div.children) {
    for (i = 0, l = div.children.length; i < l; i++) {
      children.push(div.children[i])
    }
  } else {
    for (i = 0, l = div.childNodes.length; i < l; i++) {
      var child = div.childNodes[i]
      if (child.nodeType === 1) {
        children.push(child)
      }
    }
  }
  return children.length > 1 ? div : children[0]
}
<commit_msg>refine calHeight<commit_after>/**
* @Author: Yingya Zhang <zyy>
* @Date:   2016-07-08 11:29:00
* @Email:  zyy7259@gmail.com
* @Last modified by:   zyy
* @Last modified time: 2016-07-12T16:30:42+08:00
*/

import {
  isFunction,
  exist
} from './type'

export function calHeight (node) {
  const parent = node.parentNode || document.body
  node = node.cloneNode(true)
  node.style.display = 'block'
  node.style.opacity = 0
  node.style.height = 'auto'
  parent.appendChild(node)
  const height = node.offsetHeight
  parent.removeChild(node)
  return height
}

export function remove (node) {
  if (node.parentNode) {
    node.parentNode.removeChild(node)
  }
}

export function dataset (node, key, value) {
  if (exist(value)) {
    node.setAttribute('data-' + key, value)
  } else {
    return node.getAttribute('data-' + key)
  }
}

export const addEventListener = (node, type, callback) => {
  if (node.addEventListener) {
    node.addEventListener(type, callback, false)
  } else if (node.attachEvent) {
    node.attachEvent('on' + type, callback)
  }
}
export const on = addEventListener

export const removeEventListener = (node, type, callback) => {
  if (node.removeEventListener) {
    node.removeEventListener(type, callback, false)
  } else if (node.detachEvent) {
    node.detachEvent('on' + type, callback)
  }
}
export const off = removeEventListener

export function target (event) {
  return event.target || event.srcElement
}

export function createIframe (options) {
  options = options || {}
  var iframe = document.createElement('iframe')
  iframe.frameBorder = 0
  if (options.name) {
    iframe.name = options.name
  }
  if (!options.visible) {
    iframe.style.display = 'none'
  }
  if (isFunction(options.onload)) {
    var onIframeLoad = function (event) {
      if (!iframe.src) {
        return
      }
      if (!options.multi) {
        off(iframe, 'load', onIframeLoad)
      }
      options.onload(event)
    }
    on(iframe, 'load', onIframeLoad)
  }
    // will trigger onload
  var parent = options.parent;
  (parent || document.body).appendChild(iframe)
    // ensure trigger onload async
  var src = options.src || 'about:blank'
  setTimeout(() => {
    iframe.src = src
  }, 0)
  return iframe
}

export function html2node (html) {
  const div = window.document.createElement('div')
  div.innerHTML = html
  const children = []
  let i
  let l
  if (div.children) {
    for (i = 0, l = div.children.length; i < l; i++) {
      children.push(div.children[i])
    }
  } else {
    for (i = 0, l = div.childNodes.length; i < l; i++) {
      var child = div.childNodes[i]
      if (child.nodeType === 1) {
        children.push(child)
      }
    }
  }
  return children.length > 1 ? div : children[0]
}
<|endoftext|>


<commit_before>import {
    getFieldType,
    DATE_TIME,
    STRING,
    STRING_LIKE,
    NUMBER,
    BOOLEAN,
    LOCATION,
    COORDINATE,
    foreignKeyCountsByOriginTable
} from 'metabase/lib/schema_metadata';

import { TYPE } from "metabase/lib/types";

describe('schema_metadata', () => {
    describe('getFieldType', () => {
        it('should know a date', () => {
            expect(getFieldType({ base_type: TYPE.Date })).toEqual(DATE_TIME)
            expect(getFieldType({ base_type: TYPE.DateTime })).toEqual(DATE_TIME)
            expect(getFieldType({ base_type: TYPE.Time })).toEqual(DATE_TIME)
            expect(getFieldType({ special_type: TYPE.UNIXTimestampSeconds })).toEqual(DATE_TIME)
            expect(getFieldType({ special_type: TYPE.UNIXTimestampMilliseconds })).toEqual(DATE_TIME)
        });
        it('should know a number', () => {
            expect(getFieldType({ base_type: TYPE.BigInteger })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Integer })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Float })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Decimal })).toEqual(NUMBER)
        });
        it('should know a string', () => {
            expect(getFieldType({ base_type: TYPE.Text })).toEqual(STRING)
        });
        it('should know a bool', () => {
            expect(getFieldType({ base_type: TYPE.Boolean })).toEqual(BOOLEAN)
        });
        it('should know a location', () => {
            expect(getFieldType({ special_type: TYPE.City })).toEqual(LOCATION)
            expect(getFieldType({ special_type: TYPE.Country })).toEqual(LOCATION)
        });
        it('should know a coordinate', () => {
            expect(getFieldType({ special_type: TYPE.Latitude })).toEqual(COORDINATE)
            expect(getFieldType({ special_type: TYPE.Longitude })).toEqual(COORDINATE)
        });
        it('should know something that is string-like', () => {
            expect(getFieldType({ base_type: TYPE.StringLike })).toEqual(STRING_LIKE);
            expect(getFieldType({ base_type: TYPE.IPAddress })).toEqual(STRING_LIKE);
        });
        it('should know what it doesn\'t know', () => {
            expect(getFieldType({ base_type: 'DERP DERP DERP' })).toEqual(undefined)
        });
    });

    describe('foreignKeyCountsByOriginTable', () => {
        it('should work with null input', () => {
            expect(foreignKeyCountsByOriginTable(null)).toEqual(null)
        });
        it('should require an array as input', () => {
            expect(foreignKeyCountsByOriginTable({})).toEqual(null)
        });
        it('should count occurrences by origin.table.id', () => {
            expect(foreignKeyCountsByOriginTable([{ origin: {table: {id: 123}} }, { origin: {table: {id: 123}} }, { origin: {table: {id: 123}} }, { origin: {table: {id: 456}} }])).toEqual({123: 3, 456: 1})
        });
    });
});
<commit_msg>Test fix :wrench:<commit_after>import {
    getFieldType,
    DATE_TIME,
    STRING,
    STRING_LIKE,
    NUMBER,
    BOOLEAN,
    LOCATION,
    COORDINATE,
    foreignKeyCountsByOriginTable
} from 'metabase/lib/schema_metadata';

import { TYPE } from "metabase/lib/types";

describe('schema_metadata', () => {
    describe('getFieldType', () => {
        it('should know a date', () => {
            expect(getFieldType({ base_type: TYPE.Date })).toEqual(DATE_TIME)
            expect(getFieldType({ base_type: TYPE.DateTime })).toEqual(DATE_TIME)
            expect(getFieldType({ base_type: TYPE.Time })).toEqual(DATE_TIME)
            expect(getFieldType({ special_type: TYPE.UNIXTimestampSeconds })).toEqual(DATE_TIME)
            expect(getFieldType({ special_type: TYPE.UNIXTimestampMilliseconds })).toEqual(DATE_TIME)
        });
        it('should know a number', () => {
            expect(getFieldType({ base_type: TYPE.BigInteger })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Integer })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Float })).toEqual(NUMBER)
            expect(getFieldType({ base_type: TYPE.Decimal })).toEqual(NUMBER)
        });
        it('should know a string', () => {
            expect(getFieldType({ base_type: TYPE.Text })).toEqual(STRING)
        });
        it('should know a bool', () => {
            expect(getFieldType({ base_type: TYPE.Boolean })).toEqual(BOOLEAN)
        });
        it('should know a location', () => {
            expect(getFieldType({ special_type: TYPE.City })).toEqual(LOCATION)
            expect(getFieldType({ special_type: TYPE.Country })).toEqual(LOCATION)
        });
        it('should know a coordinate', () => {
            expect(getFieldType({ special_type: TYPE.Latitude })).toEqual(COORDINATE)
            expect(getFieldType({ special_type: TYPE.Longitude })).toEqual(COORDINATE)
        });
        it('should know something that is string-like', () => {
            expect(getFieldType({ base_type: TYPE.TextLike })).toEqual(STRING_LIKE);
            expect(getFieldType({ base_type: TYPE.IPAddress })).toEqual(STRING_LIKE);
        });
        it('should know what it doesn\'t know', () => {
            expect(getFieldType({ base_type: 'DERP DERP DERP' })).toEqual(undefined)
        });
    });

    describe('foreignKeyCountsByOriginTable', () => {
        it('should work with null input', () => {
            expect(foreignKeyCountsByOriginTable(null)).toEqual(null)
        });
        it('should require an array as input', () => {
            expect(foreignKeyCountsByOriginTable({})).toEqual(null)
        });
        it('should count occurrences by origin.table.id', () => {
            expect(foreignKeyCountsByOriginTable([{ origin: {table: {id: 123}} }, { origin: {table: {id: 123}} }, { origin: {table: {id: 123}} }, { origin: {table: {id: 456}} }])).toEqual({123: 3, 456: 1})
        });
    });
});
<|endoftext|>


<commit_before>(function(){
    /**
     * ONES前端缓存对象，用于当前页面生命周期中的数据缓存及持久化缓存。
     * 使用ones.caches._cachesData对象，localStorage和sessionStorage三种方式存储
     * */
    ones.caches = {
        /**
         * @params k
         * @params v
         * @params persistence default:undefined
         *  可接受：-1: 使用ones.caches.cacheData 刷新/关闭清除
         *         1  使用localStorage
         *         0 使用sessionStorage 当前页面生命周期，关闭页面清除
         * @param toJson 是否存储为JSON字符串，用于对象存储
         * */
        setItem: function(k, v, persistence, toJson) {

            if(angular.isObject(v)) {
                toJson = true;
            }

            if(undefined == persistence) {
                persistence = -1;
            }

            switch(persistence) {
                case -1:
                    ones.caches._cachesData[k] = v;
                    break;
                case 1:
                    if(toJson) {
                        v = angular.toJson(v);
                    }
                    console.log(v);
                    localStorage.setItem(k, v);
                    break;
                case 0:
                    if(toJson) {
                        v = angular.toJson(v);
                    }
                    sessionStorage.setItem(k, v);
                    break;
            }
            return v;
        },
        getItem: function(k) {
            var v = ones.caches._cachesData[k];

            if(undefined == v) {
                v = sessionStorage.getItem(k);
            }

            if(null == v) {
                v = localStorage.getItem(k);
            }

            try {
                v = angular.fromJson(v);
            } catch(e) {}

            return null === v ? false : v;

        },
        clear: function(persistence) {
            ones.caches._cachesData = {};
            localStorage.clear();
            sessionStorage.clear();
        },
        _cachesData: {}
    };

})(ones);<commit_msg>ones.caches.clear() 方法加入分级别清除缓存<commit_after>(function(){
    /**
     * ONES前端缓存对象，用于当前页面生命周期中的数据缓存及持久化缓存。
     * 使用ones.caches._cachesData对象，localStorage和sessionStorage三种方式存储
     * */
    ones.caches = {
        /**
         * @params k
         * @params v
         * @params persistence default:undefined
         *  可接受：-1: 使用ones.caches.cacheData 刷新/关闭清除
         *         1  使用localStorage
         *         0 使用sessionStorage 当前页面生命周期，关闭页面清除
         * @param toJson 是否存储为JSON字符串，用于对象存储
         * */
        setItem: function(k, v, persistence, toJson) {

            if(angular.isObject(v) || angular.isArray(v)) {
                toJson = true;
            }

            if(undefined == persistence) {
                persistence = -1;
            }

            switch(persistence) {
                case -1:
                    ones.caches._cachesData[k] = v;
                    break;
                case 1:
                    if(toJson) {
                        v = angular.toJson(v);
                    }
                    localStorage.setItem(k, v);
                    break;
                case 0:
                    if(toJson) {
                        v = angular.toJson(v);
                    }
                    sessionStorage.setItem(k, v);
                    break;
            }
            return v;
        },
        getItem: function(k) {
            var v = ones.caches._cachesData[k];

            if(undefined == v) {
                v = sessionStorage.getItem(k);
            }

            if(null == v) {
                v = localStorage.getItem(k);
            }

            try {
                v = angular.fromJson(v);
            } catch(e) {}

            return v;

        },
        clear: function(level) {
            switch(level) {
                case -1:
                    ones.caches._cachesData = {};
                    break;
                case 0:
                    sessionStorage.clear();
                    break;
                case 1:
                    localStorage.clear();
                    break;
                default:
                    localStorage.clear();
                    sessionStorage.clear();
                    ones.caches._cachesData = {};
            }
        },
        _cachesData: {}
    };

})(ones);<|endoftext|>