<commit_before>(function($){
    /**
     * The OpenCms select-box jQuery plugin.
     *
     * Takes a classic select-box and replaces it with a styled version.
     *
     * Use following options:
     * open: function(elem) called when select-box is opened
     * select: function(this, elem, value) called when a value is selected
     *
     * The following methods can be called by $(selector).selectbox('method name', additionalValue):
     * 'getValue': returns the currently selected value
     * 'getIndex': returns the currently selected index
     * 'setValue': sets the value to additionalValue
     *
     * The following styles are necessary:
     *
     *
     *
     *
     * @param {Object} options the options object or the method string
     * @param {Object} additional the additional value object
     */
$.fn.selectBox=function(options, additional){
		var self=this;
        var opts;
        if (typeof options == 'string' && options.indexOf('_')!=0){
            return eval(options+'(additional)');
        }

		opts=$.extend({}, $.fn.selectBox.defaults, options);
		_init();
		return self;

        function _init(){
			self.each(function(){

				var replacer=_generateReplacer(_getValues($(this)));
                replacer.insertBefore(this);
            }).hide();
			$(document.body).click(_close);
		}

		function _start(){
            var $this=$(this);
            $this.toggleClass('cms-open');
            if ($this.hasClass('cms-open')) {
                if (opts.appendTo){
                    var selectbox=$this.data('selectbox');
                    var offset=$this.offset();
                    if (($.isFunction(opts.selectorPosition) && opts.selectorPosition() == 'top') || opts.selectorPosition == 'top'){
                        offset.top-=21 * selectbox.valueCount;
                        selectbox.selector.removeClass('ui-corner-bottom').addClass('ui-corner-top')
                    }else{
                        offset.top+=20;
                    }
                    selectbox.selector.offset(offset).css('display', 'block');
                }
                if ($.isFunction(opts.open)) {
                    opts.open(this);
                }
            }else{
                _close();
            }
            return false;
        }

		function _close(){
           $('div.cms-selectbox').removeClass('cms-open');
           if (opts.appendTo) {
               $('div.cms-selector').css('display', 'none');
           }
        }

		function _select($this, selectbox){
            var valueOptions=selectbox.selector.find('.cms-select-option');
            var index = valueOptions.index($this);
            var value=$this.attr('rel');
            selectbox.replacer.find('span.cms-current-value').html($this.html()).attr('rel',value);
            _close();
            if ($.isFunction(opts.select)){
                opts.select($this.get(0), selectbox.replacer, value, index);
            }
            return false;
        }

        function _getValues(select){
            result=[];
            select.find('option').each(function(){
                result.push({value: $(this).val(), title: $(this).text()});
            });
            return result;
        }

        function _getValue(selectbox){
            return selectbox.replacer.find('span.cms-current-value').attr('rel');
        }

        function _getIndex(selectbox){
            if (selectbox!=null) {
                var valueOptions=$('.cms-select-option', selectbox.selector);
                var currentValue=valueOptions.filter('.cms-select-option[rel="'+_getValue(selectbox)+'"]');
                return valueOptions.index(currentValue);
            }
            return -1;
        }

        function _generateReplacer(values){
            var selectbox={};
            selectbox.replacer=$('

')
			$('').appendTo(selectbox.replacer).text(values[0].title).attr('rel', values[0].value);
			selectbox.selector=_generateSelector(selectbox, values);
            if (!opts.appendTo) {
                selectbox.selector.appendTo(selectbox.replacer);
                if (($.isFunction(opts.selectorPosition) && opts.selectorPosition() == 'top') || opts.selectorPosition == 'top') {
                    var top = 21 * values.length;
                    selectbox.selector.removeClass('ui-corner-bottom').addClass('ui-corner-top').css('top', '-' + top + 'px')
                }
            }else{
                var selectorParent= $(opts.appendTo);
                if (!selectorParent.length){
                    selectorParent=$(document.body);
                }
                selectbox.selector.appendTo(selectorParent)
            }
			selectbox.replacer.click(_start);
            $('span.cms-select-option', selectbox.replacer).andSelf().hover(function(){$(this).addClass('ui-state-hover');}, function(){$(this).removeClass('ui-state-hover')});

            selectbox.valueCount= values.length;
            selectbox.values=values;
            selectbox.replacer.data('selectbox', selectbox);
            if (opts.width){
                selectbox.replacer.width(opts.width);
                selectbox.selector.width(opts.width);
            }
            return selectbox.replacer;
        }

        function _generateSelector(selectbox, values){
            var selector=$('

');
			for (i=0; i<values.length; i++){
				$('', {
                    'class': "cms-select-option",
                    'rel': values[i].value,
                    'html': values[i].title,
                    'click': function(){
                        _select($(this), selectbox);
                    }
                }).appendTo(selector);
            }
            return selector;
        }

        function generate(options){
            opts=$.extend({}, $.fn.selectBox.defaults, options);
            if ($.isArray(opts.values)){
                return _generateReplacer(opts.values);
            }
        }

        function getValue(){
            return _getValue(self.data('selectbox'));
        }

        function getIndex(){
            return _getIndex(self.data('selectbox'));
        }

        function setValue(value){
            var selectbox=self.data('selectbox');
            selectSpan=selectbox.selector.find('span[rel="'+value+'"]:first');
            if (selectSpan.length) {
                selectbox.replacer.find('span.cms-current-value').html(selectSpan.html()).attr('rel', value);
            };
        }
	};

	$.fn.selectBox.defaults={
        width: null,
		open: null,
        select: null,
        appendTo: null

	}
})(jQuery);<commit_msg>Added 'setEnabled' function.<commit_after>(function($){
    /**
     * The OpenCms select-box jQuery plugin.
     *
     * Takes a classic select-box and replaces it with a styled version.
     *
     * Use following options:
     * open: function(elem) called when select-box is opened
     * select: function(this, elem, value) called when a value is selected
     *
     * The following methods can be called by $(selector).selectbox('method name', additionalValue):
     * 'getValue': returns the currently selected value
     * 'getIndex': returns the currently selected index
     * 'setValue': sets the value to additionalValue
     *
     * The following styles are necessary:
     *
     *
     *
     *
     * @param {Object} options the options object or the method string
     * @param {Object} additional the additional value object
     */
$.fn.selectBox=function(options, additional){
		var self=this;
        var opts={};
        if (typeof options == 'string' && options.indexOf('_')!=0){
            return eval(options+'(additional)');
        }

		opts=$.extend({}, $.fn.selectBox.defaults, options);
		_init();
		return self;

        function _init(){
			self.each(function(){

				var replacer=_generateReplacer(_getValues($(this)));
                replacer.insertBefore(this);
            }).hide();
			$(document.body).click(_close);
		}

		function _start(){
            var $this=$(this);
            var selectbox=$this.data('selectbox');
            $this.toggleClass('cms-open');
            if ($this.hasClass('cms-open')) {
                if (selectbox.opts.appendTo){

                    var offset=$this.offset();
                    if (($.isFunction(selectbox.opts.selectorPosition) && selectbox.opts.selectorPosition() == 'top') || selectbox.opts.selectorPosition == 'top'){
                        offset.top-=21 * selectbox.valueCount;
                        selectbox.selector.removeClass('ui-corner-bottom').addClass('ui-corner-top')
                    }else{
                        offset.top+=20;
                    }
                    selectbox.selector.offset(offset).css('display', 'block');
                }
                if ($.isFunction(selectbox.opts.open)) {
                    selectbox.opts.open(this);
                }
            }else{
                _close();
            }
            return false;
        }

		function _close(){
           $('div.cms-selectbox').removeClass('cms-open');
           if (opts.appendTo) {
               $('div.cms-selector').css('display', 'none');
           }
        }

		function _select($this, selectbox){
            var valueOptions=selectbox.selector.find('.cms-select-option');
            var index = valueOptions.index($this);
            var value=$this.attr('rel');
            selectbox.replacer.find('span.cms-current-value').html($this.html()).attr('rel',value);
            _close();
            if ($.isFunction(selectbox.opts.select)){
                selectbox.opts.select($this.get(0), selectbox.replacer, value, index);
            }
            return false;
        }

        function _getValues(select){
            result=[];
            select.find('option').each(function(){
                result.push({value: $(this).val(), title: $(this).text()});
            });
            return result;
        }

        function _getValue(selectbox){
            return selectbox.replacer.find('span.cms-current-value').attr('rel');
        }

        function _getIndex(selectbox){
            if (selectbox!=null) {
                var valueOptions=$('.cms-select-option', selectbox.selector);
                var currentValue=valueOptions.filter('.cms-select-option[rel="'+_getValue(selectbox)+'"]');
                return valueOptions.index(currentValue);
            }
            return -1;
        }

        function _generateReplacer(values){
            var selectbox={};
            selectbox.replacer=$('

')
			$('').appendTo(selectbox.replacer).text(values[0].title).attr('rel', values[0].value);
			selectbox.selector=_generateSelector(selectbox, values);
            if (!opts.appendTo) {
                selectbox.selector.appendTo(selectbox.replacer);
                if (($.isFunction(opts.selectorPosition) && opts.selectorPosition() == 'top') || opts.selectorPosition == 'top') {
                    var top = 21 * values.length;
                    selectbox.selector.removeClass('ui-corner-bottom').addClass('ui-corner-top').css('top', '-' + top + 'px')
                }
            }else{
                var selectorParent= $(opts.appendTo);
                if (!selectorParent.length){
                    selectorParent=$(document.body);
                }
                selectbox.selector.appendTo(selectorParent)
            }
			selectbox.replacer.click(_start);
            $('span.cms-select-option', selectbox.replacer).andSelf().hover(function(){$(this).addClass('ui-state-hover');}, function(){$(this).removeClass('ui-state-hover')});

            selectbox.valueCount= values.length;
            selectbox.values=values;
            selectbox.opts=opts;
            selectbox.replacer.data('selectbox', selectbox);
            if (opts.width){
                selectbox.replacer.width(opts.width);
                selectbox.selector.width(opts.width);
            }
            return selectbox.replacer;
        }

        function _generateSelector(selectbox, values){
            var selector=$('

');
			for (i=0; i<values.length; i++){
				$('', {
                    'class': "cms-select-option",
                    'rel': values[i].value,
                    'html': values[i].title,
                    'click': function(){
                        _select($(this), selectbox);
                    }
                }).appendTo(selector);
            }
            return selector;
        }

        function generate(options){
            opts=$.extend({}, $.fn.selectBox.defaults, options);
            if ($.isArray(opts.values)){
                return _generateReplacer(opts.values);
            }
        }

        function getValue(){
            return _getValue(self.data('selectbox'));
        }

        function getIndex(){
            return _getIndex(self.data('selectbox'));
        }

        function setValue(value){
            var selectbox=self.data('selectbox');
            selectSpan=selectbox.selector.find('span[rel="'+value+'"]:first');
            if (selectSpan.length) {
                selectbox.replacer.find('span.cms-current-value').html(selectSpan.html()).attr('rel', value);
            };
        }

        function setEnabled(enable){
            var selectbox=self.data('selectbox');
            if (enable){
                selectbox.replacer.removeClass('cms-selectbox-disabled');
                selectbox.replacer.unbind('click');
                selectbox.replacer.click(_start);
            }else{
                _close();
                selectbox.replacer.addClass('cms-selectbox-disabled');
                selectbox.replacer.unbind('click');
            }
        }
	};

	$.fn.selectBox.defaults={
        width: null,
		open: null,
        select: null,
        appendTo: null

	}
})(jQuery);<|endoftext|>


<commit_before>/*
Copyright 2020 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.
*/

// app.yaml standard reference: https://cloud.google.com/appengine/docs/standard/nodejs/config/appref
// app.yaml flex reference: https://cloud.google.com/appengine/docs/flexible/nodejs/reference/app-yaml
// service.yaml reference: https://github.com/knative/docs/blob/master/docs/serving/spec/knative-api-specification-1.0.md

/**
 * @param {Object} gaeService - Information about the App Engine service, should at minimum contain {"app.yaml" : {}}
 */
function appToRun(gaeService) {
  let runService = {
    'service.yaml': {
      'apiVersion': 'serving.knative.dev/v1',
      'kind': 'Service',
      'metadata': {
        'name' : 'default',
        'labels': {
          'migrated-from': 'app-engine'
        }
      },
      'spec': {
        'template': {
          'metadata': {
              'annotations': {
                'run.googleapis.com/cpu-throttling': 'false'
              }
          },
          'spec': {
            'containers': [
              {
                'image': 'gcr.io/<YOUR-PROJECT>/image'
              }
            ]
          }
        }
      }
    }
  };

  const extractFunctions = [
    extractServiceAccount,
    extractRegion,
    extractName,
    extractImageURL,
    extractEnvVars,
    extractProjectIDEnvVar,
    extractMaxInstances,
    extractMinInstances,
    extractConcurrency,
    extractMemory,
    extractCPU,
    extractMigrateToSecondGen,
    extractVPCAccess,
    extractCloudSQL,
    extractBuild,
    extractStatic,
    extractAllowUnauthenticated,
    extractEntrypoint,
    extractMigrateOffAppEngineAPIs,
  ]

  for (const extractFunction of extractFunctions) {
    extractFunction(gaeService, runService);
  }

  return runService;
}

const firstGenRuntimes = ['go111', 'python', 'python27', 'php55'];

const firstGenMigrationGuides = {
'go111': 'https://cloud.google.com/appengine/docs/standard/go/go-differences',
'python27': 'https://cloud.google.com/appengine/docs/standard/python/migrate-to-python3',
'python': 'https://cloud.google.com/appengine/docs/standard/python/migrate-to-python3',
'php55': 'https://cloud.google.com/appengine/docs/standard/php7/php-differences',
// (Java does not use an app.yaml): 'https://cloud.google.com/appengine/docs/standard/java11/java-differences',
}

function gaeRegionToGCPRegion(region) {
  if(region === 'us-central') { return 'us-central1'; }
  if(region === 'europe-west') { return 'europe-west1'; }
  return region;
}

function getProject(gae) {
    return gae['project-id'] || '<YOUR-PROJECT>';
}

function extractServiceAccount(gae, run) {
  // App Engine uses the App Engine default service account, while Cloud Run uses the Compute Engine default service account
  run['service.yaml']['spec']['template']['spec']['serviceAccountName'] = `${getProject(gae)}@appspot.gserviceaccount.com`
}

function extractRegion(gae, run) {
  run['region'] = gaeRegionToGCPRegion(gae['region']) || 'us-central1';

  if(!run['service.yaml']['metadata']['labels']) {
    run['service.yaml']['metadata']['labels'] = {};
  }

  run['service.yaml']['metadata']['labels']['cloud.googleapis.com/location'] = run['region'];
}

function extractName(gae, run) {
  if(gae['app.yaml']['service']) {
    run['service.yaml']['metadata']['name'] = gae['app.yaml']['service'];
   }
}

function extractEnvVars(gae, run) {
  if(gae['app.yaml']['env_variables']) {
    const container = run['service.yaml']['spec']['template']['spec']['containers'][0];
    container['env'] = container['env'] || [];
    for (const key of Object.keys(gae['app.yaml']['env_variables'])) {
      container['env'].push({
        'name': key,
        'value': gae['app.yaml']['env_variables'][key]
      })
    }
   }
}

function extractProjectIDEnvVar(gae, run) {
  if(gae['project-id']) {
    const container = run['service.yaml']['spec']['template']['spec']['containers'][0];
    container['env'] = container['env'] || [];
    container['env'].push({
      'name': 'GOOGLE_CLOUD_PROJECT',
      'value': gae['project-id']
    })
   }
}

function extractMaxInstances(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['max_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/maxScale'] = gae['app.yaml']['automatic_scaling']['max_instances'].toString();
  }
  if(gae['app.yaml']['automatic_scaling']?.['max_num_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/maxScale'] = gae['app.yaml']['automatic_scaling']['max_num_instances'].toString();
  }
}

function extractMinInstances(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['min_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/minScale'] = gae['app.yaml']['automatic_scaling']['min_instances'].toString();
  }
  if(gae['app.yaml']['automatic_scaling']?.['min_num_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/minScale'] = gae['app.yaml']['automatic_scaling']['min_num_instances'].toString();
  }
}

function extractConcurrency(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['max_concurrent_requests']) {
    run['service.yaml']['spec']['template']['spec']['containerConcurrency'] = gae['app.yaml']['automatic_scaling']['max_concurrent_requests'];
  }
}

function extractMemory(gae, run) {
  // see https://cloud.google.com/appengine/docs/standard/#instance_classes

  const instanceClassMemory = {
    'F1': '256Mi',
    'F2': '512Mi',
    'F4': '1Gi',
    'F4_HIGHMEM': '2Gi',
    'F4_1G': '2Gi',
  }

  function flexMemory(memory) {
    // Cloud Run max memory is 2GiB
    return Math.min(memory, 2);
  }

  const container = run['service.yaml']['spec']['template']['spec']['containers'][0];

  if(gae['app.yaml']['instance_class']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['memory'] = instanceClassMemory[gae['app.yaml']['instance_class']];
   }

  if(gae['app.yaml']['resources']?.['memory_gb']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['memory'] = flexMemory(gae['app.yaml']['resources']['memory_gb']) + 'Gi';
  }
}

function extractCPU(gae, run) {
  // see https://cloud.google.com/appengine/docs/standard/#instance_classes

  const instanceClassCPU = {
    'F1': '1',
    'F2': '1',
    'F4': '2',
    'F4_HIGHMEM': '2',
    'F4_1G': '2',
  }

  function flexCPU(cpu) {
    // Flex cpu is an integer.
    // Cloud Run max CPU is 2
    return Math.min(cpu, 2);
  }

  const container = run['service.yaml']['spec']['template']['spec']['containers'][0];

  if(gae['app.yaml']['instance_class']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['cpu'] = instanceClassCPU[gae['app.yaml']['instance_class']];
   }

   if(gae['app.yaml']['resources']?.['cpu']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['cpu'] = flexCPU(gae['app.yaml']['resources']['cpu']);
  }
}

function extractMigrateToSecondGen(gae, run) {
  const runtime = gae['app.yaml']['runtime'];
  // "api_version" was deprecated for second gen runtimes
  if(gae['app.yaml']['api_version'] || firstGenRuntimes.includes(runtime)) {
    run['migrate_to_second_gen'] = true;
    if(!run.warnings) {
      run.warnings = [];
    }

    let warning = {message: 'You are using a first generation App Engine runtime, please migrate to a second generation App Engine runtime before migrating to Cloud Run.'};
    if(firstGenMigrationGuides[runtime]) {
      warning.link = {
        'href': firstGenMigrationGuides[runtime],
        'text': 'Migration guide',
      }
    }
    run.warnings.push(warning);
  }
}

function extractMigrateOffAppEngineAPIs(gae, run) {
  if(gae['app.yaml']['app_engine_apis']) {
    run.migrate_off_app_engine_apis = true;
    if(!run.warnings) {
      run.warnings = [];
    }

    run.warnings.push({message: 'The "app_engine_apis" attribute in your app.yaml means that your code might depend on APIs that are only available on App Engine, please migrate your code to use Google Cloud client libraries and remove the "app_engine_apis" attribute from your app.yaml'});
  }
}

function extractBuild(gae, run) {
  run['gcloud'] = `gcloud builds submit --pack image=${run['service.yaml']['spec']['template']['spec']['containers'][0]['image']} && gcloud beta run services replace service.yaml --region ${run['region']}`;
}

function extractStatic(gae, run) {
  let useStatic = false;
  if(gae['app.yaml']['handlers']) {
    for( const handler of gae['app.yaml']['handlers']) {
      if(handler.static_dir || handler.static_files) {
        useStatic = true;
      }
    }
  }

  if(useStatic) {
    if(!run['warnings']) {
      run['warnings'] = [];
    }

    run['warnings'].push({
      'message': 'You are using App Engine static file handlers. Cloud Run does not provide support for static file serving. We recommend you to serve your static files from your code.',
    })
  }
}

function extractVPCAccess(gae, run){
  if(gae['app.yaml']['vpc_access_connector']?.['name']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['run.googleapis.com/vpc-access-connector'] = gae['app.yaml']['vpc_access_connector']['name'];
  }
}

function extractCloudSQL(gae, run) {
  if(gae['cloudsql-instance']) {
    // Capture instance explicitely as annotation
    run['service.yaml']['spec']['template']['metadata']['annotations']['run.googleapis.com/cloudsql-instances'] = [gae['project-id'], run['region'], gae['cloudsql-instance']].join(':');

    // Need to enable API
    let enableAPIHref = 'https://console.developers.google.com/apis/api/sqladmin.googleapis.com/overview';
    if(gae['project-id']) {
      enableAPIHref += '?project=' + gae['project-id'];
    }
    if(!run['warnings']) {
      run['warnings'] = [];
    }
    run['warnings'].push({
      'message': 'You must enable the Cloud SQL Admin API. ',
      'link': {
        'href': enableAPIHref,
        'text': 'Enable API',
      }
    });
  }

}

function extractImageURL(gae, run) {
  let imageName = gae['app.yaml']['service'] || 'image';

  run['service.yaml']['spec']['template']['spec']['containers'][0]['image'] = `gcr.io/${getProject(gae)}/${imageName}`;
}

function extractAllowUnauthenticated(gae, run) {
  run['make-public'] = `gcloud run services add-iam-policy-binding ${run['service.yaml']['metadata']['name']} --member="allUsers" --role="roles/run.invoker" --region ${run['service.yaml']['metadata']['labels']['cloud.googleapis.com/location']} --platform managed `;
}

function extractEntrypoint(gae, run) {
  let entrypoint = gae['app.yaml']['entrypoint'];

  if(entrypoint) {
    run['Procfile'] = `web: ${entrypoint}`;
  }
}

export {appToRun}
<commit_msg>Mark service as Beta to use Always on CPU<commit_after>/*
Copyright 2020 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.
*/

// app.yaml standard reference: https://cloud.google.com/appengine/docs/standard/nodejs/config/appref
// app.yaml flex reference: https://cloud.google.com/appengine/docs/flexible/nodejs/reference/app-yaml
// service.yaml reference: https://github.com/knative/docs/blob/master/docs/serving/spec/knative-api-specification-1.0.md

/**
 * @param {Object} gaeService - Information about the App Engine service, should at minimum contain {"app.yaml" : {}}
 */
// TODO: Remove "'run.googleapis.com/launch-stage': 'BETA'" when all use features are GA
function appToRun(gaeService) {
  let runService = {
    'service.yaml': {
      'apiVersion': 'serving.knative.dev/v1',
      'kind': 'Service',
      'metadata': {
        'name' : 'default',
        'labels': {
          'migrated-from': 'app-engine'
        },
        'annotations': {
          'run.googleapis.com/launch-stage': 'BETA'
        }
      },
      'spec': {
        'template': {
          'metadata': {
              'annotations': {
                'run.googleapis.com/cpu-throttling': 'false'
              }
          },
          'spec': {
            'containers': [
              {
                'image': 'gcr.io/<YOUR-PROJECT>/image'
              }
            ]
          }
        }
      }
    }
  };

  const extractFunctions = [
    extractServiceAccount,
    extractRegion,
    extractName,
    extractImageURL,
    extractEnvVars,
    extractProjectIDEnvVar,
    extractMaxInstances,
    extractMinInstances,
    extractConcurrency,
    extractMemory,
    extractCPU,
    extractMigrateToSecondGen,
    extractVPCAccess,
    extractCloudSQL,
    extractBuild,
    extractStatic,
    extractAllowUnauthenticated,
    extractEntrypoint,
    extractMigrateOffAppEngineAPIs,
  ]

  for (const extractFunction of extractFunctions) {
    extractFunction(gaeService, runService);
  }

  return runService;
}

const firstGenRuntimes = ['go111', 'python', 'python27', 'php55'];

const firstGenMigrationGuides = {
'go111': 'https://cloud.google.com/appengine/docs/standard/go/go-differences',
'python27': 'https://cloud.google.com/appengine/docs/standard/python/migrate-to-python3',
'python': 'https://cloud.google.com/appengine/docs/standard/python/migrate-to-python3',
'php55': 'https://cloud.google.com/appengine/docs/standard/php7/php-differences',
// (Java does not use an app.yaml): 'https://cloud.google.com/appengine/docs/standard/java11/java-differences',
}

function gaeRegionToGCPRegion(region) {
  if(region === 'us-central') { return 'us-central1'; }
  if(region === 'europe-west') { return 'europe-west1'; }
  return region;
}

function getProject(gae) {
    return gae['project-id'] || '<YOUR-PROJECT>';
}

function extractServiceAccount(gae, run) {
  // App Engine uses the App Engine default service account, while Cloud Run uses the Compute Engine default service account
  run['service.yaml']['spec']['template']['spec']['serviceAccountName'] = `${getProject(gae)}@appspot.gserviceaccount.com`
}

function extractRegion(gae, run) {
  run['region'] = gaeRegionToGCPRegion(gae['region']) || 'us-central1';

  if(!run['service.yaml']['metadata']['labels']) {
    run['service.yaml']['metadata']['labels'] = {};
  }

  run['service.yaml']['metadata']['labels']['cloud.googleapis.com/location'] = run['region'];
}

function extractName(gae, run) {
  if(gae['app.yaml']['service']) {
    run['service.yaml']['metadata']['name'] = gae['app.yaml']['service'];
   }
}

function extractEnvVars(gae, run) {
  if(gae['app.yaml']['env_variables']) {
    const container = run['service.yaml']['spec']['template']['spec']['containers'][0];
    container['env'] = container['env'] || [];
    for (const key of Object.keys(gae['app.yaml']['env_variables'])) {
      container['env'].push({
        'name': key,
        'value': gae['app.yaml']['env_variables'][key]
      })
    }
   }
}

function extractProjectIDEnvVar(gae, run) {
  if(gae['project-id']) {
    const container = run['service.yaml']['spec']['template']['spec']['containers'][0];
    container['env'] = container['env'] || [];
    container['env'].push({
      'name': 'GOOGLE_CLOUD_PROJECT',
      'value': gae['project-id']
    })
   }
}

function extractMaxInstances(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['max_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/maxScale'] = gae['app.yaml']['automatic_scaling']['max_instances'].toString();
  }
  if(gae['app.yaml']['automatic_scaling']?.['max_num_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/maxScale'] = gae['app.yaml']['automatic_scaling']['max_num_instances'].toString();
  }
}

function extractMinInstances(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['min_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/minScale'] = gae['app.yaml']['automatic_scaling']['min_instances'].toString();
  }
  if(gae['app.yaml']['automatic_scaling']?.['min_num_instances']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['autoscaling.knative.dev/minScale'] = gae['app.yaml']['automatic_scaling']['min_num_instances'].toString();
  }
}

function extractConcurrency(gae, run) {
  if(gae['app.yaml']['automatic_scaling']?.['max_concurrent_requests']) {
    run['service.yaml']['spec']['template']['spec']['containerConcurrency'] = gae['app.yaml']['automatic_scaling']['max_concurrent_requests'];
  }
}

function extractMemory(gae, run) {
  // see https://cloud.google.com/appengine/docs/standard/#instance_classes

  const instanceClassMemory = {
    'F1': '256Mi',
    'F2': '512Mi',
    'F4': '1Gi',
    'F4_HIGHMEM': '2Gi',
    'F4_1G': '2Gi',
  }

  function flexMemory(memory) {
    // Cloud Run max memory is 2GiB
    return Math.min(memory, 2);
  }

  const container = run['service.yaml']['spec']['template']['spec']['containers'][0];

  if(gae['app.yaml']['instance_class']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['memory'] = instanceClassMemory[gae['app.yaml']['instance_class']];
   }

  if(gae['app.yaml']['resources']?.['memory_gb']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['memory'] = flexMemory(gae['app.yaml']['resources']['memory_gb']) + 'Gi';
  }
}

function extractCPU(gae, run) {
  // see https://cloud.google.com/appengine/docs/standard/#instance_classes

  const instanceClassCPU = {
    'F1': '1',
    'F2': '1',
    'F4': '2',
    'F4_HIGHMEM': '2',
    'F4_1G': '2',
  }

  function flexCPU(cpu) {
    // Flex cpu is an integer.
    // Cloud Run max CPU is 2
    return Math.min(cpu, 2);
  }

  const container = run['service.yaml']['spec']['template']['spec']['containers'][0];

  if(gae['app.yaml']['instance_class']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['cpu'] = instanceClassCPU[gae['app.yaml']['instance_class']];
   }

   if(gae['app.yaml']['resources']?.['cpu']) {
    container['resources'] = container['resources'] || {'limits': {}};
    container['resources']['limits']['cpu'] = flexCPU(gae['app.yaml']['resources']['cpu']);
  }
}

function extractMigrateToSecondGen(gae, run) {
  const runtime = gae['app.yaml']['runtime'];
  // "api_version" was deprecated for second gen runtimes
  if(gae['app.yaml']['api_version'] || firstGenRuntimes.includes(runtime)) {
    run['migrate_to_second_gen'] = true;
    if(!run.warnings) {
      run.warnings = [];
    }

    let warning = {message: 'You are using a first generation App Engine runtime, please migrate to a second generation App Engine runtime before migrating to Cloud Run.'};
    if(firstGenMigrationGuides[runtime]) {
      warning.link = {
        'href': firstGenMigrationGuides[runtime],
        'text': 'Migration guide',
      }
    }
    run.warnings.push(warning);
  }
}

function extractMigrateOffAppEngineAPIs(gae, run) {
  if(gae['app.yaml']['app_engine_apis']) {
    run.migrate_off_app_engine_apis = true;
    if(!run.warnings) {
      run.warnings = [];
    }

    run.warnings.push({message: 'The "app_engine_apis" attribute in your app.yaml means that your code might depend on APIs that are only available on App Engine, please migrate your code to use Google Cloud client libraries and remove the "app_engine_apis" attribute from your app.yaml'});
  }
}

function extractBuild(gae, run) {
  run['gcloud'] = `gcloud builds submit --pack image=${run['service.yaml']['spec']['template']['spec']['containers'][0]['image']} && gcloud beta run services replace service.yaml --region ${run['region']}`;
}

function extractStatic(gae, run) {
  let useStatic = false;
  if(gae['app.yaml']['handlers']) {
    for( const handler of gae['app.yaml']['handlers']) {
      if(handler.static_dir || handler.static_files) {
        useStatic = true;
      }
    }
  }

  if(useStatic) {
    if(!run['warnings']) {
      run['warnings'] = [];
    }

    run['warnings'].push({
      'message': 'You are using App Engine static file handlers. Cloud Run does not provide support for static file serving. We recommend you to serve your static files from your code.',
    })
  }
}

function extractVPCAccess(gae, run){
  if(gae['app.yaml']['vpc_access_connector']?.['name']) {
    run['service.yaml']['spec']['template']['metadata']['annotations']['run.googleapis.com/vpc-access-connector'] = gae['app.yaml']['vpc_access_connector']['name'];
  }
}

function extractCloudSQL(gae, run) {
  if(gae['cloudsql-instance']) {
    // Capture instance explicitely as annotation
    run['service.yaml']['spec']['template']['metadata']['annotations']['run.googleapis.com/cloudsql-instances'] = [gae['project-id'], run['region'], gae['cloudsql-instance']].join(':');

    // Need to enable API
    let enableAPIHref = 'https://console.developers.google.com/apis/api/sqladmin.googleapis.com/overview';
    if(gae['project-id']) {
      enableAPIHref += '?project=' + gae['project-id'];
    }
    if(!run['warnings']) {
      run['warnings'] = [];
    }
    run['warnings'].push({
      'message': 'You must enable the Cloud SQL Admin API. ',
      'link': {
        'href': enableAPIHref,
        'text': 'Enable API',
      }
    });
  }

}

function extractImageURL(gae, run) {
  let imageName = gae['app.yaml']['service'] || 'image';

  run['service.yaml']['spec']['template']['spec']['containers'][0]['image'] = `gcr.io/${getProject(gae)}/${imageName}`;
}

function extractAllowUnauthenticated(gae, run) {
  run['make-public'] = `gcloud run services add-iam-policy-binding ${run['service.yaml']['metadata']['name']} --member="allUsers" --role="roles/run.invoker" --region ${run['service.yaml']['metadata']['labels']['cloud.googleapis.com/location']} --platform managed `;
}

function extractEntrypoint(gae, run) {
  let entrypoint = gae['app.yaml']['entrypoint'];

  if(entrypoint) {
    run['Procfile'] = `web: ${entrypoint}`;
  }
}

export {appToRun}
<|endoftext|>


<commit_before>'use strict';

angular.module('cms.controllers')
	.controller('mediaCtrl', ['genService', 'MenuService', '$routeParams', '$scope', '$log', '$timeout', '$route', function(genService, MenuService, $routeParams, $scope, $log, $timeout, $route) {
		// set menu according to its Name
		MenuService.update("Media");

		$scope.apiPath 	 = 'files';
		$scope.menuName  = 'Veranstaltung bearbeiten';
		$scope.deleteMsg = 'Löschen';

		// get all uploaded files
		$scope.loadingFiles = true;
		genService.getAllObjects('files').then(function(response) {
			if (response == null) {
				$scope.message = "Keine hochgeladenen Dateien";
				return;
			}

			$scope.files = response;

			$timeout(function () {
				$scope.loadingFiles = false;
			}, 300);
		});
	}])
	.controller('mediaAddCtrl', ['MenuService', '$routeParams', '$scope', '$log', '$upload', '$window', '$location', '$timeout', 'toaster', function(MenuService, $routeParams, $scope, $log, $upload, $window, $location, $timeout, toaster) {
		// set menu according to its Name
		MenuService.update("Media");
		$scope.percent = 0;

		// cancel this promise on route change
		var redirectTimeoutPromise;
		// allowed file extensions
		var allowedExts = new Array("jpg", "jpeg", "png", "gif", "tiff", "svg",
									"doc", "ppt", "docx", "pptx", "xls", "xlsx", "pages", "numbers", "keynote", "pdf", "pps", "ppsx", "odt", "txt",
									"mp3", "m4a", "ogg", "wav",
									"mp4", "m4v", "mkv", "mov", "wmv", "avi", "mpg", "ogv", "3gp", "3g2");

		$scope.onFileSelect = function($file) {
			//$files: an array of files selected, each file has name, size, and type.
			var file = $file[0]; // allow only one file a time
			if ($scope.debugModus) {
				$log.log(file);
			}

			// get alt name
			$scope.altDescription = file.name.replace(/[ \t\r\n\v\f]/g, ' ');

			// get file type
			var name = file.name.split('.');
			var fileType = name[name.length-1];

			if (!$scope.file.description) {
				toaster.pop('error', null, 'Die Dateibeschreibung muss angegeben werden');
				return;
			}

			// check if filetype is allowed
			if (allowedExts.indexOf(fileType) == -1) {
				toaster.pop('error', null, 'Der Dateityp "' + fileType + '" ist aus Sicherheitsgründen nicht erlaubt');
				return;
			}

			$scope.upload = $upload.upload({
				url: '/api/files', //upload.php script, node.js route, or servlet url
				method: 'POST',
				transformRequest: angular.identity, // Angular’s default transformRequest function will try to serialize our FormData object, so we override it with the identity function to leave the data intact.
				headers: {'Content-Type': undefined}, //Angular’s default Content-Type header for POST and PUT requests is application/json, so we want to change this, too. By setting ‘Content-Type’: undefined, the browser sets the Content-Type to multipart/form-data for us and fills in the correct boundary. Manually setting ‘Content-Type’: multipart/form-data will fail to fill in the boundary parameter of the request
				// withCredential: true,
				data: {
						description 		: $scope.file.description
					  },
				file: file,
				// file: $files, //upload multiple files, this feature only works in HTML5 FromData browsers
				/* set file formData name for 'Content-Desposition' header. Default: 'file' */
				//fileFormDataName: myFile, //OR for HTML5 multiple upload only a list: ['name1', 'name2', ...]
				/* customize how data is added to formData. See #40#issuecomment-28612000 for example */
				//formDataAppender: function(formData, key, val){}
			}).progress(function (evt) {
				if ($scope.debugModus) {
					$log.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total, 10));
				}
				var percent = parseInt(100.0 * evt.loaded/evt.total, 10);
				$scope.percent = percent;
				$window.document.getElementsByClassName("progress-bar-percentage")[0].style.width=percent+"%";
			}).success(function (data, status, headers, config) {
				// file has been uploaded successfully
				// Check errors which may happen on the server
				if ($scope.debugModus) {
					$log.log(data);
				}

				if (data !== "") {
					// error happend at file validation
					toaster.pop('error', 'Datei', data);
				} else {
					toaster.pop('success', null, 'Die Datei wurde erfolgreich hochgeladen');
					redirectTimeoutPromise = $timeout(function() {
						$location.path('/media');}, 1000);
				}
			})
			.error(function(data, status, headers, config) {
				$log.error("upload failed" + data);
				if (status === 409) {
					toaster.pop('error', null, 'Eine Datei mit dem gleichen Namen exisitiert bereits');
				} else {
					toaster.pop('error', null, 'Der Upload konnte nicht ausgeführt werden.');
				}
			});
		};

		// cancel redirect promises on route change
		$scope.$on('$locationChangeStart', function(){
		    $timeout.cancel(redirectTimeoutPromise);
		});

	}])<commit_msg>Remove unnecessary title statement in toaster<commit_after>'use strict';

angular.module('cms.controllers')
	.controller('mediaCtrl', ['genService', 'MenuService', '$routeParams', '$scope', '$log', '$timeout', '$route', function(genService, MenuService, $routeParams, $scope, $log, $timeout, $route) {
		// set menu according to its Name
		MenuService.update("Media");

		$scope.apiPath 	 = 'files';
		$scope.menuName  = 'Veranstaltung bearbeiten';
		$scope.deleteMsg = 'Löschen';

		// get all uploaded files
		$scope.loadingFiles = true;
		genService.getAllObjects('files').then(function(response) {
			if (response == null) {
				$scope.message = "Keine hochgeladenen Dateien";
				return;
			}

			$scope.files = response;

			$timeout(function () {
				$scope.loadingFiles = false;
			}, 300);
		});
	}])
	.controller('mediaAddCtrl', ['MenuService', '$routeParams', '$scope', '$log', '$upload', '$window', '$location', '$timeout', 'toaster', function(MenuService, $routeParams, $scope, $log, $upload, $window, $location, $timeout, toaster) {
		// set menu according to its Name
		MenuService.update("Media");
		$scope.percent = 0;

		// cancel this promise on route change
		var redirectTimeoutPromise;
		// allowed file extensions
		var allowedExts = new Array("jpg", "jpeg", "png", "gif", "tiff", "svg",
									"doc", "ppt", "docx", "pptx", "xls", "xlsx", "pages", "numbers", "keynote", "pdf", "pps", "ppsx", "odt", "txt",
									"mp3", "m4a", "ogg", "wav",
									"mp4", "m4v", "mkv", "mov", "wmv", "avi", "mpg", "ogv", "3gp", "3g2");

		$scope.onFileSelect = function($file) {
			//$files: an array of files selected, each file has name, size, and type.
			var file = $file[0]; // allow only one file a time
			if ($scope.debugModus) {
				$log.log(file);
			}

			// get alt name
			$scope.altDescription = file.name.replace(/[ \t\r\n\v\f]/g, ' ');

			// get file type
			var name = file.name.split('.');
			var fileType = name[name.length-1];

			if (!$scope.file.description) {
				toaster.pop('error', null, 'Die Dateibeschreibung muss angegeben werden');
				return;
			}

			// check if filetype is allowed
			if (allowedExts.indexOf(fileType) == -1) {
				toaster.pop('error', null, 'Der Dateityp "' + fileType + '" ist aus Sicherheitsgründen nicht erlaubt');
				return;
			}

			$scope.upload = $upload.upload({
				url: '/api/files', //upload.php script, node.js route, or servlet url
				method: 'POST',
				transformRequest: angular.identity, // Angular’s default transformRequest function will try to serialize our FormData object, so we override it with the identity function to leave the data intact.
				headers: {'Content-Type': undefined}, //Angular’s default Content-Type header for POST and PUT requests is application/json, so we want to change this, too. By setting ‘Content-Type’: undefined, the browser sets the Content-Type to multipart/form-data for us and fills in the correct boundary. Manually setting ‘Content-Type’: multipart/form-data will fail to fill in the boundary parameter of the request
				// withCredential: true,
				data: {
						description 		: $scope.file.description
					  },
				file: file,
				// file: $files, //upload multiple files, this feature only works in HTML5 FromData browsers
				/* set file formData name for 'Content-Desposition' header. Default: 'file' */
				//fileFormDataName: myFile, //OR for HTML5 multiple upload only a list: ['name1', 'name2', ...]
				/* customize how data is added to formData. See #40#issuecomment-28612000 for example */
				//formDataAppender: function(formData, key, val){}
			}).progress(function (evt) {
				if ($scope.debugModus) {
					$log.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total, 10));
				}
				var percent = parseInt(100.0 * evt.loaded/evt.total, 10);
				$scope.percent = percent;
				$window.document.getElementsByClassName("progress-bar-percentage")[0].style.width=percent+"%";
			}).success(function (data, status, headers, config) {
				// file has been uploaded successfully
				// Check errors which may happen on the server
				if ($scope.debugModus) {
					$log.log(data);
				}

				if (data !== "") {
					// error happend at file validation
					toaster.pop('error', null, data);
				} else {
					toaster.pop('success', null, 'Die Datei wurde erfolgreich hochgeladen');
					redirectTimeoutPromise = $timeout(function() {
						$location.path('/media');}, 1000);
				}
			})
			.error(function(data, status, headers, config) {
				$log.error("upload failed" + data);
				if (status === 409) {
					toaster.pop('error', null, 'Eine Datei mit dem gleichen Namen exisitiert bereits');
				} else {
					toaster.pop('error', null, 'Der Upload konnte nicht ausgeführt werden.');
				}
			});
		};

		// cancel redirect promises on route change
		$scope.$on('$locationChangeStart', function(){
		    $timeout.cancel(redirectTimeoutPromise);
		});

	}])<|endoftext|>


<commit_before>/*jsl:option explicit*/
/*jsl:import shake-util.js*/
"use strict";

// Data
//     {name :: String
//     ,values :: [Progress]
//     }
//
// Progress
//     {idealSecs :: Double
//     ,idealPerc :: Double
//     ,actualSecs :: Double
//     ,actualPerc :: Double
//     }

$(function(){
    $("#output").html("");
    for (var i = 0; i < shake.length; i++)
    {
        var raw = [];
        var raw2 = [];
        for (var j = 10; j < shake[i].values.length; j++)
        {
            raw.push([-shake[i].values[j].idealSecs, shake[i].values[j].actualSecs]);
            raw2.push([-shake[i].values[j].idealSecs, shake[i].values[j].idealSecs]);
        }
        var ys = [{label:shake[i].name, data:raw, color:"red"},{data:raw2, color:"blue"}];
        var div = $("
").width(300).height(200);
        $("#output").append(div);

        $.plot(div, ys, {width: 100, height: 100});
    }
})
<commit_msg>Only start the progress graphs from 5 seconds in<commit_after>/*jsl:option explicit*/
/*jsl:import shake-util.js*/
"use strict";

// Data
//     {name :: String
//     ,values :: [Progress]
//     }
//
// Progress
//     {idealSecs :: Double
//     ,idealPerc :: Double
//     ,actualSecs :: Double
//     ,actualPerc :: Double
//     }

$(function(){
    $("#output").html("");
    for (var i = 0; i < shake.length; i++)
    {
        var raw = [];
        var raw2 = [];
        for (var j = 5; j < shake[i].values.length; j++)
        {
            raw.push([-shake[i].values[j].idealSecs, shake[i].values[j].actualSecs]);
            raw2.push([-shake[i].values[j].idealSecs, shake[i].values[j].idealSecs]);
        }
        var ys = [{label:shake[i].name, data:raw, color:"red"},{data:raw2, color:"blue"}];
        var div = $("
").width(300).height(200);
        $("#output").append(div);

        $.plot(div, ys, {width: 100, height: 100});
    }
})
<|endoftext|>


<commit_before>define( [ 'dojo/_base/declare',
          'JBrowse/Store/SeqFeature',
          'JBrowse/Util',
          'JBrowse/Digest/Crc32'
        ],
        function( declare, SeqFeatureStore, Util, Crc32 ) {

var Feature = Util.fastDeclare({
    constructor: function(args) {
        this.start = args.start;
        this.end = args.end;
        this.seq = args.seq;
        this.seq_id = args.seq_id;
    },
    get: function( field ) {
        return this[field];
    },
    tags: function() {
        return ['seq_id','start','end','seq'];
    }
});

return declare( SeqFeatureStore,

/**
 * @lends JBrowse.Store.Sequence.StaticChunked
 * @extends JBrowse.Store.SeqFeature
 */
{

/**
 * Storage backend for sequences broken up into chunks, stored and
 * served as static text files.
 * @constructs
 */
    constructor: function(args) {
        this.chunkCache   = {};
        this.compress     = args.compress;
        this.urlTemplate  = args.urlTemplate;
        if( ! this.urlTemplate ) {
            throw "no urlTemplate provided, cannot open sequence store";
        }

        this.baseUrl      = args.baseUrl;
        this.seqChunkSize = args.seqChunkSize;
    },

    getFeatures: function( query, callback, endCallback ) {

        var start = query.start;
        var end   = query.end;
        var seqname    = query.ref;
        var chunkSize  = query.seqChunkSize || this.refSeq.name == query.ref && this.refSeq.seqChunkSize || this.seqChunkSize;
        var firstChunk = Math.floor( Math.max(0,start) / chunkSize );
        var lastChunk  = Math.floor( (end - 1)         / chunkSize );

        // if a callback spans more than one chunk, we need to wrap the
        // callback in another one that will be passed to each chunk to
        // concatenate the different pieces from each chunk and *then*
        // call the main callback
            callback = (function() {
                            var chunk_seqs = [],
                            chunks_still_needed = lastChunk-firstChunk+1,
                            orig_callback = callback;
                            return function( start, end, seq, chunkNum) {
                                chunk_seqs[chunkNum] = seq;
                                if( --chunks_still_needed == 0 ) {
                                    orig_callback( new Feature({seq_id: query.ref, start: start, end: end, seq: chunk_seqs.join("")}) );
                                    if( endCallback )
                                        endCallback();
                                }
                            };
                        })();

        var callbackInfo = { start: start, end: end, callback: callback };

        if( !this.chunkCache[seqname] ) {
            this.chunkCache[seqname] = [];
        }
        var chunkCacheForSeq = this.chunkCache[seqname];

        for (var i = firstChunk; i <= lastChunk; i++) {
            //console.log("working on chunk %d for %d .. %d", i, start, end);

            var chunk = chunkCacheForSeq[i];
            if (chunk) {
                if (chunk.loaded) {
                    callback( start,
                              end,
                              chunk.sequence.substring(
                                  start - i*chunkSize,
                                  end - i*chunkSize
                              ),
                              i
                            );
                } else {
                    //console.log("added callback for %d .. %d", start, end);
                    chunk.callbacks.push(callbackInfo);
                }
            } else {
                chunkCacheForSeq[i] = {
                    loaded: false,
                    num: i,
                    callbacks: [callbackInfo]
                };

                var sequrl = Util.resolveUrl(
                    this.baseUrl,
                    Util.fillTemplate(
                        this.urlTemplate,
                        {
                            'refseq': query.ref,
                            'refseq_dirpath': function() {
                                var hex = Crc32.crc32( query.ref )
                                               .toString(16)
                                               .toLowerCase()
                                               .replace('-','n');
                                // zero-pad the hex string to be 8 chars if necessary
                                while( hex.length < 8 )
                                    hex = '0'+hex;
                                var dirpath = [];
                                for( var i = 0; i < hex.length; i += 3 ) {
                                    dirpath.push( hex.substring( i, i+3 ) );
                                }
                                return dirpath.join('/');
                            }
                        })
                );

                dojo.xhrGet({
                                url: sequrl + i + ".txt" + ( this.compress ? 'z' : '' ),
                                load: dojo.hitch( this, function( chunkRecord, response ) {
                                    //console.log('response for chunk '+chunkRecord.num);
                                    chunkRecord.sequence = response;
                                    chunkRecord.loaded = true;
                                    dojo.forEach( chunkRecord.callbacks, function(ci) {
                                        ci.callback( ci.start,
                                                     ci.end,
                                                     response.substring( ci.start - chunkRecord.num*chunkSize,
                                                                         ci.end   - chunkRecord.num*chunkSize
                                                                       ),
                                                     i
                                                   );
                                    });
                                    delete chunkRecord.callbacks;

                                }, chunkCacheForSeq[i] )
                            });
            }
        }
    }
});
});<commit_msg>fix StaticChunked store error handling<commit_after>define( [ 'dojo/_base/declare',
          'JBrowse/Store/SeqFeature',
          'JBrowse/Util',
          'JBrowse/Digest/Crc32'
        ],
        function( declare, SeqFeatureStore, Util, Crc32 ) {

var Feature = Util.fastDeclare({
    constructor: function(args) {
        this.start = args.start;
        this.end = args.end;
        this.seq = args.seq;
        this.seq_id = args.seq_id;
    },
    get: function( field ) {
        return this[field];
    },
    tags: function() {
        return ['seq_id','start','end','seq'];
    }
});

return declare( SeqFeatureStore,

/**
 * @lends JBrowse.Store.Sequence.StaticChunked
 * @extends JBrowse.Store.SeqFeature
 */
{

/**
 * Storage backend for sequences broken up into chunks, stored and
 * served as static text files.
 * @constructs
 */
    constructor: function(args) {
        this.chunkCache   = {};
        this.compress     = args.compress;
        this.urlTemplate  = args.urlTemplate;
        if( ! this.urlTemplate ) {
            throw "no urlTemplate provided, cannot open sequence store";
        }

        this.baseUrl      = args.baseUrl;
        this.seqChunkSize = args.seqChunkSize;
    },

    getFeatures: function( query, callback, endCallback, errorCallback ) {

        var start = query.start;
        var end   = query.end;
        var seqname    = query.ref;
        var chunkSize  = query.seqChunkSize || this.refSeq.name == query.ref && this.refSeq.seqChunkSize || this.seqChunkSize;
        var firstChunk = Math.floor( Math.max(0,start) / chunkSize );
        var lastChunk  = Math.floor( (end - 1)         / chunkSize );

        // if a callback spans more than one chunk, we need to wrap the
        // callback in another one that will be passed to each chunk to
        // concatenate the different pieces from each chunk and *then*
        // call the main callback
            callback = (function() {
                            var chunk_seqs = [],
                            chunks_still_needed = lastChunk-firstChunk+1,
                            orig_callback = callback;
                            return function( start, end, seq, chunkNum) {
                                chunk_seqs[chunkNum] = seq;
                                if( --chunks_still_needed == 0 ) {
                                    orig_callback( new Feature({seq_id: query.ref, start: start, end: end, seq: chunk_seqs.join("")}) );
                                    if( endCallback )
                                        endCallback();
                                }
                            };
                        })();

        var callbackInfo = { start: start, end: end, success: callback, error: errorCallback  };

        if( !this.chunkCache[seqname] ) {
            this.chunkCache[seqname] = [];
        }
        var chunkCacheForSeq = this.chunkCache[seqname];

        for (var i = firstChunk; i <= lastChunk; i++) {
            //console.log("working on chunk %d for %d .. %d", i, start, end);

            var chunk = chunkCacheForSeq[i];
            if (chunk) {
                if (chunk.loaded) {
                    callback( start,
                              end,
                              chunk.sequence.substring(
                                  start - i*chunkSize,
                                  end - i*chunkSize
                              ),
                              i
                            );
                }
                else if( chunk.error ) {
                    errorCallback( chunk.error );
                }
                else {
                    //console.log("added callback for %d .. %d", start, end);
                    chunk.callbacks.push(callbackInfo);
                }
            } else {
                chunkCacheForSeq[i] = {
                    loaded: false,
                    num: i,
                    callbacks: [callbackInfo]
                };

                var sequrl = Util.resolveUrl(
                    this.baseUrl,
                    Util.fillTemplate(
                        this.urlTemplate,
                        {
                            'refseq': query.ref,
                            'refseq_dirpath': function() {
                                var hex = Crc32.crc32( query.ref )
                                               .toString(16)
                                               .toLowerCase()
                                               .replace('-','n');
                                // zero-pad the hex string to be 8 chars if necessary
                                while( hex.length < 8 )
                                    hex = '0'+hex;
                                var dirpath = [];
                                for( var i = 0; i < hex.length; i += 3 ) {
                                    dirpath.push( hex.substring( i, i+3 ) );
                                }
                                return dirpath.join('/');
                            }
                        })
                );

                dojo.xhrGet({
                                url: sequrl + i + ".txt" + ( this.compress ? 'z' : '' ),
                                load: dojo.hitch( this, function( chunkRecord, response ) {
                                                      //console.log('response for chunk '+chunkRecord.num);
                                                      chunkRecord.sequence = response;
                                                      chunkRecord.loaded = true;
                                                      dojo.forEach( chunkRecord.callbacks, function(ci) {
                                                                        ci.success( ci.start,
                                                                                ci.end,
                                                                                response.substring( ci.start - chunkRecord.num*chunkSize,
                                                                                ci.end   - chunkRecord.num*chunkSize
                                                                                ),
                                                                                i
                                                                                );
                                                                    });
                                                      delete chunkRecord.callbacks;

                                                  }, chunkCacheForSeq[i] ),
                                error: dojo.hitch( this, function( chunkRecord, error ) {
                                    chunkRecord.error = error;
                                    dojo.forEach( chunkRecord.callbacks, function(ci) {
                                        ci.error( error );
                                    });
                                    delete chunkRecord.callbacks;
                                }, chunkCacheForSeq[i])
                            });
            }
        }
    }
});
});<|endoftext|>


<commit_before>import Ember from 'ember';
import layout from '../templates/components/ember-chosen';

export default Ember.Component.extend({
  tagName: 'select',
  layout: layout,

  classNames: ['ember-chosen'],
  classNameBindings: ['isRTL:chosen-rtl'],

  attributeBindings: ['multiple', 'disabled', 'style'],

  ////////////////
  //! Variables //
  ////////////////

  isRTL: false,

  multiple: false,

  disabled: false,

  /*
   * The content path where the group name is located.
   * OPTIONAL
   */
  optionGroupPath: "",

  /*
   * The content path where the value is located.
   * REQUIRED
   */
  optionValuePath: "",

  /*
   * The content path where the label is located.
   * REQUIRED
   */
  optionLabelPath: "",

  /*
   * Hides the empty option.
   */
  skipEmptyItem: false,

  /*
   * Content that is sent to the ember-chosen.
   * This is used to build the options array.
   */
  content: null,

  /*
   * The action to execute on change.
   */
  action: "",

  ///////////////
  //! Settings //
  ///////////////

  /*
   * Placeholder text for both the multiple version of the chosen
   * and the single version.
   */
  placeholder: "Select an Option",

  /*
   * Chosen default options.
   * Reference: http://harvesthq.github.io/chosen/options.html
   */
  allowSingleDeselect: false,
  disableSearch: false,
  disableSearchThreshold: 0,
  enableSplitWordSearch: true,
  inheritSelectClasses: true,
  maxSelectedOptions: "Infinity",
  noResultsText: "No Results Match",
  searchContains: false,
  singleBackstrokeDelete: true,
  width: "100%",
  displayDisabledOptions: true,
  displaySelectedOptions: true,
  includeGroupLabelInSelected: false,

  /*
   * Aliased properties to the placeholder for easier setting.
   */
  placeholderTextMultiple: Ember.computed.alias('placeholder'),
  placeholderTextSingle: Ember.computed.alias('placeholder'),

  ///////////////
  //! Computed //
  ///////////////

  /*
   * Validates the optionGroupPath in the content array.
   */
  validGroupPath: Ember.computed('optionGroupPath', {
    get: function(){
      var that = this,
        validGroupPath,
        lastObject = that.get('content.lastObject');

      if(!that.get('optionGroupPath')) {
        return false;
      }

      if(lastObject.hasOwnProperty(that.get('optionGroupPath'))) {
        validGroupPath = true;
      } else {
        console.log(
          "%c%s#validGroupPath Invalid optionGroupPath `%s`.",
          "color: red", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          that.get('optionGroupPath')
        );

        validGroupPath = false;
      }

      return validGroupPath;
    }
  }),

  /*
   * Built options from the content sent in to the ember-select.
   */
  options: Ember.computed('content', 'optionValuePath', 'optionLabelPath', 'optionGroupPath', 'value', {
    get: function(){
      var that = this,
        groupNames = [],
        groups = [],
        options = Ember.A();

      if(!that.get('content')) {
        return null;
      }

      if(that.get('validGroupPath')) {
        groupNames = that.get('content').mapBy(that.get('optionGroupPath'));
        groups = _.uniq(groupNames);

        /*  /
        console.log(
          "%c%s#options creating groups: %O from %O",
          "color: purple", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          groups,
          groupNames
        );
        //*/

        // Build the options with groups
        groups.forEach(function(group) {
          var groupOptions = [];

          that.get('content').filterBy(that.get('optionGroupPath'), group).forEach(function(option) {
            groupOptions.push({
              value: that._lookupOptionValue(option),
              label: that._lookupOptionLabel(option),
              selected: that._checkSelected(that._lookupOptionValue(option))
            });
          });

          options.push({
            label: group,
            options: groupOptions
          });
        });
      } else {
        // Build the options array
        that.get('content').forEach(function(option) {
          options.push({
            value: that._lookupOptionValue(option),
            label: that._lookupOptionLabel(option),
            selected: that._checkSelected(that._lookupOptionValue(option))
          });
        });
      }

      /*  /
      console.log(
        "%c%s#options: %O, value: %O",
        "color: purple", // http://www.w3schools.com/html/html_colornames.asp
        that.toString(),
        options,
        that.get('value')
      );
      //*/

      that._updateChosen();

      return options;
    }
  }),

  /*
   * Initializes the settings for th chosen select box.
   * Reformatts the camelized properties to underscired settings for chosen.
   */
  settings: Ember.computed(
    'isRtl',
    'multiple',
    'disabled',
    'placeholder',
    'allowSingleDeselect',
    'disableSearch',
    'disableSearchThreshold',
    'enableSplitWordSearch',
    'inheritSelectClasses',
    'maxSelectedOptions',
    'noResultsText',
    'placeholderTextMultiple',
    'placeholderTextSingle',
    'searchContains',
    'singleBackstrokeDelete',
    'width',
    'displayDisabledOptions',
    'displaySelectedOptions',
    'includeGroupLabelInSelected',
    function(){
      var that = this,
        properties = that.getProperties(
          'prompt',
          'isRtl',
          'multiple',
          'allowSingleDeselect',
          'disableSearch',
          'disableSearchThreshold',
          'enableSplitWordSearch',
          'inheritSelectClasses',
          'maxSelectedOptions',
          'noResultsText',
          'placeholderTextMultiple',
          'placeholderTextSingle',
          'searchContains',
          'singleBackstrokeDelete',
          'width',
          'displayDisabledOptions',
          'displaySelectedOptions',
          'includeGroupLabelInSelected'
        ),
        settings = {};

      for(var prop in properties){
        if( !properties.hasOwnProperty(prop) ){ continue; }

        // Convert the camelized properties to underscored for chosen.
        settings[Ember.String.underscore(prop)] = properties[prop];
      }

      that._updateChosen();

      return settings;
    }
  ),

  style: Ember.computed({
    get: function(){
      var that = this,
        style = String('width: ' + that.get('width'));

      return Ember.String.htmlSafe(style);
    }
  }),

  /////////////
  //! Events //
  /////////////

  didInsertElement: function(){
    this._setup();
  },

  willDestroyElement: function(){
    this._teardown();
  },

  /*
   * Default change event. Linked to the chosen change event.
   */
  change: function(){
    this.send('valueUpdate', this.$().val());
  },

  ////////////////
  //! Functions //
  ////////////////

  /*
   * Updates the chosen select box.
   */
  _updateChosen: function() {
    var that = this;

    Ember.run.next(that, function(){
      /*  /
      console.log(
        "%c%s#_updateChosen...",
        "color: purple", // http://www.w3schools.com/html/html_colornames.asp
        that.toString()
      );
      //*/

      that.$().trigger("chosen:updated");
    });
  },

  /*
   * Looks up the option's value
   */
  _lookupOptionValue: function(option) {
    var that = this, optionValue;

    if(that.get('optionValuePath')) {
      optionValue = option[that.get('optionValuePath')];
    } else {
      if(that.get('optionLabelPath')) {
        optionValue = option[that.get('optionLabelPath')];
      } else {
        optionValue = option;
      }
    }

    return optionValue;
  },

  /*
   * Looks up the option's label
   */
  _lookupOptionLabel: function(option) {
    var that = this, optionLabel;

    if(that.get('optionLabelPath')) {
      optionLabel = option[that.get('optionLabelPath')];
    } else {
      if(that.get('optionValuePath')) {
        optionLabel = option[that.get('optionValuePath')];
      } else {
        optionLabel = option;
      }
    }

    return optionLabel;
  },

  /*
   * Checks to see if a value is selected
   */
  _checkSelected: function(value) {
    var that = this,
      valueStr = String(value),
      selectedValue = that.get('value'),
      selected = false;

    if(Ember.$.isArray(value)){
      if(Ember.$.inArray(value, selectedValue) !== -1) {
        selected = true;
      }
    } else {
      if(valueStr === String(selectedValue)) {
        selected = true;
      }
    }

    return selected;
  },

  /*
   * Initializes the chosen select.
   */
  _setup: function(){
    var that = this;

    // If there is no content assume that we are using block content and attempt to select the appropriate option.
    if(!that.get('content')) {
      // Look for the selection via it's value.
      var foundSelectedOption = that.$('option[value="' + that.get('value') + '"]');

      // If not found, look for selection via it's HTML content.
      if(foundSelectedOption.length === 0){
        foundSelectedOption = that.$('option').filter(function() {
          return Ember.$(this).html() === that.get('value');
        });
      }

      if(foundSelectedOption.length === 0){
        // If still not found, log notification.
        console.log(
          "%c%s#_setup unable to select option with a value or text of `%s`.",
          "color: red", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          that.get('value')
        );
      } else {
        // If found, select the option.
        foundSelectedOption.attr('selected', true);
      }
    }

    // Initialize the select box.
    that.$().chosen(that.get('settings'));
  },

  /*
   * Destroys the chosen select.
   */
  _teardown: function(){
    this.$().chosen('destroy');
  },

  //////////////
  //! Actions //
  //////////////

  actions: {
    /*
     * Handles setting the value when the select box's value changes.
     */
    valueUpdate: function(value){
      this.set('value', value);

      if(this.get('action')) {
        Ember.run.once(this, 'sendAction');
      }
    }
  }
});
<commit_msg>Added disabled to computed prop for updates<commit_after>import Ember from 'ember';
import layout from '../templates/components/ember-chosen';

export default Ember.Component.extend({
  tagName: 'select',
  layout: layout,

  classNames: ['ember-chosen'],
  classNameBindings: ['isRTL:chosen-rtl'],

  attributeBindings: ['multiple', 'disabled', 'style'],

  ////////////////
  //! Variables //
  ////////////////

  isRTL: false,

  multiple: false,

  disabled: false,

  /*
   * The content path where the group name is located.
   * OPTIONAL
   */
  optionGroupPath: "",

  /*
   * The content path where the value is located.
   * REQUIRED
   */
  optionValuePath: "",

  /*
   * The content path where the label is located.
   * REQUIRED
   */
  optionLabelPath: "",

  /*
   * Hides the empty option.
   */
  skipEmptyItem: false,

  /*
   * Content that is sent to the ember-chosen.
   * This is used to build the options array.
   */
  content: null,

  /*
   * The action to execute on change.
   */
  action: "",

  ///////////////
  //! Settings //
  ///////////////

  /*
   * Placeholder text for both the multiple version of the chosen
   * and the single version.
   */
  placeholder: "Select an Option",

  /*
   * Chosen default options.
   * Reference: http://harvesthq.github.io/chosen/options.html
   */
  allowSingleDeselect: false,
  disableSearch: false,
  disableSearchThreshold: 0,
  enableSplitWordSearch: true,
  inheritSelectClasses: true,
  maxSelectedOptions: "Infinity",
  noResultsText: "No Results Match",
  searchContains: false,
  singleBackstrokeDelete: true,
  width: "100%",
  displayDisabledOptions: true,
  displaySelectedOptions: true,
  includeGroupLabelInSelected: false,

  /*
   * Aliased properties to the placeholder for easier setting.
   */
  placeholderTextMultiple: Ember.computed.alias('placeholder'),
  placeholderTextSingle: Ember.computed.alias('placeholder'),

  ///////////////
  //! Computed //
  ///////////////

  /*
   * Validates the optionGroupPath in the content array.
   */
  validGroupPath: Ember.computed('optionGroupPath', {
    get: function(){
      var that = this,
        validGroupPath,
        lastObject = that.get('content.lastObject');

      if(!that.get('optionGroupPath')) {
        return false;
      }

      if(lastObject.hasOwnProperty(that.get('optionGroupPath'))) {
        validGroupPath = true;
      } else {
        console.log(
          "%c%s#validGroupPath Invalid optionGroupPath `%s`.",
          "color: red", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          that.get('optionGroupPath')
        );

        validGroupPath = false;
      }

      return validGroupPath;
    }
  }),

  /*
   * Built options from the content sent in to the ember-select.
   */
  options: Ember.computed('content', 'optionValuePath', 'optionLabelPath', 'optionGroupPath', 'value', 'disabled', {
    get: function(){
      var that = this,
        groupNames = [],
        groups = [],
        options = Ember.A();

      if(!that.get('content')) {
        return null;
      }

      if(that.get('validGroupPath')) {
        groupNames = that.get('content').mapBy(that.get('optionGroupPath'));
        groups = _.uniq(groupNames);

        /*  /
        console.log(
          "%c%s#options creating groups: %O from %O",
          "color: purple", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          groups,
          groupNames
        );
        //*/

        // Build the options with groups
        groups.forEach(function(group) {
          var groupOptions = [];

          that.get('content').filterBy(that.get('optionGroupPath'), group).forEach(function(option) {
            groupOptions.push({
              value: that._lookupOptionValue(option),
              label: that._lookupOptionLabel(option),
              selected: that._checkSelected(that._lookupOptionValue(option))
            });
          });

          options.push({
            label: group,
            options: groupOptions
          });
        });
      } else {
        // Build the options array
        that.get('content').forEach(function(option) {
          options.push({
            value: that._lookupOptionValue(option),
            label: that._lookupOptionLabel(option),
            selected: that._checkSelected(that._lookupOptionValue(option))
          });
        });
      }

      /*  /
      console.log(
        "%c%s#options: %O, value: %O",
        "color: purple", // http://www.w3schools.com/html/html_colornames.asp
        that.toString(),
        options,
        that.get('value')
      );
      //*/

      that._updateChosen();

      return options;
    }
  }),

  /*
   * Initializes the settings for th chosen select box.
   * Reformatts the camelized properties to underscired settings for chosen.
   */
  settings: Ember.computed(
    'isRtl',
    'multiple',
    'disabled',
    'placeholder',
    'allowSingleDeselect',
    'disableSearch',
    'disableSearchThreshold',
    'enableSplitWordSearch',
    'inheritSelectClasses',
    'maxSelectedOptions',
    'noResultsText',
    'placeholderTextMultiple',
    'placeholderTextSingle',
    'searchContains',
    'singleBackstrokeDelete',
    'width',
    'displayDisabledOptions',
    'displaySelectedOptions',
    'includeGroupLabelInSelected',
    function(){
      var that = this,
        properties = that.getProperties(
          'prompt',
          'isRtl',
          'multiple',
          'allowSingleDeselect',
          'disableSearch',
          'disableSearchThreshold',
          'enableSplitWordSearch',
          'inheritSelectClasses',
          'maxSelectedOptions',
          'noResultsText',
          'placeholderTextMultiple',
          'placeholderTextSingle',
          'searchContains',
          'singleBackstrokeDelete',
          'width',
          'displayDisabledOptions',
          'displaySelectedOptions',
          'includeGroupLabelInSelected'
        ),
        settings = {};

      for(var prop in properties){
        if( !properties.hasOwnProperty(prop) ){ continue; }

        // Convert the camelized properties to underscored for chosen.
        settings[Ember.String.underscore(prop)] = properties[prop];
      }

      that._updateChosen();

      return settings;
    }
  ),

  style: Ember.computed({
    get: function(){
      var that = this,
        style = String('width: ' + that.get('width'));

      return Ember.String.htmlSafe(style);
    }
  }),

  /////////////
  //! Events //
  /////////////

  didInsertElement: function(){
    this._setup();
  },

  willDestroyElement: function(){
    this._teardown();
  },

  /*
   * Default change event. Linked to the chosen change event.
   */
  change: function(){
    this.send('valueUpdate', this.$().val());
  },

  ////////////////
  //! Functions //
  ////////////////

  /*
   * Updates the chosen select box.
   */
  _updateChosen: function() {
    var that = this;

    Ember.run.next(that, function(){
      /*  /
      console.log(
        "%c%s#_updateChosen...",
        "color: purple", // http://www.w3schools.com/html/html_colornames.asp
        that.toString()
      );
      //*/

      that.$().trigger("chosen:updated");
    });
  },

  /*
   * Looks up the option's value
   */
  _lookupOptionValue: function(option) {
    var that = this, optionValue;

    if(that.get('optionValuePath')) {
      optionValue = option[that.get('optionValuePath')];
    } else {
      if(that.get('optionLabelPath')) {
        optionValue = option[that.get('optionLabelPath')];
      } else {
        optionValue = option;
      }
    }

    return optionValue;
  },

  /*
   * Looks up the option's label
   */
  _lookupOptionLabel: function(option) {
    var that = this, optionLabel;

    if(that.get('optionLabelPath')) {
      optionLabel = option[that.get('optionLabelPath')];
    } else {
      if(that.get('optionValuePath')) {
        optionLabel = option[that.get('optionValuePath')];
      } else {
        optionLabel = option;
      }
    }

    return optionLabel;
  },

  /*
   * Checks to see if a value is selected
   */
  _checkSelected: function(value) {
    var that = this,
      valueStr = String(value),
      selectedValue = that.get('value'),
      selected = false;

    if(Ember.$.isArray(value)){
      if(Ember.$.inArray(value, selectedValue) !== -1) {
        selected = true;
      }
    } else {
      if(valueStr === String(selectedValue)) {
        selected = true;
      }
    }

    return selected;
  },

  /*
   * Initializes the chosen select.
   */
  _setup: function(){
    var that = this;

    // If there is no content assume that we are using block content and attempt to select the appropriate option.
    if(!that.get('content')) {
      // Look for the selection via it's value.
      var foundSelectedOption = that.$('option[value="' + that.get('value') + '"]');

      // If not found, look for selection via it's HTML content.
      if(foundSelectedOption.length === 0){
        foundSelectedOption = that.$('option').filter(function() {
          return Ember.$(this).html() === that.get('value');
        });
      }

      if(foundSelectedOption.length === 0){
        // If still not found, log notification.
        console.log(
          "%c%s#_setup unable to select option with a value or text of `%s`.",
          "color: red", // http://www.w3schools.com/html/html_colornames.asp
          that.toString(),
          that.get('value')
        );
      } else {
        // If found, select the option.
        foundSelectedOption.attr('selected', true);
      }
    }

    // Initialize the select box.
    that.$().chosen(that.get('settings'));
  },

  /*
   * Destroys the chosen select.
   */
  _teardown: function(){
    this.$().chosen('destroy');
  },

  //////////////
  //! Actions //
  //////////////

  actions: {
    /*
     * Handles setting the value when the select box's value changes.
     */
    valueUpdate: function(value){
      this.set('value', value);

      if(this.get('action')) {
        Ember.run.once(this, 'sendAction');
      }
    }
  }
});
<|endoftext|>


<commit_before>describe('C&E Generator', function() {
    beforeEach(function beforeEach() {
        browser.get('http://localhost:4000/')
    })

    it('should have a title', function hasTitle() {
        expect(browser.getTitle()).toEqual('C&E Generator')
    })

    it('should display allowed number of participants', function participants() {
        element(by.cssContainingText('option', 'NU')).click()
        element(by.model('ce.participants')).getText().then(function (options) {
            expect(options.trim().split(/\s+/)).toEqual(['8', '16', '32', '64'])
        })
    })

    it('should display allowed number of participants for monotype', function monotypeParticipants() {
        element(by.cssContainingText('option', 'Monotype')).click()
        element(by.cssContainingText('option', 'Dragon')).click()
        element(by.model('ce.participants')).getText().then(function (options) {
            expect(options.trim().split(/\s+/)).toEqual(['8'])
        })
    })
})
<commit_msg>Add test for non-mega dragon monotype.<commit_after>describe('C&E Generator', function() {
    beforeEach(function beforeEach() {
        browser.get('http://localhost:4000/')
    })

    it('should have a title', function hasTitle() {
        expect(browser.getTitle()).toEqual('C&E Generator')
    })

    it('should display allowed number of participants', function participants() {
        element(by.cssContainingText('option', 'NU')).click()
        element(by.model('ce.participants')).getText().then(function (options) {
            expect(options.trim().split(/\s+/)).toEqual(['8', '16', '32', '64'])
        })
    })

    it('should display allowed number of participants for monotype', function monotypeParticipants() {
        element(by.cssContainingText('option', 'Monotype')).click()
        element(by.cssContainingText('option', 'Dragon')).click()
        element(by.model('ce.participants')).getText().then(function (options) {
            expect(options.trim().split(/\s+/)).toEqual(['8'])
        })
    })

    it('should not display allowed number of participants for non-mega dragon monotype', function nonMegaDragon() {
        element(by.cssContainingText('option', 'Monotype')).click()
        element(by.cssContainingText('option', 'Dragon')).click()
        element(by.model('ce.megas')).click()
        element(by.model('ce.participants')).getText().then(function (options) {
            expect(options.trim()).toEqual("")
        })
    })
})
<|endoftext|>


<commit_before>window.c.admin.Contributions = (function(m, c, h){
  var admin = c.admin;
  return {
    controller: function(){
      var listVM = admin.contributionListVM,
          filterVM = admin.contributionFilterVM,
          error = m.prop(''),
          itemBuilder = [
            {
              component: 'AdminUser',
              wrapperClass: '.w-col.w-col-4'
            },
            {
              component: 'AdminProject',
              wrapperClass: '.w-col.w-col-4'
            },
            {
              component: 'AdminContribution',
              wrapperClass: '.w-col.w-col-2'
            },
            {
              component: 'PaymentStatus',
              wrapperClass: '.w-col.w-col-2'
            }
          ],
          itemActions = [
            {
              component: 'AdminInputAction',
              data: {
                getKey: 'user_id',
                updateKey: 'id',
                callToAction: 'Transferir',
                innerLabel: 'Id do novo apoiador:',
                outerLabel: 'Transferir Apoio',
                placeholder: 'ex: 129908',
                model: c.models.contributionDetail
              }
            }
          ],
          filterBuilder = [
            { //full_text_index
              component: 'FilterMain',
              data: {
                vm: filterVM.full_text_index,
                placeholder: 'Busque por projeto, email, Ids do usuário e do apoio...'
              }
            },
            { //state
              component: 'FilterDropdown',
              data: {
                label: 'Com o estado',
                name: 'state',
                vm: filterVM.state,
                options: [
                  {value: '', option: 'Qualquer um'},
                  {value: 'paid', option: 'paid'},
                  {value: 'refused', option: 'refused'},
                  {value: 'pending', option: 'pending'},
                  {value: 'pending_refund', option: 'pending_refund'},
                  {value: 'refunded', option: 'refunded'},
                  {value: 'chargeback', option: 'chargeback'},
                  {value: 'deleted', option: 'deleted'}
                ]
              }
            },
            { //gateway
              component: 'FilterDropdown',
              data: {
                label: 'gateway',
                name: 'gateway',
                vm: filterVM.gateway,
                options: [
                  {value: '', option: 'Qualquer um'},
                  {value: 'Pagarme', option: 'Pagarme'},
                  {value: 'MoIP', option: 'MoIP'},
                  {value: 'PayPal', option: 'PayPal'},
                  {value: 'Credits', option: 'Créditos'}
                ]
              }
            },
            { //value
              component: 'FilterNumberRange',
              data: {
                label: 'Valores entre',
                first: filterVM.value.gte,
                last: filterVM.value.lte
              }
            },
            { //created_at
              component: 'FilterDateRange',
              data: {
                label: 'Período do apoio',
                first: filterVM.created_at.gte,
                last: filterVM.created_at.lte
              }
            }
          ],
          submit = function(){
            listVM.firstPage(filterVM.parameters()).then(null, function(serverError){
              error(serverError.message);
            });
            return false;
          };

      return {
        filterVM: filterVM,
        filterBuilder: filterBuilder,
        itemActions: itemActions,
        itemBuilder: itemBuilder,
        listVM: {list: listVM, error: error},
        submit: submit
      };
    },

    view: function(ctrl){
      return [
        m.component(c.AdminFilter,{form: ctrl.filterVM.formDescriber, filterBuilder: ctrl.filterBuilder, submit: ctrl.submit}),
        m.component(c.AdminList, {vm: ctrl.listVM, itemBuilder: ctrl.itemBuilder, itemActions: ctrl.itemActions})
      ];
    }
  };
}(window.m, window.c, window.c.h));
<commit_msg>Add admin radio descriptior to ContributionsJS.<commit_after>window.c.admin.Contributions = (function(m, c, h){
  var admin = c.admin;
  return {
    controller: function(){
      var listVM = admin.contributionListVM,
          filterVM = admin.contributionFilterVM,
          error = m.prop(''),
          itemBuilder = [
            {
              component: 'AdminUser',
              wrapperClass: '.w-col.w-col-4'
            },
            {
              component: 'AdminProject',
              wrapperClass: '.w-col.w-col-4'
            },
            {
              component: 'AdminContribution',
              wrapperClass: '.w-col.w-col-2'
            },
            {
              component: 'PaymentStatus',
              wrapperClass: '.w-col.w-col-2'
            }
          ],
          itemActions = [
            {
              component: 'AdminInputAction',
              data: {
                getKey: 'user_id',
                updateKey: 'id',
                callToAction: 'Transferir',
                innerLabel: 'Id do novo apoiador:',
                outerLabel: 'Transferir Apoio',
                placeholder: 'ex: 129908',
                model: c.models.contributionDetail
              }
            },
            {
              component: 'AdminRadioAction',
              data: {
                getKey: 'project_id',
                updateKey: 'id',
                model: c.models.rewardDetail,
                callToAction: 'Alterar Recompensa'
              }
            }
          ],
          filterBuilder = [
            { //full_text_index
              component: 'FilterMain',
              data: {
                vm: filterVM.full_text_index,
                placeholder: 'Busque por projeto, email, Ids do usuário e do apoio...'
              }
            },
            { //state
              component: 'FilterDropdown',
              data: {
                label: 'Com o estado',
                name: 'state',
                vm: filterVM.state,
                options: [
                  {value: '', option: 'Qualquer um'},
                  {value: 'paid', option: 'paid'},
                  {value: 'refused', option: 'refused'},
                  {value: 'pending', option: 'pending'},
                  {value: 'pending_refund', option: 'pending_refund'},
                  {value: 'refunded', option: 'refunded'},
                  {value: 'chargeback', option: 'chargeback'},
                  {value: 'deleted', option: 'deleted'}
                ]
              }
            },
            { //gateway
              component: 'FilterDropdown',
              data: {
                label: 'gateway',
                name: 'gateway',
                vm: filterVM.gateway,
                options: [
                  {value: '', option: 'Qualquer um'},
                  {value: 'Pagarme', option: 'Pagarme'},
                  {value: 'MoIP', option: 'MoIP'},
                  {value: 'PayPal', option: 'PayPal'},
                  {value: 'Credits', option: 'Créditos'}
                ]
              }
            },
            { //value
              component: 'FilterNumberRange',
              data: {
                label: 'Valores entre',
                first: filterVM.value.gte,
                last: filterVM.value.lte
              }
            },
            { //created_at
              component: 'FilterDateRange',
              data: {
                label: 'Período do apoio',
                first: filterVM.created_at.gte,
                last: filterVM.created_at.lte
              }
            }
          ],
          submit = function(){
            listVM.firstPage(filterVM.parameters()).then(null, function(serverError){
              error(serverError.message);
            });
            return false;
          };

      return {
        filterVM: filterVM,
        filterBuilder: filterBuilder,
        itemActions: itemActions,
        itemBuilder: itemBuilder,
        listVM: {list: listVM, error: error},
        submit: submit
      };
    },

    view: function(ctrl){
      return [
        m.component(c.AdminFilter,{form: ctrl.filterVM.formDescriber, filterBuilder: ctrl.filterBuilder, submit: ctrl.submit}),
        m.component(c.AdminList, {vm: ctrl.listVM, itemBuilder: ctrl.itemBuilder, itemActions: ctrl.itemActions})
      ];
    }
  };
}(window.m, window.c, window.c.h));
<|endoftext|>


<commit_before>import React   from 'react'
import Sidebar from 'react-sidebar'
import Host    from './Host'
import Mixer   from './Mixer'
import Stream  from './Stream'

class Ui extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      sidebarOpen    : false,
      sidebarDocked  : false,
      mediaQueryList : null
    }
    this.mediaQueryChanged = this.mediaQueryChanged.bind(this)
  }
  onSetSidebarOpen(open) {
    this.setState({sidebarOpen: open})
  }
  componentWillMount() {
    const mediaQueryList = window.matchMedia(`(min-width: 800px)`)
    mediaQueryList.addListener(this.mediaQueryChanged)
    this.setState({ mediaQueryList, sidebarDocked : mediaQueryList.matches })
  }
  componentWillUnmount() {
    this.state.mediaQueryList.removeListener(this.mediaQueryChanged)
  }
  mediaQueryChanged() {
    this.setState({ sidebarDocked : this.state.mediaQueryList.matches })
  }
  render() {
    return (
      <Sidebar sidebar = {(

            <Host {...this.props} />

        )}
        open      = {this.state.sidebarOpen}
        docked    = {this.state.sidebarDocked}
        onSetOpen = {this.onSetSidebarOpen.bind(this)}>
        <Mixer {...this.props} />
      </Sidebar>
    )
  }
}

export default Ui
<commit_msg>fix some alignment<commit_after>import React   from 'react'
import Sidebar from 'react-sidebar'
import Host    from './Host'
import Mixer   from './Mixer'
import Stream  from './Stream'

class Ui extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      sidebarOpen    : false,
      sidebarDocked  : false,
      mediaQueryList : null
    }
    this.mediaQueryChanged = this.mediaQueryChanged.bind(this)
  }
  onSetSidebarOpen(open) {
    this.setState({sidebarOpen: open})
  }
  componentWillMount() {
    const mediaQueryList = window.matchMedia(`(min-width: 800px)`)
    mediaQueryList.addListener(this.mediaQueryChanged)
    this.setState({ mediaQueryList, sidebarDocked : mediaQueryList.matches })
  }
  componentWillUnmount() {
    this.state.mediaQueryList.removeListener(this.mediaQueryChanged)
  }
  mediaQueryChanged() {
    this.setState({ sidebarDocked : this.state.mediaQueryList.matches })
  }
  render() {
    return (
      <Sidebar sidebar = {(

          <Host {...this.props} />

      )}
        open      = {this.state.sidebarOpen}
        docked    = {this.state.sidebarDocked}
        onSetOpen = {this.onSetSidebarOpen.bind(this)}>
        <Mixer {...this.props} />
      </Sidebar>
    )
  }
}

export default Ui
<|endoftext|>