<commit_before>//helpful: http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-examples.html

var controller = module.exports;
var request = require('request');
var Photo = require('./photos.model.js');
var seed = require('./photos.seed.js');
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
var fs = require('fs');

//POSTING A PHOTO: intended process
//client sends a GET to api/phots/addnew.  includes user id, event name, file extension, other details.
//server creates an entry in photos table. generates and returns presigned S3 URL to client.
//client then uses presigned URL to upload the photo to S3.
//if successful upload: just say 'photo uploaded!'
//if error: notify client that upload failed, and notify server so it can drop that recently created record.

//TODO: photo bucket currently allows anonymous read/write access.  refactor this.
//should allow credentialed read-write access (for dev environment - have api keys cached on dev machine)
//'When deploying, you should change the ‘AllowedOrigin’ to only accept requests from your domain.''

//images can be viewed by the client very simply, like this:
//

controller.addOne = function(req,res){
  new Photo(req.query)
  .save()
  .then(function(record){
    var fileName = record.attributes.id.toString();
    var params = {Bucket: 'base9photos', Key: fileName + '.jpg'};
    var url = s3.getSignedUrl('putObject', params);
    res.json(url);
  });
}

//deletes a photo record from the DB, if it exists and the request
//is coming from that photo's owner. does NOT do anything to
//remove the photo from the S3 server!
controller.deleteOne = function(req,res){
  Photo.where({id:req.params.id}).fetch({
    }).then(function (record) {

      //delete the record
      if(record && record.user_id===req.params.user_id){
        record.destroy()
        .on('destroyed',function(){
          res.status(204).end();
        };

      //unauthorized
      } else if(record) {
        res.status(403).end()

      //record not found
      } else {
        res.status(404).end()
      }
  });
};

<commit_msg>fixes paren<commit_after>//helpful: http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-examples.html

var controller = module.exports;
var request = require('request');
var Photo = require('./photos.model.js');
var seed = require('./photos.seed.js');
var AWS = require('aws-sdk');
var s3 = new AWS.S3();
var fs = require('fs');

//POSTING A PHOTO: intended process
//client sends a GET to api/phots/addnew.  includes user id, event name, file extension, other details.
//server creates an entry in photos table. generates and returns presigned S3 URL to client.
//client then uses presigned URL to upload the photo to S3.
//if successful upload: just say 'photo uploaded!'
//if error: notify client that upload failed, and notify server so it can drop that recently created record.

//TODO: photo bucket currently allows anonymous read/write access.  refactor this.
//should allow credentialed read-write access (for dev environment - have api keys cached on dev machine)
//'When deploying, you should change the ‘AllowedOrigin’ to only accept requests from your domain.''

//images can be viewed by the client very simply, like this:
//

controller.addOne = function(req,res){
  new Photo(req.query)
  .save()
  .then(function(record){
    var fileName = record.attributes.id.toString();
    var params = {Bucket: 'base9photos', Key: fileName + '.jpg'};
    var url = s3.getSignedUrl('putObject', params);
    res.json(url);
  });
}

//deletes a photo record from the DB, if it exists and the request
//is coming from that photo's owner. does NOT do anything to
//remove the photo from the S3 server!
controller.deleteOne = function(req,res){
  Photo.where({id:req.params.id}).fetch({
    }).then(function (record) {

      //delete the record
      if(record && record.user_id===req.params.user_id){
        record.destroy()
        .on('destroyed',function(){
          res.status(204).end();
        });

      //unauthorized
      } else if(record) {
        res.status(403).end()

      //record not found
      } else {
        res.status(404).end()
      }
  });
};

<|endoftext|>


<commit_before>'use strict';

// Declare app level module which depends on views, and components
angular.module('baikalApp', [
  'ngRoute',
  'baikalApp.home',
  'baikalApp.about',
  'baikalApp.photo',
  'baikalApp.version',
  'baikalApp.services',
  'baikalApp.controllers',
  'baikalApp.filters',
  'pascalprecht.translate',
  'ngCookies',
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/home'});
}])
.filter('to_trusted', ['$sce', function($sce){
    return function(text) {
        return $sce.trustAsHtml(text);
    };
}])
.config(function ($translateProvider) {
  $translateProvider.translations('ru', {
    TITLE: 'Лига Байкальских Капитанов',
    COPYRIGHT_TEXT: 'Все права защищены',
    COPYRIGHT_AUTHOR: 'Александр Бурмейстер',
    PHOTO: 'Фото',
    SPRING: 'Весна',
    SUMMER: 'Лето',
    AUTUMN: 'Осень',
    WINTER: 'Зима',
    ABOUT_US: 'О нас',
    FAMILY: 'Семья',
    MEDIA: 'СМИ',
    CREATIVE: 'Творчество',
    YOGA: 'Йога',
    OUR_GUESTS: 'Наши гости',
    JOURNEY: 'Путешествия',
    VOLUNTEERS: 'Волонтёры',
    CONTACTS: 'Контакты',
    BAIKAL_JOURNEY_TITLE: 'ЛИГА БАЙКАЛЬСКИХ ЛЕДОВЫХ КАПИТАНОВ им. А. Ю. БУРМЕЙСТЕРА',
    BAIKAL_JOURNEY_DESCRIPTION: 'У нас, в Сибири, говорят: «Тот, кто испил воды из священного озера Байкал, тот будет жить долго и счастливо». Здесь, на Байкале, существует и по сегодняшний день древнейшая культура общения Человека и Природы. Байкал завораживает, дает мудрость, истинное понимание красоты и раскрывает внутренние способности. Посвященным Байкал дает возможность пережить разные стихии: ураганный ветер, жесткие шторма, зеркальный штиль и чистейший лед!  Байкал формирует духовную культуру и истинные отношения между людьми. Дни, проведенные на Байкале, Господь не засчитывает в счет прожитых лет.',
    BAIKAL_JOURNEY_AUTHOR: 'Александр Бурмейстер',
    BAIKAL_JOURNEY_BUTTON: 'ОТПРАВИТЬСЯ В ПУТЕШЕСТВИЕ',
    OUR_CONTACTS: 'Наши контакты',
    ADDRESS: 'Адрес',
    ADDRESS_TEXT: 'г. Иркутск, ул. Лермонтова, д. 777, кв. 7',
    PHONE: 'Телефон',
    PHONE_TEXT: '+7 (3952) 33-44-55'
  });
  $translateProvider.translations('en', {
    TITLE: 'Baikal Captain Ligue',
    COPYRIGHT_TEXT: 'All rights reserved',
    COPYRIGHT_AUTHOR: 'Alexander Burmeister',
    PHOTO: 'Photo',
    SPRING: 'Spring',
    SUMMER: 'Summer',
    AUTUMN: 'Autumn',
    WINTER: 'Winter',
    ABOUT_US: 'About us',
    FAMILY: 'Family',
    MEDIA: 'Media',
    CREATIVE: 'Creative',
    YOGA: 'Yoga',
    OUR_GUESTS: 'Our guests',
    JOURNEY: 'Journey',
    VOLUNTEERS: 'Volunteers',
    CONTACTS: 'Contacts',
    BAIKAL_JOURNEY_TITLE: 'BAIKAL LEAGUE of ICE CAPTAINS named after A.BURMEISTER',
    BAIKAL_JOURNEY_DESCRIPTION: 'In Siberia we say: «One that has tried water from the sacred lake Baikal, will live a long and happy life». There is still an ancient culture of communication between a Man and Nature. Baikal charms, gives wisdom, the real understanding of beauty, and reveals inner powers. Baikal gives an opportunity to experiense different elements, to initiated: storms, savage gales, smooth calm, and the cristal-clear ice!  Baikal forms spiritual culture and true relationship between people. Days spent on the lake Baikal, the Lord doesn\'t count against past years.',
    BAIKAL_JOURNEY_AUTHOR: 'Aleksander Burmeister',
    BAIKAL_JOURNEY_BUTTON: 'The first step to my adventure',
    OUR_CONTACTS: 'Our contacts',
    ADDRESS: 'Address',
    ADDRESS_TEXT: 'Irkutsk, ul. Lermontova, 777, 7',
    PHONE: 'Phone',
    PHONE_TEXT: '+7 (3952) 33-44-55'
  });
  $translateProvider.preferredLanguage('ru');
  $translateProvider.useLocalStorage();
});
<commit_msg>changes<commit_after>'use strict';

// Declare app level module which depends on views, and components
angular.module('baikalApp', [
  'ngRoute',
  'baikalApp.home',
  'baikalApp.about',
  'baikalApp.photo',
  'baikalApp.version',
  'baikalApp.services',
  'baikalApp.controllers',
  'baikalApp.filters',
  'pascalprecht.translate',
  'ngCookies',
]).
config(['$routeProvider', function($routeProvider) {
  $routeProvider.otherwise({redirectTo: '/home'});
}])
.filter('to_trusted', ['$sce', function($sce){
    return function(text) {
        return $sce.trustAsHtml(text);
    };
}])
.config(function ($translateProvider) {
  $translateProvider.translations('ru', {
    TITLE: 'Лига Байкальских Капитанов',
    COPYRIGHT_TEXT: 'Все права защищены',
    COPYRIGHT_AUTHOR: 'Александр Бурмейстер',
    PHOTO: 'Фото',
    SPRING: 'Весна',
    SUMMER: 'Лето',
    AUTUMN: 'Осень',
    WINTER: 'Зима',
    ABOUT_US: 'О нас',
    FAMILY: 'Семья',
    MEDIA: 'СМИ',
    CREATIVE: 'Творчество',
    YOGA: 'Йога',
    OUR_GUESTS: 'Наши гости',
    JOURNEY: 'Путешествия',
    VOLUNTEERS: 'Волонтёры',
    CONTACTS: 'Контакты',
    BAIKAL_JOURNEY_TITLE: 'ЛИГА БАЙКАЛЬСКИХ ЛЕДОВЫХ КАПИТАНОВ им. А. Ю. БУРМЕЙСТЕРА',
    BAIKAL_JOURNEY_DESCRIPTION: 'У нас, в Сибири, говорят: «Тот, кто испил воды из священного озера Байкал, тот будет жить долго и счастливо». Здесь, на Байкале, существует и по сегодняшний день древнейшая культура общения Человека и Природы. Байкал завораживает, дает мудрость, истинное понимание красоты и раскрывает внутренние способности. Посвященным Байкал дает возможность пережить разные стихии: ураганный ветер, жесткие шторма, зеркальный штиль и чистейший лед!  Байкал формирует духовную культуру и истинные отношения между людьми. Дни, проведенные на Байкале, Господь не засчитывает в счет прожитых лет.',
    BAIKAL_JOURNEY_AUTHOR: 'Александр Бурмейстер',
    BAIKAL_JOURNEY_BUTTON: 'Отправиться в путешествие',
    OUR_CONTACTS: 'Наши контакты',
    ADDRESS: 'Адрес',
    ADDRESS_TEXT: 'г. Иркутск, ул. Лермонтова, д. 777, кв. 7',
    PHONE: 'Телефон',
    PHONE_TEXT: '+7 (3952) 33-44-55'
  });
  $translateProvider.translations('en', {
    TITLE: 'Baikal Captain Ligue',
    COPYRIGHT_TEXT: 'All rights reserved',
    COPYRIGHT_AUTHOR: 'Alexander Burmeister',
    PHOTO: 'Photo',
    SPRING: 'Spring',
    SUMMER: 'Summer',
    AUTUMN: 'Autumn',
    WINTER: 'Winter',
    ABOUT_US: 'About us',
    FAMILY: 'Family',
    MEDIA: 'Media',
    CREATIVE: 'Creative',
    YOGA: 'Yoga',
    OUR_GUESTS: 'Our guests',
    JOURNEY: 'Journey',
    VOLUNTEERS: 'Volunteers',
    CONTACTS: 'Contacts',
    BAIKAL_JOURNEY_TITLE: 'BAIKAL LEAGUE of ICE CAPTAINS named after A.BURMEISTER',
    BAIKAL_JOURNEY_DESCRIPTION: 'In Siberia we say: «One that has tried water from the sacred lake Baikal, will live a long and happy life». There is still an ancient culture of communication between a Man and Nature. Baikal charms, gives wisdom, the real understanding of beauty, and reveals inner powers. Baikal gives an opportunity to experiense different elements, to initiated: storms, savage gales, smooth calm, and the cristal-clear ice!  Baikal forms spiritual culture and true relationship between people. Days spent on the lake Baikal, the Lord doesn\'t count against past years.',
    BAIKAL_JOURNEY_AUTHOR: 'Aleksander Burmeister',
    BAIKAL_JOURNEY_BUTTON: 'The first step to my adventure',
    OUR_CONTACTS: 'Our contacts',
    ADDRESS: 'Address',
    ADDRESS_TEXT: 'Irkutsk, ul. Lermontova, 777, 7',
    PHONE: 'Phone',
    PHONE_TEXT: '+7 (3952) 33-44-55'
  });
  $translateProvider.preferredLanguage('ru');
  $translateProvider.useLocalStorage();
});
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare", "dijit/layout/BorderContainer", "dojo/on",
	"./ActionBar","./ContainerActionBar","dijit/layout/TabContainer",
	"./TrackController","circulus/Viewer","circulus/LineTrack",
	"circulus/SectionTrack","dojo/_base/lang","dojo/request","./DataItemFormatter"
], function(
	declare,BorderContainer,on,
	ActionBar, ContainerActionBar,TabContainer,
	TrackController,CirculusViewer,LineTrack,SectionTrack,lang,xhr,DataItemFormatter
){

	return declare([BorderContainer], {
		gutters: true,
		query: null,
		genome_id: "",
		apiServiceUrl: window.App.dataAPI,

		_setQueryAttr: function(query){
		},

		onSetGenomeId: function(attr,oldVal,gid){
			this.getReferenceSequences(gid).then(lang.hitch(this, function(refseqs){
				this.set("referenceSequences",refseqs)
			}))
		},

		getReferenceSequences: function(gid, includeSequences, refresh){

			var query = "?eq(genome_id," + gid + ")&select(topology,gi,accession,length,sequence_id,gc_content,owner,sequence_type,taxon_id,public,genome_id,genome_name,date_inserted,date_modified" + (includeSequences?",sequence":"")+ ")&sort(+accession)&limit(1000)";

			return xhr.get(this.apiServiceUrl + "/genome_sequence/" + query, {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(refseqs){
				refseqs = refseqs.map(function(r){
					r.name = r.accession;
					r.start = 0;
					r.end = r.length;
					return r;
				}).sort(function(a,b){
					return a.name > b.name;
				})
				return refseqs;
			}));
		},

		addFeatureTrack: function(title, gid, filter, strand,fill,stroke,background){
			var fields=["feature_id","feature_type","sequence_id","segments","gi","na_length","pos_group","strand","public","aa_length","patric_id","owner",
						"location","protein_id","refseq_locus_tag","taxon_id","accession","end", "genome_name", "product","genome_id","annotation","start"]

			var query =  "?and(eq(genome_id," + gid + "),ne(feature_type,source)," + filter + ")&sort(+accession,+start)" + "&select(" + fields.join(",") + ")&limit(25000)";

			var track = this.viewer.addTrack({
				type: SectionTrack,
				options: {
					title: title, loading: true, trackWidth: 0.08,fill: fill, stroke: stroke, gap: 0, background: background,
					formatPopupContent: function(item){
						return item.patric_id + " (" + item.feature_type + ")
Product: " + item.product + "
Location: " + item.location;
					},
					formatDialogContent: function(item){
						return DataItemFormatter(item,"feature_data")
					}
				}
			})

			return xhr.get(this.apiServiceUrl + "/genome_feature/" + query, {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(refseqs){
				refseqs = refseqs.filter(function(r){
					if (strand === null){ return true};
					if (strand){
						return r.strand && r.strand=="+"
					}else{
						return r.strand != "+";
					}
				}).map(function(r){
					r.name = r.accession;
					r.length = r.end - r.start;
					return r;
				}).sort(function(a,b){
					return a.name > b.name;
				})

				console.log("Features: ", refseqs)

				track.set("data", refseqs)

				return refseqs;
			}));
		},

		onSetReferenceSequences: function(attr,oldVal, refseqs){
			console.log("RefSeqs: ", refseqs);

			this.viewer.addTrack({
				type: SectionTrack,
				options: {title: "Contigs/Chromosomes",trackWidth: 0.02,fill: "#000F7D", stroke: null, gap: .5, background: {fill: null, stroke: null}},
				data: refseqs
			},"perimeter",true);

			this.addFeatureTrack("CDS - FWD",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,CDS),eq(strand,\+))", true, "#307D32", null)
			this.addFeatureTrack("CDS - REV",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,CDS),eq(strand,%22-%22))", false, "#833B76", null)

			var fillFn = function(item){
				switch(item.feature_type){
					case "pseudogene":
						return "#75DF6F"
					case "tRNA":
						return "#3F76DF"
					case "rRNA":
						return "#DFC63A"
					default:
						return "#21DFD7"
				}
			}
			this.addFeatureTrack("Non-CDS Features",this.state.genome_ids[0], "and(eq(annotation,PATRIC),ne(feature_type,CDS))", false, fillFn,null, {fill: null,stroke: null})
			// this.addFeatureTrack("Pseudogenes",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,pseudogene))", null, [77, 83, 233], null, {stroke: "", fill: "#eeeeee"})
			// this.addFeatureTrack("tRNA", this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,tRNA))", null, [162, 0, 152], null, {stroke: ""})
			// this.addFeatureTrack("rRNA", this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,rRNA))", null, [243, 110, 0], null, {stroke: "",fill: "#eeeeee"})

			var gcContentTrack = this.viewer.addTrack({
				type: LineTrack,

				options: {title: "GC Content",visible: false, max: .6, min: 0,trackWidth: 0.18,stroke: {width: .5,color: "black"}, gap: .35, background: {fill: "#EBD4F4", stroke: null}},
			},"outer")

			var gcSkewTrack = this.viewer.addTrack({
				type: LineTrack,
				options: {title: "GC Skew",visible: false, max: 1, min: -1, scoreProperty: "skew", trackWidth: 0.1,stroke: {width: .5,color: "black"}, gap: .35, background: {fill: "#F3CDA0", stroke: null}},
			},"outer")

			this.getReferenceSequences(this.genome_id, true).then(lang.hitch(this, function(data){
				var gcContentData = this.getGCContent(data);
				console.log("GC CONTENT: ", gcContentData);
				gcContentTrack.set('data', gcContentData)
				gcSkewTrack.set('data', gcContentData)
			}))
		},

		getGCContent: function(data,windowSize){
			windowSize = windowSize||400;

			var gcData=[]

			function calculateGC(accession, seq,ws){
				var cur = seq;
				var slen = seq.length;
				var gc=[];
				var current=0;
				for(current=0;current<seq.length;current+=ws){
					var win = seq.substr(current,ws).toUpperCase();
					var wl = win.length;
					var G=0;
					var C=0;
					var gs = win.match(/G/g ||[]);
					if (gs) {
						G = gs.length;
					}

					var cs = win.match(/C/g ||[]);
					if (cs) {
						C = cs.length;
					}

					var GC = G+C; // for skew, (G-C)/(G+C), G+C can't be 0
					if (GC == 0){
						GC = 1;
					}
					gcData.push({accession: accession, score: (G+C)/wl, skew: (G-C)/GC, start: current,end: current+wl});
				}
				return gc;
			}

			data.forEach(function(contig){
					calculateGC(contig.accession, contig.sequence,windowSize);
			})
			return gcData
		},

		onSetState: function(attr,oldVal,state){
			console.log("CircularViewerContainer onSetState", state);
			if (state.genome_ids && state.genome_ids[0]){
				this.set("genome_id", state.genome_ids[0]);

				// this.addFeatureTrack(state.genome_ids[0], "eq(feature_type,CDS)", false, [71, 154, 43], null)
				// this.addFeatureTrack(state.genome_ids[0], "eq(feature_type,tRNA)", null, [154, 58, 133], null)
				// this.addFeatureTrack(state.genome_ids[0], "eq(feature_type,pseudogene)", null, [154, 58, 133], null)
				// this.addFeatureTrack(state.genome_ids[0], "eq(feature_type,rRNA)", null, [154, 58, 133], null)
			}
		},

		postCreate: function(){
			this.inherited(arguments);
			this.watch("state", lang.hitch(this, "onSetState"));
			this.watch("genome_id", lang.hitch(this,"onSetGenomeId"));
			this.watch("referenceSequences",lang.hitch(this,"onSetReferenceSequences"));
		},

		visible: false,
		_setVisibleAttr: function(visible) {
			// console.log("GridContainer setVisible: ", visible)
			this.visible = visible;
			if (this.visible && !this._firstView) {
				// console.log("Trigger First View: ", this.id)
				this.onFirstView();
				this._firstView=true;
			}
		},

		onFirstView: function(){
			console.log("onFirstView()")
			if (this._firstView) {
				return;
			}
			if (!this.controlPanel){
				this.controlPanel = new TrackController({region: "left",splitter:true, style:"width:250px;"});
			}

			if (!this.viewer){
				this.viewer = new CirculusViewer({
					region: "center",
					centerRadius: 100
			    });
			}

			this.addChild(this.controlPanel);
			this.addChild(this.viewer);
		}
	});
});

<commit_msg>some circ viewer updates<commit_after>define([
	"dojo/_base/declare", "dijit/layout/BorderContainer", "dojo/on",
	"./ActionBar","./ContainerActionBar","dijit/layout/TabContainer",
	"./TrackController","circulus/Viewer","circulus/LineTrack",
	"circulus/SectionTrack","dojo/_base/lang","dojo/request","./DataItemFormatter"
], function(
	declare,BorderContainer,on,
	ActionBar, ContainerActionBar,TabContainer,
	TrackController,CirculusViewer,LineTrack,SectionTrack,lang,xhr,DataItemFormatter
){

	return declare([BorderContainer], {
		gutters: true,
		query: null,
		genome_id: "",
		apiServiceUrl: window.App.dataAPI,

		_setQueryAttr: function(query){
		},

		onSetGenomeId: function(attr,oldVal,gid){
			this.getReferenceSequences(gid).then(lang.hitch(this, function(refseqs){
				this.set("referenceSequences",refseqs)
			}))
		},

		getReferenceSequences: function(gid, includeSequences, refresh){

			var query = "?eq(genome_id," + gid + ")&select(topology,gi,accession,length,sequence_id,gc_content,owner,sequence_type,taxon_id,public,genome_id,genome_name,date_inserted,date_modified" + (includeSequences?",sequence":"")+ ")&sort(+accession)&limit(1000)";

			return xhr.get(this.apiServiceUrl + "/genome_sequence/" + query, {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(refseqs){
				refseqs = refseqs.map(function(r){
					r.name = r.accession;
					r.start = 0;
					r.end = r.length;
					return r;
				}).sort(function(a,b){
					return a.name > b.name;
				})
				return refseqs;
			}));
		},

		addFeatureTrack: function(title, gid, filter, strand,fill,stroke,background){
			var fields=["feature_id","feature_type","sequence_id","segments","gi","na_length","pos_group","strand","public","aa_length","patric_id","owner",
						"location","protein_id","refseq_locus_tag","taxon_id","accession","end", "genome_name", "product","genome_id","annotation","start"]

			var query =  "?and(eq(genome_id," + gid + "),ne(feature_type,source)," + filter + ")&sort(+accession,+start)" + "&select(" + fields.join(",") + ")&limit(25000)";

			var track = this.viewer.addTrack({
				type: SectionTrack,
				options: {
					title: title, loadingText: "LOADING " + title.toUpperCase(), loading: true, trackWidth: 0.08,fill: fill, stroke: stroke, gap: 0, background: background,
					formatPopupContent: function(item){
						return item.patric_id + " (" + item.feature_type + ")
Product: " + item.product + "
Location: " + item.location;
					},
					formatDialogContent: function(item){
						return DataItemFormatter(item,"feature_data")
					}
				}
			})

			return xhr.get(this.apiServiceUrl + "/genome_feature/" + query, {
				headers: {
					accept: "application/json",
					'X-Requested-With': null,
					'Authorization': (window.App.authorizationToken || "")
				},
				handleAs: "json"
			}).then(lang.hitch(this, function(refseqs){
				refseqs = refseqs.filter(function(r){
					if (strand === null){ return true};
					if (strand){
						return r.strand && r.strand=="+"
					}else{
						return r.strand != "+";
					}
				}).map(function(r){
					r.name = r.accession;
					r.length = r.end - r.start;
					return r;
				}).sort(function(a,b){
					return a.name > b.name;
				})

				track.set("data", refseqs)

				return refseqs;
			}));
		},

		onSetReferenceSequences: function(attr,oldVal, refseqs){
			console.log("RefSeqs: ", refseqs);

			this.viewer.addTrack({
				type: SectionTrack,
				options: {title: "Contigs/Chromosomes",trackWidth: 0.02,fill: "#000F7D", stroke: null, gap: .5, background: {fill: null, stroke: null}},
				data: refseqs
			},"perimeter",true);

			this.addFeatureTrack("CDS - FWD",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,CDS),eq(strand,\+))", true, "#307D32", null)
			this.addFeatureTrack("CDS - REV",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,CDS),eq(strand,%22-%22))", false, "#833B76", null)

			var fillFn = function(item){
				switch(item.feature_type){
					case "pseudogene":
						return "#75DF6F"
					case "tRNA":
						return "#3F76DF"
					case "rRNA":
						return "#DFC63A"
					default:
						return "#21DFD7"
				}
			}
			this.addFeatureTrack("Non-CDS Features",this.state.genome_ids[0], "and(eq(annotation,PATRIC),ne(feature_type,CDS))", false, fillFn,null, {fill: null,stroke: null})
			// this.addFeatureTrack("Pseudogenes",this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,pseudogene))", null, [77, 83, 233], null, {stroke: "", fill: "#eeeeee"})
			// this.addFeatureTrack("tRNA", this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,tRNA))", null, [162, 0, 152], null, {stroke: ""})
			// this.addFeatureTrack("rRNA", this.state.genome_ids[0], "and(eq(annotation,PATRIC),eq(feature_type,rRNA))", null, [243, 110, 0], null, {stroke: "",fill: "#eeeeee"})

			var gcContentTrack = this.viewer.addTrack({
				type: LineTrack,

				options: {title: "GC Content",loadingText: "LOADING GC CONTENT", visible: false, max: .6, min: 0,trackWidth: 0.18,stroke: {width: .5,color: "black"}, gap: .35, background: {fill: "#EBD4F4", stroke: null}},
			},"outer")

			var gcSkewTrack = this.viewer.addTrack({
				type: LineTrack,
				options: {title: "GC Skew",loadingText: "LOADING GC SKEW", visible: false, max: 1, min: -1, scoreProperty: "skew", trackWidth: 0.1,stroke: {width: .5,color: "black"}, gap: .35, background: {fill: "#F3CDA0", stroke: null}},
			},"outer")

			this.getReferenceSequences(this.genome_id, true).then(lang.hitch(this, function(data){
				var gcContentData = this.getGCContent(data);
				console.log("GC CONTENT: ", gcContentData);
				gcContentTrack.set('data', gcContentData)
				gcSkewTrack.set('data', gcContentData)
			}))
		},

		getGCContent: function(data,windowSize){
			windowSize = windowSize||400;

			var gcData=[]

			function calculateGC(accession, seq,ws){
				var cur = seq;
				var slen = seq.length;
				var gc=[];
				var current=0;
				for(current=0;current<seq.length;current+=ws){
					var win = seq.substr(current,ws).toUpperCase();
					var wl = win.length;
					var G=0;
					var C=0;
					var gs = win.match(/G/g ||[]);
					if (gs) {
						G = gs.length;
					}

					var cs = win.match(/C/g ||[]);
					if (cs) {
						C = cs.length;
					}

					var GC = G+C; // for skew, (G-C)/(G+C), G+C can't be 0
					if (GC == 0){
						GC = 1;
					}
					gcData.push({accession: accession, score: (G+C)/wl, skew: (G-C)/GC, start: current,end: current+wl});
				}
				return gc;
			}

			data.forEach(function(contig){
					calculateGC(contig.accession, contig.sequence,windowSize);
			})
			return gcData
		},

		onSetState: function(attr,oldVal,state){
			console.log("CircularViewerContainer onSetState", state);
			if (state.genome_ids && state.genome_ids[0]){
				this.set("genome_id", state.genome_ids[0]);
			}
		},

		postCreate: function(){
			this.inherited(arguments);
			this.watch("state", lang.hitch(this, "onSetState"));
			this.watch("genome_id", lang.hitch(this,"onSetGenomeId"));
			this.watch("referenceSequences",lang.hitch(this,"onSetReferenceSequences"));
		},

		visible: false,
		_setVisibleAttr: function(visible) {
			// console.log("GridContainer setVisible: ", visible)
			this.visible = visible;
			if (this.visible && !this._firstView) {
				// console.log("Trigger First View: ", this.id)
				this.onFirstView();
				this._firstView=true;
			}
		},

		onFirstView: function(){
			console.log("onFirstView()")
			if (this._firstView) {
				return;
			}
			if (!this.controlPanel){
				this.controlPanel = new TrackController({region: "left",splitter:true, style:"width:250px;"});
			}

			if (!this.viewer){
				this.viewer = new CirculusViewer({
					region: "center",
					centerRadius: 100
			    });
			}

			this.addChild(this.controlPanel);
			this.addChild(this.viewer);
		}
	});
});

<|endoftext|>


<commit_before>'use strict';
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then((reg) => {
      // console.log('TagSpaces service worker registered.', reg);
      return true;
    }).catch(err => console.warn('Error registering TagSpaces service worker ' + err));
  });
}
<commit_msg>showing hostname for the PWA<commit_after>'use strict';

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then((reg) => {
      document.title = 'TagSpaces PWA - ' + document.location.hostname;
      // console.log('TagSpaces service worker registered.', reg);
      return true;
    }).catch(err => console.warn('Error registering TagSpaces service worker ' + err));
  });
}
<|endoftext|>


<commit_before>/**
 * html2Json 改造来自: https://github.com/Jxck/html2json
 *
 *
 * author: Di (微信小程序开发工程师)
 * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
 *               垂直微信小程序开发交流社区
 *
 * github地址: https://github.com/icindy/wxParse
 *
 * for: 微信小程序富文本解析
 * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
 */

var __placeImgeUrlHttps = "https";
var __emojisReg = '';
var __emojisBaseSrc = '';
var __emojis = {};
var wxDiscode = require('./wxDiscode.js');
var HTMLParser = require('./htmlparser.js');
// Empty Elements - HTML 5
var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
// Block Elements - HTML 5
var block = makeMap("br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");

// Inline Elements - HTML 5
var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");

// Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");

// Attributes that have their values filled in disabled="disabled"
var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");

// Special Elements (can contain anything)
var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
function makeMap(str) {
    var obj = {}, items = str.split(",");
    for (var i = 0; i < items.length; i++)
        obj[items[i]] = true;
    return obj;
}

function q(v) {
    return '"' + v + '"';
}

function removeDOCTYPE(html) {
    return html
        .replace(/<\?xml.*\?>\n/, '')
        .replace(/<.*!doctype.*\>\n/, '')
        .replace(/<.*!DOCTYPE.*\>\n/, '');
}

function html2json(html, bindName) {
    //处理字符串
    html = removeDOCTYPE(html);
    html = wxDiscode.strDiscode(html);
    //生成node节点
    var bufArray = [];
    var results = {
        node: bindName,
        nodes: [],
        images:[],
        imageUrls:[]
    };
    var index = 0;
    HTMLParser(html, {
        start: function (tag, attrs, unary) {
            //debug(tag, attrs, unary);
            // node for this element
            var node = {
                node: 'element',
                tag: tag,
            };

            if (bufArray.length === 0) {
                node.index = index.toString()
                index += 1
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                node.index = parent.index + '.' + parent.nodes.length
            }

            if (block[tag]) {
                node.tagType = "block";
            } else if (inline[tag]) {
                node.tagType = "inline";
            } else if (closeSelf[tag]) {
                node.tagType = "closeSelf";
            }

            if (attrs.length !== 0) {
                node.attr = attrs.reduce(function (pre, attr) {
                    var name = attr.name;
                    var value = attr.value;
                    if (name == 'class') {
                        console.dir(value);
                        //  value = value.join("")
                        node.classStr = value;
                    }
                    // has multi attibutes
                    // make it array of attribute
                    if (name == 'style') {
                        console.dir(value);
                        //  value = value.join("")
                        node.styleStr = value;
                    }
                    if (value.match(/ /)) {
                        value = value.split(' ');
                    }

                    // if attr already exists
                    // merge it
                    if (pre[name]) {
                        if (Array.isArray(pre[name])) {
                            // already array, push to last
                            pre[name].push(value);
                        } else {
                            // single value, make it array
                            pre[name] = [pre[name], value];
                        }
                    } else {
                        // not exist, put it
                        pre[name] = value;
                    }

                    return pre;
                }, {});
            }

            //对img添加额外数据
            if (node.tag === 'img') {
                node.imgIndex = results.images.length;
                var imgUrl = node.attr.src;
                if (imgUrl[0] == '') {
                    imgUrl.splice(0, 1);
                }
                imgUrl = wxDiscode.urlToHttpUrl(imgUrl, __placeImgeUrlHttps);
                node.attr.src = imgUrl;
                node.from = bindName;
                results.images.push(node);
                results.imageUrls.push(imgUrl);
            }

            // 处理font标签样式属性
            if (node.tag === 'font') {
                var fontSize = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '-webkit-xxx-large'];
                var styleAttrs = {
                    'color': 'color',
                    'face': 'font-family',
                    'size': 'font-size'
                };
                if (!node.attr.style) node.attr.style = [];
                if (!node.styleStr) node.styleStr = '';
                for (var key in styleAttrs) {
                    if (node.attr[key]) {
                        var value = key === 'size' ? fontSize[node.attr[key]-1] : node.attr[key];
                        node.attr.style.push(styleAttrs[key]);
                        node.attr.style.push(value);
                        node.styleStr += styleAttrs[key] + ': ' + value + ';';
                    }
                }
            }

            //临时记录source资源
            if(node.tag === 'source'){
                results.source = node.attr.src;
            }

            if (unary) {
                // if this tag dosen't have end tag
                // like
                // add to parents
                var parent = bufArray[0] || results;
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                parent.nodes.push(node);
            } else {
                bufArray.unshift(node);
            }
        },
        end: function (tag) {
            //debug(tag);
            // merge into parent tag
            var node = bufArray.shift();
            if (node.tag !== tag) console.error('invalid state: mismatch end tag');

            //当有缓存source资源时于于video补上src资源
            if(node.tag === 'video' && results.source){
                node.attr.src = results.source;
                delete result.source;
            }

            if (bufArray.length === 0) {
                results.nodes.push(node);
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                parent.nodes.push(node);
            }
        },
        chars: function (text) {
            //debug(text);
            var node = {
                node: 'text',
                text: text,
                textArray:transEmojiStr(text)
            };

            if (bufArray.length === 0) {
                results.nodes.push(node);
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                node.index = parent.index + '.' + parent.nodes.length
                parent.nodes.push(node);
            }
        },
        comment: function (text) {
            //debug(text);
            // var node = {
            //     node: 'comment',
            //     text: text,
            // };
            // var parent = bufArray[0];
            // if (parent.nodes === undefined) {
            //     parent.nodes = [];
            // }
            // parent.nodes.push(node);
        },
    });
    return results;
};

function transEmojiStr(str){
  // var eReg = new RegExp("["+__reg+' '+"]");
//   str = str.replace(/\[([^\[\]]+)\]/g,':$1:')

  var emojiObjs = [];
  //如果正则表达式为空
  if(__emojisReg.length == 0 || !__emojis){
      var emojiObj = {}
      emojiObj.node = "text";
      emojiObj.text = str;
      array = [emojiObj];
      return array;
  }
  //这个地方需要调整
  str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
  var eReg = new RegExp("[:]");
  var array = str.split(eReg);
  for(var i = 0; i < array.length; i++){
    var ele = array[i];
    var emojiObj = {};
    if(__emojis[ele]){
      emojiObj.node = "element";
      emojiObj.tag = "emoji";
      emojiObj.text = __emojis[ele];
      emojiObj.baseSrc= __emojisBaseSrc;
    }else{
      emojiObj.node = "text";
      emojiObj.text = ele;
    }
    emojiObjs.push(emojiObj);
  }

  return emojiObjs;
}

function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
    __emojisReg = reg;
    __emojisBaseSrc=baseSrc;
    __emojis=emojis;
}

module.exports = {
    html2json: html2json,
    emojisInit:emojisInit
};

<commit_msg>Fixed: #131<commit_after>/**
 * html2Json 改造来自: https://github.com/Jxck/html2json
 *
 *
 * author: Di (微信小程序开发工程师)
 * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
 *               垂直微信小程序开发交流社区
 *
 * github地址: https://github.com/icindy/wxParse
 *
 * for: 微信小程序富文本解析
 * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
 */

var __placeImgeUrlHttps = "https";
var __emojisReg = '';
var __emojisBaseSrc = '';
var __emojis = {};
var wxDiscode = require('./wxDiscode.js');
var HTMLParser = require('./htmlparser.js');
// Empty Elements - HTML 5
var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
// Block Elements - HTML 5
var block = makeMap("br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");

// Inline Elements - HTML 5
var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");

// Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");

// Attributes that have their values filled in disabled="disabled"
var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");

// Special Elements (can contain anything)
var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
function makeMap(str) {
    var obj = {}, items = str.split(",");
    for (var i = 0; i < items.length; i++)
        obj[items[i]] = true;
    return obj;
}

function q(v) {
    return '"' + v + '"';
}

function removeDOCTYPE(html) {
    return html
        .replace(/<\?xml.*\?>\n/, '')
        .replace(/<.*!doctype.*\>\n/, '')
        .replace(/<.*!DOCTYPE.*\>\n/, '');
}

function trimHtml(html) {
  return html
        .replace(/\n+/g, '')
        .replace(//ig, '')
        .replace(/\/\*.*?\*\//ig, '')
        .replace(/[ ]+</ig, '<')
}

function html2json(html, bindName) {
    //处理字符串
    html = removeDOCTYPE(html);
    html = trimHtml(html);
    html = wxDiscode.strDiscode(html);
    //生成node节点
    var bufArray = [];
    var results = {
        node: bindName,
        nodes: [],
        images:[],
        imageUrls:[]
    };
    var index = 0;
    HTMLParser(html, {
        start: function (tag, attrs, unary) {
            //debug(tag, attrs, unary);
            // node for this element
            var node = {
                node: 'element',
                tag: tag,
            };

            if (bufArray.length === 0) {
                node.index = index.toString()
                index += 1
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                node.index = parent.index + '.' + parent.nodes.length
            }

            if (block[tag]) {
                node.tagType = "block";
            } else if (inline[tag]) {
                node.tagType = "inline";
            } else if (closeSelf[tag]) {
                node.tagType = "closeSelf";
            }

            if (attrs.length !== 0) {
                node.attr = attrs.reduce(function (pre, attr) {
                    var name = attr.name;
                    var value = attr.value;
                    if (name == 'class') {
                        console.dir(value);
                        //  value = value.join("")
                        node.classStr = value;
                    }
                    // has multi attibutes
                    // make it array of attribute
                    if (name == 'style') {
                        console.dir(value);
                        //  value = value.join("")
                        node.styleStr = value;
                    }
                    if (value.match(/ /)) {
                        value = value.split(' ');
                    }

                    // if attr already exists
                    // merge it
                    if (pre[name]) {
                        if (Array.isArray(pre[name])) {
                            // already array, push to last
                            pre[name].push(value);
                        } else {
                            // single value, make it array
                            pre[name] = [pre[name], value];
                        }
                    } else {
                        // not exist, put it
                        pre[name] = value;
                    }

                    return pre;
                }, {});
            }

            //对img添加额外数据
            if (node.tag === 'img') {
                node.imgIndex = results.images.length;
                var imgUrl = node.attr.src;
                if (imgUrl[0] == '') {
                    imgUrl.splice(0, 1);
                }
                imgUrl = wxDiscode.urlToHttpUrl(imgUrl, __placeImgeUrlHttps);
                node.attr.src = imgUrl;
                node.from = bindName;
                results.images.push(node);
                results.imageUrls.push(imgUrl);
            }

            // 处理font标签样式属性
            if (node.tag === 'font') {
                var fontSize = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '-webkit-xxx-large'];
                var styleAttrs = {
                    'color': 'color',
                    'face': 'font-family',
                    'size': 'font-size'
                };
                if (!node.attr.style) node.attr.style = [];
                if (!node.styleStr) node.styleStr = '';
                for (var key in styleAttrs) {
                    if (node.attr[key]) {
                        var value = key === 'size' ? fontSize[node.attr[key]-1] : node.attr[key];
                        node.attr.style.push(styleAttrs[key]);
                        node.attr.style.push(value);
                        node.styleStr += styleAttrs[key] + ': ' + value + ';';
                    }
                }
            }

            //临时记录source资源
            if(node.tag === 'source'){
                results.source = node.attr.src;
            }

            if (unary) {
                // if this tag dosen't have end tag
                // like
                // add to parents
                var parent = bufArray[0] || results;
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                parent.nodes.push(node);
            } else {
                bufArray.unshift(node);
            }
        },
        end: function (tag) {
            //debug(tag);
            // merge into parent tag
            var node = bufArray.shift();
            if (node.tag !== tag) console.error('invalid state: mismatch end tag');

            //当有缓存source资源时于于video补上src资源
            if(node.tag === 'video' && results.source){
                node.attr.src = results.source;
                delete result.source;
            }

            if (bufArray.length === 0) {
                results.nodes.push(node);
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                parent.nodes.push(node);
            }
        },
        chars: function (text) {
            //debug(text);
            var node = {
                node: 'text',
                text: text,
                textArray:transEmojiStr(text)
            };

            if (bufArray.length === 0) {
                results.nodes.push(node);
            } else {
                var parent = bufArray[0];
                if (parent.nodes === undefined) {
                    parent.nodes = [];
                }
                node.index = parent.index + '.' + parent.nodes.length
                parent.nodes.push(node);
            }
        },
        comment: function (text) {
            //debug(text);
            // var node = {
            //     node: 'comment',
            //     text: text,
            // };
            // var parent = bufArray[0];
            // if (parent.nodes === undefined) {
            //     parent.nodes = [];
            // }
            // parent.nodes.push(node);
        },
    });
    return results;
};

function transEmojiStr(str){
  // var eReg = new RegExp("["+__reg+' '+"]");
//   str = str.replace(/\[([^\[\]]+)\]/g,':$1:')

  var emojiObjs = [];
  //如果正则表达式为空
  if(__emojisReg.length == 0 || !__emojis){
      var emojiObj = {}
      emojiObj.node = "text";
      emojiObj.text = str;
      array = [emojiObj];
      return array;
  }
  //这个地方需要调整
  str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
  var eReg = new RegExp("[:]");
  var array = str.split(eReg);
  for(var i = 0; i < array.length; i++){
    var ele = array[i];
    var emojiObj = {};
    if(__emojis[ele]){
      emojiObj.node = "element";
      emojiObj.tag = "emoji";
      emojiObj.text = __emojis[ele];
      emojiObj.baseSrc= __emojisBaseSrc;
    }else{
      emojiObj.node = "text";
      emojiObj.text = ele;
    }
    emojiObjs.push(emojiObj);
  }

  return emojiObjs;
}

function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
    __emojisReg = reg;
    __emojisBaseSrc=baseSrc;
    __emojis=emojis;
}

module.exports = {
    html2json: html2json,
    emojisInit:emojisInit
};

<|endoftext|>


<commit_before>var util = require('util'),
	events = require('events'),
	Q = require('q'),
	helpers = require('../helpers'),
	debug = require('debug')('bp:probes:PerfLogProbe');

function PerfLogProbe() {
	events.EventEmitter.call(this);
}

util.inherits(PerfLogProbe, events.EventEmitter);

PerfLogProbe.prototype.id = 'PerfLogProbe';

PerfLogProbe.prototype.setup = function(cfg) {
	var me = this;
	cfg.browsers = cfg.browsers.map(function(browser) {
		helpers.extend(browser, {
			loggingPrefs: {
				performance: 'ALL'
			}
		});
		return browser;
	});
	return Q(cfg);
};

PerfLogProbe.prototype.start = function(browser) {
	var me = this;
	return browser.logTypes().then(function(logs) {
		debug('Supported log types', logs);
		me.enabled = (logs.indexOf('performance') !== -1);
	}).then(function() {
		if (me.enabled) {
			return browser.log('performance');
		}
	});
};

PerfLogProbe.prototype.teardown = function(browser) {
	if (this.enabled) {
		var me = this;
		return browser.log('performance').then(function(arg) {
			debug('Got Performance log results');
			//require('fs').writeFileSync('_perflog.json', JSON.stringify(arg));
			return arg.map(function(x) {
				if (typeof x.message !== 'undefined') {
					// ChromeDriver - format: message: "[{method:'Tracing.dataCollected', params:{cat:...,pid:...}}]"
					return JSON.parse(x.message).message;
				} else {
					// Appium - format: [{startTime:..., name:..., endTime:...}]
					return {
						method: 'Timeline.eventRecorded',
						params: x
					}
				}
			}).filter(function(d) {
				return (typeof d !== 'undefined');
			});
		}).then(function(data) {
			me.emit('data', {
				type: 'perfLog',
				value: data
			});
		});
	}
};

module.exports = PerfLogProbe;<commit_msg>(refactor): Modify Perflog result inline<commit_after>var util = require('util'),
	events = require('events'),
	Q = require('q'),
	helpers = require('../helpers'),
	debug = require('debug')('bp:probes:PerfLogProbe');

function PerfLogProbe() {
	events.EventEmitter.call(this);
}

util.inherits(PerfLogProbe, events.EventEmitter);

PerfLogProbe.prototype.id = 'PerfLogProbe';

PerfLogProbe.prototype.setup = function(cfg) {
	var me = this;
	cfg.browsers = cfg.browsers.map(function(browser) {
		helpers.extend(browser, {
			loggingPrefs: {
				performance: 'ALL'
			}
		});
		return browser;
	});
	return Q(cfg);
};

PerfLogProbe.prototype.start = function(browser) {
	var me = this;
	return browser.logTypes().then(function(logs) {
		debug('Supported log types', logs);
		me.enabled = (logs.indexOf('performance') !== -1);
	}).then(function() {
		if (me.enabled) {
			return browser.log('performance');
		}
	});
};

PerfLogProbe.prototype.teardown = function(browser) {
	if (this.enabled) {
		var me = this;
		return browser.log('performance').then(function(arg) {
			debug('Got Performance log results');
			//require('fs').writeFileSync('_perflog.json', JSON.stringify(arg));
			arg.forEach(function(x, i) {
				if (typeof x.message !== 'undefined') {
					// ChromeDriver - format: message: "[{method:'Tracing.dataCollected', params:{cat:...,pid:...}}]"
					arg[i] = JSON.parse(x.message).message;
				} else {
					// Appium - format: [{startTime:..., name:..., endTime:...}]
					arg[i] = {
						method: 'Timeline.eventRecorded',
						params: x
					}
				}
			});
			return arg;
		}).then(function(data) {
			me.emit('data', {
				type: 'perfLog',
				value: data
			});
		});
	}
};

module.exports = PerfLogProbe;<|endoftext|>


<commit_before>/*
____________________________________
/ The index JS file, using babel and \
\ browserify.                       /
------------------------------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
               ||----w |
               ||     ||
*/

import getURLParameter from './modules/geturlparams';

// set defaults
let b = [];
let s = [];
let m = 6;
let y = 2015;
let t = '';
let container = document.querySelector("textarea");

// Get URL arguments if passed
//     b   bounds sw.lng, sw.lat, ne.lng, le.lat
//     m   metric number
//     y   year
//     s   selected
//     t   map title
if (getURLParameter('b') !== null) {
    b = getURLParameter('b').split(',');
}
if (getURLParameter('m') !== null) {
    m = getURLParameter('m');
}
if (getURLParameter('y') !== null) {
    y = getURLParameter('y');
}
if (getURLParameter('s') !== null) {
    s = getURLParameter('s').split(",");
}
if (getURLParameter('t') !== null) {
    t = getURLParameter('t');
}

// set iframe src
document.querySelector('.embed iframe').src = setURL(m, y, b, s, t);
setEmbed(setURL(m, y, b, s, t), container);

// URL for the iframe
function setURL(m, y, b, s, t) {
    let url = `${window.location.href.substring(0, window.location.href.lastIndexOf("/")) + '/embed.html'}?m=${m}&y=${y}&b=${b}&s=${s}&t=${encodeURI(t)}`;
    return url;
}

// iframe tag for copying by user
function setEmbed(url, con) {
    con.value = `<iframe src="${url}" width="500px" height="600px"></iframe>`;
}

// parent/iframe communications
window.titleChange = function (title) {
    t = title;
    document.querySelector("iframe").contentWindow.postMessage({"title": t}, '*');
    setEmbed(setURL(m, y, b, s, t), container);
};
window.onmessage = function(e){
    let data = e.data;
    if (data.bounds) {
        b = data.bounds;
    }
    if (data.maptitle) {
        t = data.maptitle;
        document.querySelector("#maptitle").value = t;
    }
    setEmbed(setURL(m, y, b, s, t), container);
};
<commit_msg>changed embed code styling<commit_after>/*
____________________________________
/ The index JS file, using babel and \
\ browserify.                       /
------------------------------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/\
               ||----w |
               ||     ||
*/

import getURLParameter from './modules/geturlparams';

// set defaults
let b = [];
let s = [];
let m = 6;
let y = 2015;
let t = '';
let container = document.querySelector("textarea");

// Get URL arguments if passed
//     b   bounds sw.lng, sw.lat, ne.lng, le.lat
//     m   metric number
//     y   year
//     s   selected
//     t   map title
if (getURLParameter('b') !== null) {
    b = getURLParameter('b').split(',');
}
if (getURLParameter('m') !== null) {
    m = getURLParameter('m');
}
if (getURLParameter('y') !== null) {
    y = getURLParameter('y');
}
if (getURLParameter('s') !== null) {
    s = getURLParameter('s').split(",");
}
if (getURLParameter('t') !== null) {
    t = getURLParameter('t');
}

// set iframe src
document.querySelector('.embed iframe').src = setURL(m, y, b, s, t);
setEmbed(setURL(m, y, b, s, t), container);

// URL for the iframe
function setURL(m, y, b, s, t) {
    let url = `${window.location.href.substring(0, window.location.href.lastIndexOf("/")) + '/embed.html'}?m=${m}&y=${y}&b=${b}&s=${s}&t=${encodeURI(t)}`;
    return url;
}

// iframe tag for copying by user
function setEmbed(url, con) {
    con.value = `<iframe src="${url}" style="width: 500px; height: 500px; border: 1px solid #595959"></iframe>`;
}

// parent/iframe communications
window.titleChange = function (title) {
    t = title;
    document.querySelector("iframe").contentWindow.postMessage({"title": t}, '*');
    setEmbed(setURL(m, y, b, s, t), container);
};
window.onmessage = function(e){
    let data = e.data;
    if (data.bounds) {
        b = data.bounds;
    }
    if (data.maptitle) {
        t = data.maptitle;
        document.querySelector("#maptitle").value = t;
    }
    setEmbed(setURL(m, y, b, s, t), container);
};
<|endoftext|>


<commit_before>/**
 * Data wrapper around the api provided by Visma
 */
import Url from 'url'
import assert from 'assert'
import toVismaQuery from './utils/toVismaQuery'
import toVismaCompareQuery from './utils/toVismaCompareQuery'
import {wrap, httpStatusToErrorCode} from './utils/errors'

function wrapError(error) {
  const code = httpStatusToErrorCode(error.statusCode)
  const details = {
    message: error.json ? error.json.Message : error.stack
  }

  return Promise.reject(wrap(error, code, details))
}

function upCaseKeys(object) {
  return Object.keys(object).reduce((downcased, key) => {
    const downcasedKey = key.substring(0, 1).toUpperCase() + key.substring(1)
    downcased[downcasedKey] = object[key]
    return downcased
  }, {})
}

function sortHeaderGroupVariable(variable, sortFn) {
  return headerGroups => {
    return headerGroups.map(headerGroup => {
      if (!headerGroup[variable]) {
        return headerGroup
      }
      return Object.assign({}, headerGroup, {
        [variable]: headerGroup[variable].slice().sort(sortFn)
      })
    })
  }
}

export function create({baseUrl, connector} = {}) {

  assert(baseUrl, 'Missing required option `baseUrl` when calling create(...) in Visma API Client')
  assert(connector, 'Missing required option `connector` when calling create(...) in Visma API Client')

  const parsedBaseUrl = Url.parse(baseUrl)
  const headerGroupsCache = {}

  return {
    _getTables, // only used by tests for now
    getHeaderGroups,
    query
  }

  function _getTables() {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, 'metadata/tables')
      })
      return connector
        .get(Url.format(url))
        .then(response => response.json)
        .catch(wrapError)
    })
  }

  function getHeaderGroups(table) {
    if (headerGroupsCache[table]) {
      return headerGroupsCache[table]
    }
    headerGroupsCache[table] = _getHeaderGroups(table)
      .catch(error => {
        delete headerGroupsCache[table]
        return Promise.reject(error)
      })
    return headerGroupsCache[table]
  }

  function _getHeaderGroups(table) {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, `metadata/headergroups/${table}`)
      })
      return connector
        .get(Url.format(url))
        .then(response => response.json)
        .then(sortHeaderGroupVariable('aar', (year, otherYear) => Number(year) - Number(otherYear)))
        .catch(wrapError)
    })
  }

  function query(q) {
    if ((q.comparisonRegions || []).length > 0) {
      return continuedQueryVisma('data/compare', toVismaCompareQuery(q)).then(res => {
        console.log('data', res)
        return res
      })
    }
    // TODO: Move over to data/compare for all queries
    return continuedQueryVisma('data/query', toVismaQuery(q))
  }

  function continuedQueryVisma(endpoint, vismaQuery, continuationToken) {

    return queryVisma(endpoint, vismaQuery, continuationToken).then(response => {

      const {continuation:newContinuationToken, data} = response
      if (!newContinuationToken) {
        return data
      }

      return continuedQueryVisma(endpoint, vismaQuery, newContinuationToken).then(nextResult => {
        return data.concat(nextResult)
      })

    })
  }

  function queryVisma(endpoint, vismaQuery, continuationToken) {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, endpoint)
      })

      vismaQuery = Object.assign({}, toQueryParams(vismaQuery))

      if (continuationToken) {
        vismaQuery.continuation = continuationToken
      }

      console.info("My query", vismaQuery)

      return connector
        .post(Url.format(url), vismaQuery)
        .then(response => response.json)
        .catch(wrapError)
    })
  }
}

function toQueryParams(query) {
  // Todo: validate query

  // This fixes inconsistent key casing in api endpoint
  return upCaseKeys(query)
}
<commit_msg>Remove logging<commit_after>/**
 * Data wrapper around the api provided by Visma
 */
import Url from 'url'
import assert from 'assert'
import toVismaQuery from './utils/toVismaQuery'
import toVismaCompareQuery from './utils/toVismaCompareQuery'
import {wrap, httpStatusToErrorCode} from './utils/errors'

function wrapError(error) {
  const code = httpStatusToErrorCode(error.statusCode)
  const details = {
    message: error.json ? error.json.Message : error.stack
  }

  return Promise.reject(wrap(error, code, details))
}

function upCaseKeys(object) {
  return Object.keys(object).reduce((downcased, key) => {
    const downcasedKey = key.substring(0, 1).toUpperCase() + key.substring(1)
    downcased[downcasedKey] = object[key]
    return downcased
  }, {})
}

function sortHeaderGroupVariable(variable, sortFn) {
  return headerGroups => {
    return headerGroups.map(headerGroup => {
      if (!headerGroup[variable]) {
        return headerGroup
      }
      return Object.assign({}, headerGroup, {
        [variable]: headerGroup[variable].slice().sort(sortFn)
      })
    })
  }
}

export function create({baseUrl, connector} = {}) {

  assert(baseUrl, 'Missing required option `baseUrl` when calling create(...) in Visma API Client')
  assert(connector, 'Missing required option `connector` when calling create(...) in Visma API Client')

  const parsedBaseUrl = Url.parse(baseUrl)
  const headerGroupsCache = {}

  return {
    _getTables, // only used by tests for now
    getHeaderGroups,
    query
  }

  function _getTables() {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, 'metadata/tables')
      })
      return connector
        .get(Url.format(url))
        .then(response => response.json)
        .catch(wrapError)
    })
  }

  function getHeaderGroups(table) {
    if (headerGroupsCache[table]) {
      return headerGroupsCache[table]
    }
    headerGroupsCache[table] = _getHeaderGroups(table)
      .catch(error => {
        delete headerGroupsCache[table]
        return Promise.reject(error)
      })
    return headerGroupsCache[table]
  }

  function _getHeaderGroups(table) {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, `metadata/headergroups/${table}`)
      })
      return connector
        .get(Url.format(url))
        .then(response => response.json)
        .then(sortHeaderGroupVariable('aar', (year, otherYear) => Number(year) - Number(otherYear)))
        .catch(wrapError)
    })
  }

  function query(q) {
    if ((q.comparisonRegions || []).length > 0) {
      return continuedQueryVisma('data/compare', toVismaCompareQuery(q)).then(res => {
        return res
      })
    }
    // TODO: Move over to data/compare for all queries
    return continuedQueryVisma('data/query', toVismaQuery(q))
  }

  function continuedQueryVisma(endpoint, vismaQuery, continuationToken) {

    return queryVisma(endpoint, vismaQuery, continuationToken).then(response => {

      const {continuation:newContinuationToken, data} = response
      if (!newContinuationToken) {
        return data
      }

      return continuedQueryVisma(endpoint, vismaQuery, newContinuationToken).then(nextResult => {
        return data.concat(nextResult)
      })

    })
  }

  function queryVisma(endpoint, vismaQuery, continuationToken) {
    return Promise.resolve().then(() => {
      const url = Url.format({
        protocol: parsedBaseUrl.protocol,
        host: parsedBaseUrl.host,
        pathname: Url.resolve(parsedBaseUrl.pathname, endpoint)
      })

      vismaQuery = Object.assign({}, toQueryParams(vismaQuery))

      if (continuationToken) {
        vismaQuery.continuation = continuationToken
      }

      return connector
        .post(Url.format(url), vismaQuery)
        .then(response => response.json)
        .catch(wrapError)
    })
  }
}

function toQueryParams(query) {
  // Todo: validate query

  // This fixes inconsistent key casing in api endpoint
  return upCaseKeys(query)
}
<|endoftext|>


<commit_before>import url from 'url';
import validator from 'validator';

function normalizeUrl(testUrl) {
    // add protocol if protocol not found
    let normalized = testUrl;
    const parsed = url.parse(normalized);
    if (!parsed.protocol) {
        normalized = 'http://' + normalized;
    }
    if (!validator.isURL(normalized, {require_protocol: true, require_tld: false})) {
        throw `Your Url: "${normalized}" is invalid!`;
    }
    return normalized;
}

export default normalizeUrl;
<commit_msg>Fix #308 - Allow mDNS addresses (ending with 'local.') during URL validation (#346)<commit_after>import url from 'url';
import validator from 'validator';

function normalizeUrl(testUrl) {
    // add protocol if protocol not found
    let normalized = testUrl;
    const parsed = url.parse(normalized);
    if (!parsed.protocol) {
        normalized = 'http://' + normalized;
    }

    const validatorOptions = {
        require_protocol: true,
        require_tld: false,
        allow_trailing_dot: true // mDNS addresses, https://github.com/jiahaog/nativefier/issues/308
    };
    if (!validator.isURL(normalized, validatorOptions)) {
        throw `Your Url: "${normalized}" is invalid!`;
    }
    return normalized;
}

export default normalizeUrl;
<|endoftext|>


<commit_before>var EmberCore = require('../../../lib/helpers/ember-core');
var JsFile = require('jscs/lib/js-file');
var createFixtureLoader = require('fixture-loader');
var esprima = require('esprima');
var assert = require('assert');

describe('lib/helpers/ember-core', function() {
  var checker = global.checker({
    plugins: ['./lib/index']
  });

  beforeEach(function() {
    fixtureLoader = createFixtureLoader.create(__dirname, '../../fixtures');
    BASE_PATH = './ember';
  });

  describe('basic ember application', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'basic.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'basic.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === 'Ember');
    });

    it('should find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');

      assert(3 === viewClasses.length);

      // App.TeacherView
      assert(17 === viewClasses[0].loc.start.line);
      assert(24 === viewClasses[0].loc.start.column);
      assert(17 === viewClasses[0].loc.end.line);
      assert(28 === viewClasses[0].loc.end.column);

      // App.StudentView
      assert(21 === viewClasses[1].loc.start.line);
      assert(24 === viewClasses[1].loc.start.column);
      assert(21 === viewClasses[1].loc.end.line);
      assert(28 === viewClasses[1].loc.end.column);

      // App.StudentView.emptyView
      assert(23 === viewClasses[2].loc.start.line);
      assert(21 === viewClasses[2].loc.start.column);
      assert(23 === viewClasses[2].loc.end.line);
      assert(25 === viewClasses[2].loc.end.column);
    });

    it('should find Ember helper functions', function() {
      var keys = ember.findEmberFunction('keys', 0);
      assert(1 === keys.length);
    });

    it('should not find Ember helper functions if argument length not match', function() {
      var keys = ember.findEmberFunction('keys', 10);
      assert(0 === keys.length);
    });

    it('should find .extend() blocks', function() {
      assert(6 === ember.findExtendBlocks().length);
    });

    it('should find properties in .extend() blocks', function() {
      var properties = ember.findExtendBlocksProperties('students');
      assert(1 === properties.length);
    });
  });

  describe('basic ember application with no ES6 imports', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'basic-no-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'basic-no-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');
      assert(3 === viewClasses.length);

      // App.TeacherView
      assert(15 === viewClasses[0].loc.start.line);
      assert(24 === viewClasses[0].loc.start.column);
      assert(15 === viewClasses[0].loc.end.line);
      assert(28 === viewClasses[0].loc.end.column);

      // App.StudentView
      assert(19 === viewClasses[1].loc.start.line);
      assert(24 === viewClasses[1].loc.start.column);
      assert(19 === viewClasses[1].loc.end.line);
      assert(28 === viewClasses[1].loc.end.column);

      // App.StudentView.emptyView
      assert(21 === viewClasses[2].loc.start.line);
      assert(21 === viewClasses[2].loc.start.column);
      assert(21 === viewClasses[2].loc.end.line);
      assert(25 === viewClasses[2].loc.end.column);
    });
  });

  describe('malformed ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'bad-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'bad-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should not find Ember import statement', function() {
      assert(ember.emberImport() === false);
    });
  });

  describe('unconventional ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'em-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'em-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === 'Em');
    });

    it('should not find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');
      assert(0 === viewClasses.length);
    });
  });

  describe('multiple ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'multiple-ember-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'multiple-ember-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === false);
    });
  });
});
<commit_msg>Add additional assertions to findExtendBlocksProperties() test<commit_after>var EmberCore = require('../../../lib/helpers/ember-core');
var JsFile = require('jscs/lib/js-file');
var createFixtureLoader = require('fixture-loader');
var esprima = require('esprima');
var assert = require('assert');

describe('lib/helpers/ember-core', function() {
  var checker = global.checker({
    plugins: ['./lib/index']
  });

  beforeEach(function() {
    fixtureLoader = createFixtureLoader.create(__dirname, '../../fixtures');
    BASE_PATH = './ember';
  });

  describe('basic ember application', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'basic.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'basic.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === 'Ember');
    });

    it('should find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');

      assert(3 === viewClasses.length);

      // App.TeacherView
      assert(17 === viewClasses[0].loc.start.line);
      assert(24 === viewClasses[0].loc.start.column);
      assert(17 === viewClasses[0].loc.end.line);
      assert(28 === viewClasses[0].loc.end.column);

      // App.StudentView
      assert(21 === viewClasses[1].loc.start.line);
      assert(24 === viewClasses[1].loc.start.column);
      assert(21 === viewClasses[1].loc.end.line);
      assert(28 === viewClasses[1].loc.end.column);

      // App.StudentView.emptyView
      assert(23 === viewClasses[2].loc.start.line);
      assert(21 === viewClasses[2].loc.start.column);
      assert(23 === viewClasses[2].loc.end.line);
      assert(25 === viewClasses[2].loc.end.column);
    });

    it('should find Ember helper functions', function() {
      var keys = ember.findEmberFunction('keys', 0);
      assert(1 === keys.length);
    });

    it('should not find Ember helper functions if argument length not match', function() {
      var keys = ember.findEmberFunction('keys', 10);
      assert(0 === keys.length);
    });

    it('should find .extend() blocks', function() {
      assert(6 === ember.findExtendBlocks().length);
    });

    it('should find properties in .extend() blocks', function() {
      var properties = ember.findExtendBlocksProperties('students');
      assert(1 === properties.length);

      var property = properties[0];
      assert('Property' === property.type);
      assert('students' === property.key.name);
      assert('Identifier' === property.key.type);
      assert(null === property.value.value);
    });
  });

  describe('basic ember application with no ES6 imports', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'basic-no-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'basic-no-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');
      assert(3 === viewClasses.length);

      // App.TeacherView
      assert(15 === viewClasses[0].loc.start.line);
      assert(24 === viewClasses[0].loc.start.column);
      assert(15 === viewClasses[0].loc.end.line);
      assert(28 === viewClasses[0].loc.end.column);

      // App.StudentView
      assert(19 === viewClasses[1].loc.start.line);
      assert(24 === viewClasses[1].loc.start.column);
      assert(19 === viewClasses[1].loc.end.line);
      assert(28 === viewClasses[1].loc.end.column);

      // App.StudentView.emptyView
      assert(21 === viewClasses[2].loc.start.line);
      assert(21 === viewClasses[2].loc.start.column);
      assert(21 === viewClasses[2].loc.end.line);
      assert(25 === viewClasses[2].loc.end.column);
    });
  });

  describe('malformed ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'bad-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'bad-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should not find Ember import statement', function() {
      assert(ember.emberImport() === false);
    });
  });

  describe('unconventional ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'em-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'em-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === 'Em');
    });

    it('should not find Ember classes', function() {
      var viewClasses = ember.findEmberClass('View');
      assert(0 === viewClasses.length);
    });
  });

  describe('multiple ember import', function() {
    beforeEach(function() {
      var fixture = fixtureLoader.loadString(BASE_PATH, 'multiple-ember-import.fixture');
      var file = new JsFile({
        source: fixture,
        filename: 'multiple-ember-import.fixture',
        esprima: esprima
      });
      ember = new EmberCore(file);
    });

    it('should find Ember import statement', function() {
      assert(ember.emberImport() === false);
    });
  });
});
<|endoftext|>


<commit_before>const async = require('async');
const { errors, versioning } = require('arsenal');

const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const services = require('../services');
const { pushMetric } = require('../utapi/utilities');
const createAndStoreObject = require('./apiUtils/object/createAndStoreObject');
const { decodeVersionId, preprocessingVersioningDelete }
    = require('./apiUtils/object/versioning');
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
const { isObjectLocked } = require('./apiUtils/object/objectLockHelpers');

const versionIdUtils = versioning.VersionID;
const objectLockedError = new Error('object locked');

/**
 * objectDelete - DELETE an object from a bucket
 * @param {AuthInfo} authInfo - requester's infos
 * @param {object} request - request object given by router,
 *                           includes normalized headers
 * @param {Logger} log - werelogs request instance
 * @param {function} cb - final cb to call with the result and response headers
 * @return {undefined}
 */
function objectDelete(authInfo, request, log, cb) {
    log.debug('processing request', { method: 'objectDelete' });
    if (authInfo.isRequesterPublicUser()) {
        log.debug('operation not available for public user');
        return cb(errors.AccessDenied);
    }
    const bucketName = request.bucketName;
    const objectKey = request.objectKey;

    const decodedVidResult = decodeVersionId(request.query);
    if (decodedVidResult instanceof Error) {
        log.trace('invalid versionId query', {
            versionId: request.query.versionId,
            error: decodedVidResult,
        });
        return cb(decodedVidResult);
    }
    const reqVersionId = decodedVidResult;

    const valParams = {
        authInfo,
        bucketName,
        objectKey,
        versionId: reqVersionId,
        requestType: 'objectDelete',
    };

    const canonicalID = authInfo.getCanonicalID();
    return async.waterfall([
        function validateBucketAndObj(next) {
            return metadataValidateBucketAndObj(valParams, log,
            (err, bucketMD, objMD) => {
                if (err) {
                    return next(err, bucketMD);
                }
                const versioningCfg = bucketMD.getVersioningConfiguration();
                if (!objMD) {
                    if (!versioningCfg) {
                        return next(errors.NoSuchKey, bucketMD);
                    }
                    // AWS does not return an error when trying to delete a
                    // specific version that does not exist. We skip to the end
                    // of the waterfall here.
                    if (reqVersionId) {
                        log.debug('trying to delete specific version ' +
                        ' that does not exist');
                        return next(errors.NoSuchVersion, bucketMD);
                    }
                    // To adhere to AWS behavior, create a delete marker even
                    // if trying to delete an object that does not exist when
                    // versioning has been configured
                    return next(null, bucketMD, objMD);
                }
                // AWS only returns an object lock error if a version id
                // is specified, else continue to create a delete marker
                if (reqVersionId &&
                isObjectLocked(bucketMD, objMD, request.headers)) {
                    log.debug('trying to delete locked object');
                    return next(objectLockedError, bucketMD);
                }
                if (reqVersionId && objMD.location &&
                    Array.isArray(objMD.location) && objMD.location[0]) {
                    // we need this information for data deletes to AWS
                    // eslint-disable-next-line no-param-reassign
                    objMD.location[0].deleteVersion = true;
                }
                if (objMD['content-length'] !== undefined) {
                    log.end().addDefaultFields({
                        bytesDeleted: objMD['content-length'],
                    });
                }
                return next(null, bucketMD, objMD);
            });
        },
        function getVersioningInfo(bucketMD, objectMD, next) {
            return preprocessingVersioningDelete(bucketName,
                bucketMD, objectMD, reqVersionId, log,
                (err, options) => {
                    if (err) {
                        log.error('err processing versioning info',
                        { error: err });
                        return next(err, bucketMD);
                    }
                    return next(null, bucketMD, objectMD, options);
                });
        },
        function deleteOperation(bucketMD, objectMD, delOptions, next) {
            const deleteInfo = {
                removeDeleteMarker: false,
                newDeleteMarker: false,
            };
            if (delOptions && delOptions.deleteData) {
                if (objectMD.isDeleteMarker) {
                    // record that we deleted a delete marker to set
                    // response headers accordingly
                    deleteInfo.removeDeleteMarker = true;
                }
                return services.deleteObject(bucketName, objectMD, objectKey,
                    delOptions, log, (err, delResult) => next(err, bucketMD,
                    objectMD, delResult, deleteInfo));
            }
            // putting a new delete marker
            deleteInfo.newDeleteMarker = true;
            return createAndStoreObject(bucketName, bucketMD,
                objectKey, objectMD, authInfo, canonicalID, null, request,
                deleteInfo.newDeleteMarker, null, log, (err, newDelMarkerRes) =>
                next(err, bucketMD, objectMD, newDelMarkerRes, deleteInfo));
        },
    ], (err, bucketMD, objectMD, result, deleteInfo) => {
        const resHeaders = collectCorsHeaders(request.headers.origin,
            request.method, bucketMD);
        // if deleting a specific version or delete marker, return version id
        // in the response headers, even in case of NoSuchVersion
        if (reqVersionId) {
            resHeaders['x-amz-version-id'] = reqVersionId === 'null' ?
                reqVersionId : versionIdUtils.encode(reqVersionId);
            if (deleteInfo && deleteInfo.removeDeleteMarker) {
                resHeaders['x-amz-delete-marker'] = true;
            }
        }
        if (err === objectLockedError) {
            log.error('error deleting object', { error: errors.AccessDenied,
                objectLocked: true, method: 'objectDelete' });
            return cb(errors.AccessDenied, resHeaders);
        }
        if (err) {
            log.debug('error processing request', { error: err,
                method: 'objectDelete' });
            return cb(err, resHeaders);
        }
        if (deleteInfo.newDeleteMarker) {
            // if we created a new delete marker, return true for
            // x-amz-delete-marker and the version ID of the new delete marker
            if (result.versionId) {
                resHeaders['x-amz-delete-marker'] = true;
                resHeaders['x-amz-version-id'] = result.versionId === 'null' ?
                    result.versionId : versionIdUtils.encode(result.versionId);
            }
            pushMetric('putDeleteMarkerObject', log, { authInfo,
                bucket: bucketName, keys: [objectKey] });
        } else {
            log.end().addDefaultFields({
                contentLength: objectMD['content-length'],
            });
            pushMetric('deleteObject', log, {
                authInfo,
                canonicalID: bucketMD.getOwner(),
                bucket: bucketName,
                keys: [objectKey],
                byteLength: Number.parseInt(objectMD['content-length'], 10),
                numberOfObjects: 1 });
        }
        return cb(err, resHeaders);
    });
}

module.exports = objectDelete;
<commit_msg>bf: S3C-3145 change log to trace<commit_after>const async = require('async');
const { errors, versioning } = require('arsenal');

const collectCorsHeaders = require('../utilities/collectCorsHeaders');
const services = require('../services');
const { pushMetric } = require('../utapi/utilities');
const createAndStoreObject = require('./apiUtils/object/createAndStoreObject');
const { decodeVersionId, preprocessingVersioningDelete }
    = require('./apiUtils/object/versioning');
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
const { isObjectLocked } = require('./apiUtils/object/objectLockHelpers');

const versionIdUtils = versioning.VersionID;
const objectLockedError = new Error('object locked');

/**
 * objectDelete - DELETE an object from a bucket
 * @param {AuthInfo} authInfo - requester's infos
 * @param {object} request - request object given by router,
 *                           includes normalized headers
 * @param {Logger} log - werelogs request instance
 * @param {function} cb - final cb to call with the result and response headers
 * @return {undefined}
 */
function objectDelete(authInfo, request, log, cb) {
    log.debug('processing request', { method: 'objectDelete' });
    if (authInfo.isRequesterPublicUser()) {
        log.debug('operation not available for public user');
        return cb(errors.AccessDenied);
    }
    const bucketName = request.bucketName;
    const objectKey = request.objectKey;

    const decodedVidResult = decodeVersionId(request.query);
    if (decodedVidResult instanceof Error) {
        log.trace('invalid versionId query', {
            versionId: request.query.versionId,
            error: decodedVidResult,
        });
        return cb(decodedVidResult);
    }
    const reqVersionId = decodedVidResult;

    const valParams = {
        authInfo,
        bucketName,
        objectKey,
        versionId: reqVersionId,
        requestType: 'objectDelete',
    };

    const canonicalID = authInfo.getCanonicalID();
    return async.waterfall([
        function validateBucketAndObj(next) {
            return metadataValidateBucketAndObj(valParams, log,
            (err, bucketMD, objMD) => {
                if (err) {
                    return next(err, bucketMD);
                }
                const versioningCfg = bucketMD.getVersioningConfiguration();
                if (!objMD) {
                    if (!versioningCfg) {
                        return next(errors.NoSuchKey, bucketMD);
                    }
                    // AWS does not return an error when trying to delete a
                    // specific version that does not exist. We skip to the end
                    // of the waterfall here.
                    if (reqVersionId) {
                        log.debug('trying to delete specific version ' +
                        ' that does not exist');
                        return next(errors.NoSuchVersion, bucketMD);
                    }
                    // To adhere to AWS behavior, create a delete marker even
                    // if trying to delete an object that does not exist when
                    // versioning has been configured
                    return next(null, bucketMD, objMD);
                }
                // AWS only returns an object lock error if a version id
                // is specified, else continue to create a delete marker
                if (reqVersionId &&
                isObjectLocked(bucketMD, objMD, request.headers)) {
                    log.debug('trying to delete locked object');
                    return next(objectLockedError, bucketMD);
                }
                if (reqVersionId && objMD.location &&
                    Array.isArray(objMD.location) && objMD.location[0]) {
                    // we need this information for data deletes to AWS
                    // eslint-disable-next-line no-param-reassign
                    objMD.location[0].deleteVersion = true;
                }
                if (objMD['content-length'] !== undefined) {
                    log.end().addDefaultFields({
                        bytesDeleted: objMD['content-length'],
                    });
                }
                return next(null, bucketMD, objMD);
            });
        },
        function getVersioningInfo(bucketMD, objectMD, next) {
            return preprocessingVersioningDelete(bucketName,
                bucketMD, objectMD, reqVersionId, log,
                (err, options) => {
                    if (err) {
                        log.error('err processing versioning info',
                        { error: err });
                        return next(err, bucketMD);
                    }
                    return next(null, bucketMD, objectMD, options);
                });
        },
        function deleteOperation(bucketMD, objectMD, delOptions, next) {
            const deleteInfo = {
                removeDeleteMarker: false,
                newDeleteMarker: false,
            };
            if (delOptions && delOptions.deleteData) {
                if (objectMD.isDeleteMarker) {
                    // record that we deleted a delete marker to set
                    // response headers accordingly
                    deleteInfo.removeDeleteMarker = true;
                }
                return services.deleteObject(bucketName, objectMD, objectKey,
                    delOptions, log, (err, delResult) => next(err, bucketMD,
                    objectMD, delResult, deleteInfo));
            }
            // putting a new delete marker
            deleteInfo.newDeleteMarker = true;
            return createAndStoreObject(bucketName, bucketMD,
                objectKey, objectMD, authInfo, canonicalID, null, request,
                deleteInfo.newDeleteMarker, null, log, (err, newDelMarkerRes) =>
                next(err, bucketMD, objectMD, newDelMarkerRes, deleteInfo));
        },
    ], (err, bucketMD, objectMD, result, deleteInfo) => {
        const resHeaders = collectCorsHeaders(request.headers.origin,
            request.method, bucketMD);
        // if deleting a specific version or delete marker, return version id
        // in the response headers, even in case of NoSuchVersion
        if (reqVersionId) {
            resHeaders['x-amz-version-id'] = reqVersionId === 'null' ?
                reqVersionId : versionIdUtils.encode(reqVersionId);
            if (deleteInfo && deleteInfo.removeDeleteMarker) {
                resHeaders['x-amz-delete-marker'] = true;
            }
        }
        if (err === objectLockedError) {
            log.debug('preventing deletion due to object lock',
                {
                    error: errors.AccessDenied,
                    objectLocked: true,
                    method: 'objectDelete',
                });
            return cb(errors.AccessDenied, resHeaders);
        }
        if (err) {
            log.debug('error processing request', { error: err,
                method: 'objectDelete' });
            return cb(err, resHeaders);
        }
        if (deleteInfo.newDeleteMarker) {
            // if we created a new delete marker, return true for
            // x-amz-delete-marker and the version ID of the new delete marker
            if (result.versionId) {
                resHeaders['x-amz-delete-marker'] = true;
                resHeaders['x-amz-version-id'] = result.versionId === 'null' ?
                    result.versionId : versionIdUtils.encode(result.versionId);
            }
            pushMetric('putDeleteMarkerObject', log, { authInfo,
                bucket: bucketName, keys: [objectKey] });
        } else {
            log.end().addDefaultFields({
                contentLength: objectMD['content-length'],
            });
            pushMetric('deleteObject', log, {
                authInfo,
                canonicalID: bucketMD.getOwner(),
                bucket: bucketName,
                keys: [objectKey],
                byteLength: Number.parseInt(objectMD['content-length'], 10),
                numberOfObjects: 1 });
        }
        return cb(err, resHeaders);
    });
}

module.exports = objectDelete;
<|endoftext|>