<commit_before>Meteor.methods({
  'txt2json': function (filename) {
/*  	var sys = Meteor.npmRequire('sys');
	var exec = Meteor.npmRequire('child_process').exec;
*/
    var cdPath ='/uploads/' + Meteor.userId() + '/';
    var inPath=cdPath+filename+".txt";
    var outPath=cdPath+filename+".json"
    var outPath=cdPath+filename+".json"

    shell.exec('dna2json '+inPath+" "+outPath, function(code, output) {
  	 console.log(output);
    });

/*var dna = Meteor.npmRequire('dna2json');
var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');

var JSONStream = Meteor.npmRequire('JSONStream');*/
//console.log(path.join(__meteor_bootstrap__.serverDir,'../web.browser/app'));

//fs.createReadStream(process.cwd()+'/uploads/'+filename+".txt").pipe(dna.createParser()).pipe(JSONStream.stringify()).pipe(fs.createWriteStream(process.cwd()+'/uploads/'+filename+".json"));

//       var t2j = Async.runSync(function(done) {

//       	var txt = fs.readFileSync(path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.txt'), 'utf8');
// //console.log(typeof txt);
// dna.parse(txt, function(err, snps){
//   fs.writeFileSync(path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.json'), JSON.stringify(snps, null, 2));
//         var justForReturning=1;
//       }, function(err, snps){

//       	done(null, snps);
//       });
// });

/*var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');

//var inpath=path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.txt');
//var outpath=path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.json');
var sys = Meteor.npmRequire('sys');
var exec = Meteor.npmRequire('child_process').exec;

var cdPath = process.cwd()+'/uploads/'

function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("cd "+cdPath, puts);
exec("dna2json "+filename+".txt "+filename+".json", puts);*/

// console.log(t2j.result)
// return t2j.result;

/*var sys = Meteor.npmRequire('sys');
var exec = Meteor.npmRequire('child_process').exec;
var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');
var JSONStream = Meteor.npmRequire('JSONStream');

var dna = Meteor.npmRequire('dna2json');

      this.unblock();

      Future = Npm.require('fibers/future');
      var future = new Future();

      var cdPath = process.cwd()+'/uploads/' + Meteor.userId() + '/';
      var inPath=cdPath+filename+".txt";
      var outPath=cdPath+filename+".json"*/

/*      var txt = fs.readFile(inPath, 'utf8',  function (err, data) {
  if (err) throw err;
  console.log("DONE");
});
		dna.parse(txt, function(err, snps){
  	  if (err) {
    		return console.error('Error parsing file:', err.message);
  		}
  		fs.writeFile(outPath, JSON.stringify(snps, null, 2), function (err, data) {
  		if (err) throw err;
  		console.log("Done");
	});

  		future.return(console.log('All done! Your file is at', outPath));
		});
*/
  //	fs.createReadStream(inPath).pipe(dna.createParser()).pipe(JSONStream.stringify()).pipe(fs.createWriteStream(outPath));

/*      var command="cd "+cdPath+" && dna2json "+filename+".txt "+filename+".json";
      exec(command,function(error,stdout,stderr){
          if(error){
              console.log(error);
              throw new Meteor.Error(500,command+" failed");
          }
          future.return(stdout.toString());
      });
*/
//      this.unblock();

/*
      var command2="dna2json "+filename+".txt "+filename+".json";
      exec(command2,function(error,stdout,stderr){
          if(error){
              console.log(error);
              throw new Meteor.Error(500,command2+" failed");
          }
          future.return(stdout.toString());
      });
*/
   //   return future.wait();

},

'dnaAnalysis': function (filename){

var path = Meteor.npmRequire('path');
var gql = Meteor.npmRequire('gql');
var cdPath = process.cwd() +'/uploads/' + Meteor.userId() + '/';
var outPath=cdPath+filename+".json";
var dna = Meteor.npmRequire(outPath);

var result= Risks.findOne({});

console.log(result.DNARiskValues);

for (var key in result.DNARiskValues) {
  if (result.DNARiskValues.hasOwnProperty(key) && result.DNARiskValues[key]!="") {
      //console.log("key   "+key+"value  "+result.DNARiskValues[key]);

      console.log(gql.exact(key,result.DNARiskValues[key]));
  }
}

//var abc=gql.exact('rs334', 'TT');
//var pqr= gql.exact('i3003137', 'AA');

var query = gql.or([abc,pqr]);

var isMatch = query(dna);
console.log(isMatch);

var dna = Meteor.npmRequire(outPath);

console.log("DNARiskValues     " + result);

}

});<commit_msg>GQL OR and AND working<commit_after>Meteor.methods({
  'txt2json': function (filename) {
/*  	var sys = Meteor.npmRequire('sys');
	var exec = Meteor.npmRequire('child_process').exec;
*/
    var cdPath ='/uploads/' + Meteor.userId() + '/';
    var inPath=cdPath+filename+".txt";
    var outPath=cdPath+filename+".json"
    var outPath=cdPath+filename+".json"

    shell.exec('dna2json '+inPath+" "+outPath, function(code, output) {
  	 console.log(output);
    });

/*var dna = Meteor.npmRequire('dna2json');
var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');

var JSONStream = Meteor.npmRequire('JSONStream');*/
//console.log(path.join(__meteor_bootstrap__.serverDir,'../web.browser/app'));

//fs.createReadStream(process.cwd()+'/uploads/'+filename+".txt").pipe(dna.createParser()).pipe(JSONStream.stringify()).pipe(fs.createWriteStream(process.cwd()+'/uploads/'+filename+".json"));

//       var t2j = Async.runSync(function(done) {

//       	var txt = fs.readFileSync(path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.txt'), 'utf8');
// //console.log(typeof txt);
// dna.parse(txt, function(err, snps){
//   fs.writeFileSync(path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.json'), JSON.stringify(snps, null, 2));
//         var justForReturning=1;
//       }, function(err, snps){

//       	done(null, snps);
//       });
// });

/*var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');

//var inpath=path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.txt');
//var outpath=path.join(__meteor_bootstrap__.serverDir, '../web.browser/app/dna1.json');
var sys = Meteor.npmRequire('sys');
var exec = Meteor.npmRequire('child_process').exec;

var cdPath = process.cwd()+'/uploads/'

function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("cd "+cdPath, puts);
exec("dna2json "+filename+".txt "+filename+".json", puts);*/

// console.log(t2j.result)
// return t2j.result;

/*var sys = Meteor.npmRequire('sys');
var exec = Meteor.npmRequire('child_process').exec;
var fs = Meteor.npmRequire('fs');
var path = Meteor.npmRequire('path');
var JSONStream = Meteor.npmRequire('JSONStream');

var dna = Meteor.npmRequire('dna2json');

      this.unblock();

      Future = Npm.require('fibers/future');
      var future = new Future();

      var cdPath = process.cwd()+'/uploads/' + Meteor.userId() + '/';
      var inPath=cdPath+filename+".txt";
      var outPath=cdPath+filename+".json"*/

/*      var txt = fs.readFile(inPath, 'utf8',  function (err, data) {
  if (err) throw err;
  console.log("DONE");
});
		dna.parse(txt, function(err, snps){
  	  if (err) {
    		return console.error('Error parsing file:', err.message);
  		}
  		fs.writeFile(outPath, JSON.stringify(snps, null, 2), function (err, data) {
  		if (err) throw err;
  		console.log("Done");
	});

  		future.return(console.log('All done! Your file is at', outPath));
		});
*/
  //	fs.createReadStream(inPath).pipe(dna.createParser()).pipe(JSONStream.stringify()).pipe(fs.createWriteStream(outPath));

/*      var command="cd "+cdPath+" && dna2json "+filename+".txt "+filename+".json";
      exec(command,function(error,stdout,stderr){
          if(error){
              console.log(error);
              throw new Meteor.Error(500,command+" failed");
          }
          future.return(stdout.toString());
      });
*/
//      this.unblock();

/*
      var command2="dna2json "+filename+".txt "+filename+".json";
      exec(command2,function(error,stdout,stderr){
          if(error){
              console.log(error);
              throw new Meteor.Error(500,command2+" failed");
          }
          future.return(stdout.toString());
      });
*/
   //   return future.wait();

},

'dnaAnalysis': function (filename){

var path = Meteor.npmRequire('path');
var gql = Meteor.npmRequire('gql');
var cdPath = process.cwd() +'/uploads/' + Meteor.userId() + '/';
var outPath=cdPath+filename+".json";
var dna = Meteor.npmRequire(outPath);

var result= Risks.findOne({});

console.log(result.DNARiskValues);

var exactArray=new Array();

for (var key in result.DNARiskValues) {
  if (result.DNARiskValues.hasOwnProperty(key) && result.DNARiskValues[key]!="") {
      //console.log("key   "+key+"value  "+result.DNARiskValues[key]);

      exactArray.push(gql.exact(key,result.DNARiskValues[key]));

  }
}

//var abc=gql.exact('rs334', 'TT');
//var pqr= gql.exact('i3003137', 'AA');

var query = gql.or(exactArray);

var isMatch = query(dna);
console.log(isMatch);

var dna = Meteor.npmRequire(outPath);

console.log("DNARiskValues     " + result);

}

});<|endoftext|>


<commit_before>Meteor.methods({
  newMemberNumber: function () {
    var highestMember = Members.findOne({}, {sort: {number: -1}});
    return highestMember.number + 1;
  },
  findMemberById: function (memberId) {
    var member = Members.findOne(memberId);
    return member;
  },
  findMemberByName: function (memberNumber) {
    var member = Members.findOne({number: memberNumber});
    if (member) {
      return member;
    } else {
      throw new Meteor.Error('member-not-found', "Invalid number");
    }
  },
  sendSMS: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var client = new Twilio({
      from: Meteor.settings.TWILIO.FROM,
      sid: Meteor.settings.TWILIO.SID,
      token: Meteor.settings.TWILIO.TOKEN
    });

    var trade = Trades.findOne(tradeId);
    var member = Members.findOne(trade.member);

    var PNF = LibPhoneNumber.PhoneNumberFormat;
    var phoneUtil = LibPhoneNumber.PhoneNumberUtil.getInstance();

    var phoneNumber = phoneUtil.parse(member.phoneNumber, 'CA');
    var formattedPhoneNumber = phoneUtil.format(phoneNumber, PNF.E164);

    console.log(formattedPhoneNumber);

    var receiptUrl = Meteor.absoluteUrl('trades/' + tradeId);

    console.log(receiptUrl);

    try {
      client.sendSMS({
        to: formattedPhoneNumber,
        body: "Thanks for dealing with Satoshi Counter. Here is a link to your receipt: " + receiptUrl
      });
    } catch (error) {
      throw new Meteor.Error(error.code, error.message, error.moreInfo);
    }
  },
  sendEmail: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var trade = Trades.findOne(tradeId);
    var member = Members.findOne(trade.member);

    var receiptUrl = Meteor.absoluteUrl('trades/' + tradeId);

    Email.send({
      to: member.firstName + member.lastName + "<" + member.email + ">",
      from: "Satoshi Counter <info@satoshicounter.com>",
      subject: "Receipt from Satoshi Counter",
      text: "Thanks for dealing with Satoshi Counter. Here is a link to your receipt: " + receiptUrl
    });
  },
  newTradeNotification: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var trade = Trades.findOne(tradeId);

    var baseCurrency = Currencies.findOne(trade.baseCurrency);
    var counterCurrency = Currencies.findOne(trade.counterCurrency);
    var exchangeRateProvider = ExchangeRateProviders.findOne(trade.exchangeRateProvider);
    var paymentMethodForAmountReceived = PaymentMethods.findOne(trade.paymentMethodForAmountReceived);
    var paymentMethodForAmountSent = PaymentMethods.findOne(trade.paymentMethodForAmountSent);
    var marketValueCurrency = Currencies.findOne(trade.marketValueCurrency);
    var member = Members.findOne(trade.member);
    var employee = Meteor.users.findOne(trade.createdBy);
    var envelope = trade.transactionIdForAmountReceived || "not specified";

    Email.send({
      to: "btcmbc8@gmail.com",
      from: "Satoshi Counter <info@satoshicounter.com>",
      subject: "[Satoshi Counter] New trade notification",
      text: "Price type: " + trade.priceType + "\n" +
            "Base currency: " + baseCurrency.code + "\n" +
            "Counter currency: " + counterCurrency.code + "\n" +
            "Exchange rate provider: " + exchangeRateProvider.name + "\n" +
            "Exchange rate: " + trade.exchangeRate + "\n" +
            "Percentage fee: " + trade.percentageFee + "\n" +
            "Company price: " + trade.companyPrice + "\n" +
            "Amount received: " + trade.amountReceived + "\n" +
            "Payment method (for amount received): " + paymentMethodForAmountReceived.name + "\n" +
            "Amount sent: " + trade.amountSent + "\n" +
            "Payment method (for amount sent): " + paymentMethodForAmountSent.name + "\n" +
            "Market value: " + trade.marketValue + "\n" +
            "Market value currency: " + marketValueCurrency.code + "\n" +
            "Subtotal: " + trade.subtotal + "\n" +
            "Flat fee: " + trade.flatFee + "\n" +
            "Percentage fee (for amount received): " + trade.percentageFeeForAmountReceived + "\n" +
            "Calculated fee (for amount received): " + trade.calculatedFeeForAmountReceived + "\n" +
            "Member: " + member.number + "\n" +
            "Created at: " + trade.createdAt + "\n" +
            "Created by: " + employee.profile.name + "\n" +
            "Envelope: " + envelope + "\n" +
            "Bitcoin address: " + trade.bitcoinAddress
    });

    return tradeId;
  }
});
<commit_msg>add Trade ID<commit_after>Meteor.methods({
  newMemberNumber: function () {
    var highestMember = Members.findOne({}, {sort: {number: -1}});
    return highestMember.number + 1;
  },
  findMemberById: function (memberId) {
    var member = Members.findOne(memberId);
    return member;
  },
  findMemberByName: function (memberNumber) {
    var member = Members.findOne({number: memberNumber});
    if (member) {
      return member;
    } else {
      throw new Meteor.Error('member-not-found', "Invalid number");
    }
  },
  sendSMS: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var client = new Twilio({
      from: Meteor.settings.TWILIO.FROM,
      sid: Meteor.settings.TWILIO.SID,
      token: Meteor.settings.TWILIO.TOKEN
    });

    var trade = Trades.findOne(tradeId);
    var member = Members.findOne(trade.member);

    var PNF = LibPhoneNumber.PhoneNumberFormat;
    var phoneUtil = LibPhoneNumber.PhoneNumberUtil.getInstance();

    var phoneNumber = phoneUtil.parse(member.phoneNumber, 'CA');
    var formattedPhoneNumber = phoneUtil.format(phoneNumber, PNF.E164);

    console.log(formattedPhoneNumber);

    var receiptUrl = Meteor.absoluteUrl('trades/' + tradeId);

    console.log(receiptUrl);

    try {
      client.sendSMS({
        to: formattedPhoneNumber,
        body: "Thanks for dealing with Satoshi Counter. Here is a link to your receipt: " + receiptUrl
      });
    } catch (error) {
      throw new Meteor.Error(error.code, error.message, error.moreInfo);
    }
  },
  sendEmail: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var trade = Trades.findOne(tradeId);
    var member = Members.findOne(trade.member);

    var receiptUrl = Meteor.absoluteUrl('trades/' + tradeId);

    Email.send({
      to: member.firstName + member.lastName + "<" + member.email + ">",
      from: "Satoshi Counter <info@satoshicounter.com>",
      subject: "Receipt from Satoshi Counter",
      text: "Thanks for dealing with Satoshi Counter. Here is a link to your receipt: " + receiptUrl
    });
  },
  newTradeNotification: function (tradeId) {
    if (! Meteor.userId()) {
      throw new Meteor.Error("not-authorized");
    }

    var receiptUrl = Meteor.absoluteUrl('trades/' + tradeId);

    var trade = Trades.findOne(tradeId);

    var baseCurrency = Currencies.findOne(trade.baseCurrency);
    var counterCurrency = Currencies.findOne(trade.counterCurrency);
    var exchangeRateProvider = ExchangeRateProviders.findOne(trade.exchangeRateProvider);
    var paymentMethodForAmountReceived = PaymentMethods.findOne(trade.paymentMethodForAmountReceived);
    var paymentMethodForAmountSent = PaymentMethods.findOne(trade.paymentMethodForAmountSent);
    var marketValueCurrency = Currencies.findOne(trade.marketValueCurrency);
    var member = Members.findOne(trade.member);
    var employee = Meteor.users.findOne(trade.createdBy);
    var envelope = trade.transactionIdForAmountReceived || "not specified";

    Email.send({
      to: "btcmbc8@gmail.com",
      from: "Satoshi Counter <info@satoshicounter.com>",
      subject: "[Satoshi Counter] New trade notification",
      text: receiptUrl + "\n\n" +
            "Trade ID: " + trade._id + "\n" +
            "Price type: " + trade.priceType + "\n" +
            "Base currency: " + baseCurrency.code + "\n" +
            "Counter currency: " + counterCurrency.code + "\n" +
            "Exchange rate provider: " + exchangeRateProvider.name + "\n" +
            "Exchange rate: " + trade.exchangeRate + "\n" +
            "Percentage fee: " + trade.percentageFee + "\n" +
            "Company price: " + trade.companyPrice + "\n" +
            "Amount received: " + trade.amountReceived + "\n" +
            "Payment method (for amount received): " + paymentMethodForAmountReceived.name + "\n" +
            "Amount sent: " + trade.amountSent + "\n" +
            "Payment method (for amount sent): " + paymentMethodForAmountSent.name + "\n" +
            "Market value: " + trade.marketValue + "\n" +
            "Market value currency: " + marketValueCurrency.code + "\n" +
            "Subtotal: " + trade.subtotal + "\n" +
            "Flat fee: " + trade.flatFee + "\n" +
            "Percentage fee (for amount received): " + trade.percentageFeeForAmountReceived + "\n" +
            "Calculated fee (for amount received): " + trade.calculatedFeeForAmountReceived + "\n" +
            "Member: " + member.number + "\n" +
            "Created at: " + trade.createdAt + "\n" +
            "Created by: " + employee.profile.name + "\n" +
            "Envelope: " + envelope + "\n" +
            "Bitcoin address: " + trade.bitcoinAddress
    });

    return tradeId;
  }
});
<|endoftext|>


<commit_before>/*! Leaflet-WFST 0.0.1 2015-03-03 */
(function(window, document, undefined) {

"use strict";

L.XmlUtil = {
    // comes from OL
    namespaces: {
        xlink: "http://www.w3.org/1999/xlink",
        xsi: "http://www.w3.org/2001/XMLSchema-instance",
        wfs: "http://www.opengis.net/wfs",
        gml: "http://www.opengis.net/gml",
        ogc: "http://www.opengis.net/ogc",
        ows: "http://www.opengis.net/ows",
        xmlns: "http://www.w3.org/2000/xmlns/"
    },

    //TODO: есть ли нормальная реализация для создания нового документа с doctype text/xml?
    xmldoc: (new DOMParser()).parseFromString('<root />', 'text/xml'),

    setAttributes: function (node, attributes) {
        for (var name in attributes) {
            if (attributes[name] != null && attributes[name].toString) {
                var value = attributes[name].toString();
                var uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
                node.setAttributeNS(uri, name, value);
            }
        }
    },

    evaluate: function (xpath, rawxml) {
        var parser = new DOMParser();
        var xmlDoc = parser.parseFromString(rawxml, 'text/xml');
        var xpe = new XPathEvaluator();
        var nsResolver = xpe.createNSResolver(xmlDoc.documentElement);

        return xpe.evaluate(xpath, xmlDoc, nsResolver, XPathResult.ANY_TYPE, null);
    },

    createElementNS: function (name, attributes, options) {
        options = options || {};

        var uri = options.uri;

        if (!uri) {
            uri = this.namespaces[name.substring(0, name.indexOf(":"))];
        }

        if (!uri) {
            uri = this.namespaces[options.prefix];
        }

        var node = uri ? this.xmldoc.createElementNS(uri, name) : this.xmldoc.createElement(name);

        if (attributes) {
            this.setAttributes(node, attributes);
        }

        if (options.value != null) {
            node.appendChild(this.xmldoc.createTextNode(options.value));
        }

        return node;
    },

    createTextNode: function (value) {
        return this.xmldoc.createTextNode(value);
    },

    createXmlDocumentString: function (node) {
        var doc = document.implementation.createDocument("", "", null);
        doc.appendChild(node);
        var serializer = new XMLSerializer();
        return serializer.serializeToString(doc);
    },

    createXmlString: function (node) {
        var serializer = new XMLSerializer();
        return serializer.serializeToString(node);
    }

};
L.Util.request = function (options) {
    options = L.extend({
        async: true,
        method: 'POST',
        data: '',
        params: {},
        headers: {},
        url: window.location.href,
        success: function (data) {
            console.log(data);
        },
        error: function (data) {
            console.log('Ajax fail');
            console.log(data);
        }
    }, options);

    // good bye IE 6,7
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                options.success(xhr.responseText);
            } else {
                options.error(xhr.responseText);
            }
        }
    };

    var url = options.url + L.Util.getParamString(options.params, options.url);

    xhr.open(options.method, url, options.async);
    for (var header in options.headers) {
        xhr.setRequestHeader(header, options.headers[header]);
    }

    xhr.send(options.data);
};
L.Filter = L.Class.extend({
    initialize: function () {
        this.filter = L.XmlUtil.createElementNS('ogc:Filter');
    },

    /**
     * Represents this filter as GML node
     *
     * Returns:
     * {XmlElement} Gml representation of this filter
     */
    toGml: function () {
        return this.filter;
    },

    append: function () {
        return this;
    }
});
L.Filter.GmlObjectID = L.Filter.extend({
    append: function (id) {
        this.filter.appendChild(L.XmlUtil.createElementNS('ogc:GmlObjectId', {'gml:id': id}));
        return this;
    }
});
L.Format = L.Class.extend({
    defaultOptions: {
        crs: L.CRS.EPSG3857,
        coordsToLatLng: function (coords) {
            return new L.LatLng(coords[1], coords[0], coords[2]);
        },
        latLngToCoords: function (latlng) {
            var coords = [latlng.lng, latlng.lat];
            if (latlng.alt !== undefined) {
                coords.push(latlng.alt);
            }
            return coords;
        }
    },

    setCRS: function (crs) {
        this.options.crs = crs;
        if (crs !== undefined) {
            this.options.coordsToLatLng = function (coords) {
                var point = L.point(coords[0], coords[1]);
                return crs.projection.unproject(point);
            };
            this.options.latLngToCoords = function (ll) {
                var point = new L.latLng(ll[0], ll[1]);
                return crs.projection.project(point);
            };
        }
    },

    initialize: function (options) {
        L.setOptions(this, L.extend(this.defaultOptions, options));
    }
});
L.Format.GeoJSON = L.Format.extend({

    initialize: function (options) {
        L.Format.prototype.initialize.call(this, options);
        this.outputFormat = 'application/json';
    },

    responseToLayers: function (rawData, coordsToLatLng) {
        var layers = [];
        var geoJson = JSON.parse(rawData);
        for (var i = 0; i < geoJson.features.length; i++) {
            var layer = L.GeoJSON.geometryToLayer(geoJson.features[i], null, coordsToLatLng, null);
            layer.feature = geoJson.features[i];
            layers.push(layer);
        }

        return layers;
    }
});

L.Format.GML = L.Format.extend({});
L.Util.project = function (crs, latlngs) {
    if (L.Util.isArray(latlngs)) {
        var result = [];
        latlngs.forEach(function (ll) {
            result.push(crs.projection.project(ll));
        });

        return result;
    }
    else {
        return crs.projection.project(latlngs);
    }
};

L.GMLUtil = {
    posNode: function (coord) {
        return L.XmlUtil.createElementNS('gml:pos', {srsDimension: 2}, {value: coord.x + ' ' + coord.y});
    },

    posListNode: function (coords, close) {
        var localcoords = [];
        coords.forEach(function (coord) {
            localcoords.push(coord.x + ' ' + coord.y);
        });
        if (close) {
            var coord = coords[0];
            localcoords.push(coord.x + ' ' + coord.y);
        }

        var posList = localcoords.join(' ');
        return L.XmlUtil.createElementNS('gml:posList', {}, {value: posList});
    }
};
L.Marker.include({
    toGml: function (crs) {
        var node = L.XmlUtil.createElementNS('gml:Point', {srsName: crs.code});
        node.appendChild(L.GMLUtil.posNode(L.Util.project(crs, this.getLatLng())));
        return node;
    }
});
L.Polygon.include({
    toGml: function (crs) {
        var node = L.XmlUtil.createElementNS('gml:Polygon', {srsName: crs.code, srsDimension: 2});
        node.appendChild(L.XmlUtil.createElementNS('gml:exterior'))
            .appendChild(L.XmlUtil.createElementNS('gml:LinearRing', {srsDimension: 2}))
            .appendChild(L.GMLUtil.posListNode(L.Util.project(crs, this.getLatLngs()), true));

        if (this._holes && this._holes.length) {
            for (var hole in this._holes) {
                node.appendChild(L.XmlUtil.createElementNS('gml:interior'))
                    .appendChild(L.XmlUtil.createElementNS('gml:LinearRing', {srsDimension: 2}))
                    .appendChild(L.GMLUtil.posListNode(L.Util.project(crs, this._holes[hole]), true));
            }
        }

        return node;
    }
});

L.WFS = L.FeatureGroup.extend({

    options: {
        crs: L.CRS.EPSG3857,
        showExisting: true,
        geometryField: 'Shape',
        url: '',
        version: '1.1.0',
        typeNS: '',
        typeName: '',
        typeNSName: '',
        style: {
            color: 'black',
            weight: 1
        },
        namespaceUri: ''
    },

    state: {},

    initialize: function (options, readFormat) {
        L.setOptions(this, options);
        var crs = this.options.crs;

        this.state =  {exist: 'exist'};

        this.options.coordsToLatLng = function (coords) {
            var point = L.point(coords[0], coords[1]);
            return crs.projection.unproject(point);
        };

        this.options.latLngToCoords = function (latlng) {
            var coords = crs.projection.project(latlng);

            if (latlng.alt !== undefined) {
                coords.push(latlng.alt);
            }
            return coords;
        };

        this._layers = {};

        this.readFormat = readFormat || new L.Format.GeoJSON();

        this.options.typeNSName = this.namespaceName(this.options.typeName);
        this.options.srsName = this.options.crs.code;

        if (this.options.showExisting) {
            this.loadFeatures();
        }
    },

    namespaceName: function (name) {
        return this.options.typeNS + ':' + name;
    },

    getFeature: function (filter) {
        var request = L.XmlUtil.createElementNS('wfs:GetFeature',
            {
                service: 'WFS',
                version: this.options.version,
                outputFormat: this.readFormat.outputFormat
            });

        var query = request.appendChild(L.XmlUtil.createElementNS('wfs:Query',
            {
                typeName: this.options.typeNSName,
                srsName: this.options.srsName
            }));

        if (filter && filter.toGml) {
            query.appendChild(filter.toGml());
        }

        return request;
    },

    loadFeatures: function (filter) {
        var that = this;
        L.Util.request({
            url: this.options.url,
            data: L.XmlUtil.createXmlDocumentString(that.getFeature(filter)),
            success: function (data) {
                var layers = that.readFormat.responseToLayers(data, that.options.coordsToLatLng);
                layers.forEach(function (element) {
                    element.state = that.state.exist;
                    that.addLayer(element);
                });

                that.setStyle(that.options.style);
                that.fire('load');
                return that;
            }
        });
    }
});

L.wfs = function (options, readFormat) {
    return new L.WFS(options, readFormat);
};
L.WFS.Transaction = L.WFS.extend({
    initialize: function (options, readFormat) {
        L.WFS.prototype.initialize.call(this, options, readFormat);
        this.describeFeatureType();
        this.state = L.extend(this.state, {
            insert: 'insert',
            update: 'update',
            remove: 'remove'
        });

        this.changes = {};
        var that = this;
        this.on('save:success', function () {
            that.changes = {};
        });
    },

    describeFeatureType: function () {
        var requestData = L.XmlUtil.createElementNS('wfs:DescribeFeatureType', {service: 'WFS', version: this.options.version});
        requestData.appendChild(L.XmlUtil.createElementNS('TypeName', {}, {value: this.options.typeNSName}));

        var that = this;
        L.Util.request({
            url: this.options.url,
            data: L.XmlUtil.createXmlDocumentString(requestData),
            success: function (data) {
                var parser = new DOMParser();
                var featureInfo = parser.parseFromString(data, "text/xml").documentElement;
                that.options.namespaceUri = featureInfo.attributes.targetNamespace.value;
            }
        });
    },

    addLayer: function (layer) {
        L.FeatureGroup.prototype.addLayer.call(this, layer);
        if (!layer.feature) {
            layer.feature = {properties: {}};
        }

        if (!layer.state) {
            layer.state = this.state.insert;
            var id = this.getLayerId(layer);
            this.changes[id] = layer;
        }
        return this;
    },

    removeLayer: function (layer) {
        L.FeatureGroup.prototype.removeLayer.call(this, layer);

        var id = this.getLayerId(layer);

        if (id in this.changes) {
            var change = this.changes[id];
            if (change.state === this.state.insert) {
                delete this.changes[id];
            }
            else {
                change.state = this.state.remove;
            }
        }
        else {
            layer.state = this.state.remove;
            this.changes[id] = layer;
        }
    },

    editLayer: function (layer) {
        if (layer.state !== this.state.insert) {
            layer.state = this.state.update;
        }

        var id = this.getLayerId(layer);
        this.changes[id] = layer;
        return this;
    },

    save: function () {
        var transaction = L.XmlUtil.createElementNS('wfs:Transaction', {service: 'WFS', version: this.options.version});

        var inserted = [];

        for (var id in this.changes) {
            var layer = this.changes[id];
            var action = this[layer.state](layer);
            transaction.appendChild(action);

            if (layer.state === this.state.insert) {
                inserted.push(layer);
            }
        }

        var that = this;

        L.Util.request({
            url: this.options.url,
            data: L.XmlUtil.createXmlDocumentString(transaction),
            success: function (data) {
                var insertResult = L.XmlUtil.evaluate('//wfs:InsertResults/wfs:Feature/ogc:FeatureId[@fid!="none"]/@fid', data);
                var filter = new L.Filter.GmlObjectID();
                var id = insertResult.iterateNext();
                while (id) {
                    filter.append(id.value);
                    id = insertResult.iterateNext();
                }

                inserted.forEach(function (layer) {
                    L.FeatureGroup.prototype.removeLayer.call(that, layer);
                });

                that.once('load', function () {
                    that.fire('save:success');
                });

                that.loadFeatures(filter);
            }
        });

        return this;
    }
});
L.WFS.Transaction.include({
    gmlFeature: function (layer) {
        var featureNode = L.XmlUtil.createElementNS(this.options.typeNSName, {}, {uri: this.options.namespaceUri});
        var feature = layer.feature;
        for (var propertyName in feature.properties) {
            featureNode.appendChild(this.gmlProperty(propertyName,
                feature.properties[propertyName]));
        }

        featureNode.appendChild(this.gmlProperty(this.options.geometryField,
            layer.toGml(this.options.crs)));
        return featureNode;
    },

    gmlProperty: function (name, value) {
        var propertyNode = L.XmlUtil.createElementNS(this.namespaceName(name));
        if (value instanceof Element) {
            propertyNode.appendChild(value);
        }
        else {
            propertyNode.appendChild(L.XmlUtil.createTextNode(value || ''));
        }

        return propertyNode;
    },

    wfsProperty: function (name, value) {
        var propertyNode = L.XmlUtil.createElementNS('wfs:Property');
        propertyNode.appendChild(L.XmlUtil.createElementNS('wfs:Name', {}, {value: name}));
        var valueNode = L.XmlUtil.createElementNS('wfs:Value');
        if (value instanceof Element) {
            valueNode.appendChild(value);
        }
        else {
            valueNode.appendChild(L.XmlUtil.createTextNode(value || ''));
        }

        propertyNode.appendChild(valueNode);

        return propertyNode;
    }
});

L.WFS.Transaction.include({

    insert: function (layer) {
        var node = L.XmlUtil.createElementNS('wfs:Insert');
        node.appendChild(this.gmlFeature(layer));
        return node;
    },

    update: function (layer) {
        var node = L.XmlUtil.createElementNS('wfs:Update', {typeName: this.options.typeNSName});
        var feature = layer.feature;
        for (var propertyName in feature.properties) {
            node.appendChild(this.wfsProperty(propertyName, feature.properties[propertyName]));
        }

        node.appendChild(this.wfsProperty(this.namespaceName(this.options.geometryField),
            layer.toGml(this.options.crs)));

        var filter = new L.Filter.GmlObjectID().append(layer.feature.id);
        node.appendChild(filter.toGml());
        return node;
    },

    remove: function (layer) {
        var node = L.XmlUtil.createElementNS('wfs:Delete', {typeName: this.options.typeNSName});
        var filter = new L.Filter.GmlObjectID().append(layer.feature.id);
        node.appendChild(filter.toGml());
        return node;
    }
});

})(window, document);<commit_msg>remove file<commit_after><|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var EOL = require('os').EOL;

var through = require('through2');
var gutil = require('gulp-util');
var glob = require('glob');

module.exports = function(options) {
	options = options || {};

	var startReg = /<!--\s*build:(\w+)(?:\(([^\)]+?)\))?\s+(\/?([^\s]+?))\s*-->/gim;
	var endReg = /<!--\s*endbuild\s*-->/gim;
	var jsReg = /<\s*script\s+.*?src\s*=\s*"([^"]+?)".*?><\s*\/\s*script\s*>/gi;
	var cssReg = /<\s*link\s+.*?href\s*=\s*"([^"]+)".*?>/gi;
	var basePath, mainPath, mainName, alternatePath;

	function createFile(name, content) {
		return new gutil.File({
			path: path.join(path.relative(basePath, mainPath), name),
			contents: new Buffer(content)
		})
	}

	function getBlockType(content) {
		return jsReg.test(content) ? 'js' : 'css';
	}

	function getFiles(content, reg) {
		var paths = [];
		var files = [];

		content
			.replace(/<!--(?:(?:.|\r|\n)*?)-->/gim, '')
			.replace(reg, function (a, b) {
				var filePath = path.resolve(path.join(alternatePath || mainPath, b));

				if (options.assetsDir)
					filePath = path.resolve(path.join(options.assetsDir, path.relative(basePath, filePath)));

				paths.push(filePath);
			});

		for (var i = 0, l = paths.length; i < l; ++i) {
			var filepath = glob.sync(paths[i])[0];
			files.push(new gutil.File({
				path: filepath,
				contents: fs.readFileSync(filepath)
			}));
		}

		return files;
	}

	function concat(files, name) {
		var buffer = [];

		files.forEach(function(file) {
			buffer.push(String(file.contents));
		});

		return createFile(name, buffer.join(EOL));
	}

	function processTask(index, tasks, name, files, callback) {
		var newFiles = [];

		if (tasks[index] == 'concat') {
			newFiles = [concat(files, name)];
		}
		else {
			var stream = tasks[index];

			function write(file) {
				newFiles.push(file);
			}

			stream.on('data', write);
			files.forEach(function(file) {
				stream.write(file);
			});
			stream.removeListener('data', write);
		}

		if (tasks[++index])
			processTask(index, tasks, name, newFiles, callback);
		else
			newFiles.forEach(callback);
	}

	function process(name, files, pipelineId, callback) {
		var tasks = options[pipelineId] || [];
		if (tasks.indexOf('concat') == -1)
			tasks.unshift('concat');

		processTask(0, tasks, name, files, callback);
	}

	function processHtml(content, push, callback) {
		var html = [];
		var sections = content.split(endReg);

		for (var i = 0, l = sections.length; i < l; ++i)
			if (sections[i].match(startReg)) {
				var section = sections[i].split(startReg);
				alternatePath = section[2];

				html.push(section[0]);

				if (getBlockType(section[5]) == 'js')
					process(section[4], getFiles(section[5], jsReg), section[1], function(name, file) {
						push(file);
						if (path.extname(file.path) == '.js')
							html.push('<script src="' + name.replace(path.basename(name), path.basename(file.path)) + '"></script>');
					}.bind(this, section[3]));
				else
					process(section[4], getFiles(section[5], cssReg), section[1], function(name, file) {
						push(file);
						html.push('<link rel="stylesheet" href="' + name.replace(path.basename(name), path.basename(file.path)) + '"/>');
					}.bind(this, section[3]));
			}
			else
				html.push(sections[i]);

		process(mainName, [createFile(mainName, html.join(''))], 'html', function(file) {
			push(file);
			callback();
		});
	}

	return through.obj(function(file, enc, callback) {
		if (file.isNull()) {
			this.push(file); // Do nothing if no contents
			callback();
		}
		else if (file.isStream()) {
			this.emit('error', new gutil.PluginError('gulp-usemin', 'Streams are not supported!'));
			callback();
		}
		else {
			basePath = file.base;
			mainPath = path.dirname(file.path);
			mainName = path.basename(file.path);

			processHtml(String(file.contents), this.push.bind(this), callback);
		}
	});
};
<commit_msg>When a file does not exist throw an error containing the missing path<commit_after>var path = require('path');
var fs = require('fs');
var EOL = require('os').EOL;

var through = require('through2');
var gutil = require('gulp-util');
var glob = require('glob');

module.exports = function(options) {
	options = options || {};

	var startReg = /<!--\s*build:(\w+)(?:\(([^\)]+?)\))?\s+(\/?([^\s]+?))\s*-->/gim;
	var endReg = /<!--\s*endbuild\s*-->/gim;
	var jsReg = /<\s*script\s+.*?src\s*=\s*"([^"]+?)".*?><\s*\/\s*script\s*>/gi;
	var cssReg = /<\s*link\s+.*?href\s*=\s*"([^"]+)".*?>/gi;
	var basePath, mainPath, mainName, alternatePath;

	function createFile(name, content) {
		return new gutil.File({
			path: path.join(path.relative(basePath, mainPath), name),
			contents: new Buffer(content)
		})
	}

	function getBlockType(content) {
		return jsReg.test(content) ? 'js' : 'css';
	}

	function getFiles(content, reg) {
		var paths = [];
		var files = [];

		content
			.replace(/<!--(?:(?:.|\r|\n)*?)-->/gim, '')
			.replace(reg, function (a, b) {
				var filePath = path.resolve(path.join(alternatePath || mainPath, b));

				if (options.assetsDir)
					filePath = path.resolve(path.join(options.assetsDir, path.relative(basePath, filePath)));

				paths.push(filePath);
			});

		for (var i = 0, l = paths.length; i < l; ++i) {
			var filepath = glob.sync(paths[i])[0];
			if(filepath === undefined) {
				throw new gutil.PluginError('gulp-usemin', 'Path ' + paths[i] + ' not found!');
			}
			files.push(new gutil.File({
				path: filepath,
				contents: fs.readFileSync(filepath)
			}));
		}

		return files;
	}

	function concat(files, name) {
		var buffer = [];

		files.forEach(function(file) {
			buffer.push(String(file.contents));
		});

		return createFile(name, buffer.join(EOL));
	}

	function processTask(index, tasks, name, files, callback) {
		var newFiles = [];

		if (tasks[index] == 'concat') {
			newFiles = [concat(files, name)];
		}
		else {
			var stream = tasks[index];

			function write(file) {
				newFiles.push(file);
			}

			stream.on('data', write);
			files.forEach(function(file) {
				stream.write(file);
			});
			stream.removeListener('data', write);
		}

		if (tasks[++index])
			processTask(index, tasks, name, newFiles, callback);
		else
			newFiles.forEach(callback);
	}

	function process(name, files, pipelineId, callback) {
		var tasks = options[pipelineId] || [];
		if (tasks.indexOf('concat') == -1)
			tasks.unshift('concat');

		processTask(0, tasks, name, files, callback);
	}

	function processHtml(content, push, callback) {
		var html = [];
		var sections = content.split(endReg);

		for (var i = 0, l = sections.length; i < l; ++i)
			if (sections[i].match(startReg)) {
				var section = sections[i].split(startReg);
				alternatePath = section[2];

				html.push(section[0]);

				if (getBlockType(section[5]) == 'js')
					process(section[4], getFiles(section[5], jsReg), section[1], function(name, file) {
						push(file);
						if (path.extname(file.path) == '.js')
							html.push('<script src="' + name.replace(path.basename(name), path.basename(file.path)) + '"></script>');
					}.bind(this, section[3]));
				else
					process(section[4], getFiles(section[5], cssReg), section[1], function(name, file) {
						push(file);
						html.push('<link rel="stylesheet" href="' + name.replace(path.basename(name), path.basename(file.path)) + '"/>');
					}.bind(this, section[3]));
			}
			else
				html.push(sections[i]);

		process(mainName, [createFile(mainName, html.join(''))], 'html', function(file) {
			push(file);
			callback();
		});
	}

	return through.obj(function(file, enc, callback) {
		if (file.isNull()) {
			this.push(file); // Do nothing if no contents
			callback();
		}
		else if (file.isStream()) {
			this.emit('error', new gutil.PluginError('gulp-usemin', 'Streams are not supported!'));
			callback();
		}
		else {
			basePath = file.base;
			mainPath = path.dirname(file.path);
			mainName = path.basename(file.path);

			processHtml(String(file.contents), this.push.bind(this), callback);
		}
	});
};
<|endoftext|>


<commit_before>function SwatCheckboxEntryList(id)
{
	this.entry_list = [];

	SwatCheckboxEntryList.superclass.constructor.call(this, id);

	var check_id;
	for (i = 0; i < this.check_list.length; i++) {
		var option = this.check_list[i];
		this.entry_list[i] = document.getElementById(
			id + '_entry_' + option.value);

		this.check_list[i]._index = i;
	}

	this.updateFields();
}

YAHOO.lang.extend(SwatCheckboxEntryList, SwatCheckboxList, {

handleClick: function(event)
{
	SwatCheckboxEntryList.superclass.handleClick.call(this, event);
	var target = YAHOO.util.Event.getTarget(event);
	this.toggleEntry(target._index);
},

checkAll: function(checked)
{
	SwatCheckboxEntryList.superclass.checkAll.call(this, checked);
	for (i = 0; i < this.check_list.length; i++)
		this.setEntrySensitivity(i, checked);
}

});

SwatCheckboxEntryList.prototype.toggleEntry = function(index)
{
	if (this.entry_list[index])
		this.setEntrySensitivity(index, this.entry_list[index].disabled);
}

SwatCheckboxEntryList.prototype.setEntrySensitivity = function(index,
	sensitivity)
{
	if (this.entry_list[index]) {
		if (sensitivity) {
			this.entry_list[index].disabled = false;
			YAHOO.util.Dom.removeClass(this.entry_list[index],
				'swat-insensitive');
		} else {
			this.entry_list[index].disabled = true;
			YAHOO.util.Dom.addClass(this.entry_list[index], 'swat-insensitive');
		}
	}
}

SwatCheckboxEntryList.prototype.updateFields = function()
{
	for (i = 0; i < this.check_list.length; i++)
		this.setEntrySensitivity(i, this.check_list[i].checked);
}
<commit_msg>'event' is a JavaScript keyword.<commit_after>function SwatCheckboxEntryList(id)
{
	this.entry_list = [];

	SwatCheckboxEntryList.superclass.constructor.call(this, id);

	var check_id;
	for (i = 0; i < this.check_list.length; i++) {
		var option = this.check_list[i];
		this.entry_list[i] = document.getElementById(
			id + '_entry_' + option.value);

		this.check_list[i]._index = i;
	}

	this.updateFields();
}

YAHOO.lang.extend(SwatCheckboxEntryList, SwatCheckboxList, {

handleClick: function(e)
{
	SwatCheckboxEntryList.superclass.handleClick.call(this, e);
	var target = YAHOO.util.Event.getTarget(e);
	this.toggleEntry(target._index);
},

checkAll: function(checked)
{
	SwatCheckboxEntryList.superclass.checkAll.call(this, checked);
	for (i = 0; i < this.check_list.length; i++)
		this.setEntrySensitivity(i, checked);
}

});

SwatCheckboxEntryList.prototype.toggleEntry = function(index)
{
	if (this.entry_list[index])
		this.setEntrySensitivity(index, this.entry_list[index].disabled);
}

SwatCheckboxEntryList.prototype.setEntrySensitivity = function(index,
	sensitivity)
{
	if (this.entry_list[index]) {
		if (sensitivity) {
			this.entry_list[index].disabled = false;
			YAHOO.util.Dom.removeClass(this.entry_list[index],
				'swat-insensitive');
		} else {
			this.entry_list[index].disabled = true;
			YAHOO.util.Dom.addClass(this.entry_list[index], 'swat-insensitive');
		}
	}
}

SwatCheckboxEntryList.prototype.updateFields = function()
{
	for (i = 0; i < this.check_list.length; i++)
		this.setEntrySensitivity(i, this.check_list[i].checked);
}
<|endoftext|>


<commit_before>let mongoose = require('mongoose');
let Schema = mongoose.Schema;
mongoose.Promise = require('bluebird');

let recipeSchema = new Schema({
  rootVersion: Schema.Types.ObjectId,       //The root version of the recipe
  previousVersion: Schema.Types.ObjectId,   //The preceding version of the curent recipe
  deleted: Boolean,                         //set to true when deleted, but cannot remove because of downstream branches
  branch: {                                 //Name of branch
    changed: Boolean,
    value: String
  },
  userID: {                                 //Creator of recipe
    changed: Boolean,
    value: Schema.Types.ObjectId
  },
  name: {                                   //Recipe Title / Name
    changed: Boolean,
    value: String
  },
  description: {                            //Recipe description
    changed: Boolean,
    value: String
  },
  servings: {                               //Number of people served
    changed: Boolean,
    value: Number
  },
  cookTime: {                               //Cook time in minutes
    changed: Boolean,
    value: Number,
  },
  skillLevel: {                             //Recipe difficulty [easy, medium, hard]
    changed: Boolean,
    value: String
  },
  picture: {                                //OPTIONAL: URL of recipe picture
    changed: Boolean,
    value: String
  },
  dependencies: [{                          //Tools used for the recipe
    changed: Boolean,
    position: Number,
    dependencyId: Schema.Types.ObjectId
  }],
  ingredients: [{
    changed: Boolean,
    name: String,                 //name of ingredient
    type: String,                 //type of ingredient (dairy, meat, vegetable, etc)
    position: Number,             //Order of ingredients
    amount: Number,               //OPTIONAL: Amount of ingredient
    unit: String,                 //OPTIONAL: Unit of ingredient (cups, tbsp, etc)
    prep: String,                 //OPTIONAL: Preperation of ingredient (chopped, diced)
    substitutes: [String]         //Optional: Substitute ingredients for that ingredient
    optional: Boolean             //Whether ingredient is necessary
  }],
  steps: [{
    changed: Boolean,
    position: Number,             //Step position in order
    description: String,          //Step details
    time: Number,                 //OPTIONAL: Time to complete step
    ingredients: [String],  //OPTIONAL: Ingredients required in step
  }],
  tags: [{
    changed: Boolean,
    position: Number,
    tagId: Schema.Types.ObjectId
  }],
  issues: [{
    changed: Boolean,
    position: Number,
    issueId: Schema.Types.ObjectId
  }],
  stars: Number,                  //Number of people who starred this recipe
});

let userRecipeSchema = new Schema({
  userID: Number,                   //User who owns recipes / forks
  recipes: [Schema.Types.ObjectId], //Forks and created recipes belonging to that user
});

let dependencySchema = new Schema({
  name: String,                         //name of dependency
  type: String                          //type of dependency (measuring containers, utensil, pans)
});

let tagSchema = new Schema({
  name: String,                         //tag name
  type: String                          //tag type [cuisine, dietary restriction, etc]
});

let issueSchema = new Schema({
  userID: String,                       //User who left issue
  description: String,                  //Description of the problem / issue
  step: Number                          //Optional: Step in the recipe that had issue
});

module.exports = {
  Recipe: mongoose.model('Recipe', recipeSchema),
  UserRecipe: mongoose.model('UserRecipe', userRecipeSchema),
  Dependency: mongoose.model('Dependency', dependencySchema),
  Tag: mongoose.model('Tag', tagSchema),
  Issue: mongoose.model('Issue', issueSchema)
};<commit_msg>Fix syntax error in schemas.js<commit_after>let mongoose = require('mongoose');
let Schema = mongoose.Schema;
mongoose.Promise = require('bluebird');

let recipeSchema = new Schema({
  rootVersion: Schema.Types.ObjectId,       //The root version of the recipe
  previousVersion: Schema.Types.ObjectId,   //The preceding version of the curent recipe
  deleted: Boolean,                         //set to true when deleted, but cannot remove because of downstream branches
  branch: {                                 //Name of branch
    changed: Boolean,
    value: String
  },
  userID: {                                 //Creator of recipe
    changed: Boolean,
    value: Schema.Types.ObjectId
  },
  name: {                                   //Recipe Title / Name
    changed: Boolean,
    value: String
  },
  description: {                            //Recipe description
    changed: Boolean,
    value: String
  },
  servings: {                               //Number of people served
    changed: Boolean,
    value: Number
  },
  cookTime: {                               //Cook time in minutes
    changed: Boolean,
    value: Number,
  },
  skillLevel: {                             //Recipe difficulty [easy, medium, hard]
    changed: Boolean,
    value: String
  },
  picture: {                                //OPTIONAL: URL of recipe picture
    changed: Boolean,
    value: String
  },
  dependencies: [{                          //Tools used for the recipe
    changed: Boolean,
    position: Number,
    dependencyId: Schema.Types.ObjectId
  }],
  ingredients: [{
    changed: Boolean,
    name: String,                 //name of ingredient
    type: String,                 //type of ingredient (dairy, meat, vegetable, etc)
    position: Number,             //Order of ingredients
    amount: Number,               //OPTIONAL: Amount of ingredient
    unit: String,                 //OPTIONAL: Unit of ingredient (cups, tbsp, etc)
    prep: String,                 //OPTIONAL: Preperation of ingredient (chopped, diced)
    substitutes: [String],         //Optional: Substitute ingredients for that ingredient
    optional: Boolean             //Whether ingredient is necessary
  }],
  steps: [{
    changed: Boolean,
    position: Number,             //Step position in order
    description: String,          //Step details
    time: Number,                 //OPTIONAL: Time to complete step
    ingredients: [String],  //OPTIONAL: Ingredients required in step
  }],
  tags: [{
    changed: Boolean,
    position: Number,
    tagId: Schema.Types.ObjectId
  }],
  issues: [{
    changed: Boolean,
    position: Number,
    issueId: Schema.Types.ObjectId
  }],
  stars: Number,                  //Number of people who starred this recipe
});

let userRecipeSchema = new Schema({
  userID: Number,                   //User who owns recipes / forks
  recipes: [Schema.Types.ObjectId], //Forks and created recipes belonging to that user
});

let dependencySchema = new Schema({
  name: String,                         //name of dependency
  type: String                          //type of dependency (measuring containers, utensil, pans)
});

let tagSchema = new Schema({
  name: String,                         //tag name
  type: String                          //tag type [cuisine, dietary restriction, etc]
});

let issueSchema = new Schema({
  userID: String,                       //User who left issue
  description: String,                  //Description of the problem / issue
  step: Number                          //Optional: Step in the recipe that had issue
});

module.exports = {
  Recipe: mongoose.model('Recipe', recipeSchema),
  UserRecipe: mongoose.model('UserRecipe', userRecipeSchema),
  Dependency: mongoose.model('Dependency', dependencySchema),
  Tag: mongoose.model('Tag', tagSchema),
  Issue: mongoose.model('Issue', issueSchema)
};<|endoftext|>


<commit_before>'use strict';

var fancyLog = require('fancy-log');
var PluginError = require('plugin-error');
var supportsColor = require('supports-color');
var File = require('vinyl');
var MemoryFileSystem = require('memory-fs');
var nodePath = require('path');
var through = require('through');
var ProgressPlugin = require('webpack/lib/ProgressPlugin');
var clone = require('lodash.clone');
var some = require('lodash.some');

var defaultStatsOptions = {
  colors: supportsColor.stdout.hasBasic,
  hash: false,
  timings: false,
  chunks: false,
  chunkModules: false,
  modules: false,
  children: true,
  version: true,
  cached: false,
  cachedAssets: false,
  reasons: false,
  source: false,
  errorDetails: false
};

module.exports = function (options, wp, done) {
  options = clone(options) || {};
  var config = options.config || options;
  if (typeof done !== 'function') {
    var callingDone = false;
    done = function (err, stats) {
      if (err) {
        // The err is here just to match the API but isnt used
        return;
      }
      stats = stats || {};
      if (options.quiet || callingDone) {
        return;
      }

      // Debounce output a little for when in watch mode
      if (options.watch) {
        callingDone = true;
        setTimeout(function () {
          callingDone = false;
        }, 500);
      }

      if (options.verbose) {
        fancyLog(stats.toString({
          colors: supportsColor.stdout.hasBasic
        }));
      } else {
        var statsOptions = (options && options.stats) || {};

        if (typeof statsOptions === 'object') {
          Object.keys(defaultStatsOptions).forEach(function (key) {
            if (typeof statsOptions[key] === 'undefined') {
              statsOptions[key] = defaultStatsOptions[key];
            }
          });
        }
        var statusLog
        if (statusLog = stats.toString(statsOptions)) {
          fancyLog(statusLog)
        }
      }
    };
  }

  var webpack = wp || require('webpack');
  var entry = [];
  var entries = Object.create(null);

  var stream = through(function (file) {
    if (file.isNull()) {
      return;
    }
    if ('named' in file) {
      if (!Array.isArray(entries[file.named])) {
        entries[file.named] = [];
      }
      entries[file.named].push(file.path);
    } else {
      entry = entry || [];
      entry.push(file.path);
    }
  }, function () {
    var self = this;
    var handleConfig = function (config) {
      config.output = config.output || {};
      config.watch = !!options.watch;

      // Determine pipe'd in entry
      if (Object.keys(entries).length > 0) {
        entry = entries;
        if (!config.output.filename) {
          // Better output default for multiple chunks
          config.output.filename = '[name].js';
        }
      } else if (entry.length < 2) {
        entry = entry[0] || entry;
      }

      config.entry = config.entry || entry;
      config.output.path = config.output.path || process.cwd();
      config.output.filename = config.output.filename || '[hash].js';
      config.watch = options.watch;
      entry = [];

      if (!config.entry || config.entry.length < 1) {
        fancyLog('webpack-stream - No files given; aborting compilation');
        self.emit('end');
        return false;
      }
      return true;
    };

    var succeeded;
    if (Array.isArray(config)) {
      for (var i = 0; i < config.length; i++) {
        succeeded = handleConfig(config[i]);
        if (!succeeded) {
          return false;
        }
      }
    } else {
      succeeded = handleConfig(config);
      if (!succeeded) {
        return false;
      }
    }

    var compiler = webpack(config, function (err, stats) {
      if (err) {
        self.emit('error', new PluginError('webpack-stream', err));
        return;
      }
      var jsonStats = stats ? stats.toJson() || {} : {};
      var errors = jsonStats.errors || [];
      if (errors.length) {
        var errorMessage = errors.join('\n');
        var compilationError = new PluginError('webpack-stream', errorMessage);
        if (!options.watch) {
          self.emit('error', compilationError);
        }
        self.emit('compilation-error', compilationError);
      }
      if (!options.watch) {
        self.queue(null);
      }
      done(err, stats);
      if (options.watch && !options.quiet) {
        fancyLog('webpack is watching for changes');
      }
    });

    var handleCompiler = function (compiler) {
      // In watch mode webpack returns a wrapper object so we need to get
      // the underlying compiler
      if (options.watch && compiler.compiler) {
        compiler = compiler.compiler;
      }

      if (options.progress) {
        compiler.apply(new ProgressPlugin(function (percentage, msg) {
          percentage = Math.floor(percentage * 100);
          msg = percentage + '% ' + msg;
          if (percentage < 10) msg = ' ' + msg;
          fancyLog('webpack', msg);
        }));
      }

      var fs = compiler.outputFileSystem = new MemoryFileSystem();

      var afterEmitPlugin = compiler.hooks
        // Webpack 4
        ? function (callback) { compiler.hooks.afterEmit.tapAsync('WebpackStream', callback); }
        // Webpack 2/3
        : function (callback) { compiler.plugin('after-emit', callback); };

      afterEmitPlugin(function (compilation, callback) {
        Object.keys(compilation.assets).forEach(function (outname) {
          if (compilation.assets[outname].emitted) {
            var file = prepareFile(fs, compiler, outname);
            self.queue(file);
          }
        });
        callback();
      });
    };

    if (Array.isArray(options.config) && options.watch) {
      compiler.watchings.forEach(function (compiler) {
        handleCompiler(compiler);
      });
    } else if (Array.isArray(options.config)) {
      compiler.compilers.forEach(function (compiler) {
        handleCompiler(compiler);
      });
    } else {
      handleCompiler(compiler);
    }
  });

  // If entry point manually specified, trigger that
  var hasEntry = Array.isArray(config)
    ? some(config, function (c) { return c.entry; })
    : config.entry;
  if (hasEntry) {
    stream.end();
  }

  return stream;
};

function prepareFile (fs, compiler, outname) {
  var path = fs.join(compiler.outputPath, outname);
  if (path.indexOf('?') !== -1) {
    path = path.split('?')[0];
  }

  var contents = fs.readFileSync(path);

  var file = new File({
    base: compiler.outputPath,
    path: nodePath.join(compiler.outputPath, outname),
    contents: contents
  });
  return file;
}

// Expose webpack if asked
Object.defineProperty(module.exports, 'webpack', {
  get: function () {
    return require('webpack');
  }
});
<commit_msg>fix with style guide.<commit_after>'use strict';

var fancyLog = require('fancy-log');
var PluginError = require('plugin-error');
var supportsColor = require('supports-color');
var File = require('vinyl');
var MemoryFileSystem = require('memory-fs');
var nodePath = require('path');
var through = require('through');
var ProgressPlugin = require('webpack/lib/ProgressPlugin');
var clone = require('lodash.clone');
var some = require('lodash.some');

var defaultStatsOptions = {
  colors: supportsColor.stdout.hasBasic,
  hash: false,
  timings: false,
  chunks: false,
  chunkModules: false,
  modules: false,
  children: true,
  version: true,
  cached: false,
  cachedAssets: false,
  reasons: false,
  source: false,
  errorDetails: false
};

module.exports = function (options, wp, done) {
  options = clone(options) || {};
  var config = options.config || options;
  if (typeof done !== 'function') {
    var callingDone = false;
    done = function (err, stats) {
      if (err) {
        // The err is here just to match the API but isnt used
        return;
      }
      stats = stats || {};
      if (options.quiet || callingDone) {
        return;
      }

      // Debounce output a little for when in watch mode
      if (options.watch) {
        callingDone = true;
        setTimeout(function () {
          callingDone = false;
        }, 500);
      }

      if (options.verbose) {
        fancyLog(stats.toString({
          colors: supportsColor.stdout.hasBasic
        }));
      } else {
        var statsOptions = (options && options.stats) || {};

        if (typeof statsOptions === 'object') {
          Object.keys(defaultStatsOptions).forEach(function (key) {
            if (typeof statsOptions[key] === 'undefined') {
              statsOptions[key] = defaultStatsOptions[key];
            }
          });
        }
        var statusLog = stats.toString(statsOptions);
        if (statusLog) {
          fancyLog(statusLog);
        }
      }
    };
  }

  var webpack = wp || require('webpack');
  var entry = [];
  var entries = Object.create(null);

  var stream = through(function (file) {
    if (file.isNull()) {
      return;
    }
    if ('named' in file) {
      if (!Array.isArray(entries[file.named])) {
        entries[file.named] = [];
      }
      entries[file.named].push(file.path);
    } else {
      entry = entry || [];
      entry.push(file.path);
    }
  }, function () {
    var self = this;
    var handleConfig = function (config) {
      config.output = config.output || {};
      config.watch = !!options.watch;

      // Determine pipe'd in entry
      if (Object.keys(entries).length > 0) {
        entry = entries;
        if (!config.output.filename) {
          // Better output default for multiple chunks
          config.output.filename = '[name].js';
        }
      } else if (entry.length < 2) {
        entry = entry[0] || entry;
      }

      config.entry = config.entry || entry;
      config.output.path = config.output.path || process.cwd();
      config.output.filename = config.output.filename || '[hash].js';
      config.watch = options.watch;
      entry = [];

      if (!config.entry || config.entry.length < 1) {
        fancyLog('webpack-stream - No files given; aborting compilation');
        self.emit('end');
        return false;
      }
      return true;
    };

    var succeeded;
    if (Array.isArray(config)) {
      for (var i = 0; i < config.length; i++) {
        succeeded = handleConfig(config[i]);
        if (!succeeded) {
          return false;
        }
      }
    } else {
      succeeded = handleConfig(config);
      if (!succeeded) {
        return false;
      }
    }

    var compiler = webpack(config, function (err, stats) {
      if (err) {
        self.emit('error', new PluginError('webpack-stream', err));
        return;
      }
      var jsonStats = stats ? stats.toJson() || {} : {};
      var errors = jsonStats.errors || [];
      if (errors.length) {
        var errorMessage = errors.join('\n');
        var compilationError = new PluginError('webpack-stream', errorMessage);
        if (!options.watch) {
          self.emit('error', compilationError);
        }
        self.emit('compilation-error', compilationError);
      }
      if (!options.watch) {
        self.queue(null);
      }
      done(err, stats);
      if (options.watch && !options.quiet) {
        fancyLog('webpack is watching for changes');
      }
    });

    var handleCompiler = function (compiler) {
      // In watch mode webpack returns a wrapper object so we need to get
      // the underlying compiler
      if (options.watch && compiler.compiler) {
        compiler = compiler.compiler;
      }

      if (options.progress) {
        compiler.apply(new ProgressPlugin(function (percentage, msg) {
          percentage = Math.floor(percentage * 100);
          msg = percentage + '% ' + msg;
          if (percentage < 10) msg = ' ' + msg;
          fancyLog('webpack', msg);
        }));
      }

      var fs = compiler.outputFileSystem = new MemoryFileSystem();

      var afterEmitPlugin = compiler.hooks
        // Webpack 4
        ? function (callback) { compiler.hooks.afterEmit.tapAsync('WebpackStream', callback); }
        // Webpack 2/3
        : function (callback) { compiler.plugin('after-emit', callback); };

      afterEmitPlugin(function (compilation, callback) {
        Object.keys(compilation.assets).forEach(function (outname) {
          if (compilation.assets[outname].emitted) {
            var file = prepareFile(fs, compiler, outname);
            self.queue(file);
          }
        });
        callback();
      });
    };

    if (Array.isArray(options.config) && options.watch) {
      compiler.watchings.forEach(function (compiler) {
        handleCompiler(compiler);
      });
    } else if (Array.isArray(options.config)) {
      compiler.compilers.forEach(function (compiler) {
        handleCompiler(compiler);
      });
    } else {
      handleCompiler(compiler);
    }
  });

  // If entry point manually specified, trigger that
  var hasEntry = Array.isArray(config)
    ? some(config, function (c) { return c.entry; })
    : config.entry;
  if (hasEntry) {
    stream.end();
  }

  return stream;
};

function prepareFile (fs, compiler, outname) {
  var path = fs.join(compiler.outputPath, outname);
  if (path.indexOf('?') !== -1) {
    path = path.split('?')[0];
  }

  var contents = fs.readFileSync(path);

  var file = new File({
    base: compiler.outputPath,
    path: nodePath.join(compiler.outputPath, outname),
    contents: contents
  });
  return file;
}

// Expose webpack if asked
Object.defineProperty(module.exports, 'webpack', {
  get: function () {
    return require('webpack');
  }
});
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import styles from './App.css'
import UploadPanel from './UploadPanel'
import ConnectionPanel from './ConnectionPanel'
import Button from './Button'
import RunControl from './RunControl'
import RunLog from './RunLog'

export default function App (props) {
  const {
    // state
    isNavPanelOpen,
    isReadyToRun,
    isRunning,
    // handlers
    onRunClick,
    onNavClick
  } = props
  let runButton
  let runControl
  let runLog

  // mock prop for styling
  const startTime = Date.now()
  const timeRemaining = '00:03:25' // swap out for timer

  if (!isRunning) {
    runButton = (
      <Button
        onClick={onRunClick}
        disabled={!isReadyToRun}
        style={styles.run}
      >
        Run Job
      </Button>
    )
  }

  if (isReadyToRun) {
    runControl = (
      <RunControl
        style={styles.run_controls}
        {...{startTime, timeRemaining}}
        {...props}
      />
    )

    runLog = <RunLog style={styles.task} {...props} />
  }

  // TODO (ka) convert aside to sidebar component
  return (

        <button
          className={styles.toggle_nav}
          onClick={onNavClick}
        >
          ☰
        </button>
        {runButton}

        <UploadPanel {...props} protocolName={'dino.py'} />
        <ConnectionPanel {...props} />

      {runControl}
      {runLog}

  )
}

App.propTypes = {
  onNavClick: PropTypes.func.isRequired
}
<commit_msg>added todo for next immediate steps -  refactor sidebar, components, handlers accordingly<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import styles from './App.css'
import UploadPanel from './UploadPanel'
import ConnectionPanel from './ConnectionPanel'
import Button from './Button'
import RunControl from './RunControl'
import RunLog from './RunLog'

export default function App (props) {
  const {
    // state
    isNavPanelOpen,
    isReadyToRun,
    isRunning,
    // handlers
    onRunClick,
    onNavClick
  } = props
  let runButton
  let runControl
  let runLog

  // mock prop for styling
  const startTime = Date.now()
  const timeRemaining = '00:03:25' // swap out for timer

  if (!isRunning) {
    runButton = (
      <Button
        onClick={onRunClick}
        disabled={!isReadyToRun}
        style={styles.run}
      >
        Run Job
      </Button>
    )
  }

  if (isReadyToRun) {
    runControl = (
      <RunControl
        style={styles.run_controls}
        {...{startTime, timeRemaining}}
        {...props}
      />
    )

    runLog = <RunLog style={styles.task} {...props} />
  }

  // TODO (ka) convert aside to sidebar class based component,
  // toggle side panel content based on selected icon rather than isNavPanelOpen bool and onNavClick handler, remove hamburger
  // refactor top level component jsx and css layout accordingly
  return (

        <button
          className={styles.toggle_nav}
          onClick={onNavClick}
        >
          ☰
        </button>
        {runButton}

        <UploadPanel {...props} protocolName={'dino.py'} />
        <ConnectionPanel {...props} />

      {runControl}
      {runLog}

  )
}

App.propTypes = {
  onNavClick: PropTypes.func.isRequired
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global Handlebars, escapeHTML */

(function(OC, OCA) {
	var TEMPLATE =
		'
' +
		'
' +
		'

' +
		'
{{emptyResultLabel}}

' +
		'<input type="button" class="showMore hidden" value="{{moreLabel}}"' +
		' name="show-more" id="show-more" />' +
		'

';

	var EDIT_COMMENT_TEMPLATE =
		'
' +
		'
' +
		'        {{#if avatarEnabled}}' +
		'

' +
		'        {{/if}}' +
		'
{{actorDisplayName}}
' +
		'{{#if isEditMode}}' +
		'        ' +
		'{{/if}}' +
		'
' +
		'    <form class="newCommentForm">' +
		'        <input type="text" class="message" placeholder="{{newMessagePlaceholder}}" value="{{message}}" />' +
		'        <input class="submit icon-confirm" type="submit" value="" />' +
		'{{#if isEditMode}}' +
		'        <input class="cancel pull-right" type="button" value="{{cancelText}}" />' +
		'{{/if}}' +
		'

'+
		'    </form>' +
		'
';

	var COMMENT_TEMPLATE =
		'
' +
		'
' +
		'        {{#if avatarEnabled}}' +
		'

' +
		'        {{/if}}' +
		'
{{actorDisplayName}}
' +
		'{{#if isUserAuthor}}' +
		'        ' +
		'{{/if}}' +
		'
{{date}}
' +
		'
' +
		'
{{{formattedMessage}}}
' +
		'{{#if isLong}}' +
		'

' +
		'{{/if}}' +
		'
';

	/**
	 * @memberof OCA.Comments
	 */
	var CommentsTabView = OCA.Files.DetailTabView.extend(
		/** @lends OCA.Comments.CommentsTabView.prototype */ {
		id: 'commentsTabView',
		className: 'tab commentsTabView',

		events: {
			'submit .newCommentForm': '_onSubmitComment',
			'click .showMore': '_onClickShowMore',
			'click .action.edit': '_onClickEditComment',
			'click .action.delete': '_onClickDeleteComment',
			'click .cancel': '_onClickCloseComment',
			'click .comment': '_onClickComment'
		},

		_commentMaxLength: 1000,

		initialize: function() {
			OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
			this.collection = new OCA.Comments.CommentCollection();
			this.collection.on('request', this._onRequest, this);
			this.collection.on('sync', this._onEndRequest, this);
			this.collection.on('add', this._onAddModel, this);

			this._avatarsEnabled = !!OC.config.enable_avatars;

			this._commentMaxThreshold = this._commentMaxLength * 0.9;

			// TODO: error handling
			_.bindAll(this, '_onTypeComment');
		},

		template: function(params) {
			if (!this._template) {
				this._template = Handlebars.compile(TEMPLATE);
			}
			var currentUser = OC.getCurrentUser();
			return this._template(_.extend({
				avatarEnabled: this._avatarsEnabled,
				actorId: currentUser.uid,
				actorDisplayName: currentUser.displayName
			}, params));
		},

		editCommentTemplate: function(params) {
			if (!this._editCommentTemplate) {
				this._editCommentTemplate = Handlebars.compile(EDIT_COMMENT_TEMPLATE);
			}
			var currentUser = OC.getCurrentUser();
			return this._editCommentTemplate(_.extend({
				avatarEnabled: this._avatarsEnabled,
				actorId: currentUser.uid,
				actorDisplayName: currentUser.displayName,
				newMessagePlaceholder: t('comments', 'New comment …'),
				deleteTooltip: t('comments', 'Delete comment'),
				submitText: t('comments', 'Post'),
				cancelText: t('comments', 'Cancel')
			}, params));
		},

		commentTemplate: function(params) {
			if (!this._commentTemplate) {
				this._commentTemplate = Handlebars.compile(COMMENT_TEMPLATE);
			}

			params = _.extend({
				avatarEnabled: this._avatarsEnabled,
				editTooltip: t('comments', 'Edit comment'),
				isUserAuthor: OC.getCurrentUser().uid === params.actorId,
				isLong: this._isLong(params.message)
			}, params);

			if (params.actorType === 'deleted_users') {
				// makes the avatar a X
				params.actorId = null;
				params.actorDisplayName = t('comments', '[Deleted user]');
			}

			return this._commentTemplate(params);
		},

		getLabel: function() {
			return t('comments', 'Comments');
		},

		setFileInfo: function(fileInfo) {
			if (fileInfo) {
				this.model = fileInfo;
				this.render();
				this.collection.setObjectId(fileInfo.id);
				// reset to first page
				this.collection.reset([], {silent: true});
				this.nextPage();
			} else {
				this.model = null;
				this.render();
				this.collection.reset();
			}
		},

		render: function() {
			this.$el.html(this.template({
				emptyResultLabel: t('comments', 'No comments yet, start the conversation!'),
				moreLabel: t('comments', 'More comments …')
			}));
			this.$el.find('.comments').before(this.editCommentTemplate({}));
			this.$el.find('.has-tooltip').tooltip();
			this.$container = this.$el.find('ul.comments');
			if (this._avatarsEnabled) {
				this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 32);
			}
			this.delegateEvents();
			this.$el.find('.message').on('keydown input change', this._onTypeComment);
		},

		_formatItem: function(commentModel) {
			var timestamp = new Date(commentModel.get('creationDateTime')).getTime();
			var data = _.extend({
				date: OC.Util.relativeModifiedDate(timestamp),
				altDate: OC.Util.formatDate(timestamp),
				formattedMessage: this._formatMessage(commentModel.get('message'))
			}, commentModel.attributes);
			return data;
		},

		_toggleLoading: function(state) {
			this._loading = state;
			this.$el.find('.loading').toggleClass('hidden', !state);
		},

		_onRequest: function(type) {
			if (type === 'REPORT') {
				this._toggleLoading(true);
				this.$el.find('.showMore').addClass('hidden');
			}
		},

		_onEndRequest: function(type) {
			var fileInfoModel = this.model;
			this._toggleLoading(false);
			this.$el.find('.emptycontent').toggleClass('hidden', !!this.collection.length);
			this.$el.find('.showMore').toggleClass('hidden', !this.collection.hasMoreResults());

			if (type !== 'REPORT') {
				return;
			}

			// find first unread comment
			var firstUnreadComment = this.collection.findWhere({isUnread: true});
			if (firstUnreadComment) {
				// update read marker
				this.collection.updateReadMarker(
					null,
					{
						success: function() {
							fileInfoModel.set('commentsUnread', 0);
						}
					}
				);
			}
		},

		_onAddModel: function(model, collection, options) {
			var $el = $(this.commentTemplate(this._formatItem(model)));
			if (!_.isUndefined(options.at) && collection.length > 1) {
				this.$container.find('li').eq(options.at).before($el);
			} else {
				this.$container.append($el);
			}

			this._postRenderItem($el);
		},

		_postRenderItem: function($el) {
			$el.find('.has-tooltip').tooltip();
			if(this._avatarsEnabled) {
				$el.find('.avatar').each(function() {
					var $this = $(this);
					$this.avatar($this.attr('data-username'), 32);
				});
			}
		},

		/**
		 * Convert a message to be displayed in HTML,
		 * converts newlines to
 tags.
		 */
		_formatMessage: function(message) {
			return escapeHTML(message).replace(/\n/g, '
');
		},

		nextPage: function() {
			if (this._loading || !this.collection.hasMoreResults()) {
				return;
			}

			this.collection.fetchNext();
		},

		_onClickEditComment: function(ev) {
			ev.preventDefault();
			var $comment = $(ev.target).closest('.comment');
			var commentId = $comment.data('id');
			var commentToEdit = this.collection.get(commentId);
			var $formRow = $(this.editCommentTemplate(_.extend({
				isEditMode: true,
				submitText: t('comments', 'Save')
			}, commentToEdit.attributes)));

			$comment.addClass('hidden').removeClass('collapsed');
			// spawn form
			$comment.after($formRow);
			$formRow.data('commentEl', $comment);
			$formRow.find('textarea').on('keydown input change', this._onTypeComment);

			// copy avatar element from original to avoid flickering
			$formRow.find('.avatar').replaceWith($comment.find('.avatar').clone());
			$formRow.find('.has-tooltip').tooltip();

			return false;
		},

		_onTypeComment: function(ev) {
			var $field = $(ev.target);
			var len = $field.val().length;
			var $submitButton = $field.data('submitButtonEl');
			if (!$submitButton) {
				$submitButton = $field.closest('form').find('.submit');
				$field.data('submitButtonEl', $submitButton);
			}
			$field.tooltip('hide');
			if (len > this._commentMaxThreshold) {
				$field.attr('data-original-title', t('comments', 'Allowed characters {count} of {max}', {count: len, max: this._commentMaxLength}));
				$field.tooltip({trigger: 'manual'});
				$field.tooltip('show');
				$field.addClass('error');
			}

			var limitExceeded = (len > this._commentMaxLength);
			$field.toggleClass('error', limitExceeded);
			$submitButton.prop('disabled', limitExceeded);

			//submits form on ctrl+Enter or cmd+Enter
			if (ev.keyCode === 13 && (ev.ctrlKey || ev.metaKey)) {
				$submitButton.click();
			}
		},

		_onClickComment: function(ev) {
			var $row = $(ev.target);
			if (!$row.is('.comment')) {
				$row = $row.closest('.comment');
			}
			$row.removeClass('collapsed');
		},

		_onClickCloseComment: function(ev) {
			ev.preventDefault();
			var $row = $(ev.target).closest('.comment');
			$row.data('commentEl').removeClass('hidden');
			$row.remove();
			return false;
		},

		_onClickDeleteComment: function(ev) {
			ev.preventDefault();
			var $comment = $(ev.target).closest('.comment');
			var commentId = $comment.data('id');
			var $loading = $comment.find('.submitLoading');

			$comment.addClass('disabled');
			$loading.removeClass('hidden');
			this.collection.get(commentId).destroy({
				success: function() {
					$comment.data('commentEl').remove();
					$comment.remove();
				},
				error: function() {
					$loading.addClass('hidden');
					$comment.removeClass('disabled');
					OC.Notification.showTemporary(t('comments', 'Error occurred while retrieving comment with id {id}', {id: commentId}));
				}
			});

			return false;
		},

		_onClickShowMore: function(ev) {
			ev.preventDefault();
			this.nextPage();
		},

		_onSubmitComment: function(e) {
			var self = this;
			var $form = $(e.target);
			var commentId = $form.closest('.comment').data('id');
			var currentUser = OC.getCurrentUser();
			var $submit = $form.find('.submit');
			var $loading = $form.find('.submitLoading');
			var $textArea = $form.find('.message');
			var message = $textArea.val().trim();
			e.preventDefault();

			if (!message.length || message.length > this._commentMaxLength) {
				return;
			}

			$textArea.prop('disabled', true);
			$submit.addClass('hidden');
			$loading.removeClass('hidden');

			if (commentId) {
				// edit mode
				var comment = this.collection.get(commentId);
				comment.save({
					message: $textArea.val()
				}, {
					success: function(model) {
						var $row = $form.closest('.comment');
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$row.data('commentEl')
							.removeClass('hidden')
							.find('.message')
							.html(self._formatMessage(model.get('message')));
						$row.remove();
					},
					error: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.prop('disabled', false);

						OC.Notification.showTemporary(t('comments', 'Error occurred while updating comment with id {id}', {id: commentId}));
					}
				});
			} else {
				this.collection.create({
					actorId: currentUser.uid,
					actorDisplayName: currentUser.displayName,
					actorType: 'users',
					verb: 'comment',
					message: $textArea.val(),
					creationDateTime: (new Date()).toUTCString()
				}, {
					at: 0,
					// wait for real creation before adding
					wait: true,
					success: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.val('').prop('disabled', false);
					},
					error: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.prop('disabled', false);

						OC.Notification.showTemporary(t('comments', 'Error occurred while posting comment'));
					}
				});
			}

			return false;
		},

		/**
		 * Returns whether the given message is long and needs
		 * collapsing
		 */
		_isLong: function(message) {
			return message.length > 250 || (message.match(/\n/g) || []).length > 1;
		}
	});

	OCA.Comments.CommentsTabView = CommentsTabView;
})(OC, OCA);
<commit_msg>Use live timestamp on comments tab<commit_after>/*
 * Copyright (c) 2016
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

/* global Handlebars, escapeHTML */

(function(OC, OCA) {
	var TEMPLATE =
		'
' +
		'
' +
		'

' +
		'
{{emptyResultLabel}}

' +
		'<input type="button" class="showMore hidden" value="{{moreLabel}}"' +
		' name="show-more" id="show-more" />' +
		'

';

	var EDIT_COMMENT_TEMPLATE =
		'
' +
		'
' +
		'        {{#if avatarEnabled}}' +
		'

' +
		'        {{/if}}' +
		'
{{actorDisplayName}}
' +
		'{{#if isEditMode}}' +
		'        ' +
		'{{/if}}' +
		'
' +
		'    <form class="newCommentForm">' +
		'        <input type="text" class="message" placeholder="{{newMessagePlaceholder}}" value="{{message}}" />' +
		'        <input class="submit icon-confirm" type="submit" value="" />' +
		'{{#if isEditMode}}' +
		'        <input class="cancel pull-right" type="button" value="{{cancelText}}" />' +
		'{{/if}}' +
		'

'+
		'    </form>' +
		'
';

	var COMMENT_TEMPLATE =
		'
' +
		'
' +
		'        {{#if avatarEnabled}}' +
		'

' +
		'        {{/if}}' +
		'
{{actorDisplayName}}
' +
		'{{#if isUserAuthor}}' +
		'        ' +
		'{{/if}}' +
		'
{{date}}
' +
		'
' +
		'
{{{formattedMessage}}}
' +
		'{{#if isLong}}' +
		'

' +
		'{{/if}}' +
		'
';

	/**
	 * @memberof OCA.Comments
	 */
	var CommentsTabView = OCA.Files.DetailTabView.extend(
		/** @lends OCA.Comments.CommentsTabView.prototype */ {
		id: 'commentsTabView',
		className: 'tab commentsTabView',

		events: {
			'submit .newCommentForm': '_onSubmitComment',
			'click .showMore': '_onClickShowMore',
			'click .action.edit': '_onClickEditComment',
			'click .action.delete': '_onClickDeleteComment',
			'click .cancel': '_onClickCloseComment',
			'click .comment': '_onClickComment'
		},

		_commentMaxLength: 1000,

		initialize: function() {
			OCA.Files.DetailTabView.prototype.initialize.apply(this, arguments);
			this.collection = new OCA.Comments.CommentCollection();
			this.collection.on('request', this._onRequest, this);
			this.collection.on('sync', this._onEndRequest, this);
			this.collection.on('add', this._onAddModel, this);

			this._avatarsEnabled = !!OC.config.enable_avatars;

			this._commentMaxThreshold = this._commentMaxLength * 0.9;

			// TODO: error handling
			_.bindAll(this, '_onTypeComment');
		},

		template: function(params) {
			if (!this._template) {
				this._template = Handlebars.compile(TEMPLATE);
			}
			var currentUser = OC.getCurrentUser();
			return this._template(_.extend({
				avatarEnabled: this._avatarsEnabled,
				actorId: currentUser.uid,
				actorDisplayName: currentUser.displayName
			}, params));
		},

		editCommentTemplate: function(params) {
			if (!this._editCommentTemplate) {
				this._editCommentTemplate = Handlebars.compile(EDIT_COMMENT_TEMPLATE);
			}
			var currentUser = OC.getCurrentUser();
			return this._editCommentTemplate(_.extend({
				avatarEnabled: this._avatarsEnabled,
				actorId: currentUser.uid,
				actorDisplayName: currentUser.displayName,
				newMessagePlaceholder: t('comments', 'New comment …'),
				deleteTooltip: t('comments', 'Delete comment'),
				submitText: t('comments', 'Post'),
				cancelText: t('comments', 'Cancel')
			}, params));
		},

		commentTemplate: function(params) {
			if (!this._commentTemplate) {
				this._commentTemplate = Handlebars.compile(COMMENT_TEMPLATE);
			}

			params = _.extend({
				avatarEnabled: this._avatarsEnabled,
				editTooltip: t('comments', 'Edit comment'),
				isUserAuthor: OC.getCurrentUser().uid === params.actorId,
				isLong: this._isLong(params.message)
			}, params);

			if (params.actorType === 'deleted_users') {
				// makes the avatar a X
				params.actorId = null;
				params.actorDisplayName = t('comments', '[Deleted user]');
			}

			return this._commentTemplate(params);
		},

		getLabel: function() {
			return t('comments', 'Comments');
		},

		setFileInfo: function(fileInfo) {
			if (fileInfo) {
				this.model = fileInfo;
				this.render();
				this.collection.setObjectId(fileInfo.id);
				// reset to first page
				this.collection.reset([], {silent: true});
				this.nextPage();
			} else {
				this.model = null;
				this.render();
				this.collection.reset();
			}
		},

		render: function() {
			this.$el.html(this.template({
				emptyResultLabel: t('comments', 'No comments yet, start the conversation!'),
				moreLabel: t('comments', 'More comments …')
			}));
			this.$el.find('.comments').before(this.editCommentTemplate({}));
			this.$el.find('.has-tooltip').tooltip();
			this.$container = this.$el.find('ul.comments');
			if (this._avatarsEnabled) {
				this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 32);
			}
			this.delegateEvents();
			this.$el.find('.message').on('keydown input change', this._onTypeComment);
		},

		_formatItem: function(commentModel) {
			var timestamp = new Date(commentModel.get('creationDateTime')).getTime();
			var data = _.extend({
				timestamp: timestamp,
				date: OC.Util.relativeModifiedDate(timestamp),
				altDate: OC.Util.formatDate(timestamp),
				formattedMessage: this._formatMessage(commentModel.get('message'))
			}, commentModel.attributes);
			return data;
		},

		_toggleLoading: function(state) {
			this._loading = state;
			this.$el.find('.loading').toggleClass('hidden', !state);
		},

		_onRequest: function(type) {
			if (type === 'REPORT') {
				this._toggleLoading(true);
				this.$el.find('.showMore').addClass('hidden');
			}
		},

		_onEndRequest: function(type) {
			var fileInfoModel = this.model;
			this._toggleLoading(false);
			this.$el.find('.emptycontent').toggleClass('hidden', !!this.collection.length);
			this.$el.find('.showMore').toggleClass('hidden', !this.collection.hasMoreResults());

			if (type !== 'REPORT') {
				return;
			}

			// find first unread comment
			var firstUnreadComment = this.collection.findWhere({isUnread: true});
			if (firstUnreadComment) {
				// update read marker
				this.collection.updateReadMarker(
					null,
					{
						success: function() {
							fileInfoModel.set('commentsUnread', 0);
						}
					}
				);
			}
		},

		_onAddModel: function(model, collection, options) {
			var $el = $(this.commentTemplate(this._formatItem(model)));
			if (!_.isUndefined(options.at) && collection.length > 1) {
				this.$container.find('li').eq(options.at).before($el);
			} else {
				this.$container.append($el);
			}

			this._postRenderItem($el);
		},

		_postRenderItem: function($el) {
			$el.find('.has-tooltip').tooltip();
			if(this._avatarsEnabled) {
				$el.find('.avatar').each(function() {
					var $this = $(this);
					$this.avatar($this.attr('data-username'), 32);
				});
			}
		},

		/**
		 * Convert a message to be displayed in HTML,
		 * converts newlines to
 tags.
		 */
		_formatMessage: function(message) {
			return escapeHTML(message).replace(/\n/g, '
');
		},

		nextPage: function() {
			if (this._loading || !this.collection.hasMoreResults()) {
				return;
			}

			this.collection.fetchNext();
		},

		_onClickEditComment: function(ev) {
			ev.preventDefault();
			var $comment = $(ev.target).closest('.comment');
			var commentId = $comment.data('id');
			var commentToEdit = this.collection.get(commentId);
			var $formRow = $(this.editCommentTemplate(_.extend({
				isEditMode: true,
				submitText: t('comments', 'Save')
			}, commentToEdit.attributes)));

			$comment.addClass('hidden').removeClass('collapsed');
			// spawn form
			$comment.after($formRow);
			$formRow.data('commentEl', $comment);
			$formRow.find('textarea').on('keydown input change', this._onTypeComment);

			// copy avatar element from original to avoid flickering
			$formRow.find('.avatar').replaceWith($comment.find('.avatar').clone());
			$formRow.find('.has-tooltip').tooltip();

			return false;
		},

		_onTypeComment: function(ev) {
			var $field = $(ev.target);
			var len = $field.val().length;
			var $submitButton = $field.data('submitButtonEl');
			if (!$submitButton) {
				$submitButton = $field.closest('form').find('.submit');
				$field.data('submitButtonEl', $submitButton);
			}
			$field.tooltip('hide');
			if (len > this._commentMaxThreshold) {
				$field.attr('data-original-title', t('comments', 'Allowed characters {count} of {max}', {count: len, max: this._commentMaxLength}));
				$field.tooltip({trigger: 'manual'});
				$field.tooltip('show');
				$field.addClass('error');
			}

			var limitExceeded = (len > this._commentMaxLength);
			$field.toggleClass('error', limitExceeded);
			$submitButton.prop('disabled', limitExceeded);

			//submits form on ctrl+Enter or cmd+Enter
			if (ev.keyCode === 13 && (ev.ctrlKey || ev.metaKey)) {
				$submitButton.click();
			}
		},

		_onClickComment: function(ev) {
			var $row = $(ev.target);
			if (!$row.is('.comment')) {
				$row = $row.closest('.comment');
			}
			$row.removeClass('collapsed');
		},

		_onClickCloseComment: function(ev) {
			ev.preventDefault();
			var $row = $(ev.target).closest('.comment');
			$row.data('commentEl').removeClass('hidden');
			$row.remove();
			return false;
		},

		_onClickDeleteComment: function(ev) {
			ev.preventDefault();
			var $comment = $(ev.target).closest('.comment');
			var commentId = $comment.data('id');
			var $loading = $comment.find('.submitLoading');

			$comment.addClass('disabled');
			$loading.removeClass('hidden');
			this.collection.get(commentId).destroy({
				success: function() {
					$comment.data('commentEl').remove();
					$comment.remove();
				},
				error: function() {
					$loading.addClass('hidden');
					$comment.removeClass('disabled');
					OC.Notification.showTemporary(t('comments', 'Error occurred while retrieving comment with id {id}', {id: commentId}));
				}
			});

			return false;
		},

		_onClickShowMore: function(ev) {
			ev.preventDefault();
			this.nextPage();
		},

		_onSubmitComment: function(e) {
			var self = this;
			var $form = $(e.target);
			var commentId = $form.closest('.comment').data('id');
			var currentUser = OC.getCurrentUser();
			var $submit = $form.find('.submit');
			var $loading = $form.find('.submitLoading');
			var $textArea = $form.find('.message');
			var message = $textArea.val().trim();
			e.preventDefault();

			if (!message.length || message.length > this._commentMaxLength) {
				return;
			}

			$textArea.prop('disabled', true);
			$submit.addClass('hidden');
			$loading.removeClass('hidden');

			if (commentId) {
				// edit mode
				var comment = this.collection.get(commentId);
				comment.save({
					message: $textArea.val()
				}, {
					success: function(model) {
						var $row = $form.closest('.comment');
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$row.data('commentEl')
							.removeClass('hidden')
							.find('.message')
							.html(self._formatMessage(model.get('message')));
						$row.remove();
					},
					error: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.prop('disabled', false);

						OC.Notification.showTemporary(t('comments', 'Error occurred while updating comment with id {id}', {id: commentId}));
					}
				});
			} else {
				this.collection.create({
					actorId: currentUser.uid,
					actorDisplayName: currentUser.displayName,
					actorType: 'users',
					verb: 'comment',
					message: $textArea.val(),
					creationDateTime: (new Date()).toUTCString()
				}, {
					at: 0,
					// wait for real creation before adding
					wait: true,
					success: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.val('').prop('disabled', false);
					},
					error: function() {
						$submit.removeClass('hidden');
						$loading.addClass('hidden');
						$textArea.prop('disabled', false);

						OC.Notification.showTemporary(t('comments', 'Error occurred while posting comment'));
					}
				});
			}

			return false;
		},

		/**
		 * Returns whether the given message is long and needs
		 * collapsing
		 */
		_isLong: function(message) {
			return message.length > 250 || (message.match(/\n/g) || []).length > 1;
		}
	});

	OCA.Comments.CommentsTabView = CommentsTabView;
})(OC, OCA);
<|endoftext|>